Part 4: Tokens and Token Management

The Token That Broke Production

Three months into my first major project, our API starting timing out. Users couldn't log in. After hours of panic debugging, I discovered the issue: every token validation was making a network call to MS Entra to fetch the JWKS. Under load, this choked our system.

The fix? Cache the JWKS. It took 10 minutes to implement and saved us thousands in infrastructure costs. Understanding tokens isn't optionalβ€”it's essential.

The Three Token Types

MS Entra issues three types of tokens, each serving a different purpose:

1. Access Tokens

Purpose: Call APIs Lifetime: Short (typically 1 hour) Format: JWT (JSON Web Token) Opacity: Treat as opaque (don't decode unless you're validating)

// Access token example (decoded for illustration)
{
  "aud": "api://payment-api",              // Audience: who can use this token
  "iss": "https://login.microsoftonline.com/{tenant}/v2.0",  // Issuer
  "iat": 1708185600,                        // Issued at
  "nbf": 1708185600,                        // Not before
  "exp": 1708189200,                        // Expires (1 hour later)
  "sub": "user-object-id",                  // Subject: user ID
  "oid": "user-object-id",                  // Object ID (same as sub in v2)
  "preferred_username": "[email protected]",
  "scp": "Payments.Read Payments.Write",    // Scopes granted
  "appid": "frontend-client-id",            // Application that requested token
  "ver": "2.0"                              // Token version
}

2. ID Tokens

Purpose: Identify the user Lifetime: Short (1 hour) Format: JWT Use: Client-side, for showing user info

3. Refresh Tokens

Purpose: Get new access tokens without user interaction Lifetime: Long (typically 90 days, can be revoked) Format: Opaque random string (not JWT) Security: Store securely, never log

JWT Structure Deep Dive

JWTs have three parts separated by dots:

The kid (key ID) is crucialβ€”it tells you which public key to use for verification.

Payload (Claims)

Signature

Token Validation

Critical: Always validate tokens. Never trust decoded data without verification.

Validation Checklist

Manual Validation Example

Using Microsoft Libraries

Instead of manual validation, use official libraries:

JWKS (JSON Web Key Set)

JWKS is where MS Entra publishes its public keys for token verification.

JWKS Endpoint

JWKS Response

Caching JWKS

Problem: Fetching JWKS on every request kills performance

Solution: Cache aggressively

Key Rotation

MS Entra rotates signing keys periodically (usually every 6 weeks).

What this means:

  • JWKS contains multiple keys

  • Old tokens signed with old keys remain valid

  • Always fetch current JWKS if kid not found

Handling rotation:

Token Lifetimes

Understanding and managing token lifetimes is critical.

Default Lifetimes

Configuring Lifetimes

Token Lifetime Policies (PowerShell)

Refresh Token Behavior

Access Token vs ID Token: When to Use What

This confuses many developers. Here's the rule:

Access Token

Use for: Calling APIs Contains: Audience (aud) is the API Validate where: Backend API

ID Token

Use for: Displaying user info in UI Contains: User identity claims Validate where: Frontend (but don't trust for authorization)

Token Storage

Where you store tokens matters for security.

Frontend Storage

Security considerations:

  • βœ… Use localStorage for convenience (persists across tabs)

  • βœ… Use sessionStorage for higher security (clears on close)

  • ❌ Never store in cookies (CSRF risk)

  • ❌ Never store in URL/querystring

  • ❌ Never log tokens

Backend Storage

Token Claims and Customization

You can customize what appears in tokens.

Optional Claims

App Roles

Define roles in your app manifest:

Tokens will include:

Groups Claims

Common Pitfalls

Pitfall 1: Not Caching JWKS

Pitfall 2: Trusting Decoded Tokens

Pitfall 3: Logging Tokens

Pitfall 4: Wrong Token for Purpose

Key Takeaways

  1. Three Token Types: Access (call APIs), ID (user identity), Refresh (get new tokens)

  2. Always Validate: Signature, issuer, audience, expiration

  3. Cache JWKS: Huge performance improvement

  4. Handle Key Rotation: Clear cache and retry if kid not found

  5. Store Securely: Memory/encrypted DB, never plain text

  6. Right Token for Job: Access token for APIs, ID token for UI

  7. Never Log Tokens: Security critical

What's Next

In Part 5: API Permissions and Consent, we'll explore:

  • Delegated vs application permissions

  • Microsoft Graph permissions

  • Admin consent vs user consent

  • Permission scopes and least privilege

  • Consent frameworks

  • Pre-authorization patterns

Understanding tokens is foundational. Next, we'll see how permissions control what those tokens can do.


Previous: Part 3: Authentication Protocols and Flows Next: Part 5: API Permissions and Consent Back to Series Overview

Last updated