RP-initiated logout (end session)
A client signs its user out of the authorization server too. It sends the browser to the end-session endpoint with the identity token it was issued as id_token_hint; because the hint identifies the session, the server ends it without asking, tells every client in the session — here by a back-channel logout token posted to the web client's BackChannelLogoutUri — and shows the signed-out page, which loads the clients' front-channel logout URIs and offers the way back to post_logout_redirect_uri with the client's state. The client is the demo host's web. The test answers the back-channel POST itself (it replaces the primary handler of the server's named back-channel HttpClient, so the request the server makes is real and nothing leaves the process).
Follows: OpenID Connect RP-Initiated Logout 1.0, OpenID Connect Back-Channel Logout 1.0, OpenID Connect Front-Channel Logout 1.0.
Recorded from the demo host (src/Fdyay.IdentityServer.Host) by the EndSessionFlow test on every CI run. A value in braces, such as {access_token_1}, is one that differs on every run; the same placeholder is the same value wherever it appears. See how these pages are made.
sequenceDiagram
participant Browser
participant AuthorizationServer as Authorization Server
participant Client
Note over Browser,AuthorizationServer: The user signed in to the web client through the<br/>authorization code flow, and the client kept the<br/>identity token.
Browser->>AuthorizationServer: GET /connect/endsession
AuthorizationServer->>Client: POST https://client.example.com/signout-back
Client-->>AuthorizationServer: 200 OK
AuthorizationServer-->>Browser: 302 Found to /account/logout
Browser->>AuthorizationServer: GET /account/logout
AuthorizationServer-->>Browser: 302 Found to /Account/LoggedOut
Browser->>AuthorizationServer: GET /Account/LoggedOut
AuthorizationServer-->>Browser: 200 OK
The user signed in to the
webclient through the authorization code flow, and the client kept the identity token.
1. The client sends the browser to the end-session endpoint
The server validates the hint, ends the session — the session cookies are deleted — and notifies the session's clients before it answers. The logout_token it posts is a JWT naming the user and the session, with the back-channel logout event.
Browser → Authorization Server
GET /connect/endsession?id_token_hint={id_token_1}
&post_logout_redirect_uri=https%3A%2F%2Fclient.example.com%2Fsignout-callback
&state=x9q2w HTTP/1.1
Cookie: .AspNetCore.Antiforgery.{suffix}={antiforgery_cookie_1}; idsrv={authentication_cookie_1}
{id_token_1} decoded — the header, then the payload; the signature is not shown:
{
"alg": "RS256",
"kid": "{key_id_1}",
"typ": "JWT"
}
{
"aud": [
"web"
],
"iss": "http://localhost",
"iat": {iat},
"nbf": {iat},
"exp": {iat + 300},
"jti": "{jti_1}",
"azp": "web",
"sub": "alice",
"auth_time": {auth_time},
"idp": "local",
"amr": [
"pwd"
],
"name": "Alice Smith",
"nonce": "n-0S6_WzA2Mj",
"sid": "{session_id_1}",
"at_hash": "{at_hash_1}"
}
Authorization Server → Client
POST https://client.example.com/signout-back HTTP/1.1
Content-Type: application/x-www-form-urlencoded
logout_token={logout_token_1}
{logout_token_1} decoded — the header, then the payload; the signature is not shown:
{
"alg": "RS256",
"kid": "{key_id_1}",
"typ": "logout+jwt"
}
{
"aud": [
"web"
],
"iss": "http://localhost",
"iat": {iat},
"nbf": {iat},
"exp": {iat + 300},
"jti": "{jti_2}",
"events": {
"http://schemas.openid.net/event/backchannel-logout": {}
},
"sub": "alice",
"sid": "{session_id_1}",
"logout_reason": "user_logout"
}
Client → Authorization Server
HTTP/1.1 200 OK
Authorization Server → Browser
HTTP/1.1 302 Found
Location: /account/logout?logoutId={logout_id_1}
Cache-Control: no-cache,no-store
Pragma: no-cache
Set-Cookie: idsrv=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; samesite=none; httponly
Set-Cookie: idsrv.session=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/
2. The logout page has nothing to ask
The session is already gone, so it moves straight on to the signed-out page.
Browser → Authorization Server
GET /account/logout?logoutId={logout_id_1} HTTP/1.1
Cookie: .AspNetCore.Antiforgery.{suffix}={antiforgery_cookie_1}
Authorization Server → Browser
HTTP/1.1 302 Found
Location: /Account/LoggedOut?logoutId={logout_id_1}
3. The signed-out page
It loads the web client's front-channel logout URI in an iframe and links back to https://client.example.com/signout-callback?state=x9q2w.
Browser → Authorization Server
GET /Account/LoggedOut?logoutId={logout_id_1} HTTP/1.1
Cookie: .AspNetCore.Antiforgery.{suffix}={antiforgery_cookie_1}
Authorization Server → Browser
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
(an HTML page, not shown)