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

Run every ID token check in order and keep only the answer

Configure an ID token verifier from your own expectations, watch it run the lesson's checks in order on a real token, make it refuse missing settings, and keep the issuer and subject, not the token.

ReadyUses your lab tenant

The lesson

Builds on: Receiving the 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.

  1. Receive a fresh ID token for lab-collage

    Recorded as oauth.token succeeded for lab-collage about [email protected].

  2. Use the access token only after the ID token is accepted

    Recorded as oidc.userinfo succeeded (userinfo_served) for lab-collage.

  3. Obtain a real ID token issued to another client

    Recorded as oauth.token succeeded for lab-printer about [email protected].

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. You need lab-collage, lab-printer, Ava, the shell variables from the first lab in this track and the signin_url and exchange helpers from the authentication request lab.

  2. Write down the relying party's expectations. They come from your configuration, never from a token:

export EXPECTED_ISSUER="$ISSUER" EXPECTED_AUD="$CLIENT_ID" ID_ALGS=RS256
  1. Keep btl-lab callback running in a second terminal and press Start.

Walkthrough

  1. Fetch the key set and see what it holds:

GET$ISSUER/oauth/jwks Open in console
GET $ISSUER/oauth/jwks HTTP/1.1
Accept: application/json

Or in the shell: curl -s "$ISSUER/oauth/jwks" | jq '.keys[] | {kid, kty, alg, use}'. On a default tenant you see an RSA key for ID tokens and an EC key for access tokens.

Why it matters: one key set holds keys for different jobs. The relying party picks a key by kid and uses each key with one algorithm only.

  1. Run a fresh lab-collage sign-in: signin_url 'openid%20profile%20email', sign in as Ava, check state and iss, then exchange '<code>'. Keep ATTEMPT_NONCE=$NONCE. Until every check passes, you do not look up an account, greet Ava or touch the access token.

  1. Run the checks:

btl-lab verify "$ID_TOKEN" --issuer "$EXPECTED_ISSUER" --audience "$EXPECTED_AUD" --algs "$ID_ALGS" --type id --nonce "$ATTEMPT_NONCE"

The verifier prints one line per check and ends in ACCEPT. Match each line to the lesson's numbered list: algorithm, key, signature, issuer, audience and authorized party, time, nonce.

Why it matters: every check runs and nothing is used until all of them pass. Verifying the signature early means every later comparison is made against values the provider actually signed.

  1. Only now use the access token. First confirm that it belongs to this ID token, then call UserInfo with it:

btl-lab verify "$ID_TOKEN" --issuer "$EXPECTED_ISSUER" --audience "$EXPECTED_AUD" --algs "$ID_ALGS" --type id --nonce "$ATTEMPT_NONCE" --access-token "$TOKEN"
curl -s "$ISSUER/oidc/userinfo" -H "Authorization: Bearer $TOKEN" | jq '{sub, name, email}'

The at_hash check passes, which ties this access token to this ID token.

Why it matters: both tokens came from the same code. If the code had been misdelivered, the ID token checks are how you find out, so the access token waits for them.

  1. Compare with the tenant's own view. Open $ISSUER/token-decoder, sign in, and see the decoder report the same signature verification for its token.

  1. Keep the answer, not the token. From the accepted claims, copy iss, sub and auth_time into a session record, then drop the token with unset ID_TOKEN. The pair iss and sub identifies Ava's account. auth_time goes with the session you are about to create. The nonce is finished, and the ID token's five-minute lifetime does not carry over to the session.

Break it

Each run below uses a real token or a real configuration mistake. Watch where each one stops.

  1. A real ID token for another client. Run a lab-printer sign-in with scope=openid (as in the first lab of this track, with PRINTER_ID and PRINTER_SECRET) and keep its ID token as PRINTER_IDT and its nonce as PRINTER_NONCE. Verify it with the collage expectations and the printer's own nonce, so only the audience differs:

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.

  1. The access token offered as an ID token: btl-lab verify "$TOKEN" --issuer "$EXPECTED_ISSUER" --audience "$EXPECTED_AUD" --algs "$ID_ALGS" --type id --nonce "$ATTEMPT_NONCE" stops at the algorithm check, because ES256 is not on your ID token list.

  1. A nonce from another attempt: run step 3 with --nonce "$PRINTER_NONCE". It stops at the nonce check.

  1. A missing setting. A library must refuse, not skip, when an expected value is absent. Run step 3 with --audience '', then again with the --nonce option left out. Both runs must end in REJECT. If a verifier you use in your own code accepts either, it is skipping a check.

Check your work

Press Check my progress. It looks for oauth.token succeeded for lab-collage, then oidc.userinfo with userinfo_served for lab-collage (the access token used after the ID token was accepted), then oauth.token succeeded for lab-printer.

Audit shows a successful token request for every attempt, including the ones your verifier refused in Break it. The provider cannot see a relying party's validation result.

Cleanup

Keep EXPECTED_ISSUER, EXPECTED_AUD and ID_ALGS: the rest of the Validation section uses them. Run unset TOKEN ID_TOKEN PRINTER_IDT RESP.

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