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

Suggest an account with login_hint, pin it with id_token_hint

Prefill a sign-in with an email hint and sign in as someone else anyway, then use an expired ID token as id_token_hint and watch the tenant refuse to answer for a different person or a hint it did not sign for you.

Partly readyUses both lab tenants

The lesson

Builds on: Connecting a sign-in to an account.

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.

Needs a second tenant. This lab also uses Lab Mail, a second tenant. Additional tenants currently need a paid subscription or a BTL grant, so you may not be able to do the Lab Mail steps yet (gap G66).

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. Sign in as Ben although the hint named Ava

    Recorded as oauth.authorize succeeded (user_signed_in) for lab-collage about [email protected].

  2. Get a silent code with an expired ID token as the hint

    Recorded as oauth.authorize succeeded (code_issued) for lab-collage about [email protected].

  3. See the tenant refuse to answer for someone else

    Recorded as oauth.authorize rejected (id_token_hint_mismatch) for lab-collage.

  4. Send a hint the tenant did not sign for lab-collage

    Recorded as oauth.authorize rejected (invalid_id_token_hint) for lab-collage.

Setup

  1. You need ID_TOKEN_AVA, the ID token Ava received in Key accounts on issuer and subject. It expired long ago, which is the point. If your shell lost it, sign in as Ava once and keep ID_TOKEN_AVA=$ID_TOKEN, then wait for it to expire.

  2. In your lab browser's private window, open $ISSUER/account and sign out.

  3. source ~/btl-oidc.sh, run btl-lab callback before each request, and press Start.

Walkthrough

  1. Suggest an account.

signin login_hint=ava%40example.com

The tenant's sign-in form opens with [email protected] already filled in.

Why it matters: a hint saves the person effort. It skips nothing.

  1. Clear the field and sign in as Ben instead. Redeem and validate: sub is Ben's. Your relying party expected acct-8812, so it signs Ben in to his own account, if he has one, and shows him nothing of Ava's.

Why it matters: the evidence of who signed in is the validated iss and sub, never the hint you sent.

  1. Open your browser history and find the authorization URL: the email address is there in clear. The tenant uses login_hint as an email address to prefill its form, so that is the format its documentation calls for.

Why it matters: hints travel through the browser and can be recorded wherever URLs are. Send one only when it saves real effort, in the format the provider documents.

  1. Hint with an earlier ID token. Sign out, sign in as Ava, then ask silently for her by her old token:

part "$ID_TOKEN_AVA" | jq '{sub, exp, expired: (.exp < now)}'
signin prompt=none "id_token_hint=$ID_TOKEN_AVA"

expired is true, and a code still comes back.

Why it matters: the hint points to a person. It is not proof of a current sign-in, so its exp does not matter, and it was addressed to your client, not to the provider.

  1. Switch people under the hint. In another tab of the same window, sign out and sign in as Ben at $ISSUER/login. Run the step 4 request again with a fresh signin: the listener prints error=login_required. Run it once more without the hint:

signin prompt=none

A valid code comes back, for Ben.

Why it matters: without id_token_hint, a silent request can return a perfectly valid sign-in for the wrong account. With it, the provider knows that is not the person you asked about.

Break it

  1. A real hint meant for someone else. Sign in to lab-mail-collage at Lab Mail as Ava Lin and keep that ID token, then send it to Lab Photos as a hint:

ISSUER_A=$ISSUER CLIENT_A=$CLIENT_ID SECRET_A=$CLIENT_SECRET
ISSUER=$ISSUER2 CLIENT_ID=$MAIL_CLIENT_ID CLIENT_SECRET=$MAIL_CLIENT_SECRET
signin
redeem '<code>'
MAIL_ID_TOKEN=$ID_TOKEN
ISSUER=$ISSUER_A CLIENT_ID=$CLIENT_A CLIENT_SECRET=$SECRET_A
signin prompt=none "id_token_hint=$MAIL_ID_TOKEN"

The listener prints error=invalid_request and a description saying the hint must be an ID token this issuer signed for this client. Lab Photos accepts only hints it signed for lab-collage, and only with a key it still publishes.

  1. Write the relying-party check the lesson ends on. After a hint-driven sign-in, compare the result's sub with the session's before applying anything:

EXPECTED_SUB=$(part "$ID_TOKEN_AVA" | jq -r .sub)
[ "$(part "$ID_TOKEN" | jq -r .sub)" = "$EXPECTED_SUB" ] && echo "same person: continue" || echo "different person: discard pending work, end session"

Feed it Ben's token from step 5: it refuses to apply anything to Ava's session.

Check your work

Press Check my progress. The checks look for Ben's sign-in despite Ava's hint, the silent code issued with an expired hint, the id_token_hint_mismatch refusal, and the refused Lab Mail hint.

Nothing about the hint changed what the tenant asked for at sign-in: Audit shows the same user_signed_in event for Ben that any password sign-in produces.

Cleanup

Sign Ben out and sign Ava back in. Nothing in either tenant was changed.

Missing infrastructure

  • G66 Second lab tenant: this lab uses Lab Mail, a second tenant. Additional tenants currently need a paid subscription or a BTL grant, so an ordinary learner can do only the Lab Photos steps until every learner can have a second lab tenant.

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