OpenID Connect RP-Initiated Logout 1.0

This section contains the generic implementation of OpenID Connect RP-Initiated Logout 1.0. This specification enables Relying Parties (RPs) to request that an OpenID Provider (OP) log out the End-User.

End Session Endpoint

To add RP-Initiated Logout support, create a subclass of EndSessionEndpoint and implement the required methods:

from authlib.oidc.rpinitiated import EndSessionEndpoint

class MyEndSessionEndpoint(EndSessionEndpoint):
    def get_server_jwks(self):
        return load_jwks()

    def end_session(self, end_session_request):
        # Terminate user session
        session.clear()

server.register_endpoint(MyEndSessionEndpoint)

Then create a logout route. You have two options:

Non-interactive mode (simple, no confirmation page):

@app.route('/logout', methods=['GET', 'POST'])
def logout():
    return (
        server.create_endpoint_response("end_session")
        or render_template('logged_out.html')
    )

Interactive mode (with confirmation page):

@app.route('/logout', methods=['GET', 'POST'])
def logout():
    try:
        req = server.validate_endpoint_request("end_session")
    except OAuth2Error as error:
        return server.handle_error_response(None, error)

    # Show confirmation page on GET when no id_token_hint was provided
    # User confirms by submitting the form (POST)
    if req.needs_confirmation and request.method == 'GET':
        return render_template('confirm_logout.html', client=req.client)

    return (
        server.create_endpoint_response("end_session", req)
        or render_template('logged_out.html')
    )

The create_endpoint_response method returns None when there is no post_logout_redirect_uri, allowing you to provide your own response page.

Request Parameters

The endpoint accepts the following parameters (via GET or POST):

  • id_token_hint (Recommended): A previously issued ID Token passed as a hint about the End-User’s authenticated session.

  • logout_hint (Optional): A hint to the OP about the End-User that is logging out.

  • client_id (Optional): The OAuth 2.0 Client Identifier. When both client_id and id_token_hint are present, the OP verifies that the Client Identifier matches the aud claim in the ID Token.

  • post_logout_redirect_uri (Optional): URI to which the End-User’s User Agent is redirected after logout. Must exactly match a pre-registered value.

  • state (Optional): Opaque value used by the RP to maintain state between the logout request and the callback.

  • ui_locales (Optional): End-User’s preferred languages for the user interface.

Confirmation Flow

Per the specification, logout requests without a valid id_token_hint are a potential means of denial of service. The EndSessionRequest.needs_confirmation property indicates when user confirmation is recommended.

You control the confirmation page rendering - simply check needs_confirmation and render your own template as shown in the interactive mode example above.

Post-Logout Redirection

Post-logout redirection only happens when:

  1. A post_logout_redirect_uri is provided

  2. The client is resolved (via id_token_hint or client_id)

  3. The URI is registered in the client’s post_logout_redirect_uris

If all conditions are met, EndSessionRequest.redirect_uri contains the validated URI (with state appended if provided).

If conditions are not met, create_endpoint_response returns None and you should provide a default logout page:

server.create_endpoint_response("end_session", req) or render_template('logged_out.html')

Session Validation

When an id_token_hint is provided, the id_token_claims attribute of EndSessionRequest contains all claims from the ID Token, including sid (session ID) if present.

Per the specification, you SHOULD verify that the sid matches the current session to detect potentially suspect logout requests:

def end_session(self, end_session_request):
    if end_session_request.id_token_claims:
        sid = end_session_request.id_token_claims.get("sid")
        if sid and sid != get_current_session_id():
            # Treat as suspect - may require additional confirmation
            pass
    session.clear()

Client Registration

Relying Parties can register their post_logout_redirect_uris through RFC7591: OAuth 2.0 Dynamic Client Registration Protocol.

To support RP-Initiated Logout client metadata, add the claims class to your registration and configuration endpoints:

from authlib import oidc
from authlib.oauth2 import rfc7591

authorization_server.register_endpoint(
    ClientRegistrationEndpoint(
        claims_classes=[
            rfc7591.ClientMetadataClaims,
            oidc.registration.ClientMetadataClaims,
            oidc.rpinitiated.ClientMetadataClaims,
        ]
    )
)

The post_logout_redirect_uris parameter is an array of URLs to which the End-User’s User Agent may be redirected after logout. These URLs SHOULD use the https scheme.

API Reference

class authlib.oidc.rpinitiated.EndSessionEndpoint(server=None)

OpenID Connect RP-Initiated Logout endpoint.

This endpoint follows a two-phase pattern for interactive flows:

  1. Call server.validate_endpoint_request("end_session") to validate the request and get an EndSessionRequest

  2. Check end_session_request.needs_confirmation and show UI if needed

  3. Call server.create_endpoint_response("end_session", end_session_request) to execute logout and create the response

Example usage:

class MyEndSessionEndpoint(EndSessionEndpoint):
    def get_server_jwks(self):
        return load_jwks()

    def end_session(self, end_session_request):
        session.clear()


server.register_endpoint(MyEndSessionEndpoint)


@app.route("/logout", methods=["GET", "POST"])
def logout():
    try:
        req = server.validate_endpoint_request("end_session")
    except OAuth2Error as error:
        return server.handle_error_response(None, error)

    if req.needs_confirmation and request.method == "GET":
        return render_template("confirm_logout.html", client=req.client)

    return server.create_endpoint_response(
        "end_session", req
    ) or render_template("logged_out.html")

For non-interactive usage (no confirmation page), use the standard pattern:

@app.route("/logout", methods=["GET", "POST"])
def logout():
    return server.create_endpoint_response("end_session") or render_template(
        "logged_out.html"
    )
ENDPOINT_NAME: str | None = 'end_session'

Endpoint name used for registration

validate_request(request: OAuth2Request) EndSessionRequest

Validate an end session request.

Parameters:

request – The OAuth2Request to validate

Returns:

EndSessionRequest with validated data

Raises:

InvalidRequestError – If validation fails

create_response(validated_request: EndSessionRequest) tuple[int, Any, list[tuple[str, str]]] | None

Create the end session HTTP response.

Executes the logout via end_session(), then returns a redirect response if a valid redirect_uri is present, or None to let the application provide its own response.

Parameters:

validated_request – The validated EndSessionRequest

Returns:

Tuple of (status_code, body, headers) for redirect, or None

resolve_client_from_id_token_claims(id_token_claims: dict) Any | None

Resolve client from id_token aud claim.

When aud is a single string, resolves the client directly. When aud is a list, returns None (ambiguous case). Override for custom resolution logic.

is_post_logout_redirect_uri_legitimate(request: OAuth2Request, post_logout_redirect_uri: str, client, logout_hint: str | None) bool

Confirm redirect_uri legitimacy when no id_token_hint is provided.

Override if you have alternative confirmation mechanisms, e.g.:

def is_post_logout_redirect_uri_legitimate(self, ...):
    return client and client.is_trusted

By default returns False (no redirection without id_token_hint).

get_server_jwks() dict | KeySet

Return the server’s JSON Web Key Set for validating ID tokens.

get_algorithms() list[str]

Return the list of allowed algorithms for ID token validation.

By default, returns all algorithms compatible with the keys in the JWKS. Override to restrict to specific algorithms.

end_session(end_session_request: EndSessionRequest) None

Terminate the user’s session.

Implement this method to perform the actual logout logic, such as clearing session data, revoking tokens, etc.

Use end_session_request.logout_hint to help identify the user (e.g. email, username) when no id_token_hint is provided.

Parameters:

end_session_request – The validated EndSessionRequest

class authlib.oidc.rpinitiated.EndSessionRequest(request: OAuth2Request, client: Any = None, id_token_claims: dict | None = None, redirect_uri: str | None = None, logout_hint: str | None = None, ui_locales: str | None = None)

Validated end session request data.

This object is returned by EndSessionEndpoint.validate_request() and contains all the validated information from the logout request.

property needs_confirmation: bool

Whether user confirmation is recommended before logout.

class authlib.oidc.rpinitiated.ClientMetadataClaims(claims: dict[str, Any], header: dict[str, Any], options: dict[str, ClaimsOption] | None = None, params: dict[str, Any] = None)

Client metadata for OpenID Connect RP-Initiated Logout 1.0.

This can be used with RFC7591: OAuth 2.0 Dynamic Client Registration Protocol and RFC7592: OAuth 2.0 Dynamic Client Registration Management Protocol endpoints:

server.register_endpoint(
    ClientRegistrationEndpoint(
        claims_classes=[
            rfc7591.ClientMetadataClaims,
            oidc.registration.ClientMetadataClaims,
            oidc.rpinitiated.ClientMetadataClaims,
        ]
    )
)
class authlib.oidc.rpinitiated.OpenIDProviderMetadata