OAuth & Federated Identity
OAuth2/OIDC/SAML flows and token security — the authorization-code flow, PKCE, state, redirect_uri validation, id_token, JWT verification, algorithm confusion and SAML signature wrapping.
12 questions
JuniorTheoryVery commonWhat is the OAuth2 authorization-code flow, and why does a code ride the redirect?
What is the OAuth2 authorization-code flow, and why does a code ride the redirect?
The user authenticates at the authorization server, which redirects back to the client with a short-lived code. The client exchanges that code for tokens on a direct server call. Only the code crosses the redirect, since redirect URLs reach logs.
Common mistakes
- ✗Thinking the access token itself is returned in the redirect
- ✗Treating the authorization code as a durable credential worth storing
- ✗Assuming the client sends the user password to the authorization server
Follow-up questions
- →Why must an authorization code be single-use and short-lived?
- →What does the client authenticate itself with at the token endpoint?
JuniorTheoryVery commonWhat does the state parameter protect an OAuth2 redirect against, and how?
What does the state parameter protect an OAuth2 redirect against, and how?
state is an unguessable value the client generates, binds to the user session and sends on the authorization request. The server echoes it on the redirect, and a callback whose state does not match is rejected as forged.
Common mistakes
- ✗Generating
statebut never comparing it when the callback arrives - ✗Storing
stateunbound to the session, so any user callback validates - ✗Confusing
statewith the OIDCnonce, which binds theid_tokeninstead
Follow-up questions
- →How does
statediffer from thenoncein the identity layerOpenID Connect? - →Where should
statelive so a second browser tab cannot break the check?
MiddleTheoryVery commonWhy must redirect_uri be matched exactly, and what does a loose match allow?
Why must redirect_uri be matched exactly, and what does a loose match allow?
The authorization server compares the requested redirect_uri against a pre-registered value string for string — scheme, host, port and path. Prefix or wildcard matching lets a lookalike URL resolve elsewhere, and the code is delivered there.
Common mistakes
- ✗Allowing wildcards or prefix matches on the registered URI
- ✗Leaving an open redirect on an allowlisted host, which forwards the code onward
- ✗Assuming a single-use code is harmless wherever it is delivered
Follow-up questions
- →Why does an open redirect on an allowlisted host defeat the allowlist?
- →How does PKCE limit the damage when a code does end up in the wrong place?
JuniorTheoryCommonWhat are the three parts of a JWT, and what must a server do before trusting claims?
What are the three parts of a JWT, and what must a server do before trusting claims?
A JWT is header, payload and signature, base64url-encoded and joined by dots. Header and payload are encoded, not encrypted, so any holder reads them. Before trusting a claim the server verifies the signature, then checks iss, aud and exp.
Common mistakes
- ✗Believing the payload is encrypted, and putting secrets into claims
- ✗Decoding a token and trusting claims without verifying the signature
- ✗Verifying the signature but never validating
iss,audandexp
Follow-up questions
- →Why does revoking a JWT need short lifetimes or a denylist?
- →Which key verifies an asymmetrically signed token, and where does it come from?
MiddleTheoryCommonWhat does Proof Key for Code Exchange (PKCE) add, and why do public clients need it?
What does Proof Key for Code Exchange (PKCE) add, and why do public clients need it?
The client makes a random code_verifier, sends its hash as code_challenge on the authorization request, then presents the verifier at the token endpoint. The code is redeemed only when they match, binding it to whoever started the flow.
Common mistakes
- ✗Assuming PKCE replaces
state, when the two solve different problems - ✗Choosing the
plainchallenge method instead ofS256 - ✗Reusing one
code_verifieracross authorization requests
Follow-up questions
- →Why is
S256preferred over theplainchallenge method? - →Does PKCE remove the need for exact
redirect_urimatching?
MiddleTheoryCommonIn OpenID Connect, how do the id_token and the access_token differ in audience?
In OpenID Connect, how do the id_token and the access_token differ in audience?
The id_token is authentication output addressed to the client — its aud is the client id and it states who signed in. The access_token is authorization output addressed to the API. OAuth2 grants access; OIDC says who the user is.
Common mistakes
- ✗Sending the
id_tokento the API as a bearer credential - ✗Treating a valid
access_tokenas proof of who the user is - ✗Trusting an unverified
emailclaim to identify an existing account
Follow-up questions
- →Why is an unverified
emailclaim unsafe as an account key? - →What breaks if an API starts accepting an
id_tokenas a bearer token?
SeniorTheoryCommonWhat is JWT algorithm confusion, and how does pinning the algorithm prevent it?
What is JWT algorithm confusion, and how does pinning the algorithm prevent it?
A verifier that takes its algorithm from the token own alg header can be pushed from an asymmetric setup to a symmetric one, where the public key — which is not secret — becomes the HMAC key. Pin the expected algorithm and key per issuer.
Common mistakes
- ✗Letting the library choose its algorithm from the token header
- ✗Treating a public key as a secret because it is used for verification
- ✗Fetching a key from a
kidorjkuvalue supplied inside the token
Follow-up questions
- →Why is a
kidorjkuvalue taken from the token an untrusted input? - →How do short lifetimes and a denylist together bound revocation delay?
MiddleDebuggingOccasionalA gateway log shows a token with alg set to none being accepted — find and fix the flaw
A gateway log shows a token with alg set to none being accepted — find and fix the flaw
The gateway decodes rather than verifies, so a token declaring no algorithm carries no signature yet is trusted. Verify with a pinned algorithm and the issuer published key, reject any other alg, and read claims only after that passes.
Common mistakes
- ✗Reading the
algheader to decide how the token should be verified - ✗Calling a decode helper and assuming it also checks the signature
- ✗Trusting a
roleclaim taken from a token that was never verified
Follow-up questions
- →Why must the accepted algorithm be pinned by the server rather than by the token?
- →What would you add to detect further unverified-token acceptance in these logs?
MiddleTheoryOccasionalWhen does a service use client credentials rather than a user-delegated flow?
When does a service use client credentials rather than a user-delegated flow?
Client credentials fit a background service acting as itself — no user, no redirect, no consent. The client authenticates and gets a token carrying its own identity. Scopes say what it may do, so grant only the narrowest set the job needs.
Common mistakes
- ✗Using client credentials to act on one specific user behalf
- ✗Issuing one broad scope set to every service for convenience
- ✗Confusing scopes, which limit actions, with claims, which describe identity
Follow-up questions
- →Why does a machine token still need a short lifetime?
- →How would you rotate a client secret without downtime?
MiddleTheoryOccasionalWhich OAuth2 grant fits which client, and why were implicit and password grants dropped?
Which OAuth2 grant fits which client, and why were implicit and password grants dropped?
Browser, mobile and server-side apps acting for a user all use authorization code with PKCE; callers with no user use client credentials. Implicit returned tokens in the URL and the password grant took real user credentials, so both are retired.
Common mistakes
- ✗Still choosing implicit for single-page apps
- ✗Using the password grant to avoid a redirect in a native app
- ✗Keeping refresh tokens indefinitely with no rotation or reuse detection
Follow-up questions
- →What does refresh-token rotation with reuse detection accomplish?
- →Why is a token placed in a URL fragment hard to keep out of logs?
MiddleTheoryOccasionalWhat does the OIDC nonce bind, and which id_token claims must a client validate?
What does the OIDC nonce bind, and which id_token claims must a client validate?
The client puts a random nonce in the authorization request and demands the same value inside the id_token, binding it to this login and blocking replay. It must also verify the signature and check iss, exp and aud.
Common mistakes
- ✗Verifying the signature but skipping the
audcomparison - ✗Accepting an
id_tokenwhosenoncewas never compared to the stored one - ✗Trusting the
issvalue printed in the token instead of pinning the expected issuer
Follow-up questions
- →Why does
nonceprotect theid_tokenwhilestateprotects the callback? - →How does a client learn which published key verified a given
id_token?
SeniorTheoryOccasionalHow do tokens leak through referrers and logs, and what does audience restriction fix?
How do tokens leak through referrers and logs, and what does audience restriction fix?
Anything placed in a URL — a token in a fragment or query — reaches browser history, proxy logs and Referer headers, so tokens belong in headers. Audience restriction is separate: a token names its API, so another server rejects it.
Common mistakes
- ✗Logging full request URLs that still contain tokens or authorization codes
- ✗Assuming a valid signature also means the token was meant for this API
- ✗Accepting an identity-provider-initiated login with no flow the client started
Follow-up questions
- →Why is an identity-provider-initiated single sign-on login weaker than a client-initiated one?
- →How does a client avoid confusing responses arriving from two configured issuers?