django에서 인증/인가 (bcrypt, JWT) 를 구현하는 방법과,
refresh token 그리고 OAuth 소개
0
인증/인가 간단 summary
1
How to use bcrypt
제 아무리 서버라 할지라도, 사용자의 비밀번호를 그대~로 저장하면 안된다.
(언제 누구에게 언제 해킹당할 줄 알고?)
(그리고 법적으로도 정해져 있다 - 개인정보 보호법 제 7조)
그래서, django로 API를 구현할 때, 사용자의 비밀번호를 전달 받으면 bcrypt라는 라이브러리를 통해 이를 암호화해야 한다.
bcrypt는 salting, key-stretching까지 포함해서 작업해 준다.
import bcrypt
bcrypt.hashpw(data['password'].encode('utf-8'), bcrypt.gensalt()).decode('utf-8')
>>> DB에 저장할 때는, decode까지 해서 str 형태로 저장한다 (파이썬 버전에 따라 다름)
그리고 비밀번호 확인할 때는 아래와 같이 작성한다.
이 때 둘 다 byte 형태여야 하므로, DB에 있는 암호화된 패스워드도 encode해서 str > byte로 바꿔줘야 한다.
bcrypt.checkpw(사용자로부터 입력 받은 패스워드.encode('utf-8'), DB에 저장된 암호화된 패스워드.encode('utf-8'))
2
How to create JWT in python?
JWT는 header.payload.signature로 구성되어 있고, python으로 작성할 때 payload와 SECRET_KEY, 그리고 알고리즘 정보가 필요하다.
import pyjwt
SECRET = SECRET_KEY
ALGORITHM = 'HS256'
acces_token =jwt.encode({'id':1}, SECRET, algorithm = ALGORITHM)
>>> pyjwt 버전에 따라 결과물이 byte 혹은 str일 수도 있음
로그인했을 때, 해당 사용자를 위한 token을 위와 같이 생성해 response때 보낸다. 이제 클라이언트는 이 token을 출입증처럼 쓸 수 있다.
암호화하는 것이 아니라 인코딩하는 것이므로, 민감 정보는 절대 사용되지 않고 JWT에도 당연히 들어가지 않는다.
최초 로그인 후 사용자가 다시 API 접근 request를 했을 때, 서버는 token을 아래와 같이 decode 해서 접근 권한을 확인한다.
그리고 decode 시 algorithm =
은 algorithms =
로 입력해야 한다.
jwt.decode(access_token, SECRET, algorithms = ALGORITHM)
>>> {'id':1}
3
access token은 수명이 있다.
(220423 update)
위에서 서술했듯, JWT의 노출 위험이 존재하다 보니 payload에 민감 정보는 넣을 수 없다. 그러다보니 JWT에 저장할 수 있는 정보도 제한적이고 공격 가능성을 완전히 0%로 만들기도 어렵다.
그래서 유효기간을 설정해 주기적으로 access token을 새로 받을 수 있도록 설정하는 것이다. (토큰 생성 시 exp
설정)
그럼 expired 될 때마다 사용자는 새롭게 받아야 하느냐?
그건 아니고 refresh token을 사용할 수 있다.
https://simpleisbetterthancomplex.com/tutorial/2018/12/19/how-to-use-jwt-authentication-with-django-rest-framework.html
-> 이 글을 보면, 서버는 access token을 전달 할 때 refresh token도 같이 전달한다. 클라이언트는 먼저 access token을 사용하고, 유효기간이 끝나면 refresh token을 사용하는 것. (서버 측의 구체적인 제공 내용은 저마다 다르다)
refresh token의 유효기간까지 끝나면 사용자는 다시 한번 인가 과정을 거쳐야 한다.
(220501 update) 혹은, payload 에 user id 대신 uuid
를 넣는 것도 방법이다. 어쨌든 user id도 해당 user의 고유 넘버이기 때문. boto3에서도 쓰이고, 여러모로 유용한 uuid
다.
4
OAuth란?
자세한 건 다음 편에.