Skip to content

fix: Prevent DPoP replay protection error due to OkHttp retry#902

Merged
pmathew92 merged 3 commits intomainfrom
SDK-7742
Feb 6, 2026
Merged

fix: Prevent DPoP replay protection error due to OkHttp retry#902
pmathew92 merged 3 commits intomainfrom
SDK-7742

Conversation

@pmathew92
Copy link
Contributor

@pmathew92 pmathew92 commented Feb 6, 2026

Description

This PR introduces a dual-client architecture in DefaultClient to prevent OkHttp from automatically retrying network requests that use DPoP (Demonstrating Proof-of-Possession). DPoP proofs contain unique, non-replayable tokens (jti claims and timestamps), and OkHttp's automatic retry mechanism can cause "proof already used" errors when the same proof is sent twice.

Changes

Core Implementation (DefaultClient.kt)

  • Added nonRetryableOkHttpClient property with retryOnConnectionFailure = false

Testing

All tests pass successfully

./gradlew auth0:testDebugUnitTest

@pmathew92 pmathew92 requested a review from a team as a code owner February 6, 2026 04:28
Copilot AI review requested due to automatic review settings February 6, 2026 04:28
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a dual-client architecture in DefaultClient to prevent OkHttp's automatic retry mechanism from causing DPoP (Demonstrating Proof-of-Possession) replay protection errors. DPoP proofs contain unique, non-replayable tokens, and when OkHttp retries a request with the same proof, the server returns a "proof already used" error.

Changes:

  • Added nonRetryableOkHttpClient property that shares configuration with the main client but has retryOnConnectionFailure set to false
  • Implemented shouldUseNonRetryableClient() method to detect DPoP requests by checking for the DPoP header
  • Modified prepareCall() to select the appropriate client based on the presence of the DPoP header

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
auth0/src/main/java/com/auth0/android/request/DefaultClient.kt Adds dual-client architecture with non-retryable client for DPoP requests, includes client selection logic based on DPoP header presence
auth0/src/test/java/com/auth0/android/request/DefaultClientTest.kt Adds 2 configuration tests verifying both clients exist with correct settings and share the same configuration

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

/**
* Determines if the request should use the non-retryable OkHttpClient.
* Returns true for:
* 1. Requests with DPoP header
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we have other conditions too for which non retryable client must be used?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently Dpop scenario is where this is causing major error. We can update these cases on need to basis like refresh token exchange etc

@pmathew92 pmathew92 merged commit 6aa2f7e into main Feb 6, 2026
6 checks passed
@pmathew92 pmathew92 deleted the SDK-7742 branch February 6, 2026 05:09
@utkrishtsahu utkrishtsahu mentioned this pull request Feb 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants