Step-Up Authentication: Progressive Security for Sensitive Edge Operations
Not every API request deserves the same level of scrutiny. When a user browses a product catalog behind a CDN, a simple session cookie suffices. When that same user changes their payment method, transfers funds, or modifies account permissions, the system should demand stronger proof of identity — even though the user already logged in minutes ago. This is the core premise of step-up authentication: a progressive security model that escalates identity verification based on the sensitivity of the operation being attempted, rather than applying a single authentication level uniformly at the front door.
The challenge becomes significantly harder when your application runs behind a distributed CDN with hundreds of edge servers across dozens of points of presence. Traditional step-up authentication assumes a monolithic origin server that controls the full authentication lifecycle. In a CDN architecture, the edge node receiving the sensitive request may be thousands of miles from the identity provider, and the round-trip latency of redirecting to the origin for re-authentication undermines the very performance gains the CDN was deployed to provide. Building step-up authentication that works natively at the edge requires rethinking how authentication state is represented, propagated, and validated across a distributed infrastructure built on zero trust principles.
What Is Step-Up Authentication and Why It Matters for CDN Operations
Step-up authentication, also called progressive authentication or adaptive authentication, is a security pattern in which the system requires a user to provide additional identity verification when they attempt to access a resource or perform an operation that is classified as sensitive. The user begins with a baseline authentication level — typically a username and password, or a single-factor session — and the system "steps up" to a higher assurance level only when the risk warrants it.
Consider an online banking application. Checking the account balance requires only a standard login. Initiating a wire transfer to a new recipient triggers a step-up: the user must confirm with a biometric scan, hardware security key, or one-time passcode before the operation proceeds. The baseline session remains valid for low-risk actions; the step-up token grants temporary elevated access that expires after a short window.
This pattern exists because uniform high-security authentication creates friction that degrades user experience. Requiring a hardware key tap for every page load is impractical. But allowing every action to proceed with only a password is insecure. Step-up authentication provides a middle path: low friction for routine operations, high assurance for sensitive ones. The MFA architecture underlying step-up defines which factors are available and when they are triggered.
For CDN-delivered applications, step-up authentication introduces architectural complexity that does not exist in monolithic deployments. The edge node processing a sensitive request must be able to determine the current authentication level of the session, compare it against the required level for the requested resource, and either allow the request, challenge the user for additional factors, or redirect to the identity provider — all without introducing latency that defeats the purpose of edge delivery. This requires careful design of token-based authentication at the edge, where the token itself carries the authentication context needed for step-up decisions.
ACR and AMR Claims: The Language of Authentication Strength
Step-up authentication depends on a standardized way to express "how strongly was this user authenticated?" The OAuth 2.0 and OpenID Connect specifications define two JWT claims for this purpose: ACR (Authentication Context Class Reference) and AMR (Authentication Methods Reference).
| Metric | Edge Processing | Origin Processing | Improvement |
|---|---|---|---|
| Latency (p50) | 8–15 ms | 120–300 ms | 15–20x faster |
| Cache Hit Ratio | 85–95% | N/A | Reduces origin load |
| TLS Handshake | 1–5 ms (nearby PoP) | 50–150 ms | 10–30x faster |
| Bandwidth Cost | $0.01–0.04/GB | $0.05–0.12/GB | 3–5x cheaper |
| Availability | 99.99% (multi-PoP) | 99.9% (single DC) | 10x fewer outages |
Authentication Context Class Reference (ACR)
The ACR claim identifies the authentication context class that was satisfied during the authentication event. It represents the overall strength or assurance level of the authentication. Common ACR values include:
# ACR values (from low to high assurance)
acr: "urn:mace:incommon:iap:bronze" # Single factor (password only)
acr: "urn:mace:incommon:iap:silver" # Multi-factor (password + OTP)
acr: "urn:mace:incommon:iap:gold" # MFA with hardware token
acr: "urn:mace:incommon:iap:platinum" # MFA + identity proofing
# Custom ACR levels (common in enterprise deployments)
acr: "https://example.com/acr/basic" # Level 1: password
acr: "https://example.com/acr/mfa" # Level 2: password + TOTP/SMS
acr: "https://example.com/acr/phishing-resistant" # Level 3: FIDO2/WebAuthn
acr: "https://example.com/acr/verified" # Level 4: Level 3 + ID verification
When a client requests authentication, it can specify the minimum ACR level required using the acr_values parameter in the authorization request. The identity provider must satisfy at least the requested level, and the resulting ID token's acr claim indicates the level actually achieved.
Authentication Methods Reference (AMR)
While ACR describes the overall strength level, AMR lists the specific methods that were used during authentication. A single authentication event might use multiple methods, and the AMR claim captures all of them:
# AMR values in a JWT payload
{
"sub": "user-12345",
"acr": "urn:mace:incommon:iap:silver",
"amr": ["pwd", "otp"], # password + one-time password
"auth_time": 1727740800,
"iat": 1727740800,
"exp": 1727744400
}
# Common AMR values (RFC 8176)
# pwd - password authentication
# otp - one-time password (TOTP/HOTP)
# sms - SMS-based verification
# hwk - hardware key (FIDO U2F, FIDO2)
# swk - software key (authenticator app)
# fpt - fingerprint biometric
# face - facial recognition biometric
# pin - personal identification number
# mfa - generic multi-factor indicator
# wia - Windows integrated authentication
# kba - knowledge-based authentication
At the CDN edge, inspecting the AMR claim provides more granular control than ACR alone. An edge policy might require that the hwk method is present for admin API endpoints, regardless of the overall ACR level. This prevents a scenario where a compromised OTP satisfies the MFA ACR level but the endpoint specifically requires a phishing-resistant hardware key. The JWT security best practices for distributed systems apply directly here — every edge node must validate these claims cryptographically, not just parse them.
Risk-Based Authentication Escalation at the Proxy Layer
Static step-up policies — "this endpoint always requires MFA" — are a starting point, but real-world threats are contextual. A legitimate user accessing their account settings from their usual device, on their usual network, during business hours, presents far less risk than the same request arriving from an unfamiliar IP address in a different country at 3 AM. Risk-based authentication escalation evaluates contextual signals at the reverse proxy layer and adjusts the required authentication level dynamically.
The risk engine at the edge evaluates multiple signals available without origin contact:
- Client IP reputation: Cross-referenced against threat intelligence feeds and the CDN's own bot management data. IPs associated with proxy networks, VPNs, Tor exit nodes, or known attack infrastructure increase the risk score.
- Geolocation anomaly: If the user's session was established from New York and a request arrives from Singapore within an impossibly short time window, the risk score spikes — a pattern known as impossible travel.
- Device fingerprint consistency: The TLS client hello, User-Agent, Accept-Language headers, and other passive fingerprinting signals should remain consistent within a session. Significant changes suggest session hijacking.
- Request pattern analysis: Rapid sequential requests to multiple sensitive endpoints, or requests that follow the exact pattern of known attack playbooks, trigger escalation. The WAF layer feeds anomaly scores into the risk engine.
- Time since last authentication: The
auth_timeclaim in the JWT indicates when the user last actively authenticated. Sessions older than a configurable threshold (e.g., 30 minutes for high-risk actions) require re-authentication regardless of other signals.
# Risk scoring policy at CDN edge (pseudocode)
risk_policy:
signals:
- name: ip_reputation
source: threat_intel_feed
weight: 0.25
high_risk_threshold: score > 70
- name: geo_anomaly
source: session_geo_history
weight: 0.20
high_risk_threshold: distance_km > 5000 AND time_delta_hours < 2
- name: device_fingerprint
source: tls_ja3_hash + ua_string
weight: 0.15
high_risk_threshold: fingerprint != session.fingerprint
- name: auth_age
source: jwt.auth_time
weight: 0.20
high_risk_threshold: now - auth_time > 1800 # 30 minutes
- name: endpoint_sensitivity
source: route_config
weight: 0.20
levels: {read_profile: 0.2, update_email: 0.7, change_password: 0.9, delete_account: 1.0}
escalation_thresholds:
- score: 0.0 - 0.3 -> required_acr: "basic"
- score: 0.3 - 0.6 -> required_acr: "mfa"
- score: 0.6 - 0.8 -> required_acr: "phishing-resistant"
- score: 0.8 - 1.0 -> required_acr: "verified" + rate_limit: strict
This risk-based approach aligns with the zero trust security model: never trust implicitly, always verify based on context. The edge node computes the risk score in under a millisecond using locally cached threat data and session state, then compares the computed required ACR against the token's actual ACR. If the token meets or exceeds the requirement, the request passes. If not, the edge issues a step-up challenge proportional to the gap between the current and required levels.
Implementation Patterns: Edge Re-Authentication vs. Origin Redirect
When the edge determines that a step-up is required, two architectural patterns are available for executing the re-authentication. Each has distinct trade-offs for latency, security, and implementation complexity.
Pattern 1: Origin Redirect for Re-Authentication
The most straightforward pattern redirects the client to the central identity provider (IdP) for re-authentication. The edge node responds with an HTTP 302 or 307 redirect to the IdP's authorization endpoint, including the required acr_values parameter. The IdP challenges the user for the additional factor, issues a new token with the elevated ACR, and redirects back to the original resource.
# Edge node step-up response: origin redirect pattern
HTTP/1.1 302 Found
Location: https://auth.example.com/authorize
?response_type=code
&client_id=edge-service-001
&redirect_uri=https://cdn.example.com/auth/callback
&scope=openid profile
&acr_values=urn:mace:incommon:iap:silver
&prompt=login
&state=eyJvcmlnaW5hbF91cmwiOiIvYXBpL3NldHRpbmdzIn0
&nonce=a1b2c3d4e5f6
Cache-Control: no-store
X-Step-Up-Reason: insufficient_acr
The state parameter encodes the original request URL so the user is returned to their intended destination after re-authentication. The prompt=login parameter forces the IdP to perform a fresh authentication rather than reusing an existing SSO session. This pattern works well when the IdP is the authoritative source for all authentication methods, and when the redirect latency (typically 200 to 500 milliseconds plus user interaction time) is acceptable for the use case.
Pattern 2: Edge-Local Re-Authentication
For latency-sensitive operations, the edge node can present an authentication challenge directly without redirecting to the origin. This pattern works best with WebAuthn/FIDO2 authentication, where the passkey verification can happen at the edge using pre-distributed public keys.
# Edge-local step-up: WebAuthn challenge
# 1. Edge returns 401 with challenge parameters
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer
error="insufficient_user_authentication",
acr_values_required="https://example.com/acr/phishing-resistant",
max_age=300
Content-Type: application/json
{
"step_up": {
"challenge": "dGhpcyBpcyBhIHJhbmRvbSBjaGFsbGVuZ2U",
"rpId": "example.com",
"allowCredentials": [
{"type": "public-key", "id": "credential-id-abc123"}
],
"timeout": 60000,
"userVerification": "required"
}
}
# 2. Client performs WebAuthn ceremony and retries
POST /api/settings HTTP/1.1
Authorization: Bearer eyJhbGciOiJSUzI1NiJ9...
X-Step-Up-Assertion: eyJhdHRlc3RhdGlvbiI6Ii4uLiJ9
X-Step-Up-Challenge: dGhpcyBpcyBhIHJhbmRvbSBjaGFsbGVuZ2U
The edge node validates the WebAuthn assertion against the user's registered public key (cached at the edge from the credential store), mints a short-lived step-up token, and attaches it to the session. This eliminates the origin round-trip entirely for the re-authentication step. The origin protection layer still validates the step-up token when the request arrives, providing defense in depth.
The trade-off is complexity: distributing user credential public keys to edge nodes requires a secure synchronization mechanism, and key revocation must propagate quickly. Organizations using this pattern typically cache public keys with a TTL of 5 to 15 minutes and fall back to the origin redirect pattern if the cached key is missing or expired.
Session Binding and Step-Up Tokens in Distributed CDN
A step-up token that is not cryptographically bound to the session that earned it is a security vulnerability. An attacker who steals a step-up token from a legitimate user's network traffic (or from a cross-site scripting attack) can replay it in their own session to bypass re-authentication. In a distributed CDN, where any edge node might receive the replayed token, session binding must be verifiable without centralized state.
Three-Layer Token Binding
Production step-up implementations bind the elevated token to three contextual anchors:
# Step-up token payload (JWT)
{
"sub": "user-12345",
"iss": "https://auth.example.com",
"aud": "https://cdn.example.com",
"iat": 1727740800,
"exp": 1727741700, # 15-minute TTL
"acr": "urn:mace:incommon:iap:silver",
"amr": ["pwd", "otp"],
# Session binding claims
"sid": "sha256:a1b2c3d4...", # Hash of session ID
"cnf": { # Confirmation claim (RFC 7800)
"jkt": "sha256:x5t_fingerprint_of_client_cert"
},
"client_ip_prefix": "203.0.113.0/24", # /24 prefix, not exact IP
"tls_binding": "sha256:ja3_hash", # TLS fingerprint
# Step-up scope
"step_up_scope": ["account:write", "payment:initiate"],
"step_up_max_uses": 5 # Limit token to N operations
}
The sid claim binds the step-up token to a specific session. The edge node computes the SHA-256 hash of the session cookie presented with the request and compares it against the sid claim. A mismatch means the token was transplanted to a different session and must be rejected. This is the same principle that underpins mutual TLS certificate binding, applied to session cookies.
The client_ip_prefix claim uses a /24 prefix rather than an exact IP to accommodate legitimate IP changes within a network (NAT traversal, mobile carrier IP rotation) while still detecting cross-network replay. The tls_binding claim captures the JA3 or JA4 fingerprint of the TLS handshake, which changes when the client software or TLS configuration changes — a signal of potential session hijacking.
Token Propagation via Signed Cookies
In a distributed CDN, the step-up token must be accessible to any edge node that might serve subsequent requests for the elevated session. Two approaches exist:
- Signed cookie: The step-up token is set as a cookie with
Secure; HttpOnly; SameSite=Strictattributes. Any edge node serving the domain can read and validate the cookie cryptographically without shared state. The token's own signature and binding claims provide security. This is the simpler approach and works for most applications. - Distributed token store: The step-up token is stored in a distributed key-value store (Redis Cluster, DynamoDB) accessible from all edge regions. The cookie contains only a reference ID. This adds latency (a KV lookup per request) but allows server-side token revocation — important for compliance-sensitive applications where a compromised step-up token must be invalidated instantly across all edge nodes.
The signed cookie approach aligns with the principle that security headers and cookie attributes are the first line of defense for client-side token security. The cookie must be scoped to the minimum necessary path (e.g., Path=/api/settings rather than Path=/) to limit exposure. The OWASP broken access control guidelines emphasize that overly broad cookie scopes are a common source of privilege escalation vulnerabilities.
Integration with MFA at Edge Nodes
The step-up authentication framework must integrate with the organization's multi-factor authentication infrastructure. The specific factors available for step-up depend on what the user has enrolled and what the edge node can verify locally.
TOTP/HOTP Verification at Edge
Time-based and HMAC-based one-time passwords are the most widely deployed second factors. Verifying a TOTP code requires only the user's TOTP seed (a 20-byte shared secret) and the current time. Edge nodes can cache TOTP seeds encrypted with a key-encryption-key (KEK) distributed via the CDN's TLS infrastructure, enabling local verification without origin contact.
# TOTP verification at edge (pseudocode)
def verify_totp_at_edge(user_id, submitted_code):
# Retrieve encrypted seed from edge cache
encrypted_seed = edge_cache.get(f"totp_seed:{user_id}")
if not encrypted_seed:
# Cache miss: fall back to origin redirect
return redirect_to_idp(acr_values="mfa")
seed = decrypt_with_kek(encrypted_seed)
# Check current and adjacent time windows (clock skew tolerance)
for offset in [-1, 0, 1]:
expected = compute_totp(seed, time_step=30, offset=offset)
if constant_time_compare(submitted_code, expected):
# Mint step-up token
return issue_step_up_token(user_id, acr="mfa", amr=["pwd", "otp"])
return {"error": "invalid_otp", "remaining_attempts": 2}
The critical security requirement is that TOTP seeds stored at edge nodes must be encrypted at rest and decrypted only in memory during verification. Compromising an edge node's disk should not expose TOTP seeds. The KEK should be rotated on a schedule aligned with the CDN's key management lifecycle, typically every 90 days.
WebAuthn/FIDO2 Verification at Edge
WebAuthn (passkey) authentication is the gold standard for phishing-resistant step-up because the cryptographic challenge-response is bound to the origin domain. The edge node generates a challenge, the client's authenticator signs it with the private key, and the edge verifies the signature against the user's registered public key.
Unlike TOTP seeds, WebAuthn public keys are not sensitive secrets — they can be cached at edge nodes without encryption. However, the credential metadata (credential ID, public key, sign count) must be kept current. A user who registers a new passkey or revokes an old one expects the change to take effect immediately. Edge caches should use a TTL of 1 to 5 minutes for WebAuthn credentials, with cache invalidation triggered by the credential store on registration or revocation events.
Push Notification MFA
Push-based MFA (where the user approves a notification on their mobile device) cannot be verified at the edge because it requires real-time communication with the push notification service and the user's device. For step-up flows requiring push MFA, the edge node must redirect to the IdP or use a WebSocket connection to the authentication backend. This introduces latency equivalent to the origin redirect pattern, making push MFA the least edge-friendly second factor.
Performance Considerations for Progressive Authentication
Step-up authentication adds latency at two points: the policy evaluation (deciding whether step-up is required) and the step-up execution (performing the re-authentication). Minimizing both is essential for maintaining the performance metrics that justify edge delivery.
Policy Evaluation Overhead
For requests that do not trigger step-up (the vast majority), the overhead is the time to parse the JWT, extract ACR/AMR claims, compute the risk score, and compare against the endpoint policy. This should take 0.1 to 0.5 milliseconds on modern edge hardware — negligible compared to TLS handshake and network latency. The TLS 1.3 handshake itself adds 1 to 2 RTTs, dwarfing the policy evaluation time.
Key optimizations for policy evaluation:
- Pre-parsed JWT cache: Cache the parsed claims of recently seen JWTs (keyed by the JWT's
jticlaim or a hash of the token) to avoid re-parsing the same token on consecutive requests. The cache TTL should match the token's remaining lifetime. - Compiled policy rules: Convert the endpoint-to-ACR-requirement mapping into a compiled lookup structure (trie or hash map) rather than evaluating rules sequentially. A well-architected CDN pre-compiles routing and policy rules at configuration deployment time.
- Lazy risk scoring: Compute the full risk score only when the endpoint has a non-trivial ACR requirement. For endpoints that require only
basicACR (the majority of read-only APIs), skip risk scoring entirely and check only the token's validity and expiration.
Step-Up Execution Latency
When step-up is triggered, the latency depends entirely on the pattern used:
| Pattern | Added Latency | User Interaction | Edge Complexity |
|---|---|---|---|
| Origin redirect (TOTP) | 200–500ms + user time | Type 6-digit code | Low (redirect only) |
| Origin redirect (push MFA) | 200–500ms + 5–30s | Tap approve | Low |
| Edge-local TOTP | 5–20ms + user time | Type 6-digit code | Medium (seed cache) |
| Edge-local WebAuthn | 5–20ms + user time | Touch/biometric | Medium (key cache) |
| Transparent (risk only) | 0.5ms (inline) | None | High (risk engine) |
The "transparent" row represents risk-based decisions that adjust rate limits or throttling without interrupting the user, used when the risk score is slightly elevated but not enough to warrant a full step-up challenge. For example, a request from an unusual IP might be allowed but rate limited more aggressively, with the step-up challenge triggered only if the suspicious behavior continues.
Caching Elevated Authentication State
The most important performance optimization is caching the elevated authentication state so that subsequent sensitive requests within the step-up TTL window do not trigger re-authentication. A user who completes MFA to access account settings should not be challenged again when they navigate to payment methods 30 seconds later, assuming both endpoints require the same ACR level.
The step-up token's step_up_scope claim defines which operations are covered by the elevated state. Scoping should be broad enough to avoid repeated challenges during a single workflow but narrow enough to enforce the principle of least privilege. A scope of ["account:*"] covers all account management operations; a scope of ["payment:initiate"] covers only payment initiation and requires a fresh step-up for other sensitive operations.
The edge computing capabilities of modern CDNs make all of these patterns feasible at global scale. Edge workers can execute authentication logic in under a millisecond, and distributed KV stores provide the session state needed for token binding and revocation. The key architectural decision is where to draw the line between edge-local verification (fast but complex to maintain) and origin-delegated verification (simpler but slower).
Securing the Step-Up Flow Against Attack Vectors
Step-up authentication introduces its own attack surface that must be addressed in the edge security design. The DDoS protection and WAF layers provide the foundation, but step-up-specific attacks require targeted defenses.
Step-Up Fatigue Attacks
An attacker who has compromised a user's password but not their second factor can trigger repeated step-up challenges, hoping the user approves one out of frustration (the same technique used in MFA fatigue attacks). Edge defenses include:
- Challenge rate limiting: Limit step-up challenges to 3 per session per 5-minute window. After the limit, lock the session and require full re-authentication from the IdP.
- Number matching: For push MFA, require the user to enter a 2-digit code displayed at the edge rather than simply tapping "approve." This prevents approval of attacker-initiated challenges.
- Challenge binding: Each step-up challenge is bound to a specific request (encoded in the challenge nonce). The step-up token minted from a challenge response is valid only for the original request, not for arbitrary future requests.
Token Downgrade Attacks
An attacker might modify the request to target a lower-sensitivity endpoint (which requires a lower ACR) and then alter the response to serve the sensitive resource. Edge defenses must ensure that the ACR check is performed on the actual resource being served, not just the requested URL. This requires the origin to echo the required ACR in its response headers, which the edge validates before forwarding to the client. The distinction between 401 and 403 becomes critical here: 401 signals that authentication can be escalated, while 403 signals that the user lacks authorization regardless of authentication level.
Session Fixation via Step-Up
If the step-up flow does not rotate the session identifier after successful re-authentication, an attacker who has fixated the session before step-up can hijack the elevated session. The edge must issue a new session cookie (and invalidate the old one) after every successful step-up, just as it would after initial login. The CORS and security header configurations must be tight enough to prevent cross-origin access to the elevated session cookie.
Deploying Step-Up Authentication: A Reference Architecture
Bringing all the pieces together, a production step-up authentication deployment at CDN scale involves coordination between several components. The load balancing layer routes authentication traffic, the edge evaluates policies, and the origin manages the credential store.
The edge configuration maps endpoints to required ACR levels:
# Edge step-up policy configuration
step_up_policy:
default_acr: "basic"
default_ttl: 3600 # 1 hour for basic sessions
endpoints:
# Public endpoints: no auth required
- pattern: "/api/v1/products/*"
required_acr: null
methods: [GET]
# Standard authenticated endpoints
- pattern: "/api/v1/user/profile"
required_acr: "basic"
methods: [GET]
# Sensitive read operations
- pattern: "/api/v1/user/sessions"
required_acr: "mfa"
step_up_ttl: 900 # 15-minute elevated window
methods: [GET]
# Sensitive write operations
- pattern: "/api/v1/user/email"
required_acr: "mfa"
amr_required: ["pwd", "otp"] # Specific methods required
step_up_ttl: 300
methods: [PUT, PATCH]
# Critical operations
- pattern: "/api/v1/user/password"
required_acr: "phishing-resistant"
amr_required: ["hwk"] # Hardware key required
step_up_ttl: 120
methods: [PUT]
# Admin operations
- pattern: "/api/v1/admin/*"
required_acr: "phishing-resistant"
amr_required: ["hwk"]
step_up_ttl: 300
risk_scoring: enabled # Dynamic escalation
methods: [GET, POST, PUT, DELETE]
risk_overrides:
high_risk_bump: 1 # Bump required ACR by 1 level
impossible_travel: block # Block and require full re-auth
The API gateway authorization layer enforces these policies before routing to the origin. Each edge PoP evaluates the policy locally using the JWT claims and cached risk data, ensuring that authentication decisions happen at the speed of edge computing rather than the speed of origin round-trips.
The AI agent authorization use case is particularly relevant for step-up authentication. AI agents that operate on behalf of users may need to escalate authentication when they attempt sensitive operations, and the edge must be able to distinguish between the agent's own credentials and the delegated user credentials that determine the step-up requirements.
Step-up authentication at the CDN edge is not a single feature but a system design that touches token architecture, edge computing, session management, and risk assessment. The fundamental principle is simple: match the authentication strength to the sensitivity of the operation, and do it as close to the user as possible. The implementation is complex because distributed systems make everything complex. But the alternative — either uniform low security or uniform high friction — is worse for both security and user experience. Build the step-up flow into the edge from the start, bind tokens to sessions cryptographically, and use risk scoring to make intelligent escalation decisions. Your users will barely notice the security, which means you built it right. The zero trust authentication model at the edge is the future of identity-aware content delivery, and step-up is the mechanism that makes it practical without making it painful. For the underlying SSL/TLS configuration that secures these token exchanges, ensure that your edge nodes enforce modern cipher suites and certificate validation at every hop.