OPENID CONNECT · LAB
Refuse near-miss issuers, another client's token and an extra audience
Give lab-collage its own ID token manager, reject near-match issuers and a genuine token issued to the printer, then add a second audience and decide deliberately whether to trust it.
ReadyUses your lab tenant
The lesson
Builds on: Validating an ID token.
New to the labs? Start with the lab toolkit and the shared cast and names every lab uses.
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.
Create the lab-collage ID token manager
Recorded as
tenant.oauth.id_token_managers.createsucceeded.Assign it to lab-collage only
Recorded as
tenant.oauth.id_token_managers.assignsucceeded.Obtain a genuine ID token issued to the printer
Recorded as
oauth.tokensucceeded forlab-printerabout[email protected].Add a second audience to lab-collage's ID tokens
Recorded as
tenant.oauth.id_token_managers.updatesucceeded.Receive an ID token with two audiences
Recorded as
oauth.tokensucceeded forlab-collageabout[email protected].Remove the extra audience again
Recorded as
tenant.oauth.id_token_managers.updatesucceeded.
Setup
You need
lab-collage,lab-printer, Ava, the helpers from the authentication request lab, andEXPECTED_ISSUER,EXPECTED_AUDandID_ALGSfrom the previous lab. Keepbtl-lab callbackrunning.Press Start.
In OAuth > ID Token Management, create a manager named
lab-collageas a copy of the defaults: the tenant's RS256 key, a 300-second lifetime and the default claim mappings. Assign it tolab-collageonly. The rest of the track changes this manager and never the tenant default, so no other client is affected.
Walkthrough
Run a fresh
lab-collagesign-in (signin_url 'openid', thenexchange) and keepATTEMPT_NONCE=$NONCE. Confirm it verifies with your normal settings.
Exact issuer. Run the verifier against four near matches:
for i in "$ISSUER/" "${ISSUER^^}" "${ISSUER/https/http}" "$ISSUER/test"; do
btl-lab verify "$ID_TOKEN" --issuer "$i" --audience "$EXPECTED_AUD" --algs "$ID_ALGS" --type id --nonce "$ATTEMPT_NONCE"; done
Each run passes the signature and stops at the issuer check.
Why it matters: an issuer is a name compared as text, never an address to be tidied up. It is also the namespace for every sub the provider issues.
Where the expected value comes from. Show the wrong design once: copy the
issvalue frombtl-lab decode "$ID_TOKEN"and pass that as--issuer. It passes, but it only compared the token with itself, and would pass a token from any provider whose keys you happened to use. Always pass--issuer "$EXPECTED_ISSUER", the value stored with the attempt.
A genuine token for another client. Run a
lab-printersign-in withscope=openidin the same browser. Ava's session is still valid, so the tenant asks nothing, just as in the lesson. KeepPRINTER_IDTandPRINTER_NONCE, then verify it as the collage app with the printer's own nonce:
btl-lab verify "$PRINTER_IDT" --issuer "$EXPECTED_ISSUER" --audience "$EXPECTED_AUD" --algs "$ID_ALGS" --type id --nonce "$PRINTER_NONCE"
The signature and issuer pass, then the audience check refuses it.
Why it matters: everything about this token is genuine, signed by the same key. Only aud shows that it was issued to someone else.
Two audiences. Open the
lab-collageID token manager, set the standard claimaudto a list of two values, yourlab-collageclient ID and yourlab-printerclient ID, and save. The tenant requires the requesting client's ID to stay in the list. Sign in again throughlab-collageand verify the new token with your normal settings. It stops at the audience check, although your client ID is in the list.
Why it matters: every party named in aud was meant to receive the same token, and any of them could present it elsewhere. A token addressed to the printer too could arrive from the printer as easily as from your own exchange.
Trust the extra audience on purpose:
btl-lab verify "$ID_TOKEN" --issuer "$EXPECTED_ISSUER" --audience "$EXPECTED_AUD" --trusted-audience "$PRINTER_ID" --algs "$ID_ALGS" --type id --nonce "$NONCE"
It now ends in ACCEPT. Trusting another audience is legitimate only for a registration you control and have decided to accept, and the value comes from your configuration.
Restore: in the lab-collage ID token manager, set aud back to the default (the client ID only) and save.
The authorized party. Decode your token and the printer's: each carries
azpequal to its own client ID. On this tenantazpis a protected claim that always names the requesting client, so a token that named a different client as its authorized party would not be one you asked for. Keep the rule on: ifazpis present, it must equal your client ID.
Break it
Client IDs compare exactly. Run step 1's verification with
--audience "${EXPECTED_AUD^^}". It stops at the audience check: an uppercase client ID is a different client.
A prefix rule. Imagine accepting any issuer that starts with your tenant's host. Write down which of the near matches in step 2 such a rule would let through, and why a multi-tenant service that signs every organization's tokens with the same keys makes that rule dangerous.
Check your work
Press Check my progress. It looks for, in order: tenant.oauth.id_token_managers.create and .assign, oauth.token succeeded for lab-printer, tenant.oauth.id_token_managers.update (the second audience), oauth.token succeeded for lab-collage, and a second tenant.oauth.id_token_managers.update (the restore).
None of your issuer or audience refusals reach the tenant. They exist only in your verifier's output.
Cleanup
Confirm that the
lab-collageID token manager issuesaudwith the client ID only.Keep the manager assigned to
lab-collage. Rununset PRINTER_IDT PRINTER_NONCE.