RP-initiated logout
How your application signs a person out of identity, what the end-session endpoint accepts, and what the person sees.
On this page
Signing out of your application is not signing out of identity. Your own session cookie is yours to clear, but the person is still signed in at identity, and the next sign-in would be silent. RP-initiated logout (OpenID Connect RP-Initiated Logout 1.0) is how your application asks identity to end the session too. The discovery document advertises the address as end_session_endpoint.
The request#
Redirect the person's browser to the end-session endpoint with these query parameters:
| Parameter | Meaning |
|---|---|
id_token_hint | The ID token you received at sign-in. It identifies the client and the person. It is the parameter that makes the sign-out happen without a question. |
post_logout_redirect_uri | Where to send the person afterwards. It must be one of the post-logout addresses registered for your client. The SDK requires id_token_hint whenever you send it. |
state | An opaque value that identity appends to the address it redirects to. |
client_id | Names your client when you have no usable ID token. If both are given and disagree, the hint is ignored and the person gets the confirmation page. |
Each parameter may appear once, and id_token_hint is at most 8192 bytes. A request that breaks either rule gets a JSON error with status 400 and invalid_request. The endpoint accepts GET and POST.
An expired ID token is accepted as a hint, because an ID token is usually old by the time the person signs out. It must still be a genuine ID token from identity: the signature, the issuer and the typ of JWT are checked, and an access token is refused as a hint. For a client registered pairwise, the hint's per-sector sub identifies the person just as the real sub does.
What the person sees#
There are two outcomes, and both end with the browser redirected.
The hint is valid and belongs to the person signed in at this browser. Identity ends the session without asking, clears its own session cookie and redirects with status 303.
There is no hint, it cannot be verified, or it names a different person than the one signed in. Identity does not end the session on a bare request, because any page could otherwise trigger it. It shows a confirmation page titled Sign out of TDACorp?. With a client named, the lead reads that the client asked to sign the person out of their TDACorp account. The buttons are Sign out and Stay signed in. If a hint was sent but could not be checked, the page adds that the request could not be checked, so the person will be signed out here only. Choosing Sign out ends the session and redirects.
If the person is not signed in at all, there is nothing to end and identity just redirects.
Where the browser goes#
- To your
post_logout_redirect_uriwithstateadded, if the client is known and not suspended and the address matches a registered one exactly. - Otherwise to identity's own page, which says You are signed out and Your session on this browser has ended., with a Sign in again button.
An address that is not registered is never followed, and nothing in the request can add one. Register it first: see Get a client registered.
What ending the session does#
The identity session ends. Everything that depended on it ends with it: refresh tokens issued under it stop working, access tokens whose session has ended are refused by identity's own endpoints, and applications that signed in through it are told by back-channel logout where they registered an address. This is also why you should map your own sessions to sid.
Your application still has to end its own session. The usual order is to clear your own cookie first, then redirect, so that your own state is correct even if identity is slow or unreachable.
With the SDK#
The logout route helper does this for you. It accepts POST only, unless you set allowGet, and refuses a cross-origin request. With logout.getIdTokenHint returning the stored ID token, it clears your cookies and redirects to the address from rp.endSessionUrl({ idTokenHint, postLogoutRedirectUri, state }). Without a hint, it sends no return address, so identity cannot send the person back.
// A sketch of what the helper builds. rp is the relying party from the Quickstart.const url = await rp.endSessionUrl({ idTokenHint: storedIdToken, postLogoutRedirectUri: 'https://app.example.com/signed-out', state: crypto.randomUUID(),})Keep the ID token you received, at least until sign-out. Without it, the person gets the confirmation page.
Related#
- Log users in for the route helpers.
- Back-channel logout for the other direction: identity telling you a session ended.