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

IDENTITY SECURITY · LAB

Control what apps can ask for, review consent and withdraw a grant

Keep a sensitive scope away from lab-printer-app until you assign it, read the consent screen Ava sees, deny and approve it, then remove the scope and watch its grant end.

Partly readyUses your lab tenant

The lesson

Builds on: Limiting what stolen access can do.

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.

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. lab-printer-app cannot ask for a scope it was not given

    Recorded as oauth.authorize rejected (invalid_scope) for lab-printer-app.

  2. Assign photos.share and always ask for consent

    Recorded as tenant.oauth.clients.update succeeded.

  3. Ava declines the consent screen

    Recorded as oauth.authorize rejected (access_denied) for lab-printer-app about [email protected].

  4. Ava approves and the app receives a code

    Recorded as oauth.authorize succeeded (code_issued) for lab-printer-app about [email protected].

  5. Remove photos.share from the app

    Recorded as tenant.oauth.clients.update succeeded.

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. Press Start on this page.

  2. In OAuth > Scopes, confirm photos.share exists and is exclusive. Create it if the Lab Photos preset did not.

  3. You need lab-printer-app and fresh PKCE and state values from eval "$(btl-lab pkce)" and eval "$(btl-lab state)", with CLIENT_ID set to its client ID.

Walkthrough

  1. Ask for photos.share before the client has it. The browser lands on the callback page with error=invalid_scope.

GET$ISSUER/oauth/authorize?response_type=code&client_id=$CLIENT_ID&redirect_uri=https%3A%2F%2Fbeyondthelogin.dev%2Flab%2Fcallback%2F&scope=photos.read%20photos.share&code_challenge=$CHALLENGE&code_challenge_method=S256&state=$STATE Open in console
GET $ISSUER/oauth/authorize?response_type=code&client_id=$CLIENT_ID&redirect_uri=https%3A%2F%2Fbeyondthelogin.dev%2Flab%2Fcallback%2F&scope=photos.read%20photos.share&code_challenge=$CHALLENGE&code_challenge_method=S256&state=$STATE

Why it matters: an exclusive scope is granted to a client on purpose by an administrator, not by asking. An app that wants to share albums has to be reviewed first, which is the lesson's "deciding which apps people can approve."

  1. In OAuth > Clients, assign photos.share to lab-printer-app and set its consent mode to always. Save. Send the same request again and sign in as Ava. Read the consent screen: it names the app and lists each scope with its description.

Why it matters: the consent screen is the only place Ava sees what she is granting. Ask the lesson's questions: did she start this, is the app the one she expected, and does printing photos need permission to share albums?

  1. Choose to deny. The callback page shows error=access_denied.

Why it matters: refusing is a real outcome, recorded with Ava as the subject. In the lesson's consent phishing, nothing else about the sign-in looks wrong, so this decision is the defense.

  1. Send the request once more and approve. The callback page shows a code. Note it is the genuine sign-in page and Ava completed it with her usual method.

Why it matters: no credential was stolen and no page was faked. A grant approved this way keeps working after a password change until it is revoked, which is why approvals need the same care as sign-ins.

  1. Remove photos.share from lab-printer-app and save. Changing what a client may request revokes the tokens and remembered consent it received under the old settings.

Why it matters: scope minimization. If the printer does not need to share albums, it should not hold that permission, and removing it ends what was already granted.

  1. Check the device flow your tenant offers. It answers that device authorization is not implemented.

POST$ISSUER/oauth/device_authorization Open in console
POST $ISSUER/oauth/device_authorization
Content-Type: application/x-www-form-urlencoded

client_id=$CLIENT_ID&scope=photos.read

Why it matters: the lesson's device code phishing needs a device flow to exist. Where nobody needs device sign-in, not offering it is the strongest setting.

  1. Review grants by event. In Audit, source Protocol activity, filter succeeded and list the oauth.authorize events with code_issued: which client, which user, and when.

Why it matters: approvals accumulate. Without a grant inventory, the Audit history is your only list of who approved which app.

Break it

  1. Set lab-printer-app's consent mode to skip and save. Run the flow as Ava: no consent screen appears, and the code arrives at once. Skipping consent suits first-party apps the organization runs itself, never a third-party app.

Restore: set the consent mode back to remember (or always) and save.

Check your work

  • Check my progress confirms the refused scope, the client change, the declined consent, the approval and the scope removal.

  • In Audit, source OAuth management, the two tenant.oauth.clients.update events show who changed the client.

  • Your notes answer the lesson's four approval questions for the screen Ava saw.

Cleanup

  1. Confirm lab-printer-app no longer has photos.share and its consent mode is remember.

  2. Keep photos.share as a scope; later labs may assign it again.

Missing infrastructure

  • G40: there is no per-user list of app grants with scopes and last use, no per-grant revoke, no tenant-wide app block, and no rule that sends sensitive scopes to an administrator for approval. Once it exists, the lab will set photos.share to need administrator approval, have Ava request it, approve it as Tenant Admin, and then block the app tenant-wide.

  • G53: the consent screen shows the client's name and scopes, but no logo, publisher or policy links, so there is no publisher to verify. Once it exists, the lab will add display metadata and compare the screens.

  • G5: device authorization is not implemented, so device approval screens cannot be reviewed. Once it exists, the lab will start a device request for lab-printer-app and read how the approval screen names the device.

  • G3: there is no sample photo API that enforces photos.share, so the effect of withdrawing the scope is seen at the tenant, not at an API. Once it exists, the lab will call the share endpoint before and after removal.

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