서버에 로그인을 성공한 유저는 서버가 발행한 토큰
을 발급받음
통상적으로, ACCESS TOKEN
이라고 부르며, 토큰에는 User id 같은 아주 중요한 정보가 아니면서도 유저를 확실하게 구분할 수 있는 정보가 들어야한다.
인증을 받은 유저는 Request를 보낼 때,
request header
에 'Authroization'
이라는 이름으로 token정보를 담아서 보낸다.
서버는 이 request에 담긴 Token 정보를 복호화
하여 발급한 Token이 맞는지 여부를 확인함과 동시에 User id를 확인한다.
user id를 통해 DB에서 해당 유저의 권한(permission)을 확인
해당 유저가 그 요청을 사용할 수 있는 권한을 가지고 있으면 요청 처리
권한을 갖고 있지않다면 Unauthorized Response(401) Error 혹은 다른 적절한 에러코드를 보냄
양방향 해시 알고리즘
이 적용 (***)ex)
{
"alg" : "HS256",
"typ" : "JWT"
}
토큰을 통해 전달할 내용이 담겨 있음
여기 담는 정보의 한 조각을 'Claim'이라고 부르며, Key-Value의 객체형으로 담김
클레임의 정보는 등록된(registerd) 클레임, 공개(public) 클레임, 비공개(private) 클레임 세종류로 구분
보통 만료 일시, 발급일시, 발급자, 권한정보 등이 포함된 공개 클래임
클라이언트와 서버간 협의 하에 사용하는 비공개 클래임
Header와 Payload 부분은 암호화하지 않고 base64로 인코딩만 하기 때문에 웹에 접속한 호스트라면 누구나 볼 수 있다. 따라서 민감함 정보는 넣지 않고, user id와 값은 PK값을 전달한다.
ex)
{
"iss": "http://example.org",
"aud": "https://exmple.com",
"exp": "1407019629",
"http://example.com/jwt_claims/is_admin" : "true",
"user_id": "3"
}
인코딩된 header 와 payload를 합쳐 header의 signature 알고리즘정보(alg)를 가져와 암호화 생성
헤더의 인코딩 값과, 정보의 인코딩 값을 합친 후 주어진 비밀키로 해쉬를 하여 생성
프론트엔드에서 JWT를 백엔드 API 서버로 전송하면 서버에서는 전송받은 JWT의 Signature 부분을 복호화하여 이 서버에서 생성한 JWT가 맞는지 확인
마치 계약서의 위변조를 막기 위해 서로 사인하는 것과 동일
HMACSHA256(
base64UrlEncode(header) + “.”+
base64UrlEncode(payload),
Secret)
파이썬에서 JWT를 이용하여 ACCESS TOKEN을 발급하는 과정
$ pip install pyjwt
import jwt
import datetime
# JWT 토큰 발행 (만료 시간을 300초로 설정)
encoded_jwt = jwt.encode({'user-id': 5, 'exp': datetime.datetime.utcnow() + datetime.timedelta(seconds=300)}, 'secret', algorithm='HS256')
# 파이썬 쉘 실행
import jwt # import할 때는 jwt
data = {'user_id':3}
>>> encoded_jwt = jwt.encode(data, 'secret', algorithm='HS256')
>>> encoded_jwt
'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjozfQ.mU
nSxfiXA4zkxTrIVT3l2FRBMfTcHTLOd5oVHDaKnWo'
>>> type(token)
<class 'bytes'>
jwt.encode({user_id, 토큰 만료시간 등 payload에 줄 정보}, 'secret key', algorithm='사용할 해싱 알고리즘')
# 토큰 검증(decode)
payload = jwt.decode(encoded_jwt, 'secret', algorithms=['HS256'])
>>> jwt.decode(encoded_jwt, "secret", algorithms="HS256")
{'user_id': 3}
>>> type(token)
<class 'str'>
jwt.decode(검증할 토큰, 'secret', algorithms=['HS256'])
decode의 algorithms 주의... 's' 꼭 들어가야함!!
encode 할 때는 algorithm
, decode할 때는 algorithms