OPENID CONNECT · LAB
Launch a sign-in from a dashboard tile
Plan clicking a lab-collage tile on your tenant's app dashboard and landing on a deep page, and today see why a plain link works through single sign-on and why a result nobody asked for must be refused.
PlannedUses 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.
Planned. The core of this lab waits on platform features that are not built yet. The planned walkthrough shows exactly how it will run; Do today is a real exercise you can do now.
- G65 Third-party initiated login (`initiate_login_uri`, tenant app launcher)
Setup
Clients have no initiate_login_uri setting yet, and tenants have no app dashboard that sends iss, login_hint and target_link_uri (G65). The relying party's side of the lesson, refusing a result it never asked for, is real today.
source ~/btl-oidc.shand runbtl-lab callbackbefore each request.Once G65 exists: on
lab-collage, set the login initiation endpoint to your relying party's HTTPS/signin/startaddress and show it on the tenant's dashboard.
Planned walkthrough
Sign in to
$ISSUER/accountas Ava. The dashboard listslab-collage, with recent items such as the autumn catalogue album.Choose that item. The browser goes to your login initiation endpoint with
iss,login_hintandtarget_link_uri, as a GET or an automatically submitted POST.Your endpoint starts a fresh code flow, as in Build a safe login initiation endpoint, and the tenant answers at once from Ava's session. The browser lands on the album.
Why it matters: the dashboard only asks the relying party to begin. Everything that comes back answers a request the relying party made, in this browser.
Audit shows the tile launch, then an ordinary
request_startedandcode_issuedforlab-collage.
Do today
The plain-link tile. With Ava signed in, open a
signinURL as if a tile linked to it:
signin
The code arrives with no page in between.
Why it matters: for one provider and one front page, a link plus single sign-on is nearly enough. It stops being enough when the click should pick a provider, an account or a deep page.
Keep pending attempts the way a relying party does, keyed by
state, and claim one exactly once:
echo '{}' > pending.json
remember() { jq --arg s "$STATE" --arg n "$NONCE" --arg v "$VERIFIER" '. + {($s): {nonce: $n, verifier: $v}}' pending.json > p.tmp && mv p.tmp pending.json; }
claim() {
jq -e --arg s "$1" 'has($s)' pending.json > /dev/null || { echo "refused: no pending sign-in for this state"; return 1; }
jq --arg s "$1" 'del(.[$s])' pending.json > p.tmp && mv p.tmp pending.json; echo "claimed: continue with the code"
}
Run a sign-in you started:
signin, thenremember, then open the URL. When the listener printscodeandstate, runclaim '<state>'and thenredeem '<code>'. It succeeds.A result nobody asked for. Present the same callback a second time, as a dashboard that sends results straight to the redirect URI would:
claim '<state from step 3>'
refused: no pending sign-in for this state, before the code is used at all.
Why it matters: an unrequested result has nothing to match in this browser, so the relying party cannot tell whose idea it was. That is why the initiator only asks the relying party to begin, and why a careful relying party refuses such a callback.
Break it
Planned, once G65 exists: remove the login initiation endpoint from lab-collage. The tile disappears from the dashboard rather than sending a code to the redirect URI unasked.
Check your work
Today: one sign-in claimed and completed, and the replayed callback refused by your own code with no second request to the tenant. Audit shows a single oauth.token success for that code.
Once G65 exists, Audit shows the tile launch followed by request_started and code_issued for lab-collage.
Cleanup
Delete pending.json. Nothing in the tenant changed.
Missing infrastructure
G65 (third-party initiated login). A client
initiate_login_urisetting (HTTPS, validated), a tenant-user app launcher, for example on/account, that sendsiss,login_hintandtarget_link_uriby GET or POST, and audit events for launches.