Skip to content

breaking : Moved the useDPoP method in the WebAuthProvider class to the login builder class#914

Merged
pmathew92 merged 4 commits intov4_developmentfrom
SDK-7798
Feb 17, 2026
Merged

breaking : Moved the useDPoP method in the WebAuthProvider class to the login builder class#914
pmathew92 merged 4 commits intov4_developmentfrom
SDK-7798

Conversation

@pmathew92
Copy link
Contributor

Description

This PR moves the DPoP (Demonstrating Proof-of-Possession) configuration from a global setting on the WebAuthProvider object to the login Builder class, enabling per-request DPoP configuration.

Motivation

Previously, DPoP was configured globally via WebAuthProvider.useDPoP(context), which meant:

  • Once enabled, DPoP was "sticky" and affected all subsequent login requests
  • Configuration couldn't be changed per-request

Changes

Before (v3):

WebAuthProvider
    .useDPoP(context)
    .login(account)
    .start(context, callback)

** After(v4):**

WebAuthProvider
    .login(account)
    .useDPoP(context)
    .start(context, callback)

… builder to scope it to individualk login requests
Copilot AI review requested due to automatic review settings February 16, 2026 10:13
@pmathew92 pmathew92 requested a review from a team as a code owner February 16, 2026 10:13
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

Moves DPoP configuration from a global WebAuthProvider.useDPoP(...) setting to a per-request WebAuthProvider.login(...).useDPoP(...) builder setting, aligning the API with request-scoped behavior and removing the prior “sticky” global configuration.

Changes:

  • Removed global WebAuthProvider.useDPoP(context) and added Builder.useDPoP(context) for per-login configuration.
  • Updated WebAuthProviderTest DPoP-related tests to use the builder-based API and removed the global-instance behavior test.
  • Updated docs (migration guide + examples) to reflect the new call pattern.

Reviewed changes

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

File Description
auth0/src/main/java/com/auth0/android/provider/WebAuthProvider.kt Removes global DPoP config and adds per-builder DPoP support via SenderConstraining<Builder>.
auth0/src/test/java/com/auth0/android/provider/WebAuthProviderTest.kt Updates DPoP tests to use builder-based configuration and removes obsolete global-instance test.
V4_MIGRATION_GUIDE.md Documents the breaking API move from global to builder-based DPoP configuration.
EXAMPLES.md Updates WebAuthProvider DPoP usage example to call useDPoP(context) on the login builder.

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

Comment on lines +552 to +555
public override fun useDPoP(context: Context): Builder {
dPoP = DPoP(context)
return this
}
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

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

Because DPoP is now configured per login Builder instance, make sure the authentication flow still survives process death/restoration: WebAuthProvider saves/restores OAuthManager via OAuthManager.toState()/fromState(), but OAuthManager.toState() does not currently persist DPoP and OAuthManagerState/PKCE reconstruction doesn’t re-enable DPoP on the restored AuthenticationAPIClient. This can cause a DPoP-enabled login to resume without DPoP proofs after restore. Consider persisting only a lightweight “DPoP enabled” flag in state and reconstructing/configuring DPoP (without serializing a Context-bearing DPoP instance) when restoring.

Copilot uses AI. Check for mistakes.

### DPoP Configuration Moved to Builder

The `useDPoP()` method has been moved from the `WebAuthProvider` object to the login `Builder` class. This change allows DPoP to be configured per-request instead of globally.
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

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

The text says the useDPoP() method moved, but the API requires a Context parameter (useDPoP(context) / useDPoP(context: Context)). Updating the inline code reference would avoid implying a zero-arg overload still exists.

Suggested change
The `useDPoP()` method has been moved from the `WebAuthProvider` object to the login `Builder` class. This change allows DPoP to be configured per-request instead of globally.
The `useDPoP(context: Context)` method has been moved from the `WebAuthProvider` object to the login `Builder` class. This change allows DPoP to be configured per-request instead of globally.

Copilot uses AI. Check for mistakes.
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: should be useDPoP(context: Context) to match the actual signature and avoid implying a zero-arg overload exists.

Comment on lines 332 to 336
public fun enablingDPoPWillGenerateNewKeyPairIfOneDoesNotExist() {
`when`(mockKeyStore.hasKeyPair()).thenReturn(false)
WebAuthProvider.useDPoP(mockContext)
.login(account)
login(account)
.useDPoP(mockContext)
.start(activity, callback)
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

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

There’s no test asserting the new per-request behavior (i.e., enabling DPoP on one login builder does not affect a subsequent login call that doesn’t call useDPoP). Adding a regression test for the non-sticky behavior would better cover the API change described in the PR motivation.

Copilot uses AI. Check for mistakes.
intentCaptor.allValues[1].getParcelableExtra<Uri>(AuthenticationActivity.EXTRA_AUTHORIZE_URI)
assertThat(secondUri, `is`(notNullValue()))
assertThat(secondUri, not(UriMatchers.hasParamWithName("dpop_jkt")))
}

Choose a reason for hiding this comment

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

👍

* @param context the Android context used to access the keystore for DPoP key management
* @return the current builder instance
*/
public override fun useDPoP(context: Context): Builder {
Copy link
Contributor

Choose a reason for hiding this comment

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

Now that DPoP is scoped to the Builder (no longer on the singleton), the DPoP state won't survive process death. OAuthManager.toState() doesn't persist DPoP, and fromState() restores without it — so a DPoP-enabled login will silently resume without DPoP proofs if the OS kills the activity mid-redirect.

Please add a dpoPEnabled: Boolean flag to OAuthManagerState, persist it in toState(), and reconstruct DPoP(context) in fromState() when the flag is true. No need to serialize the DPoP instance itself (it holds a Context).

Please:

1>Add dpoPEnabled: Boolean = false to OAuthManagerState
2>Set it in toState() based on dPoP != null
3>In fromState(), if dpoPEnabled == true, pass DPoP(context) to the reconstructed OAuthManager

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Addressed this


### DPoP Configuration Moved to Builder

The `useDPoP()` method has been moved from the `WebAuthProvider` object to the login `Builder` class. This change allows DPoP to be configured per-request instead of globally.
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: should be useDPoP(context: Context) to match the actual signature and avoid implying a zero-arg overload exists.

@@ -2861,8 +2853,7 @@ public class WebAuthProviderTest {

@Test
public fun shouldNotAffectLogoutWhenDPoPIsEnabled() {
Copy link
Contributor

Choose a reason for hiding this comment

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

This test name is now misleading — it no longer enables DPoP at all, it just tests default logout. Consider renaming to shouldNotIncludeDPoPParametersInLogoutURI.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good catch. This test is no longer required. Removed it

Copy link
Contributor

@utkrishtsahu utkrishtsahu left a comment

Choose a reason for hiding this comment

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

LGTM

@pmathew92 pmathew92 merged commit 7da0c8e into v4_development Feb 17, 2026
6 of 7 checks passed
@pmathew92 pmathew92 deleted the SDK-7798 branch February 17, 2026 07:09
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.

3 participants