👉 Authlib를 통해 구현할 수 있는 token endpoints
사용자에게 발급한 token을 만료시키고자 할 때에는 Revocation Endpoint
를 사용하면 된다.
Revocation Endpoint를 사용하기 위한 클래스를 생성해주어야 하는데, Authlib에서 제공하는 RevocationEndpoint를 이용하면 쉽게 구현할 수 있다.
from authlib.oauth2.rfc7009 import RevocationEndpoint as _RevocationEndpoint
from login.database import db
from login.models import Token
class RevocationEndpoint(_RevocationEndpoint):
# revoke할 token을 찾음
def query_token(self, token, token_type_hint, client):
if token_type_hint == 'access_token':
return db.session.query(Token).filter_by(access_token=token).first()
elif token_type_hint == 'refresh_token':
return db.session.query(Token).filter_by(refresh_token=token).first()
# without token_type_hint
else:
tok = db.session.query(Token).filter_by(access_token=token).first()
if not tok:
return db.session.query(Token).filter_by(refresh_token=token).first()
return tok
# 해당하는 token revoke
def revoke_token(self, token):
token.revoked = True
db.session.add(token)
db.session.commit()
클래스를 생성하였다면 register_endpoint()
함수를 이용해 초기화(flask_app)과 연결시켜주면 된다.
__init__.py 👇
oauth_server.register_endpoint(RevokationEndpoint)
마지막으로 revocation을 요청할 endpoint를 설정해준다.
endpoint에서는 create_endpoint_response()
함수에 ENDPOINT_NAME
을 매개변수로 return 해주도록 하는데, revocation의 경우 ENDPOINT_NAME
의 값은 revocation이다.
@oauth.route('/token/revoke', methods=[POST])
def revoke_token():
return oauth_server.create_endpoint_response(RevocationEndpoint.ENDPOINT_NAME)
revoke 요청은 설정한 revokation endpoint
로,
의 값을 form 방식으로 POST 요청을 보내면 된다.
요청 시 client id와 client secret은 basic 인증을 사용하여 보내준다.
성공적으로 revoke를 한다면 다음과 같은 응답을 받을 수 있다.
revoke 후 데이터베이스에서 값을 살펴보면 False였던 revoked의 값이
True로 변경된 것을 확인할 수 있다.
Token에 대한 검증을 하고 싶다면 Introspection Endpoint
를 사용하면 된다.
Introspection Endpoint를 사용하기 위한 클래스를 생성해주어야 하는데, Authlib에서 제공하는 IntrospectionEndpoint를 이용하면 쉽게 구현할 수 있다.
class IntrospectionEndpoint(_IntrospectionEndpoint):
# 검증할 token 찾음
def query_token(self, token, token_type_hint, client=None):
if token_type_hint == 'access_token':
tok = db.session.query(Token).filter_by(access_token=token).first()
elif token_type_hint == 'refresh_token':
tok = db.session.query(Token).filter_by(refresh_token=token).first()
else:
# without token_type_hint
tok = db.session.query(Token).filter_by(access_token=token).first()
if not tok:
tok = db.session.query(Token).filter_by(refresh_token=token).first()
return tok
def introspect_token(self, token):
return {
'active': True,
'client_id': token.client_id,
'token_type': token.token_type,
'username': token.user.email,
'scope': token.get_scope(),
'sub': token.user.id,
'aud': token.client_id,
'iss': 'https://server.example.com/',
'exp': token.expires_at,
'iat': token.issued_at,
}
# token의 유효성 여부에 대한 check
def check_permission(self, token, client, request):
# for example, we only allow internal client to access introspection endpoint
return True
# return client.client_type == 'internal'
클래스를 생성하였다면 register_endpoint()
함수를 이용해 초기화(flask_app)과 연결시켜주면 된다.
__init__.py 👇
oauth_server.register_endpoint(IntrospectionEndpoint)
마지막으로 검증을 진행할 endpoint를 설정해준다.
endpoint에서는 create_endpoint_response()
함수에 ENDPOINT_NAME
을 매개변수로 return 해주도록 하는데, introspection의 경우 ENDPOINT_NAME
의 값은 intropection이다.
@oauth.route('/token/revoke', methods=[POST])
def revoke_token():
return oauth_server.create_endpoint_response(IntrospectionEndpoint.ENDPOINT_NAME)
introspection 요청은 설정한 introspection endpoint
로,
의 값을 form 방식으로 POST 요청을 보내면 된다.
요청 시 client id와 client secret은 basic 인증을 사용하여 보내준다.