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

IDENTITY SECURITY · LAB

Revoke each kind of access and measure the revocation gap

Revoke a refresh token, lock and unlock Ava, and compare what introspection and local signature validation each say afterwards, then fill in the lesson's table for your own tenant.

Partly readyUses your lab tenant

The lesson

Builds on: Limiting what stolen access can do.

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

Partly ready. Most of this lab runs today. Steps that wait on platform features are marked, and Missing infrastructure says what they need.

Your progress

Press Start before you begin. Only events your tenant records after that count, in the order below. Checking reads your tenant's Audit, so you need Audit read access in it.

  1. lab-printer-app revokes its refresh token

    Recorded as oauth.revoke succeeded (refresh_token_found) for lab-printer-app.

  2. The revoked refresh token no longer works

    Recorded as oauth.token rejected (refresh_revoked) for lab-printer-app.

  3. Lock Ava as administrator

    Recorded as tenant.users.lock succeeded.

  4. The photo API introspects Ava's token after the lock

    Recorded as oauth.introspect succeeded (other_client_token_found) for lab-photo-api about [email protected].

  5. The photo API cannot revoke another client's token

    Recorded as oauth.revoke rejected (other_client_token) for lab-photo-api.

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

  1. Press Start on this page.

  2. You need lab-printer-app (public, with the refresh grant, its client ID in CLIENT_ID), lab-photo-api (confidential, Resource server on, its credentials in API_ID and API_SECRET) from the earlier labs, and the lab toolkit.

  3. Open a note with the lesson's table: kind of access, who checks it, and when revocation took effect in your tenant.

Walkthrough

  1. Run the authorization code flow for lab-printer-app as Ava with offline_access, exactly as in steps 1 to 3 of the previous lab, and keep the tokens in your shell as TOKEN and REFRESH.

TOKEN=$(echo "$RESPONSE" | jq -r .access_token)
REFRESH=$(echo "$RESPONSE" | jq -r .refresh_token)
btl-lab decode "$TOKEN"

Why it matters: Ava now holds three kinds of access at once: a browser session at your tenant, a refresh token, and a self-contained access token. The lesson's point is that each one ends differently.

  1. Check the access token both ways: locally, against the issuer's published keys, and by asking the tenant as lab-photo-api. Use the aud value that btl-lab decode showed.

btl-lab verify "$TOKEN" --issuer "$ISSUER" --audience "<aud from decode>" --type at+jwt
btl-lab introspect "$TOKEN" --client-env API

Why it matters: both say the token is good. Local validation checks the signature and expiry. Introspection asks the server, which also knows whether the token was revoked.

  1. Revoke the refresh token as lab-printer-app. A public client identifies itself with its client ID.

POST$ISSUER/oauth/revoke Open in console
POST $ISSUER/oauth/revoke
Content-Type: application/x-www-form-urlencoded

token=$REFRESH&token_type_hint=refresh_token&client_id=$CLIENT_ID
  1. Try to refresh with it. The tenant refuses with invalid_grant.

curl -s -d grant_type=refresh_token -d client_id="$CLIENT_ID" --data-urlencode refresh_token="$REFRESH" "$ISSUER/oauth/token" | jq .

Why it matters: a refresh token is checked by the authorization server at each use, so revocation takes effect at the next refresh.

  1. Run both checks on the access token again.

btl-lab introspect "$TOKEN" --client-env API
btl-lab verify "$TOKEN" --issuer "$ISSUER" --audience "<aud from decode>" --type at+jwt

Why it matters: your tenant ended the access tokens of the revoked family too, so introspection now reports active: false. Local validation still passes every check until exp. That difference is the lesson's revocation gap, measured on your own token: an API that never asks the server keeps accepting it.

  1. Get a fresh token pair for Ava (repeat step 1). As Tenant Admin, lock Ava in Users. Introspect the new access token, then try to sign in as Ava at $ISSUER/login.

btl-lab introspect "$TOKEN" --client-env API

Why it matters: a status change ends the account's sessions, codes and tokens in one step, and blocks new sign-ins. It is the "suspected compromise" row of the lesson's list: block new sign-ins first, then make sure what exists has ended.

  1. Unlock Ava. Fill in the table for your tenant with the time each kind of access ended: browser session, refresh token, access token checked by introspection, access token validated locally, and a session at an application that signed Ava in.

Why it matters: the last row has no answer in your tenant. An application's own session does not hear about the lock, which is what back-channel logout and shared security events exist to fix.

Break it

  1. Get one more token pair for Ava (repeat step 1). Then try to revoke her access token as lab-photo-api, a different client. The tenant refuses with unauthorized_client, and the token keeps working for lab-printer-app.

curl -s -u "$API_ID:$API_SECRET" --data-urlencode token="$TOKEN" "$ISSUER/oauth/revoke" | jq .

Why it matters: revocation ends only your own grants. A client that could revoke other clients' tokens could sign anyone out of any application.

  1. In OAuth > Clients, remove profile from lab-printer-app's scopes and save. Introspect the token again: changing what a client may request revokes the tokens and remembered consent it received under the old settings.

Restore: add profile back to lab-printer-app and save.

Check your work

  • Check my progress confirms the revocation, the refused refresh, the lock, the photo API's introspection afterwards, and the refused cross-client revocation.

  • In Audit, source User directory, tenant.users.lock and tenant.users.unlock name you as the actor and Ava as the subject.

  • Your table has a time, or "until exp", or "never told", for each kind of access.

Cleanup

  1. Clear the tokens: unset TOKEN REFRESH RESPONSE.

  2. Make sure Ava is unlocked.

Missing infrastructure

  • G17: there is no back-channel or RP-initiated logout, so lab-collage cannot be told to end Ava's session. Once it exists, the lab will sign Ava in to lab-collage, lock her, and watch the logout token arrive at the collage app.

  • G28: there is no Shared Signals transmitter, so the Security Event Token in the lesson cannot be produced by your tenant. Once it exists, the lab will configure a stream to a lab receiver and read a real session-revoked event after the lock.

  • G39: relying parties have no way to learn that access ended. The table's application-session row stays "never told" until G17 or G28 closes it.

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