Identity & Access Management

OAuth 2.0 & OpenID Connect

OAuth 2.0 is a delegated authorization protocol — it lets a client obtain limited access to a resource on a user's behalf — not an authentication protocol; OpenID Connect (OIDC) layers a verified identity (the ID token) on top of it to answer who the user actually is.
  • OAuth 2.0 grants a client an access token scoped to act on a user's behalf against an API — it says nothing, by itself, about who the user is
  • OpenID Connect (OIDC) is a thin identity layer on OAuth 2.0 that adds the ID token (a JWT describing the authenticated user) — this is what actually gives the client proof of identity
  • Authorization Code + PKCE is the only grant recommended for modern clients (SPAs, mobile apps, server apps); the Implicit grant (tokens in the URL fragment) and Resource Owner Password Credentials grant (client handles raw credentials) are deprecated for leaking tokens and passwords
  • Three distinct tokens: the authorization code (short-lived, single-use, exchanged at the token endpoint), the access token (presented to APIs), and the ID token (a JWT for the client to read) — the ID token is not a bearer credential and should never be sent to an API
  • PKCE adds a code_verifier/code_challenge pair generated by the client: the authorization server only releases tokens to whoever holds the original verifier, closing the interception gap for public clients that cannot keep a secret
  • Scope narrows what a token can do; `aud` (audience) narrows who may accept it — tightening both limits how much damage a leaked token can cause
Authorization Code + PKCE flow
The code_verifier never leaves the client until the final exchange, so an intercepted redirect alone can't be used to claim the tokens
OAuth 2.0 grant types
Grant typeUse caseStatus
Authorization Code + PKCESPAs, mobile apps, server-side web appsRecommended for all modern clients
Client CredentialsService-to-service, no user in the loopRecommended for machine-to-machine
Refresh TokenSilently obtaining new access tokensRecommended, paired with rotation
ImplicitLegacy SPAs (token returned directly in the redirect)Deprecated — leaks tokens via browser history/referrer
Resource Owner Password CredentialsLegacy first-party trusted appsDeprecated — exposes raw credentials to the client
Validating a JWT access token's signature, audience, and expiry
JwtParser parser = Jwts.parserBuilder()
    .setSigningKey(issuerPublicKey)   // RS256/ES256: verify with the issuer's public key
    .build();

Jws<Claims> parsed;
try {
    parsed = parser.parseClaimsJws(accessToken);
} catch (JwtException e) {
    throw new UnauthorizedException("invalid signature or malformed token");
}

Claims claims = parsed.getBody();
if (!claims.getAudience().equals(expectedAudience)) {
    throw new UnauthorizedException("token not intended for this API");
}
if (claims.getExpiration().before(new Date())) {
    throw new UnauthorizedException("token expired");
}
Signature, audience, and expiry are the three checks every resource server must perform — skipping any one accepts a token that was never meant for it
Sources
  • OAuth 2 in ActionCh. 4 — The Authorization Code Grant
  • System Design: The Big Archive (2024 ed.)Protocols — OAuth 2.0 and OpenID Connect Explained