OPENID CONNECT · LAB
Follow a distributed claim reference
Plan reading a reference to Lab Mail's claims endpoint with an access token Lab Mail issued, and today classify claim sources and handle a real Lab Mail access token as the bearer credential a reference would carry.
PlannedUses both lab tenants
The lesson
Builds on: Reading and validating aggregated claims.
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.
- G63 Aggregated and distributed claims (trusted claims-provider registry)
- G3 Sample protected resource API; no RFC 9728 protected resource metadata
- G66 Second lab tenant for every learner: additional tenants need a paid subscription or a BTL grant, so labs that use Lab Mail cannot be completed by an ordinary learner yet
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).
Setup
No tenant emits distributed claim references yet (G63), and no tenant hosts a claims endpoint that returns a signed claim JWT. The closest real endpoint is UserInfo, and the sample protected API is G3. Lab Mail again plays the party that knows whether Ava is enrolled.
source ~/btl-oidc.shand runbtl-lab callbackbefore each sign-in.Once G63 exists: in Lab Photos, add a distributed source for
lab_enrolledthat points at Lab Mail's claims endpoint, with Lab Photos obtaining short-lived, claim-scoped Lab Mail tokens on Ava's behalf.
Planned walkthrough
Ask for the claim at checkout and read UserInfo:
curl -s -H "Authorization: Bearer $TOKEN" "$ISSUER/oidc/userinfo" | jq '{sub, _claim_names, src1: (._claim_sources.src1 | {endpoint, access_token: (.access_token != null)})}'
_claim_sources.src1 has an endpoint at Lab Mail and an access_token, and no JWT.
Note that nothing has been fetched. You hold an address and a credential, according to Lab Photos, and no statement from Lab Mail at all.
Why it matters: a reference is a promise of where to ask, not an answer. The statement arrives only when the relying party fetches it.
Introspect the reference's token at Lab Mail as a resource server: it reads only the enrollment claim and expires within minutes.
Do today
Write the classifier the relying party needs before following anything:
source_kind() { jq -r 'if has("JWT") then "aggregated" elif has("endpoint") then "distributed" else "ignored" end'; }
echo '{"JWT":"eyJ..."}' | source_kind
echo '{"endpoint":"https://mail.example/claims","access_token":"..."}' | source_kind
echo '{"note":"unknown"}' | source_kind
aggregated, distributed, ignored.
Why it matters: the source object alone tells you which kind of claim you are reading, and one response can mix both.
Hold a real bearer credential for the other source. Sign in to
lab-mail-collageat Lab Mail as Ava Lin and keep only the access token, in a shell variable:
ISSUER_A=$ISSUER CLIENT_A=$CLIENT_ID SECRET_A=$CLIENT_SECRET
ISSUER=$ISSUER2 CLIENT_ID=$MAIL_CLIENT_ID CLIENT_SECRET=$MAIL_CLIENT_SECRET SCOPE="openid profile"
signin
redeem '<code>'
MAIL_TOKEN=$TOKEN
curl -s -u "$CLIENT_ID:$CLIENT_SECRET" "$ISSUER/oauth/introspect" --data-urlencode "token=$MAIL_TOKEN" | jq '{active, scope, exp, client_id}'
active is true, with its scope and exp.
Why it matters: whoever holds this token can call Lab Mail as Ava Lin until it expires. It stays out of logs and browsers and goes only to the endpoint it was issued for.
Fill in the lesson's comparison for your two tenants, in your notes: for each form, how current the statement would be, who learns that you asked, what must be up when you need the claim, and what Lab Photos would have to keep.
Switch back to Lab Photos (
ISSUER=$ISSUER_A CLIENT_ID=$CLIENT_A CLIENT_SECRET=$SECRET_A SCOPE="openid profile email").
Break it
Planned, once G63 exists: request the claim and decline sharing. No reference appears at all, so there is nothing to follow and nothing to leak.
Check your work
Today: your classifier's three answers, an active Lab Mail token seen only through introspection, and Lab Mail's Audit showing oauth.introspect access_token_found for lab-mail-collage.
Once G63 exists, Lab Mail's Audit shows Lab Photos obtaining a token for Ava's enrollment, and Lab Photos' Audit shows the reference served after her consent.
Cleanup
Keep MAIL_TOKEN only until the next lab, which uses it fresh. Nothing in either tenant changed.
Missing infrastructure
G63 (aggregated and distributed claims). Distributed sources in ID tokens and UserInfo, and a way for Lab Photos to obtain claim-scoped tokens from Lab Mail.
G3 (sample protected resource API). A tenant claims endpoint that returns
application/jwt, or the hosted lab API serving that role, for the reference to point at.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.