OAUTH 2.0 · LAB
Guard and rotate a registration access token
Use a registration access token for exactly one client, store its rotated replacement, and tell apart the three credentials around one client. Today, compare it with a role-based permission in the portal.
PlannedUses your lab tenant
The lesson
Builds on: Reading and updating a registration.
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.
- G9 Dynamic client registration and registration management
Setup
Once G9 exists, keep
RCUandRATfor the registered client from Read, modify and write back a client registration, and theIATinitial access token.Planned (G9): in OAuth > Registration, keep rotation On read and update, with the option Accept the previous token until the new one is first used, so a lost response does not lock the client out.
Planned walkthrough
Read your registration. The response carries a new
registration_access_token. Store it before doing anything else.
curl -s "$RCU" -H "Authorization: Bearer $RAT" | jq 'del(.client_secret, .registration_access_token)'
read -rs NEW_RAT; export NEW_RAT # paste the new registration_access_token
Why it matters: "Rotating the token". Rotation happens only in responses, so the client must store the new token durably first.
Read again with the new token: it succeeds. Then try the old one.
curl -s -o /dev/null -w '%{http_code}\n' "$RCU" -H "Authorization: Bearer $RAT"
export RAT=$NEW_RAT; unset NEW_RAT
The old token gets 401.
Why it matters: the old token stops once the new one is in use, which limits how long any one leaked token is useful.
Register a second client with
IATand save its configuration address asRCU2. CallRCU2with the first client'sRAT. Expect401.
Why it matters: "A credential for one endpoint". A registration access token is bound to one client ID.
Fill in the lesson's three-credential table from what you used: the initial access token at
$ISSUER/oauth/register, the registration access token at one configuration address, and the client secret at the token endpoint.
Why it matters: each credential is valid at its own endpoint only, and the registration access token is the one that can take over a client entirely.
Do today
Today the tenant has no registration access tokens, but it does control who may manage a client registration. Compare that with a bearer token.
In Roles, create a custom role
lab-tmp-client-viewerwith only the permission to read OAuth clients (tenant.oauth.clients.read). Assign it to Ben ([email protected]) and make sure he has a password.Sign in as Ben at
$ISSUER/managein a private window. Open OAuth > Clients: the list is readable. Open a client and try to save a change: it is refused.In your own session, open Audit. It shows the role creation and assignment with you as actor, and Ben's refused update with Ben as actor.
Remove the role from Ben and reload his window. He can no longer read the clients list.
Write the comparison the lesson invites. Ben's authority came from a permission checked against his current role on every request, and removing the role ended it at once. A registration access token is a bearer credential: whoever holds it can read, change or delete one client until it rotates or the client is deleted. That is why it belongs in secure storage next to the client's private key, never in a build log.
Break it
Once G9 exists, use the client secret as a bearer token at the configuration endpoint.
read -rs SECRET_GUESS # paste the registered client's client_secret
curl -s -o /dev/null -w '%{http_code}\n' "$RCU" -H "Authorization: Bearer $SECRET_GUESS"; unset SECRET_GUESS
Expect 401. The client secret works at the token endpoint and nowhere else.
Check your work
Today, Audit shows tenant.roles.create, tenant.users.management_roles.assign for Ben, his refused tenant.oauth.clients.update, and later the role's removal and deletion. Once G9 exists, Audit also shows a configuration endpoint read that rotated the token, and refusals of the old, cross-client and wrong-credential tokens.
Cleanup
Remove
lab-tmp-client-viewerfrom Ben if it is still assigned, and delete the role in Roles.Once G9 exists, keep one registered client for the next lab and delete the other.
Missing infrastructure
G9: registration access tokens that are random, stored only as hashes, bound to one client, rotated on read and update with a safe overlap, and invalidated when the client is deleted. Once these exist, the Planned walkthrough runs as written.