Skip to content

fix(W-23836436): allow dpop_jkt on login pool servers - #4130

Merged
wmathurin merged 7 commits into
forcedotcom:devfrom
wmathurin:dpop-jkt-pool-servers
Aug 15, 2026
Merged

fix(W-23836436): allow dpop_jkt on login pool servers#4130
wmathurin merged 7 commits into
forcedotcom:devfrom
wmathurin:dpop-jkt-pool-servers

Conversation

@wmathurin

@wmathurin wmathurin commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Removes the isPoolLoginHost guard from appendDPoPJktIfNeededTo:domain:credentials: in SFOAuthCoordinator.m — pool servers now support DPoP authorization code binding
  • welcome.salesforce.com/discovery is unaffected (it is a discovery endpoint and never directly receives an /authorize request)

Known limitation — server-side bug W-23864247

During testing against login.test1.pc-rnd.salesforce.com, the token exchange returns HTTP 400 invalid_dpop_proof even though the client's DPoP proof is cryptographically correct and its JWK thumbprint exactly matches the dpop_jkt sent in /authorize. This is a server-side issue filed as W-23864247 (Auth Protocols team). test_givenDPoP_whenLoginViaPoolServer_thenTokenTypeIsDPoP throws XCTSkip until the server fix is confirmed.

Changes

Production code

  • SFOAuthCoordinator.m — remove [SFSDKAuthConfigUtil isPoolLoginHost:domain] early-exit; only domain == nil exits early

Unit tests

  • SFOAuthCoordinatorTests.swift — invert two pool-host tests: login.salesforce.com and test.salesforce.com now assert dpop_jkt present (renamed thenUrlHasDPoPJkt)
  • welcome.salesforce.com/discovery test unchanged (still asserts absent)

UI tests (AuthFlowTester)

  • ui_test_config.json.sample — add top-level loginPoolHost field
  • UITestConfigUtils.swift — add loginPoolHost: String? to TestConfig; add getLoginPoolHost() accessor
  • BaseAuthFlowTester.swift — add useLoginPoolHost: Bool = false to login() and launchLoginAndValidate(); when true, configures the pool server URL as the login host while keeping credentials from the specified loginHost
  • DPoPLoginTests.swift — add test_givenDPoP_whenLoginViaPoolServer_thenTokenTypeIsDPoP (XCTSkip pending W-23864247); rename test_givenDPoPECA_whenAdminLogin_thenDPoPBindingWorksThroughSafariVCThroughBrowser

Test plan

  • SFOAuthCoordinatorTests — all 18 tests pass (verified locally)
  • DPoPLoginTests.test_givenDPoP_whenLoginViaPoolServer_thenTokenTypeIsDPoP — blocked on server bug W-23864247

GUS

W-23836436 — [iOS] Allow dpop_jkt on login pool servers (/authorize code binding)

@codecov

codecov Bot commented Aug 13, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 71.53%. Comparing base (322678c) to head (8c86d2b).
⚠️ Report is 5 commits behind head on dev.

Additional details and impacted files
@@            Coverage Diff             @@
##              dev    #4130      +/-   ##
==========================================
+ Coverage   67.13%   71.53%   +4.40%     
==========================================
  Files         254      254              
  Lines       22678    22679       +1     
==========================================
+ Hits        15224    16224    +1000     
+ Misses       7454     6455     -999     
Components Coverage Δ
Analytics 70.78% <ø> (ø)
Common 71.06% <ø> (+0.18%) ⬆️
Core 67.18% <100.00%> (+6.62%) ⬆️
SmartStore 73.44% <ø> (ø)
MobileSync 88.82% <ø> (ø)
Files with missing lines Coverage Δ
...lesforceSDKCore/Classes/OAuth/SFOAuthCoordinator.m 65.90% <100.00%> (+10.32%) ⬆️

... and 34 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@wmathurin
wmathurin force-pushed the dpop-jkt-pool-servers branch 2 times, most recently from cf49cfe to 47a0669 Compare August 13, 2026 00:41
@github-actions

github-actions Bot commented Aug 13, 2026

Copy link
Copy Markdown
TestsPassed ✅SkippedFailed
SalesforceSDKCore iOS ^18 Test Results975 ran975 ✅
TestResult
No test annotations available

@wmathurin
wmathurin force-pushed the dpop-jkt-pool-servers branch 2 times, most recently from bc9f998 to b0bb8f0 Compare August 13, 2026 01:03
Pool servers (login.salesforce.com, test.salesforce.com) now support
DPoP authorization code binding. Remove the isPoolLoginHost guard from
appendDPoPJktIfNeededTo:domain:credentials: so dpop_jkt is sent for
all login servers when DPoP is enabled.

- Invert two pool-host unit tests in SFOAuthCoordinatorTests
- Add loginPoolHost top-level field to ui_test_config.json.sample
- Add useLoginPoolHost param to BaseAuthFlowTester.login/launchLoginAndValidate
- Add test_givenDPoP_whenLoginViaPoolServer_thenTokenTypeIsDPoP to DPoPLoginTests
@wmathurin
wmathurin force-pushed the dpop-jkt-pool-servers branch from b0bb8f0 to bf8d6b3 Compare August 13, 2026 01:04
@github-actions

github-actions Bot commented Aug 13, 2026

Copy link
Copy Markdown
TestsPassed ☑️Skipped ⚠️Failed ❌️
AuthFlowTester UI Test Results all106 ran54 ✅5 ⚠️47 ❌
TestResult
AuthFlowTester UI Test Results all
AuthFlowTesterUITests.xctest
DPoPLoginTests.test_givenDPoPECA_whenAdminLogin_thenDPoPBindingWorksThroughSafariVC()❌ failure
DPoPLoginTests.test_givenDPoPNoHybrid_whenLogin_thenTokenTypeIsDPoPAndRefreshWorks()❌ failure
DPoPLoginTests.test_givenDPoPHybrid_whenLogin_thenTokenTypeIsDPoPAndRefreshWorks()❌ failure
DPoPLoginTests.test_givenDPoPRtrNoHybrid_whenLogin_thenRefreshTokenRotatesAndDPoPBindingHolds()❌ failure
DPoPLoginTests.test_givenDPoPUser_whenMigrateToDPoPRtr_thenRefreshTokenRotationEnabled()❌ failure
DPoPLoginTests.test_givenDPoPUserWithSubsetScopes_whenMigrateToAllScopes_thenDPoPBindingPreserved()❌ failure
DPoPLoginTests.test_givenTwoDPoPUsers_whenSwitchAndRefresh_thenTokensAndNoncesAreIsolated()❌ failure
MultiUserLoginTests.testBothStatic_DifferentApps()❌ failure
MultiUserLoginTests.testAdvancedAuthUser_HasBWFlag_RegularAuthUser_DoesNot()❌ failure
MultiUserLoginTests.testDifferentAppTypes_RevokeAccessForCaUser_EcaUserUnaffected()❌ failure
MultiUserLoginTests.testLogoutUserWithDynamicConfig_OtherUserUnaffected()❌ failure
MultiUserLoginTests.testBeaconAndNonBeacon_MultiUser()❌ failure
MultiUserLoginTests.testFirstDynamic_SecondStatic_DifferentApps()❌ failure
MultiUserLoginTests.testBothStatic_SameApp_DifferentScopes()❌ failure
MultiUserLoginTests.testFlagDiversity_BeaconNonHybridJwtVsHybridOpaque()❌ failure
MultiUserLoginTests.testFirstStatic_SecondDynamic_DifferentApps()❌ failure
MultiUserLoginTests.testRevokeAccessForUserWithDynamicConfig_OtherUserUnaffected()❌ failure
MultiUserLoginTests.testFlagDiversity_NonHybridOpaqueVsHybridJwt()❌ failure
MultiUserLoginTests.test_dpopAndNonDPoPUsers_flagOff_maintainIndependentProofs()❌ failure
MultiUserLoginTests.testBothDynamic_DifferentApps()❌ failure
MultiUserLoginTests.testDifferentAppTypes_LogoutCaUser_EcaUserUnaffected()❌ failure
MultiUserLoginTests.testBothStatic_SameApp_SameScopes()❌ failure
RefreshTokenMigrationWithRestartTests.testMigrateCAToECA_WithRestart()❌ failure
RefreshTokenMigrationWithRestartTests.testMigrateMultipleUsers_WithRestart()❌ failure
RefreshTokenMigrationWithRestartTests.testMigrateBeaconScopeAddition_WithRestart()❌ failure
RefreshTokenMigrationWithRestartTests.testMigrateScopeAddition_WithRestart()❌ failure
RefreshTokenMigrationWithRestartTests.testMigrateCAToBeacon_WithRestart()❌ failure
WelcomeLoginTests.testWelcomeDiscovery_AdvancedAuthLoginHost()❌ failure
WelcomeLoginTests.testWelcomeDiscovery_AdvancedAuthLoginHost_DynamicConfig()❌ failure
WelcomeLoginTests.testWelcomeDiscovery_RegularAuthLoginHost_DynamicConfig()❌ failure
WelcomeLoginTests.testWelcomeDiscovery_RegularAuthLoginHost()❌ failure
AdvancedAuthBeaconLoginTests.testBeaconJwt_DefaultScopes()❌ failure
AdvancedAuthBeaconLoginTests.testBeaconOpaque_SubsetScopes()❌ failure
RefreshTokenMigrationTests.testMigrateOneUserOnly()❌ failure
RefreshTokenMigrationTests.testMigrateCAToECA()❌ failure
RefreshTokenMigrationTests.testMigrateCAToBeacon()❌ failure
RefreshTokenMigrationTests.testFlagDiversity_MigratedBeaconJwtVsNonHybridOpaque()❌ failure
RefreshTokenMigrationTests.testMigrateBeaconToCA()❌ failure
RefreshTokenMigrationTests.testMigrateCAUserAgentToECAWebServer()❌ failure
RefreshTokenMigrationTests.testMigrateBeacon_AddMoreScopes()❌ failure
RefreshTokenMigrationTests.testMigrateCAToBeaconAndBack()❌ failure
RefreshTokenMigrationTests.testMigrateCAUserAgentToBeaconWebServer()❌ failure
RefreshTokenMigrationTests.testMigrateECA_AddMoreScopes()❌ failure
RefreshTokenMigrationTests.testMigrateBeaconOpaqueToJWTAndBack()❌ failure
LoginWithRestartTests.testECAJwt_DefaultScopes_DynamicConfiguration_WithRestart()❌ failure
LegacyLoginTests.testCAOpaque_DefaultScopes_WebServerFlow()❌ failure
ECALoginTests.testDynamicConfigurationWithInvalidScope()❌ failure

@sfdctaka sfdctaka left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM with a comment.

- SFOAuthCoordinator.m: remove redundant _approvalCode = nil in dealloc
  (ARC zeros strong ivars automatically) to clear Clang analyzer warning
  [nullability.NullPassedToNonnull] at line 124.
- SFOAuthCoordinator.m: replace _authInfo = nil with a known non-nil default
  (SFOAuthTypeUnknown) in stopAuthentication to clear the same analyzer
  warning at line 295; consistent with the authInfo lazy-init getter.
- BaseAuthFlowTester.swift: replace try? with do/catch + XCTFail + return on
  the getLoginPoolHost() call site so a missing/empty loginPoolHost key fails
  loudly instead of silently falling through to the regular login host.
- SFOAuthCoordinatorTests.swift: add test for the domain == nil guard in
  appendDPoPJktIfNeededTo:domain:credentials:, exercised via the ObjC runtime
  since the caller (approvalURLForEndpoint:) asserts domain non-nil before
  the helper is reached from the normal path.
… README

- XCTSkip test_givenDPoP_whenLoginViaPoolServer_thenTokenTypeIsDPoP — server-side bug
  W-23864247 causes invalid_dpop_proof on the authorization-code token exchange at
  login.test1.pc-rnd.  Re-enable when server fix is confirmed.
- Add README.md for iOS AuthFlowTester with full test suite documentation
test_givenDPoPECA_whenAdminLogin_thenDPoPBindingWorksThroughSafariVC renamed to
test_givenDPoPECA_whenAdminLogin_thenDPoPBindingWorksThroughBrowser — the SDK uses
ASWebAuthenticationSession for Login for Admin, not SFSafariViewController.
@wmathurin

Copy link
Copy Markdown
Contributor Author

I was able to run all the UI tests locally successfully.
Screenshot 2026-08-14 at 5 49 47 PM

@wmathurin
wmathurin merged commit 755622d into forcedotcom:dev Aug 15, 2026
23 of 24 checks passed
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