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

    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)

    Authentication client for endpoint with `CLIENT_AUTH_METHODS`.