Upgrade — DPoP Nonce Auto-Management#

The framework now internally manages the DPoP nonce lifecycle. Previously, callers were responsible for extracting the DPoP-Nonce header from server responses and passing it back on subsequent calls via the dpopNonce parameter. This is no longer necessary — the framework tracks and applies the latest nonce automatically through its internal URL session / interceptor.

This migration applies primarily at the Driver Layer, where HaapiTokenManager is exposed directly. Higher layers (SDK, UI) compose the Driver Layer and never required caller-managed nonces.

For the concept and rationale, see DPoP and Nonces .

What Changed#

BeforeAfter
Caller extracts DPoP-Nonce from each responseFramework extracts the header internally
Caller passes dpopNonce to the next HaapiTokenManager callFramework retrieves the latest nonce from its session
Caller is responsible for re-trying 401 + use_dpop_nonce errorsFramework handles use_dpop_nonce as a retryable error transparently

Affected Surfaces#

  • iOS Driver LayerHaapiTokenManager methods that previously accepted dpopNonce: parameters.
  • Android Driver LayerHaapiTokenManager.getDPoPTokensFor(...) (when used directly without the OkHttp interceptor) and DPoPNonceStack direct API.
  • SDK and UI Layers — no caller-facing change; the Driver-Layer improvement flows through transitively.

Migration#

Deprecated methods#

Deprecated methodReplacement
getHaapiTokenAsync(forceFresh:dpopNonce:)getHaapiTokenAsync(forceFresh:)
getHaapiToken(forceFresh:dpopNonce:completionHandler:) (Result-based)getHaapiTokenAsync(forceFresh:)

Objective-C variants remain deprecated as part of the broader Objective-C support discontinuation.

Before (deprecated API)#

var lastNonce: String? = nil

let tokenInfo = try await haapiTokenManager.getHaapiTokenAsync(
    forceFresh: false,
    dpopNonce: lastNonce
)
// Extract nonce for next call
lastNonce = tokenInfo.dpopNonce

After#

let tokenInfo = try await haapiTokenManager.getHaapiTokenAsync(
    forceFresh: false
)
// tokenInfo.dpopNonce remains readable, but you don't need to pass it back

Backward compatibility#

  • Existing code that passes dpopNonce continues to compile and work. The caller-provided nonce takes precedence over the internally managed one.
  • The dpopNonce property on DpopAccessTokenInfo remains available for reading.
  • No changes are required for users of HaapiClient, which already managed nonces internally.

Verification#

After migration:

  • Outgoing HAAPI requests still carry the correct DPoP-Nonce header — inspect a request from Charles / Proxyman / mitmproxy to confirm.
  • 401 + use_dpop_nonce responses no longer surface as errors to your code; the framework refreshes the nonce internally and retries.
  • The tokens.dpopNonce / tokenInfo.dpopNonce property remains readable if you have downstream code that needs it.

On iOS, the caller-provided nonce takes precedence over the internally managed one for backward compatibility. If you have stale code that still passes a dpopNonce parameter, the framework respects it — even when its internal value is fresher. Remove the caller-provided nonce explicitly during migration; don’t rely on the framework to override.

Was this helpful?