728x90

로그인 후에 Access Token을 발급하여 쿠키에 저장하는 것까지 구현해 보았습니다.

https://sound-story.tistory.com/19

 

[NestJS] Auth Token을 쿠키에 저장하기

email, password를 통해 로그인하여 access token을 생성하고, 생성된 access token으로 사용자 정보를 조회해 보는 것을 해보았어요. 이어서 token을 쿠키에 저장하는 로직을 구현해 보려고 합니다. 1. cookie-p

sound-story.tistory.com

오늘은 Refresh Token을 구현하기에 앞서 인증의 개념에 대해서 정리하고 시작해 보려고 합니다.

먼저 저희가 acces token발급 시 사용했던 JWT에 관한 얘기입니다.

로그인하면 제일 많이 들어본 거 같아요. 많이 쓰이기 때문에 많이 들어봤겠죠.

 

JWT란?

JSON Web Token의 약어로, 마이크로 서비스의 인증, 인가에 사용할 수 있는 JSON입니다.

서버와 클라이언트 간 정보를 주고받을 때 HTTP Request Header에 JSON토큰을 넣은 후 서버는 별도의 인증과정 없이 헤더에 포함되어 있는 JWT 정보를 통해 인증하게 됩니다.

이렇게 사용되는 JSON 데이터는 URL로 이용할 수 있는 문자 만으로 구성되게 됩니다.

 

JWT는 header, payload, signature로 구성되어 있고, 각 요소는  '.'으로 구분되어 있습니다.

jwt 구성 요소 ( jwt 구조)

실제로 저희가 구현해서 발급했던 토큰을 살펴보니 3개의 구성이 눈에 보입니다.

jwt token

이 토큰을 가지고 공식 홈페이지에서 Decoded를 해보았습니다.

https://jwt.io/

 

JWT.IO

JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties.

jwt.io

 

 

Encoded에 토큰을 입력하니 Decoded 되어 Header, Payload, Verify Signature 정보가 보입니다.

1. Header : 어떤 알고리즘이 사용되었는지에 대한 "alg"와 JWT의 유형 정보를 가진 "typ"이 있습니다.

  • "alg" : 토큰을 암호화하는 알고리즘 정보입니다. 저는 "HS256"으로 토큰을 암호화했다는 뜻입니다. 알고리즘은 "HS256"외에도 "HS512"(HMAC), "SHA256", "RSA" 등이 있습니다.
  • "typ" : 토큰의 유형 정보입니다. 저는 JWT를 사용했습니다.

 

2. Payload : 클레임(claim) 정보가 저장됩니다. 클레임은 정보 '조각'이라는 의미로, 토큰 또는 사용자에 대한 property를 <key : value>의 형태로 저장할 수 있습니다. 저는 사용자의 id와 이름, 토큰 발급 시간, 토큰 만료 시간을 payload로 사용했는데요. jwt.io에서 보면 registered, public, private claim 3가지가 있습니다.

  • Registered claims : 필수 사항은 아니지만 권장되는 claim입니다. iss(발급자), expiration(유효기간), subject(제목), aud(청취자) 등 이 있습니다. 자세한 정보는 https://datatracker.ietf.org/doc/html/rfc7519#section-4.1에서 확인할 수 있습니다.
  • Public claims : 원하는 대로 정의할 수 있는 claim으로 충돌을 피하려면 IANA JSON Web 토큰 레지스트리에서 정의하거나 충돌 방지 네임스페이스를 포함하는 URI로 정의해야 합니다.
  • Private claims : 사용에 동의한 당사자 간에 정보를 공유하기 위해 작성된 custom claim입니다.

3. Signature : 암호화가 되어 있기 때문에 구조를 보여줍니다. 암호화된 헤더, 암호화된 페이로드, 시크릿(사용자가 정한 시크릿 키), 알고리즘으로 되어 있어요. 저희는 HMAC SHA256 알고리즘을 사용하였네요.

jwt 구성 요소 ( jwt 구조)

JWT 인증과정

그렇다면 발급된 token은 어떻게 쓰일까요?

1. 애플리케이션, 사용자가 인증서버에 인증을 요청합니다. 

2. 인증에 성공하면 인증서버는 액세스 토큰을 반환합니다.

3. 애플리케이션 또는 사용자는 발급된 액세스 토큰으로 API 서버에 접속할 수 있게 됩니다.

jwt process / jwt 프로세스 (https://jwt.io/introduction)

 

JWT 왜 쓸까요?

그렇다면 어떠한 이유에서 JWT를 사용할까요.

JWT의 장단점에 대해 생각해보겠습니다.

 

JSON은 XML보다 장황하지 않기 때문에 암호화 시 사이즈가 작아져 JWT가 SAML보다 콤팩트합니다. 때문에 HTML 및 HTTP 환경에서 JWT를 사용하는 것이 효율적입니다.

보안상 SWT는 HMAC 알고리즘을 사용하여 공유 비밀에 의해서만 대칭적으로 서명할 수 있습니다. 단, JWT 토큰과 SAML 토큰은 X.509 증명서 형식으로 공개 키와 개인 키 쌍을 서명에 사용할 수 있습니다. 불분명한 보안 취약점을 도입하지 않고 XML 디지털 서명을 사용하여 XML에 서명하는 것은 JSON의 간단한 서명에 비해 매우 어렵습니다.

JSON 파서는 오브젝트에 직접 매핑되기 때문에 대부분의 프로그래밍 언어에서 일반적입니다. 반대로 XML에는 문서와 객체의 자연스러운 매핑이 없습니다. 이를 통해 SAML 어설션보다 JWT를 사용하는 것이 쉬워집니다.

이용에 관해서는 JWT를 인터넷 규모로 사용하고 있습니다. 이를 통해 여러 플랫폼(특히 모바일)에서 클라이언트 측 JSON Web 토큰을 쉽게 처리할 수 있습니다.

 

하지만, JWT에도 한계는 있습니다. 개발자의 학습영역? 범위가 끝이 없는 이유는 100% 완벽하다고 끝내기가 없어서이지 않을까 싶습니다.

구현하고 decode를 하면서 든 의문입니다.

저희가 payload에 저장하였던 email과 이름은 민감정보가 아닐까요? 이를 오픈해도 될까요?

token을 발급하고 만약 payload에 저장된 정보가 변경되었다면, payload에서 decode 한 정보와 현재 정보는 일치하지 않네요?

JWT는 토큰의 상태를 저장하지 않습니다. Stateless 이 특성 때문에 한번 만들어진 토큰을 제어할 수 없다는 단점이 있어요. 임의로 삭제할 수 없으니 만료시간이 중요한데, 이를 길게 하면 데이터나 보안이 취약해지고, 짧게 하자니 로그인을 자주 해야 하는 문제가 발생합니다. 이에 대한 대안으로 refresh token, sliding session이 많이 사용되고 있는데요.

 

JWT의 대안

1. Refresh token

JWT를 발급할 때 Access Token과 함께 Refresh Token을 함께 발급하여 Access Token의 짧은 만료시간의 문제를 해결하는 방법입니다. Access Token은 1분, 3분의 짧은 시간을 부여하고 Refresh Token에는 일주일, 2주의 비교적 긴 만료시간을 부여하여 Access Token을 보장해주는 방법입니다. Access Token이 만료되면 Refresh Token으로 서버에게 새로운 Access Token을 발급하도록 합니다.

 

2. Sliding Session

sliding session은 서비스를 사용 중인 유저에 대해서 만료시간을 연장시켜 주는 방법입니다.

쇼핑몰에 접속하여 계속 쇼핑을 하고 있으면 만료시간을 연장하여 쇼핑, 결제 등의 서비스를 지속적으로 이용 가능하도록 하는 방법입니다. 

 

앞으로는 refresh token에 대해서 구현해 보도록 하겠습니다.

 

728x90
반응형

+ Recent posts