codekingpro/portable-devtools
114k
1from authlib.consts import default_json_headers2from ..rfc6749 import TokenEndpoint3from ..rfc6749 import (4 InvalidRequestError,5 UnsupportedTokenTypeError,6)7 8 9class RevocationEndpoint(TokenEndpoint):10 """Implementation of revocation endpoint which is described in11 `RFC7009`_.12 13 .. _RFC7009: https://tools.ietf.org/html/rfc700914 """15 #: Endpoint name to be registered16 ENDPOINT_NAME = 'revocation'17 18 def authenticate_token(self, request, client):19 """The client constructs the request by including the following20 parameters using the "application/x-www-form-urlencoded" format in21 the HTTP request entity-body:22 23 token24 REQUIRED. The token that the client wants to get revoked.25 26 token_type_hint27 OPTIONAL. A hint about the type of the token submitted for28 revocation.29 """30 self.check_params(request, client)31 token = self.query_token(request.form['token'], request.form.get('token_type_hint'))32 if token and token.check_client(client):33 return token34 35 def check_params(self, request, client):36 if 'token' not in request.form:37 raise InvalidRequestError()38 39 hint = request.form.get('token_type_hint')40 if hint and hint not in self.SUPPORTED_TOKEN_TYPES:41 raise UnsupportedTokenTypeError()42 43 def create_endpoint_response(self, request):44 """Validate revocation request and create the response for revocation.45 For example, a client may request the revocation of a refresh token46 with the following request::47 48 POST /revoke HTTP/1.149 Host: server.example.com50 Content-Type: application/x-www-form-urlencoded51 Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW52 53 token=45ghiukldjahdnhzdauz&token_type_hint=refresh_token54 55 :returns: (status_code, body, headers)56 """57 # The authorization server first validates the client credentials58 client = self.authenticate_endpoint_client(request)59 60 # then verifies whether the token was issued to the client making61 # the revocation request62 token = self.authenticate_token(request, client)63 64 # the authorization server invalidates the token65 if token:66 self.revoke_token(token, request)67 self.server.send_signal(68 'after_revoke_token',69 token=token,70 client=client,71 )72 return 200, {}, default_json_headers73 74 def query_token(self, token_string, token_type_hint):75 """Get the token from database/storage by the given token string.76 Developers should implement this method::77 78 def query_token(self, token_string, token_type_hint):79 if token_type_hint == 'access_token':80 return Token.query_by_access_token(token_string)81 if token_type_hint == 'refresh_token':82 return Token.query_by_refresh_token(token_string)83 return Token.query_by_access_token(token_string) or \84 Token.query_by_refresh_token(token_string)85 """86 raise NotImplementedError()87 88 def revoke_token(self, token, request):89 """Mark token as revoked. Since token MUST be unique, it would be90 dangerous to delete it. Consider this situation:91 92 1. Jane obtained a token XYZ93 2. Jane revoked (deleted) token XYZ94 3. Bob generated a new token XYZ95 4. Jane can use XYZ to access Bob's resource96 97 It would be secure to mark a token as revoked::98 99 def revoke_token(self, token, request):100 hint = request.form.get('token_type_hint')101 if hint == 'access_token':102 token.access_token_revoked = True103 else:104 token.access_token_revoked = True105 token.refresh_token_revoked = True106 token.save()107 """108 raise NotImplementedError()109 