upgradeToDPoP

fun UserAccountManager.upgradeToDPoP(userAccount: UserAccount, onSuccess: (userAccount: UserAccount) -> Unit, onFailure: (error: String, errorDesc: String?, e: Throwable?) -> Unit)

Upgrades the userAccount's existing Bearer (non-DPoP) refresh token to a DPoP-bound one, in place — same consumer key, redirect URI, and scopes the account already uses. This is a same-config convenience over migrateRefreshToken with useDPoP = true: no re-consent is expected because nothing about the connected app / External Client App configuration changes.

The redirect URI used is the one persisted on userAccount at login time (the exact value the connected app / External Client App was configured with for this user); it only falls back to resolving the OAuth configuration for the account's login server for accounts that were persisted before the redirect URI was captured on UserAccount.

This works regardless of the global SalesforceSDKManager.useDPoP flag: that flag only sets the default DPoP posture for brand-new logins, while this call is an explicit action on an already-authenticated session. Callers wanting to migrate to a different consumer key, redirect URI, or scopes (or to explicitly downgrade a DPoP-bound session back to Bearer) should call migrateRefreshToken directly with their own OAuthConfig and useDPoP value.

Note: onFailure (and onSuccess) may be invoked off the main thread — the synchronous null-check failure below runs on the caller's thread, but the OAuth-config resolution and migration below it run on Default. Callers that touch UI from these callbacks must marshal to the main thread themselves.

No-op: if userAccount is already DPoP-bound, there's nothing to upgrade — onSuccess is invoked synchronously with the unchanged account and no migration is attempted.