나와바리 - Spring Security + JWT를 이용한 로그인 API 구현(1)

Sungmin·2023년 5월 10일
0

JWT를 통한 인증 순서

1. 사용자가 로그인 시 로그인 아이디, 패스워드를 담아 서버에 요청

2. 서버에서 서명된(Signed) JWT 토큰을 생성하여 클라이언트에 응답으로 반환

3. 클라이언트는 응답으로 반환된 JWT 토큰을 사용하여 요청 시 마다 Http Header에 JWT를 담아 요청

4. 서버에서는 요청된 Http Header의 JWT를 검증하여 토큰이 유효한지 검증 후 유효하다면 요청에 맞는 응답 반환


1. Header

Header 는 보통 토큰의 타입이나, 전자서명시 사용되는 알고리즘을 저장.
현재 프로젝트는 HS512알고리즘 사용

2. Payload

Payload 는 보통 Claim이라는 토큰에서 사용할 정보들이 담겨 있다.
위의 사진에서 key-value 형식으로 이루어진 값들은 모두 Claim이다.
인증 시에 토큰에서 실제로 사용될 정보를 의미.

Claim 표준스펙

2. sub(Subjec) : 토큰 제목 - 토큰에서 사용자에 대한 식별값이 된다.
3. aud(Audience) : 토큰 대상자
4. exp(Expiration Time) : 토큰 만료 시간
5. nbf(Not Before) : 토큰 활성 날짜 (이 날짜 이전의 토큰은 활성화 되지 않음을 보장)
6. iat(Issued At) : 토큰 발급 시간
7. jti(JWT Id) : JWT 토큰 식별자 (issuer가 여러 명일 때 구분하기 위한 값)

주의점!!

Payload는 암호화 되어있지 않기 때문에, 민감한 정보를 담지 않아야 한다.
식별을 위한 정보만을 담아야 함.

3. Signature

base64UrlEncode를 사용하여 header와 payload를 암호화 하였다.
그 다음 your-256-bit-secret로 서버가 갖고있는 개인키를 통해 암호화되어있다.
서버가 갖고있는 개인키를 통해 암호화 되어있기 때문에 외부에서 Signature를 복호화 할 수 없다.

자세한 인증과정

1. JWT 토큰을 클라이언트가 서버에 요청 시 Http Header에 담아 요청합니다.

2. 서버에서 Http Header의 JWT 토큰을 꺼내서 가져옵니다.

3. 클라이언트가 요청한 JWT 토큰을 서버가 가지고 있는 개인키를 가지고 Signature를 복호화합니다.

4. 복호화한 Signature의 base64UrlEncode(header)/base64UrlEncode(payload)가
각각 요청한 JWT 토큰의 header, payload와 일치하는지 검증합니다.

5. 일치한다면 인증을 허용하고, 일치하지 않는다면 인증이 실패합니다.

AccessToken & RefreshToken

AccessToken

처음 로그인 요청 시 서버에서 실제 유저의 정보가 담긴 AccessToken을 발행합니다.
클라이언트는 이 AccessToken을 저장한 후, 요청마다 AccessToken을 보내서
해당 AccessToken을 서버에서 검증 후 유효하면 요청에 맞는 응답을 진행합니다.

RefreshToken

처음 로그인 요청 시 서버에서 AccessToken 재발급 용도인 RefreshToken을 발행합니다.
이때, 클라이언트는 RefreshToken을 저장하지 않고 RefreshToken은 보통 서버 DB에 저장됩니다.
RefreshToken이 유효하면, AccessToken의 재발급을 진행합니다.

예를들어 AccessToken의 유효기간이 1시간일때 RefreshToken이 없다면 사용자는 1시간마다 로그인 해야하는 번거로움이 발생한다.

여기서, RefreshToken이 존재하고 유효기간이 7일이라면

클라이언트에서 AccessToken이 만료된 후 요청을 보낼 경우 서버에서 인증실패가 아닌 RefreshToken검증 단계에 진입한다.

유효하다면 새로운 AccessToken을 발행해 주고, 클라이언트는 새로받은 토큰으로 재 요청한다.
따라서, 사용자의 눈에는 별도의 재로그인 과정없이 AccessToken이 만료되지 않은 것처럼 동작하게 된다.

RefreshToken은 클라이언트에 저장되는 것이 아닌 서버 DB에 저장되기 때문에 해커 탈취 위험이 적다.

profile
Let's Coding

0개의 댓글