OAuth2 and OIDC Deep Dive: Real Flow Breakdown
Introduction
OAuth2 is an authorization framework, while OpenID Connect (OIDC) layers authentication on top of OAuth2. A correct implementation requires understanding each protocol artifact, how tokens are issued, and where validation occurs. This deep dive walks through the real flow sequence and the validation decisions that matter in production systems.
OAuth2 Roles and Artifacts
OAuth2 defines four core roles and several artifacts. Each artifact has a distinct lifecycle and security boundary.
- Resource owner: The end user or system that grants access.
- Client: The application requesting delegated access.
- Authorization server: Issues access and refresh tokens.
- Resource server: Validates access tokens and serves protected APIs.
- Artifacts: Authorization code, access token, refresh token, and (with OIDC) ID token.
Authorization Code Flow with PKCE
Authorization Code with PKCE is the modern baseline for browser and native applications. The real flow involves multiple checks on each hop.
- Client generates a high-entropy
code_verifierand derivedcode_challenge. - User authenticates on the authorization server, which stores
code_challengewith the authorization code. - Client exchanges the code for tokens by presenting the
code_verifier. - Authorization server validates the code, verifies the
code_verifier, and issues tokens. - Resource server validates access tokens on every call.
OIDC Layer: ID Token Validation
The ID token is a signed JWT that represents the authentication event. Validation must be performed by the client that receives the token.
- Issuer validation: Must match the expected OIDC issuer.
- Audience validation: Must contain the client ID.
- Signature validation: Use the current signing keys from the JWKS endpoint.
- Nonce validation: Matches the value stored before the authorization request.
- Temporal validation: Verify
exp,iat, and clock skew. - Authenticated session: Confirm
auth_timefor max-age or step-up policies.
Refresh Tokens, Rotation, and Token Exchange
Refresh tokens provide long-lived access but require strict handling.
- Use refresh token rotation to invalidate old refresh tokens.
- Bind refresh tokens to device or client with sender-constrained tokens when possible.
- Apply token exchange only when a trusted backend must call another API on behalf of a user.
C# Example: Validating an ID Token
The following C# example uses JwtSecurityTokenHandler to validate an ID token against the issuer, audience, and signing keys.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
using Microsoft.IdentityModel.Protocols;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
var issuer = "https://login.example.com";
var clientId = "web-client";
var metadataAddress = $"{issuer}/.well-known/openid-configuration";
var configurationManager = new ConfigurationManager<OpenIdConnectConfiguration>(
metadataAddress,
new OpenIdConnectConfigurationRetriever());
var oidcConfig = await configurationManager.GetConfigurationAsync();
var tokenHandler = new JwtSecurityTokenHandler();
var parameters = new TokenValidationParameters
{
ValidIssuer = issuer,
ValidAudience = clientId,
IssuerSigningKeys = oidcConfig.SigningKeys,
RequireSignedTokens = true,
ValidateLifetime = true,
ClockSkew = TimeSpan.FromMinutes(2)
};
var principal = tokenHandler.ValidateToken(idToken, parameters, out var validatedToken);
Hardening Checklist
- Enforce PKCE even for confidential clients.
- Store authorization codes server-side and make them single-use.
- Use short access token lifetimes with rotation for refresh tokens.
- Validate token
azpwhen using multiple audiences. - Prefer sender-constrained tokens for high-risk APIs.
Conclusion
OAuth2 and OIDC succeed when every artifact is validated in the correct boundary. By treating the authorization server, client, and resource server as distinct trust zones, you avoid the common mistakes that lead to token replay, misissued tokens, and excessive privilege.