[Flask] Authlib를 이용한 oauth server 구현 #3

강버섯·2022년 3월 8일
0

AUTHORIZATION

목록 보기
9/9

📁 Token Endpoints

👉 Authlib를 통해 구현할 수 있는 token endpoints

✏️ Token Revocation Endpoint

사용자에게 발급한 token을 만료시키고자 할 때에는 Revocation Endpoint를 사용하면 된다.

✏️ Revocation Enpoint 클래스 생성

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()

✏️ flask app에 연결

클래스를 생성하였다면 register_endpoint() 함수를 이용해 초기화(flask_app)과 연결시켜주면 된다.

__init__.py 👇

oauth_server.register_endpoint(RevokationEndpoint)

✏️ revocation endpoint 생성

마지막으로 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 요청 보내기

revoke 요청은 설정한 revokation endpoint로,

  • client id
  • client secret
  • token
  • token_type_hint(option)

의 값을 form 방식으로 POST 요청을 보내면 된다.
요청 시 client id와 client secret은 basic 인증을 사용하여 보내준다.

성공적으로 revoke를 한다면 다음과 같은 응답을 받을 수 있다.

revoke 후 데이터베이스에서 값을 살펴보면 False였던 revoked의 값이

True로 변경된 것을 확인할 수 있다.

✏️ Token Introspection Endpoint

Token에 대한 검증을 하고 싶다면 Introspection Endpoint를 사용하면 된다.

✏️ 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'

✏️ flask app에 연결

클래스를 생성하였다면 register_endpoint() 함수를 이용해 초기화(flask_app)과 연결시켜주면 된다.

__init__.py 👇

oauth_server.register_endpoint(IntrospectionEndpoint)

✏️ introspection endpoint 생성

마지막으로 검증을 진행할 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 요청은 설정한 introspection endpoint로,

  • client id
  • client secret
  • token
  • token_type_hint(option)

의 값을 form 방식으로 POST 요청을 보내면 된다.
요청 시 client id와 client secret은 basic 인증을 사용하여 보내준다.

profile
무럭무럭 버섯농장

0개의 댓글