The OAuth2 component that authenticates users, obtains authorization, and issues access tokens to clients after successful authentication.
OAuth2 Authorization Server (AS) authenticates the resource owner, obtains their consent, and issues authorization codes and access tokens to clients. It sits at the trust boundary of the whole protocol: every other party relies on the AS to only hand a code or token to the client that legitimately requested it, so most high-impact OAuth2 bugs are AS bugs.
// Authorization endpoint (front channel, browser)
GET /authorize
?response_type=code
&client_id=...
&redirect_uri=...
&scope=...
&state=...
&code_challenge=...
&code_challenge_method=S256
// Token endpoint (back channel, client-to-AS)
POST /token
grant_type=authorization_code
&code=...
&redirect_uri=...
&client_id=...
&client_secret=...
&code_verifier=...
The authorization code is delivered to whatever redirect_uri the AS accepts, so a matching bug hands the code to the attacker. The AS must compare the requested redirect_uri against the values registered for that client_id using exact string equality.
// Registered: https://app.com/callback
// Prefix / substring match lets these through:
redirect_uri=https://app.com.evil.com/callback
redirect_uri=https://app.com/callback/../../oauth?next=https://evil.com
redirect_uri=https://app.com@evil.com/callback
// Open redirect on a registered URI turns into token theft:
redirect_uri=https://app.com/redirect?to=https://evil.com
Even with exact matching, an open redirect anywhere under a registered origin re-exposes the code, so the AS should refuse wildcard and pattern registration. See OAuth2 Redirect URI for the client-side view.
At the token endpoint the AS must confirm the caller is the same client the code was issued to, not just any client that presents the code:
client_id it was issued for, and reject exchange by a different client.redirect_uri from the authorization request and require the same value at exchange.code_challenge with the code and verify SHA256(code_verifier) matches at exchange (see PKCE).If an attacker steals a victim's code (leaked referrer, mix-up, malicious app) they can splice it into their own session. Detecting a code that has already been redeemed and revoking the derived tokens limits replay, and PKCE stops injection outright: the injected code is worthless without the verifier that only the original client holds.
An attacker who can tamper with the front-channel request may strip code_challenge, or switch code_challenge_method from S256 to plain so the challenge equals the verifier. The AS must remember whether a code was issued with PKCE and refuse to exchange it without a valid verifier, and should reject plain for clients configured to use S256.
When a client supports multiple authorization servers, an attacker acting as a malicious AS can trick the client into sending a code issued by the honest AS to the attacker's token endpoint, or vice versa. Defenses live partly in the AS: return the iss (issuer) identifier in the authorization response so the client can confirm which AS answered, and bind each code to the client and redirect URI so a code cannot be redeemed out of context.