Beta

Create a tenant

A new tenant starts with its own users, OAuth settings, audit history and logs. You are its first Tenant Admin.

BTL Admin

OPENID CONNECT · LAB

Ask the provider to end its session

Plan a real logout request with id_token_hint, post_logout_redirect_uri and state, and today confirm the endpoint is honestly unavailable, see why foreign sign-out requests are refused, and build the fallback.

PlannedUses your lab tenant

The lesson

Builds on: Local logout and provider sessions.

New to the labs? Start with the lab toolkit and the shared cast and names every lab uses.

Planned. The core of this lab waits on platform features that are not built yet. The planned walkthrough shows exactly how it will run; Do today is a real exercise you can do now.

Request console

Requests in this lab can be sent from this page to your tenant: open one and choose Send. Fill in the values below first. They stay in this page's memory and are gone when you leave; secrets are never stored or sent anywhere except the request you send.

Setup

Your tenant has no end session endpoint, no post_logout_redirect_uris client setting and no sid claim yet (G17). Its own sign-out works only from its own pages. The planned walkthrough below is exactly what this lab will run once G17 exists. Do today runs real requests now.

  1. source ~/btl-oidc.sh and sign Ava in to lab-collage so that ID_TOKEN holds a current ID token.

  2. Once G17 exists: in OAuth > Clients > lab-collage, add the post-logout redirect URI http://127.0.0.1:8765/signed-out.

Planned walkthrough

  1. Find the endpoint in discovery.

GET$ISSUER/.well-known/openid-configuration Open in console
GET $ISSUER/.well-known/openid-configuration

end_session_endpoint will be $ISSUER/oidc/logout.

Why it matters: the relying party learns where to send the browser from the provider's metadata, like every other endpoint.

  1. End the local session first, keeping the ID token and a fresh state for the return:

LOGOUT_HINT=$ID_TOKEN; LOGOUT_STATE=$(openssl rand -hex 16); unset TOKEN
echo "$ISSUER/oidc/logout?id_token_hint=$LOGOUT_HINT&post_logout_redirect_uri=http%3A%2F%2F127.0.0.1%3A8765%2Fsigned-out&state=$LOGOUT_STATE"

Why it matters: the one sign-out the relying party controls has already happened, whatever the person decides at the provider.

  1. Open the printed URL in the browser. The hint names the client, the person and the session, and it is accepted after its exp, because it is not proof of anything. The tenant asks "Sign out of Lab Photos?".

  2. Confirm. btl-lab callback prints state on its return to /signed-out. Compare it with LOGOUT_STATE.

Why it matters: the return shows that the browser came back, not that the provider ended its session.

  1. Run signin prompt=none: error=login_required. Audit shows oidc.logout succeeded.

  2. Open the step 2 URL again. It still succeeds: signing out with no session is not an error.

Do today

  1. Ask for the endpoint the lesson describes.

GET$ISSUER/oidc/logout Open in console
GET $ISSUER/oidc/logout

The answer is 501 with {"error":"temporarily_unavailable","error_description":"This endpoint is not implemented yet."}. Logs counts the request under oidc.logout rejected not_implemented. Do not send a real ID token to it.

Why it matters: a provider that does not offer the endpoint says so honestly, in discovery and in its answer, so a relying party never assumes the session ended.

  1. See why any website cannot sign people out with a link. The tenant's own sign-out accepts only a POST from its own pages. Send one from a foreign origin:

curl -si -X POST "$ISSUER/logout" -H "Origin: https://other-site.example" | grep -i '^location'

Location: /login, and Logs counts account.sign_out rejected invalid_request. In your browser, signin prompt=none still returns a code: Ava's session is untouched.

Why it matters: the lesson's confirmation rule exists for the same reason. Without it, a link on any page could end people's sessions.

  1. Build the honest fallback from the end of the lesson. After your local logout, show a page that says "You are still signed in at Lab Photos" with a link to $ISSUER/account, where the person can choose Sign out themselves. Follow the link and do it: account.sign_out succeeded signed_out appears in Audit, and signin prompt=none now returns login_required.

Break it

Planned, once G17 exists:

  1. post_logout_redirect_uri=http://127.0.0.1:8765/signed-out/, with a trailing slash: no redirect, and the tenant shows its own page.

  2. No id_token_hint: the tenant asks for confirmation and does not redirect to an address it cannot confirm.

  3. A hint whose sid is not this browser's session, because Ben signed in since: treated as suspect, and confirmation is required.

Check your work

Today: the 501 answer and the not_implemented count in Logs, the refused foreign sign-out in Logs, and your fallback page's sign-out at the tenant in Audit.

Once G17 exists, Audit shows oidc.logout events with their outcome and reason, and account.sign_out for the ended session.

Cleanup

Once G17 exists, remove the post-logout redirect URI from lab-collage. Today nothing changed.

Missing infrastructure

  • G17 (OIDC logout). An end_session_endpoint at /oidc/logout accepting GET and POST, post_logout_redirect_uris per client with exact matching, sid in ID tokens, a confirmation page, and oidc.logout audit events. With it, the planned walkthrough runs as written and the lab becomes ready with automated checks.

Back to all labs

We value your privacy

We use cookies and similar technologies to enhance your browsing experience, and analytics to understand our traffic. By clicking "Allow All", you consent to optional analytics. Cookie Policy

The Lab