RFC7009: OAuth 2.0 Token Revocation¶
This section contains the generic implementation of RFC7009.
Register Revocation Endpoint¶
The revocation endpoint can be easily registered to Flask OAuth 2.0 Server or Django OAuth 2.0 Server. But there are missing methods to be implemented:
from authlib.oauth2.rfc7009 import RevocationEndpoint
class MyRevocationEndpoint(RevocationEndpoint):
def query_token(self, token, token_type_hint, client):
q = Token.query.filter_by(client_id=client.client_id)
if token_type_hint == 'access_token':
return q.filter_by(access_token=token).first()
elif token_type_hint == 'refresh_token':
return q.filter_by(refresh_token=token).first()
# without token_type_hint
item = q.filter_by(access_token=token).first()
if item:
return item
return q.filter_by(refresh_token=token).first()
def revoke_token(self, token):
token.revoked = True
db.session.add(token)
db.session.commit()
# register it to authorization server
authorization_server.register_endpoint(MyRevocationEndpoint)
After the registration, you can create a response with:
@app.route('/oauth/revoke', methods=['POST'])
def revoke_token():
return server.create_endpoint_response(MyRevocationEndpoint.ENDPOINT_NAME)
API Reference¶
- class authlib.oauth2.rfc7009.RevocationEndpoint(server)¶
Implementation of revocation endpoint which is described in RFC7009.
- ENDPOINT_NAME = 'revocation'¶
Endpoint name to be registered
- authenticate_token(request, client)¶
The client constructs the request by including the following parameters using the “application/x-www-form-urlencoded” format in the HTTP request entity-body:
- token
REQUIRED. The token that the client wants to get revoked.
- token_type_hint
OPTIONAL. A hint about the type of the token submitted for revocation.
- create_endpoint_response(request)¶
Validate revocation request and create the response for revocation. For example, a client may request the revocation of a refresh token with the following request:
POST /revoke HTTP/1.1 Host: server.example.com Content-Type: application/x-www-form-urlencoded Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW token=45ghiukldjahdnhzdauz&token_type_hint=refresh_token
- Returns:
(status_code, body, headers)
- query_token(token_string, token_type_hint)¶
Get the token from database/storage by the given token string. Developers should implement this method:
def query_token(self, token_string, token_type_hint): if token_type_hint == 'access_token': return Token.query_by_access_token(token_string) if token_type_hint == 'refresh_token': return Token.query_by_refresh_token(token_string) return Token.query_by_access_token(token_string) or Token.query_by_refresh_token(token_string)
- revoke_token(token, request)¶
Mark token as revoked. Since token MUST be unique, it would be dangerous to delete it. Consider this situation:
Jane obtained a token XYZ
Jane revoked (deleted) token XYZ
Bob generated a new token XYZ
Jane can use XYZ to access Bob’s resource
It would be secure to mark a token as revoked:
def revoke_token(self, token, request): hint = request.form.get('token_type_hint') if hint == 'access_token': token.access_token_revoked = True else: token.access_token_revoked = True token.refresh_token_revoked = True token.save()
- CLIENT_AUTH_METHODS = ['client_secret_basic']¶
Allowed client authenticate methods
- SUPPORTED_TOKEN_TYPES = ('access_token', 'refresh_token')¶
Supported token types
- authenticate_endpoint_client(request)¶
Authentication client for endpoint with
CLIENT_AUTH_METHODS
.