Sign users out
This guide adds a sign-out button that signs the user out of the auth server too, and brings them back to your app.
Ending your app’s own session isn’t enough. The auth server keeps a session of its own, so the next time your app sent the user to sign in, they’d be signed straight back in. Your app sends the browser to the logout endpoint, /auth/logout, with the ID token the user signed in with, and the auth server signs them out and sends them back.
Sign users out
Section titled “Sign users out”-
When the user signs in, keep the ID token from the token endpoint’s answer with the rest of their session in your app. It tells the auth server which sign-in to end.
-
Decide where the user lands afterwards, such as
https://app.example.com/signed-out, and add it to your client’s Redirect URIs in the admin console, if it isn’t there already. The auth server sends the browser only to an address registered there. -
When the user clicks your app’s sign-out button, read the ID token from their session, end your app’s own session, and delete every token your app kept for them.
-
Answer with a redirect that sends the browser to
/auth/logout, with the ID token asid_token_hint, the address from step 2 aspost_logout_redirect_uri, and a new randomstate:HTTP/1.1 302 FoundLocation: https://auth.example.com/auth/logout?id_token_hint=eyJhbGciOiJSUzI1NiIsImtpZCI6Ii4uLiJ9...&post_logout_redirect_uri=https%3A%2F%2Fapp.example.com%2Fsigned-out&state=af0ifjsldkjThe browser follows it with a GET, which is what most OpenID Connect libraries send. To keep the ID token out of the browser’s history, post the parameters instead: see Hiding the hint.
-
The auth server signs the user out at once, without asking, and sends the browser back with your
state:HTTP/1.1 302 FoundLocation: https://app.example.com/signed-out?state=af0ifjsldkjCheck that
stateis the one you sent, and show the user they’re signed out.
What a sign-out ends
Section titled “What a sign-out ends”With the ID token as its hint, a sign-out ends your app’s part of the user’s session on the auth server. If other apps signed in with the same session, the user stays signed in to them, and the session ends when the last one signs out. Either way the browser’s session cookie is cleared, so the next sign-in in that browser starts with the password.
A sign-out with no hint, or with one the auth server can’t confirm, asks the user “Do you want to sign out?” first, and when they click Sign out, it ends the whole session, every client’s part of it. RP-Initiated Logout, the OpenID Connect standard the endpoint follows, asks for that, since anyone can send a browser to /auth/logout. Ending sessions has the precise rules.
An ID token that has expired still works as a hint while the session it came from is there, so a user who leaves your app open all day can still sign out without the question.
Your app’s tokens
Section titled “Your app’s tokens”Signing out revokes no token. That’s why step 3 deletes them:
- A refresh token keeps working while the session it’s tied to does, which, when other apps share that session, is after your app has signed out. An offline refresh token, from the
offline_accessscope, isn’t tied to a session at all. - An access token is checked by its signature, so your APIs accept it until it expires.
To cut off everything a session handed out, end the session instead. A user can, under Account, Sessions in the admin console, and an administrator can, on the user’s Sessions tab. See Ending sessions.
Where the user lands
Section titled “Where the user lands”The browser goes to your post_logout_redirect_uri only when it’s one of the redirect URIs registered on the client the hint was issued to. Otherwise the user stays on the auth server’s “Signed out” page. The sign-out has happened either way. Logout gives every case.
The auth server adds state exactly as you sent it, and nothing else.
Hiding the hint
Section titled “Hiding the hint”The hint is the user’s ID token, and anyone who decodes it can read the claims about the user in it. In the query string of a GET, it’s kept in the browser’s history, and in the access log of any proxy in front of the auth server. The auth server’s own request log leaves it out.
To keep it out of both, post the parameters from a form your page submits on its own:
POST /auth/logout HTTP/1.1Host: auth.example.comContent-Type: application/x-www-form-urlencoded
id_token_hint=eyJhbGciOiJSUzI1NiIsImtpZCI6Ii4uLiJ9...&post_logout_redirect_uri=https%3A%2F%2Fapp.example.com%2Fsigned-out&state=af0ifjsldkjA confidential client can go further and encrypt the hint with a key made from its client secret, so it’s unreadable wherever it’s seen or logged on the way. Send client_id beside an encrypted hint, so the auth server knows whose secret decrypts it. Encrypting the hint gives the scheme.
When it’s refused
Section titled “When it’s refused”A POST from another origin with no hint, whether another site or another host of the same domain, is refused with 403 Forbidden, to stop a page you don’t control from signing your users out. See Sign-out answers 403.