OAUTH 2.0 · LAB
Register return addresses and see what consent shows
Register several exact return addresses, watch the tenant refuse unsafe ones, see that a client's name is free text on the consent page, and narrow a client's settings until wrong requests fail.
Partly readyUses your lab tenant
The lesson
Builds on: Client IDs and registration.
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.
- G53 Client display metadata on consent (logo, policy links)
- G54 Private-use URI scheme redirects for native apps (RFC 8252)
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.
Sign in to start this lab and check your progress. Log in or create an account.
A second registered return address is accepted
Recorded as
oauth.authorizesucceeded (request_started) forlab-printer.An unsafe redirect URI registration is refused
Recorded as
tenant.oauth.clients.updaterejected.Register a separate test client
Recorded as
tenant.oauth.clients.createsucceeded.The test address works only for the test client
Recorded as
oauth.authorizesucceeded (request_started) forlab-tmp-printer-test.A narrowed client cannot request a common scope
Recorded as
oauth.authorizerejected (invalid_scope) forlab-tmp-printer-test.
Setup
Press Start on this page.
Open OAuth > Clients > lab-printer > Edit, add a redirect URI
http://127.0.0.1:8765/oauth/add-account/callback, and save.Set
ISSUER,PRINTER_ID,APP_IDandenc, and define a request that changes only the client and return address.
eval "$(btl-lab pkce)"; eval "$(btl-lab state)"
try() { echo "$ISSUER/oauth/authorize?response_type=code&client_id=$1&redirect_uri=$(enc "$2")&scope=${3:-photos.read}&state=$STATE&code_challenge=$CHALLENGE&code_challenge_method=S256${4:+&$4}"; }
Walkthrough
Use each registered address.
try "$PRINTER_ID" http://127.0.0.1:8765/oauth/add-account/callbackreaches the sign-in page.try "$PRINTER_ID" http://127.0.0.1:8765/oauth/other/callbackstops on the tenant's error page. Close both tabs.
Why it matters: a client can register several return addresses, each request names one, and only an exact entry in the list matches.
Try to save unsafe registrations on
lab-printer, one at a time. Each is refused and nothing changes.
| Redirect URI | Why the tenant refuses it |
|---|---|
https://*.printer.example/oauth/callback | a wildcard would let any subdomain receive codes |
http://printer.example/oauth/callback | plain HTTP is allowed only for loopback |
http://localhost:8765/callback | loopback must be the literal 127.0.0.1 or [::1] |
https://printer.example/oauth/callback#done | a fragment |
http://127.0.0.1:8765/callback?code=1 | the query uses a name the response adds |
example.printer:/oauth/callback | a private-use scheme, not supported here (G54) |
Return addresses for installed apps.
lab-printer-appregistershttp://127.0.0.1/callbackwith no port, and its loopback flow in earlier labs used port 8765.try "$APP_ID" http://127.0.0.1:51234/callbackreaches the sign-in page too, whiletry "$APP_ID" http://127.0.0.1:51234/otherstops on the error page.
Why it matters: for loopback addresses the port may vary, because the operating system picks a free one, and everything else still matches exactly. Plain HTTP is acceptable because the response never leaves the machine.
Keep test and production apart. Create a temporary client from Web application named
lab-tmp-printer-test, with redirect URIhttp://127.0.0.1:8765/test/callback, and setTEST_IDto its client ID.try "$PRINTER_ID" http://127.0.0.1:8765/test/callbackstops on the error page.try "$TEST_ID" http://127.0.0.1:8765/test/callbackreaches the sign-in page.
Why it matters: the test site's return address belongs only to the test client. Had it been added to lab-printer, a mistake on the test site could leak codes for real accounts.
The name is a claim. Rename
lab-tmp-printer-testtolab-printer, the same display name as the real client. Renaming revokes nothing. Opentry "$PRINTER_ID" "$REDIRECT_URI" photos.read prompt=consentandtry "$TEST_ID" http://127.0.0.1:8765/test/callback photos.read prompt=consent, sign in as Ava, and compare the two consent pages without approving. They look identical, although the two return addresses differ.
Why it matters: anyone who can register a client can type a familiar name. The return address is the part the server enforces, and this consent page does not show it.
Narrow the test client's settings. Rename it back to
lab-tmp-printer-test, tick Restrict scopes with no assigned scopes, and save. A restricted client may use only the exclusive scopes assigned to it, sotry "$TEST_ID" http://127.0.0.1:8765/test/callbacknow returnserror=invalid_scopeto its callback.
Why it matters: settings that match the client's real behavior turn mistakes into ordinary rejections, and give someone holding the client's credentials less to work with.
Planned walkthrough
These steps need client display metadata on consent (G53).
On
lab-printer, setclient_uritohttps://printer.example, alogo_uri,policy_uriandtos_uri. Start a consent for Ava: the page shows the logo, the links and the return domain next to the name.Give
lab-tmp-printer-testthe same name and logo with a differentclient_uri. The consent page marks its unverified domain and shows a different return domain, so Ava can tell the two apart by domain instead of by name.
Break it
Step 2 is the set of deliberate registration failures. Nothing is saved.
Check your work
Press Check my progress. Logs also has oauth.authorize rejected invalid_redirect_uri rows for each address in steps 1, 3 and 4 that stopped on the error page.
Cleanup
Delete
lab-tmp-printer-test.On
lab-printer, remove thehttp://127.0.0.1:8765/oauth/add-account/callbackredirect URI and save.
Missing infrastructure
G53, client display metadata. Clients have only a name today: no
client_uri,logo_uri,policy_uri,tos_uriorcontacts, and the consent page does not show the return domain. With them, the planned steps compare a genuine and an impostor-named client by domain, and the tenant can mark clients whose domain is unverified.G54, private-use URI scheme redirects. Native apps cannot register a scheme such as
example.printer:/oauth/callback. With it, the lab would register one forlab-printer-appand show why PKCE still protects a code delivered to another app that claimed the same scheme.