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.
Sign in to start this lab and check your progress. Log in or create an account.
The tool gets tokens through the browser instead
Recorded as
oauth.tokensucceeded forlab-printer-appabout[email protected].Offer a second sign-in step
Recorded as
tenant.authentication.updatesucceeded.Ava enrolls an authenticator app
Recorded as
account.enrollsucceeded about[email protected].The browser flow asks for the second step
Recorded as
oauth.authorizesucceeded (second_step_required) forlab-printer-app.Ava completes the second step on the tenant's page
Recorded as
account.second_stepsucceeded (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
Set
ISSUER,APP_IDforlab-printer-app, andenc. You need an authenticator app on your phone for step 5.Press Start on this page.
Walkthrough
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_IDThe answer is 400 with {"error":"unsupported_grant_type","error_description":"This authorization server supports the authorization_code, refresh_token and client_credentials grants."}.
Find the refusal. Logs has
oauth.tokenrejectedunsupported_grant_typewith 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'sgrant_types_supportedomits 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.
The replacement for the lesson's
photos-cli: treatlab-printer-appas the tool. Runbtl-lab callback --port 8765in 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.
Decode the ID token:
btl-lab decode "$ID_TOKEN"showsamr: ["pwd"], a password sign-in.
Stronger sign-in that the tool did not have to learn.
Open Authentication, set TOTP to Optional with a second step for enrolled users, and save.
Sign in to
$ISSUER/account/securityas Ava and enroll TOTP with your authenticator app.Run step 3 again. After the password, the tenant asks for a TOTP code. Enter it, approve, and exchange.
btl-lab decodeon the new ID token showsamrincludingotpandmfa.
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
Step 1 is the refusal. Optionally repeat it with
lab-printer's credentials in a Basic header: stillunsupported_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
As Ava, remove the TOTP method at
$ISSUER/account/security, or reset her methods from Users > Ava Archer.In Authentication, set TOTP back to Off and save.