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.
- G17 OIDC logout: RP-initiated, front-channel, back-channel, session management
- G28 Shared Signals (SSF, CAEP, RISC)
- G39 Telling downstream apps that access ended (beyond G17 and G28)
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.
Sign in to start this lab and check your progress. Log in or create an account.
lab-printer-app revokes its refresh token
Recorded as
oauth.revokesucceeded (refresh_token_found) forlab-printer-app.The revoked refresh token no longer works
Recorded as
oauth.tokenrejected (refresh_revoked) forlab-printer-app.Lock Ava as administrator
Recorded as
tenant.users.locksucceeded.The photo API introspects Ava's token after the lock
Recorded as
oauth.introspectsucceeded (other_client_token_found) forlab-photo-apiabout[email protected].The photo API cannot revoke another client's token
Recorded as
oauth.revokerejected (other_client_token) forlab-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
Press Start on this page.
You need
lab-printer-app(public, with the refresh grant, its client ID inCLIENT_ID),lab-photo-api(confidential, Resource server on, its credentials inAPI_IDandAPI_SECRET) from the earlier labs, and the lab toolkit.Open a note with the lesson's table: kind of access, who checks it, and when revocation took effect in your tenant.
Walkthrough
Run the authorization code flow for
lab-printer-appas Ava withoffline_access, exactly as in steps 1 to 3 of the previous lab, and keep the tokens in your shell asTOKENandREFRESH.
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.
Check the access token both ways: locally, against the issuer's published keys, and by asking the tenant as
lab-photo-api. Use theaudvalue thatbtl-lab decodeshowed.
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.
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_IDTry 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.
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.
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.
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
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 withunauthorized_client, and the token keeps working forlab-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.
In OAuth > Clients, remove
profilefromlab-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.lockandtenant.users.unlockname 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
Clear the tokens:
unset TOKEN REFRESH RESPONSE.Make sure Ava is unlocked.
Missing infrastructure
G17: there is no back-channel or RP-initiated logout, so
lab-collagecannot be told to end Ava's session. Once it exists, the lab will sign Ava in tolab-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-revokedevent 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.