사용자가 ID , PW를 통해 로그인합니다.
서버에서는 회원 DB에서 값을 비교합니다(보통 PW는 일반적으로 암호화해서 들어갑니다)3~4. 로그인이 완료되면 Access Token, Refresh Token을 발급합니다. 이때 일반적으로 회원DB에 Refresh Token을 저장해둡니다.
사용자는 Refresh Token은 안전한 저장소에 저장 후, Access Token을 헤더에 실어 요청을 보냅니다.
6~7. Access Token을 검증하여 이에 맞는 데이터를 보냅니다.
시간이 지나 Access Token이 만료됐다고 보겠습니다.
사용자는 이전과 동일하게 Access Token을 헤더에 실어 요청을 보냅니다.
10~11. 서버는 Access Token이 만료됨을 확인하고 권한없음을 신호로 보냅니다.
사용자(프론트엔드)에서 Access Token의 Payload를 통해 유효기간을 알 수 있습니다. 따라서 프론트엔드 단에서 API 요청 전에 토큰이 만료됐다면 바로 재발급 요청을 할 수도 있습니다.
사용자는 Refresh Token과 Access Token을 함께 서버로 보냅니다.
13. 서버는 받은 Access Token이 조작되지 않았는지 확인한후, Refresh Token과 사용자의 DB에 저장되어 있던 Refresh Token을 비교합니다. Token이 동일하고 유효기간도 지나지 않았다면 새로운 Access Token을 발급해줍니다.
서버는 새로운 Access Token을 헤더에 실어 다시 API 요청을 진행합니다.
JWT(Json Web Token)란 Json 포맷을 이용하여 사용자에 대한 속성을 저장하는 Claim 기반의 Web Token
JWT는 토큰 자체를 정보로 사용하는 Self-Contained 방식으로 정보를 안전하게 전달한다.
주로 회원 인증이나 정보 전달에 사용되는 JWT는 아래의 로직을 따라서 처리된다.
클레임(Claim)이란 사용자 정보나 데이터 속성 등을 의미한다.
그래서 클레임 토큰이라 하면 토큰 안에 정보를 담고 있는 토큰이라 생각하면 된다.
예를 들면 아래와 같이 정보를 담고 있는 것을 클레임 기반이라 할 수 있다.
.을 이용한 3개의 구성(Header, Payload, Signature)
Header는 토큰의 타입을 나타내는 typ
과 암호화할 방식을 정하는 alg
로 구성되어 있습니다.
암호화는 이후에 자세히 설명하겠습니다.
{
"alg": 'HS256',
"typ": 'JWT'
}
Payload는 토큰에 담을 정보를 포함합니다. 여기서 하나의 정보 조각을 클레임으로 부릅니다. 클레임의 종류로는 Registered, Public, Private로 3가지가 존재합니다. 보통 만료 일시, 발급 일시, 발급자, 권한정보 등을 포함합니다.
{
"iss": "mju.com",
"exp": "1485270000000",
"https://mju.com/jwt_claims/is_admin": true,
"userId": "11028373727102",
"username": "mju"
}
등록된 클레임들은 서비스에서 필요한 정보들이 아닌, 토큰에 대한 정보들을 담기위하여 이름이 이미 정해진 클레임들입니다. 등록된 클레임의 사용은 모두 선택적 (optional)이며, 이에 포함된 클레임 이름들은 다음과 같습니다:
iss
: 토큰 발급자 (issuer)sub
: 토큰 제목 (subject)aud
: 토큰 대상자 (audience)exp
: 토큰의 만료시간 (expiraton), 시간은 NumericDate 형식으로 되어있어야 하며 (예: 1480849147370) 언제나 현재 시간보다 이후로 설정되어있어야합니다.nbf
: Not Before 를 의미하며, 토큰의 활성 날짜와 비슷한 개념입니다. 여기에도 NumericDate 형식으로 날짜를 지정하며, 이 날짜가 지나기 전까지는 토큰이 처리되지 않습니다.iat
: 토큰이 발급된 시간 (issued at), 이 값을 사용하여 토큰의age
가 얼마나 되었는지 판단 할 수 있습니다.jti
: JWT의 고유 식별자로서, 주로 중복적인 처리를 방지하기 위하여 사용됩니다. 일회용 토큰에 사용하면 유용합니다.
공개 클레임들은 충돌이 방지된 (collision-resistant) 이름을 가지고 있어야 합니다. 충돌을 방지하기 위해서는, 클레임 이름을 URI 형식으로 짓습니다.
{
"https://mju.com/jwt_claims/is_admin": true
}
등록된 클레임도아니고, 공개된 클레임들도 아닙니다. 양 측간에 (보통 클라이언트 <->서버) 협의하에 사용되는 클레임 이름들입니다. 공개 클레임과는 달리 이름이 중복되어 충돌이 될 수 있으니 사용할때에 유의해야합니다.
{
"username": "mju"
}
Signature는 Payload가 위변조되지 않았다는 사실을 증명하는 문자열입니다. Base64 방식으로 인코딩한 Header, Payload 그리고 SECRET KEY를 더한 후 서명됩니다.
HMACSHA256 {
base64UrlEncode(header) + '.' +
base64UrlEncode(payload),
your-256-bit-secret
}