# 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