JWT 로그인 인증방식

HeumHeum2·2021년 2월 7일
4
post-thumbnail

🏷 개요

HTTP 기본 인증 방식이 모바일에서는 raw한 api키를 매 요청 때마다 사용해야 하는 문제가 있어 취약점 공격에 노출될 가능성이 높다. 또한 API 키가 내장된 채로 배포하면 리버싱을 통해 API 키를 알아내는 것이 가능하기에 서비스가 악용될 소지가 있다. 그렇기에 HTTP 기본 인증 방식은 웹 브라우저나 모바일 앱과 같은 신뢰하기 힘든 환경에 적합한 인증 방식은 아니다.


🏷 Access Token

엑세스 토큰은 JWT(JSON Web Token)를 주로 사용하는데, JWT는 다음과 같은 특징을 갖는다.

  • 클라이언트로 발행될 수 있다.
  • 일정 시간 뒤에 자동으로 만료된다.
  • 당신이 생성했다는 사실을 증명할 수 있다.(서명)
  • JSON 타입으로 변수 정보를 저장할 수 있다.
  • 서버에서 쿼리하지 않아도 사용자를 로컬에서 검증할 수 있기 때문에 API 호출의 횟수를 줄일 수 있다.
  • 세션 상태를 저장하는게 아니기에 클라이언트는 Access Token(JWT Token)을 헤더에 실어 서버로 보내야 한다.

🏷 Token Structure

토큰 구조는 Header, Payload, Signature로 나눠진다.

Header, Payload, Signature 정보를 암호화 할 방식(alg), 타입(typ) 등이 들어간다.

암호화 할 방식(alg)에는 보통 HMAC SHA256 또는 RSA가 보통 사용되며, 타입(typ)에는 토큰의 타입을 지정하면 된다.

{
  "typ": "JWT",
  "alg": "HS256" // HMAC SHA256
}

Payload

토큰에 담을 정보가 들어간다. 일반적으로 사용자의 ID, 유효 기간이 포함되어 있다.

정보의 한 '조각'을 클레임(claim)이라고 부르고, name-value의 한 쌍으로 이뤄져 있다. 토큰에는 여러 개의 클레임들을 넣을 수 있는데 클레임의 종류는 다음과 같다.

  • 등록된 (registered) 클레임
  • 공개 (public) 클레임
  • 비공개 (private) 클레임

클라이언트에 대한 정보, META data 같은 내용이 들어있으며, Base64로 인코딩 되어있다.

Verify Signature

Base64 방식으로 인코딩 한 Header, payload 그리고 Secret key를 합친 후에 토큰이 생성된다.


로그인 구현을 할 때 JWT로 구현하면서 궁금한 점이 있어서 글을 적어본다.

내가 로그인 구현을 할 때 로직은 아래와 같다.

  1. 클라이언트가 서버에게 아이디와 비밀번호를 보내는 로그인 요청을 한다.
  2. 서버는 아이디와 비밀번호를 데이터베이스와 비교해 일치하면 Access Token을 넘겨주고, 실패하면 에러 메시지를 넘긴다.
  3. 토큰을 받은 클라이언트는 요청이 필요한 곳마다 서버로 Access Token을 보내면 서버에서 유효한지 확인 후 필요한 정보를 반환한다.

문제는 Access Token의 만료기간을 길게 잡으면 공격자가 탈취해 유저의 정보를 쉽게 얻을 수 있다는 점이 있다.

만료기간을 짧게 한 후, 만료되었을 때 서버에서 토큰을 재발급 해줘야 하는데 검색하다가 찾은 것이 Refresh Token이다.

🏷 Refresh Token

일반적으로 Access Token의 만료기간이 만료되면 사용자는 Access Token을 얻기 위해 다시 인증을 해야 한다. Refresh Token 을 이용하면 재 인증을 건너 뛸 수 있으며, API에 대한 요청으로 클라이언트가 애플리케이션 Resource에 계속 액세스 할 수 있는 새로운 Access Token을 얻을 수 있다.

그렇기에 만료기간이 길고, 사용횟수가 적기에 보관이 중요하다.

목적

Refresh Token을 담고 있는 저장소에서 클라이언트가 보낸 토큰이 동일한 클라이언트가 맞는지 확인하는 것이다. 동일한 클라이언트일 경우 새로운 토큰을 생성하고 반환하여 엑세스 토큰을 보낸다.

문제점

결국에 Refresh Token으로 Access Token을 발급하는데 있어, 공격자가 Refresh Token를 탈취되면 Access Token을 발급 받을 수 있고, 결국 공격자는 클라이언트로 위장해 정보를 얻어 갈 수 있다는 점이 있다.

그러면 Refresh Token이 왜 필요한지에 대한 의문점이 들었다.

물론 Access Token과 Refresh Token이 있을 경우 Access Token이 300번 요청 될 때, Refresh Token은 1번 요청 될 수도 있어서 나름 보안적이긴 하나.. Refresh Token 이 중간에 탈취 당했을 경우 어떻게 대처해야 좋을지 아직은 모르겠다.

결과

결론적으로는 완벽한 보안은 없다. 고민을 하면서 차선책으로 선택을 해야하는데 유저 편의성을 중요하게 생각하는 프로젝트냐, 보안이 좀 더 중요한 프로젝트냐에 따라서 다를 것 같다. 금융 프로젝트인 경우 보안을 조금 더 중요하게 생각하기에 수시로 로그인을 받으면 되고, 커뮤니티 프로젝트인 경우에는 편의성을 고려해 로그인을 유지시키는 게 좋을 듯 하다.

참고

https://velopert.com/2389

http://throughkim.kr/2017/03/14/Jwt/

profile
커피가 본체인 개발자 ☕️

0개의 댓글