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

Drive the prompt values and read each answer

Produce login_required, consent_required and account_selection_required on purpose, use the tenant's account chooser, force a fresh sign-in and a fresh consent, and see why none must stand alone.

ReadyUses your lab tenant

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.

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. Get login_required from a silent check with no session

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

  2. Get consent_required for a scope never approved

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

  3. Get account_selection_required with a hint for Ben

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

  4. Sign in as Ben from the chooser

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

  5. Combine none with another prompt value

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

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. In Lab Photos, open OAuth > Clients > lab-collage and add photos.share to its allowed scopes. Nobody has approved it for lab-collage, which guarantees a consent question. The Lab Photos preset creates the scope.

  2. Make sure Ava and Ben have passwords (set in Key accounts on issuer and subject).

  3. source ~/btl-oidc.sh, set SCOPE="openid profile email", and run btl-lab callback before each request.

  4. In a private window, sign in once through signin as Ava so the browser holds a tenant session and a remembered consent. Then press Start.

Walkthrough

  1. Ask without interrupting, with a session.

signin prompt=none

The browser lands on the listener with a code and no page in between. Redeem and validate, then compare iat and auth_time:

redeem '<code>'
btl-lab verify "$ID_TOKEN" --issuer "$ISSUER" --audience "$CLIENT_ID" --type id --nonce "$NONCE" && part "$ID_TOKEN" | jq '{iat, auth_time}'

iat is now. auth_time is your earlier sign-in.

Why it matters: a silent answer confirms that the browser still holds a session, not that anyone used a credential now, so your session records the older auth_time.

  1. Ask without interrupting, with no session. In the private window open $ISSUER/account and choose Sign out. Run signin prompt=none again. The listener prints error=login_required with your state and iss. Check both as you would for a success, then show your own sign-in button.

Why it matters: for a silent check an error is an ordinary answer, not a failure to investigate.

  1. Sign in as Ava normally, then ask silently for something she never approved.

SCOPE="openid photos.share"
signin prompt=none

The listener prints error=consent_required.

Why it matters: the tenant would have needed to show a consent page, and prompt=none forbids every page.

  1. Hint at a different account while Ava is signed in.

SCOPE="openid profile email"
signin prompt=none login_hint=ben%40example.com

The listener prints error=account_selection_required.

Why it matters: the tenant compares the hint only after consent is settled, so a client without consent learns nothing about who is signed in.

  1. Open the chooser.

signin prompt=select_account

The tenant shows Choose an account with a button to continue as [email protected] and one to use another account. Choose another account and sign in as Ben, approving the consent page. Validate the result: sub is Ben's.

Why it matters: the chooser belongs to the provider. The client never learns which other accounts exist, and it still identifies the result by iss and sub.

  1. Ask again for a sign-in.

signin prompt=login

The password form appears although a session exists. Sign in as Ava. The new token's auth_time is now.

Why it matters: prompt=login asks for evidence that the person can still sign in, not only that the browser holds a session.

  1. Ask again for consent, alone and combined.

signin prompt=consent
signin "prompt=login%20consent"

Open each URL. The consent page appears every time, and the second also asks for the password first.

Why it matters: prompt is a space-separated list. Consent can be requested again, but its wording stays the provider's.

Break it

  1. none combined with anything else:

signin "prompt=none%20login"

The listener prints error=invalid_request. none must stand alone, and the tenant refuses to guess which one you meant.

  1. A value this provider does not list. Read what it supports, then send create anyway.

GET$ISSUER/.well-known/openid-configuration Open in console
GET $ISSUER/.well-known/openid-configuration

prompt_values_supported is ["none","login","consent","select_account"]. signin prompt=create returns error=invalid_request, so your sign-up link sends create only to providers that list it.

Note: prompt=create is G62. The tenant already has self-service registration at /register. Once the value is supported and listed, this step will send a new user straight to registration and show that the client still cannot assume an account was created.

  1. The silent loop. Sign out, then run signin prompt=none three times in a row. Audit shows three login_required rejections from one browser within seconds. Write the rule in your notes: one silent check per visit, then wait for the person to choose to sign in.

Check your work

Press Check my progress. The checks look for the three silent errors in order, Ben's sign-in from the chooser, and the refused none login request.

In Audit, filter on oauth.authorize and lab-collage to see each answer beside its request_started event.

Cleanup

  1. Sign Ben out at $ISSUER/account and sign Ava back in.

  2. Keep photos.share on lab-collage; later labs use 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