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 Integration or Django Integration. 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=None)#

Implementation of revocation endpoint which is described in RFC7009.

ENDPOINT_NAME: str | None = '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:

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

Authenticate client for endpoint with CLIENT_AUTH_METHODS.

create_endpoint_request(request)#

Convert framework request to OAuth2Request.

create_response(validated_request: EndpointRequest) tuple[int, Any, list] | None#

Create the HTTP response from a validated request.

Parameters:

validated_request – The validated EndpointRequest

Returns:

Tuple of (status_code, body, headers), or None if the application should provide its own response

validate_request(request: OAuth2Request) EndpointRequest#

Validate the request and return a validated request object.

Parameters:

request – The OAuth2Request to validate

Returns:

EndpointRequest with validated data

Raises:

OAuth2Error – If validation fails