Skip to content

OAuth 2.0

OAuth 2.0 is an authorization framework that allows a client application to obtain limited access to a resource on behalf of a user, without the client ever handling the user’s credentials.

Defined in RFC 6749, OAuth 2.0 is about delegated authorization, not authentication (authentication is layered on via OpenID Connect).

Core Problem OAuth Solves

Without OAuth:

  • App asks for username/password.
  • App stores credentials.
  • Huge security risk.
  • No granular access control.
  • No revocation per app.

With OAuth:

  • User authenticates with trusted Identity Provider (IdP).
  • IdP issues a token to the client.
  • Client uses token to access APIs.
  • Credentials are never shared.

This enables:

  • Third-party integrations
  • Mobile + SPA architectures
  • API ecosystems
  • Enterprise SSO environments

Core Roles in OAuth

OAuth defines four roles:

Role Description
Resource Owner The user
Client The application requesting access
Authorization Server Issues tokens (IdP)
Resource Server API that validates tokens

In Azure AD terms:

  • Resource Owner → User
  • Client → Web app / SPA / mobile app
  • Authorization Server → Azure AD
  • Resource Server → Your API

Tokens in OAuth

OAuth itself does not mandate token format.

Common tokens:

  • Access Token → Used to call APIs
  • Refresh Token → Used to obtain new access tokens

Access tokens may be:

  • JWT (self-contained)
  • Opaque (reference token requiring introspection)

OAuth doesn’t require JWT — that’s an implementation choice.

Authorization Grant Types (Flows)

OAuth 2.0 defines several flows for different scenarios.

Authorization Code Flow (Most Important)

Used by:

  • Server-side web apps
  • SPAs (with PKCE)
  • Mobile apps

High-level flow

  1. Client redirects user to Authorization Server.
  2. User authenticates.
  3. Server returns an authorization code.
  4. Client exchanges code for access token.
  5. Client calls API with access token.

This keeps tokens off the browser (for confidential clients).

Authorization Code + PKCE (Modern Standard)

PKCE = Proof Key for Code Exchange.

Required for:

  • SPAs
  • Mobile apps
  • Public clients

Prevents interception attacks by binding the authorization code to a cryptographic proof.

Today, Authorization Code + PKCE is the recommended default flow.

Client Credentials Flow

Used for:

  • Service-to-service communication
  • Backend jobs
  • Daemons

No user involved.

Client authenticates using:

  • Client ID + secret
  • Or certificate

Token represents the application itself.

Device Code Flow

Used for:

  • TVs
  • IoT
  • CLI tools

User authorizes on a separate device.

Deprecated Flows

  • Resource Owner Password Credentials (ROPC)
  • Implicit Flow

These are now discouraged for security reasons.

OAuth introduces scopes — granular permissions.

Example:

read:orders
write:orders
read:profile

User consents to specific scopes.

Access token contains granted scopes.

API enforces based on scope claims.

This enables:

  • Principle of least privilege
  • Third-party integrations with limited access

What OAuth Is NOT

OAuth is NOT:

  • An authentication protocol (that’s OpenID Connect)
  • A user session mechanism
  • A replacement for authorization logic inside your API

OAuth answers:

“Can this client access this resource?”

It does NOT answer:

“Who is the user?” (OIDC does)

OAuth vs OpenID Connect (Critical Distinction)

OAuth = Authorization OIDC = Authentication layer on top of OAuth

When you log in with Microsoft / Google:

  • OAuth flow runs
  • OIDC adds an ID Token (JWT)
  • ID Token contains identity claims

In enterprise systems, you almost always use OAuth + OIDC together.

High-Level Architecture View

In a microservices / API environment:

User
  ↓
Client App
  ↓
Authorization Server (Azure AD, Auth0, etc.)
  ↓
Access Token
  ↓
API Gateway
  ↓
Microservices

Best practice:

  • Validate tokens at API gateway boundary
  • Propagate identity via claims
  • Avoid passing raw tokens between internal services
  • Use Client Credentials for service-to-service auth

Security Model Summary

OAuth relies on:

  • TLS (HTTPS mandatory)
  • Short-lived access tokens
  • Refresh tokens stored securely
  • Token validation (issuer, audience, expiry)
  • Scope enforcement
  • PKCE for public clients

Common enterprise misconfigurations:

  • Long-lived tokens
  • Overly broad scopes
  • Skipping audience validation
  • Using ROPC flow
  • Storing tokens in localStorage (SPA)

Practical .NET Context

Typical ASP.NET Core setup:

builder.Services
    .AddAuthentication("Bearer")
    .AddJwtBearer("Bearer", options =>
    {
        options.Authority = "https://login.microsoftonline.com/{tenant}";
        options.Audience = "api://orders-api";
    });

This integrates OAuth-issued tokens into the middleware pipeline.

For service-to-service:

ConfidentialClientApplicationBuilder
    .Create(clientId)
    .WithClientSecret(secret)
    .Build()
    .AcquireTokenForClient(scopes)

Conceptual Summary

OAuth 2.0 is fundamentally about:

  • Delegating access
  • Avoiding credential sharing
  • Issuing time-bound, scoped tokens
  • Separating authentication from resource access

It is the foundation of:

  • API security
  • Modern SSO
  • Cloud identity
  • Zero-trust architectures