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

# register it to authorization server

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:


REQUIRED. The token that the client wants to get revoked.


OPTIONAL. A hint about the type of the token submitted for revocation.


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


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

  1. Jane obtained a token XYZ

  2. Jane revoked (deleted) token XYZ

  3. Bob generated a new token XYZ

  4. 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
        token.access_token_revoked = True
        token.refresh_token_revoked = True
CLIENT_AUTH_METHODS = ['client_secret_basic']

Allowed client authenticate methods

SUPPORTED_TOKEN_TYPES = ('access_token', 'refresh_token')

Supported token types


Authentication client for endpoint with CLIENT_AUTH_METHODS.