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

OAUTH 2.0 · LAB

Meet unsupported_grant_type, then sign in the browser way with a second step

See the token endpoint refuse a password grant, replace it with the loopback code flow a command-line tool should use, and add a second sign-in step that only the browser flow can carry.

ReadyUses your lab tenant

The lesson

Builds on: Public and confidential clients.

New to the labs? Start with the lab toolkit and the shared cast and names every lab uses.

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. The tool gets tokens through the browser instead

    Recorded as oauth.token succeeded for lab-printer-app about [email protected].

  2. Offer a second sign-in step

    Recorded as tenant.authentication.update succeeded.

  3. Ava enrolls an authenticator app

    Recorded as account.enroll succeeded about [email protected].

  4. The browser flow asks for the second step

    Recorded as oauth.authorize succeeded (second_step_required) for lab-printer-app.

  5. Ava completes the second step on the tenant's page

    Recorded as account.second_step succeeded (second_step_completed) about [email protected].

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. Set ISSUER, APP_ID for lab-printer-app, and enc. You need an authenticator app on your phone for step 5.

  2. Press Start on this page.

Walkthrough

  1. Send the lesson's request with a placeholder password. Never put a real password in a lab request.

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

grant_type=password&username=ava%40example.com&password=demo-password-not-real&scope=photos.read&client_id=$APP_ID

The answer is 400 with {"error":"unsupported_grant_type","error_description":"This authorization server supports the authorization_code, refresh_token and client_credentials grants."}.

  1. Find the refusal. Logs has oauth.token rejected unsupported_grant_type with status 400. Audit has no entry, because the request was refused before any client was identified. Flow policy lists Password under "Not yet available", and discovery's grant_types_supported omits it.

Why it matters: RFC 9700 says the password grant must not be used. A server that never offers it cannot leave it enabled for tests and then for everything else.

  1. The replacement for the lesson's photos-cli: treat lab-printer-app as the tool. Run btl-lab callback --port 8765 in a second terminal, then open the authorization request in your system browser.

eval "$(btl-lab pkce)"; eval "$(btl-lab state)"
echo "$ISSUER/oauth/authorize?response_type=code&client_id=$APP_ID&redirect_uri=$(enc http://127.0.0.1:8765/callback)&scope=$(enc 'openid photos.read')&state=$STATE&code_challenge=$CHALLENGE&code_challenge_method=S256"

Sign in as Ava and approve. Copy the code from the listener and exchange it with the verifier only.

read -r CODE
RESPONSE=$(curl -s -d grant_type=authorization_code -d "code=$CODE" --data-urlencode "redirect_uri=http://127.0.0.1:8765/callback" \
  -d "code_verifier=$VERIFIER" -d "client_id=$APP_ID" "$ISSUER/oauth/token")
ID_TOKEN=$(echo "$RESPONSE" | jq -r .id_token)

Why it matters: Ava typed her password only on the tenant's own page, and the approval screen showed which application was asking. The tool never saw the password.

  1. Decode the ID token: btl-lab decode "$ID_TOKEN" shows amr: ["pwd"], a password sign-in.

  1. Stronger sign-in that the tool did not have to learn.

    1. Open Authentication, set TOTP to Optional with a second step for enrolled users, and save.

    2. Sign in to $ISSUER/account/security as Ava and enroll TOTP with your authenticator app.

    3. Run step 3 again. After the password, the tenant asks for a TOTP code. Enter it, approve, and exchange.

    4. btl-lab decode on the new ID token shows amr including otp and mfa.

Why it matters: a client that only knows how to post a username and password could never take part in this step. The browser flow carried it without any change to the tool.

Break it

  1. Step 1 is the refusal. Optionally repeat it with lab-printer's credentials in a Basic header: still unsupported_grant_type, because the grant type is checked before the client.

Check your work

Press Check my progress. Compare amr in the two ID tokens from steps 4 and 5.

Cleanup

  1. As Ava, remove the TOTP method at $ISSUER/account/security, or reset her methods from Users > Ava Archer.

  2. In Authentication, set TOTP back to Off and save.

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