[Web] Authentication & Authorization(1) - Authorization (+ JWT)

Jayson Hwang·2022년 5월 19일
0

Django Basics

목록 보기
10/14
post-thumbnail

1.. Authorization(인가)??

  • 요청을 보낸 유저가 그 서비스를 이용할 수 있는 유저인지 확인하는 절차

1-1.. Authorization 절차

  1. 서버에 로그인을 성공한 유저는 서버가 발행한 토큰을 발급받음
    통상적으로, ACCESS TOKEN 이라고 부르며, 토큰에는 User id 같은 아주 중요한 정보가 아니면서도 유저를 확실하게 구분할 수 있는 정보가 들어야한다.

  2. 인증을 받은 유저는 Request를 보낼 때,
    request header'Authroization'이라는 이름으로 token정보를 담아서 보낸다.

  3. 서버는 이 request에 담긴 Token 정보를 복호화하여 발급한 Token이 맞는지 여부를 확인함과 동시에 User id를 확인한다.

  4. user id를 통해 DB에서 해당 유저의 권한(permission)을 확인

  5. 해당 유저가 그 요청을 사용할 수 있는 권한을 가지고 있으면 요청 처리

  6. 권한을 갖고 있지않다면 Unauthorized Response(401) Error 혹은 다른 적절한 에러코드를 보냄

1-2.. JSON Web Token (JWT) (양방향 해쉬 알고리즘)

JWT ??

  • ACCESS TOKEN을 생성하는 하나의 방법
  • JSON 포맷을 사용하여 사용자에 대한 속성을 저장하는 Claim 기반의 Web Token
  • 인증에 필요한 정보들(JSON 객체)을 암호화 시킨 토큰
  • 토큰에 대한 기본정보(header), 전달할 정보(payload), 그리고 토큰이 검증된 것을 증명해주는 Signature를 포함
  • JWT는 양방향 해시 알고리즘이 적용 (***)
    이를 이용하여, 프론트엔드에서 API 요청 시 암호화 된 토큰 정보를 보내고, 백엔드에서는 이 토큰을 복호화해서 유저의 권한을 확인한다.

JWT 구조

1) HEADER

  • 두가지 정보를 지님 (typ, alg)
  • typ: 토큰의 타입을 지정 (JWT는 JWT)
  • alg: Signature 해싱 알고리즘 지정
    해싱 알고리즘으로 보통 HMAC-SHA256 or RSA가 사용되며, 이 알고리즘은 토큰을 검증 할 때 사용되는 Signature 부분에서 사용
ex)
  
{ 
	"alg" : "HS256", 
	"typ" : "JWT" 
}  

2) Payload

  • 토큰을 통해 전달할 내용이 담겨 있음

  • 여기 담는 정보의 한 조각을 '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"
}

3) Signature

  • 인코딩된 header 와 payload를 합쳐 header의 signature 알고리즘정보(alg)를 가져와 암호화 생성

  • 헤더의 인코딩 값과, 정보의 인코딩 값을 합친 후 주어진 비밀키로 해쉬를 하여 생성

  • 프론트엔드에서 JWT를 백엔드 API 서버로 전송하면 서버에서는 전송받은 JWT의 Signature 부분을 복호화하여 이 서버에서 생성한 JWT가 맞는지 확인

  • 마치 계약서의 위변조를 막기 위해 서로 사인하는 것과 동일

HMACSHA256( 
    base64UrlEncode(header) +.+ 
    base64UrlEncode(payload), 
    Secret)

1-3.. JSON web Token (JWT)으로 인가 구현

파이썬에서 JWT를 이용하여 ACCESS TOKEN을 발급하는 과정

1) JWT 패키지 설치

$ pip install pyjwt

** pyjwt 공식문서

2) JWT 토큰 발행 과정

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='사용할 해싱 알고리즘')

3) JWT 토큰 검증 (decode), 복호화

# 토큰 검증(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

profile
"Your goals, Minus your doubts, Equal your reality"

0개의 댓글