Skip to content

fix(auth): fix DPoP validation propagation in AuthFlowTester UI tests - #4144

Merged
wmathurin merged 4 commits into
forcedotcom:devfrom
wmathurin:fix-auth-flow-tester-tests
Aug 25, 2026
Merged

fix(auth): fix DPoP validation propagation in AuthFlowTester UI tests#4144
wmathurin merged 4 commits into
forcedotcom:devfrom
wmathurin:fix-auth-flow-tester-tests

Conversation

@wmathurin

@wmathurin wmathurin commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Fixes BaseAuthFlowTester test infrastructure so explicit useDPoP enablement correctly propagates through the full validation call chain (launchAndLoginvalidate()validateUserassertRevokeAndRefreshWorks)
  • Syncs README.md and overview.md with the actual test suite (missing tests, stale test names)
  • All non-Beacon tests pass. Beacon tests (BEACON_OPAQUE / BEACON_JWT) fail pre-existing across all suites — same failures observed on Android (forcedotcom/SalesforceMobileSDK-Android#3005), pointing to an environment or server-side issue with the Beacon app configuration in the test sandbox rather than a code regression.

Root cause (DPoP validation)

SDK 14.0 made DPoP default-on: commit a9d333f01 changed self.useDPoP = NOself.useDPoP = YES in resetAuthFlags. The validation logic in BaseAuthFlowTester derived whether to expect DPoP credentials solely from the app config name (isDPoP returns true only when the config name contains _dpop). Tests that explicitly enable DPoP via Login Options (e.g. DPoPLoginTests operating on ecaOpaque) called validate() with useDPoP: true, but validateUser and assertRevokeAndRefreshWorks still consulted userAppConfig.isDPoP — always false for ecaOpaque — so DPoP credentials were validated against Bearer expectations, causing assertion failures.

Root cause (WelcomeLoginTests / parallel flakiness)

WelcomeLoginTests non-beacon tests (testWelcomeDiscovery_RegularAuthLoginHost, _DynamicConfig) appeared to consistently fail all 3 retries when run in parallel with Beacon tests. Beacon tests each time out after 109s × 3 retries = ~327s per test, saturating the simulator pool. The same two tests pass reliably when run in isolation (117s, 118s). No code change was required; the failures were a parallelism artefact, not a product regression.

Fix

Propagate useDPoP through the BaseAuthFlowTester call chain so explicit DPoP enablement overrides the config-name-derived default:

  • launchAndLogin and loginOtherUser (no-validate variant) — added useDPoP: Bool = false, forwarded to login()
  • validateUser — added expectDP: Bool? = nil; resolves to expectDP ?? userAppConfig.isDPoP
  • validate() (private) — computes effectiveExpectDP = useDPoP || userAppConfig.isDPoP and passes it to both validateUser and assertRevokeAndRefreshWorks

No SDK production code was changed — only test infrastructure (BaseAuthFlowTester.swift, 15 lines).

Test results

All AuthFlowTester UI test suites run on simulator (iPhone 16, iOS 18.6). All non-Beacon tests pass. Beacon tests fail pre-existing across all suites; the same failures are seen on Android (#3005), pointing to a server-side / environment issue with the Beacon app configuration in the test sandbox rather than a code regression. git diff origin/dev shows zero changes to Beacon test files or Beacon app configuration.

Some tests required 1–2 retries due to network flakiness against the shared test sandbox (token endpoint timeouts at ~110s). All eventually passed within the built-in retry budget.

In WelcomeLoginTests, testWelcomeDiscovery_RegularAuthLoginHost and testWelcomeDiscovery_RegularAuthLoginHost_DynamicConfig fail when run in parallel with Beacon timeouts but pass reliably in isolation (117s, 118s). Root cause: Beacon tests time out after 109s × 3 retries each, exhausting simulator concurrency.

Test plan

  • All 10 runnable DPoPLoginTests pass (2 skipped — W-22512846 and pending server-side fix)
  • All ECALoginTests pass (9/9)
  • All LegacyLoginTests pass (7/7)
  • Non-Beacon MultiUserLoginTests pass (2/2; testBothStatic_SameApp_SameScopes needed 2 retries)
  • Non-Beacon RefreshTokenMigrationTests pass (3/3; 2 tests needed 2 retries each)
  • Non-Beacon WelcomeLoginTests pass in isolation (2/2; fail under parallel Beacon load — parallelism artefact, not a regression)
  • Non-Beacon LoginWithRestartTests pass (6/6; all first-attempt)
  • Non-Beacon RefreshTokenMigrationWithRestartTests pass (2/2; all first-attempt)
  • Beacon failures confirmed pre-existing and cross-platform (Android PR Sign In with Apple requirements #3005); no Beacon test code was modified

… and validate

Beacon consumer keys are DPoP-enforced server-side. Tests that log in with beacon
configs need to pass useDPoP:true so the SDK includes dpop_jkt in /authorize.
Without it, the server rejects the request before the login form loads.

- launchAndLogin: add useDPoP parameter (default false), forward to login()
- loginOtherUser: add useDPoP parameter (default false), forward to login()
- validateUser: add expectDP optional override (nil = use userAppConfig.isDPoP)
- validate: compute effectiveExpectDP = useDPoP || userAppConfig.isDPoP and pass
  to both validateUser and assertRevokeAndRefreshWorks so beacon+DPoP sessions
  are properly validated without requiring _dpop in the app config name
…suite

- Fix WelcomeLoginTests test names in overview.md (camelCase → underscore format)
- Add missing test_givenNoDPoP_whenLoginViaPoolServer_thenSessionIsValid to ECALoginTests (both docs); update count 8→9
- Add missing testAdvancedAuthUser_HasBWFlag_RegularAuthUser_DoesNot and test_dpopAndNonDPoPUsers_flagOff_maintainIndependentProofs to MultiUserLoginTests in overview.md; update count 13→15

@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!

…DME, delete overview.md

overview.md (Dec 2025) and README.md (Aug 2026) duplicated the same test-suite tables.
Android has always used a single README; align iOS with that pattern.

Changes:
- Add LegacyLoginTestsNotHybrid section (was in overview.md only)
- Add Scope Definitions table to Configuration section
- Add credential setup instructions linking to internal workspace doc
- Delete overview.md

For cross-platform setup details see docs/auth/auth-ui-testing.md in the workspace repo.
- Add missing RefreshTokenMigrationWithRestartTests section (5 tests)
- Add B/L marker reference tables (were in overview.md, not carried over)
- Fix testBothStatic_SameApp_SameScopes description (CA → ECA Opaque)
- Fix testBothStatic_DifferentApps description (CA+ECA → ECA Opaque+JWT)
- Fix test_dpopAndNonDPoPUsers description (process-global flag, not per-user)
@wmathurin
wmathurin merged commit be15ae7 into forcedotcom:dev Aug 25, 2026
12 of 14 checks passed
@github-actions

github-actions Bot commented Aug 25, 2026

Copy link
Copy Markdown
TestsPassed ☑️Skipped ⚠️Failed ❌️
AuthFlowTester UI Test Results all110 ran69 ✅4 ⚠️37 ❌
TestResult
AuthFlowTester UI Test Results all
AuthFlowTesterUITests.xctest
DPoPLoginTests.testLogin_DPoP_ECA_Without_DPoP_Fails()❌ failure
DPoPLoginTests.test_givenDPoPSession_whenDowngradeFromDPoP_thenBearerUnbound()❌ failure
DPoPLoginTests.test_givenBearerSession_whenUpgradeToDPoP_thenDPoPBound()❌ failure
DPoPLoginTests.test_givenTwoDPoPUsers_whenSwitchAndRefresh_thenTokensAndNoncesAreIsolated()❌ failure
ForceAdvancedAuthTests.testForceAdvancedAuth_AddAdditionalUser_BackButtonAccessible()❌ failure
AdvancedAuthBeaconLoginTests.testBeaconOpaque_AllScopes()❌ failure
AdvancedAuthBeaconLoginTests.testBeaconJwt_DefaultScopes()❌ failure
AdvancedAuthBeaconLoginTests.testBeaconJwt_SubsetScopes()❌ failure
AdvancedAuthBeaconLoginTests.testBeaconJwt_AllScopes()❌ failure
AdvancedAuthBeaconLoginTests.testBeaconOpaque_DefaultScopes()❌ failure
AdvancedAuthBeaconLoginTests.testBeaconOpaque_SubsetScopes()❌ failure
LoginWithRestartTests.testBeaconOpaque_DefaultScopes_WithRestart()❌ failure
LoginWithRestartTests.testAdvancedAuth_WithRestart()❌ failure
LoginWithRestartTests.testBeaconJwt_DefaultScopes_DynamicConfiguration_WithRestart()❌ failure
LoginWithRestartTests.testWelcomeDiscovery_WithRestart()❌ failure
LoginWithRestartTests.testBeaconJwt_SubsetScopes_DynamicConfiguration_WithRestart()❌ failure
RefreshTokenMigrationTests.testMigrateCAToBeaconAndBack()❌ failure
RefreshTokenMigrationTests.testMigrateCAToBeacon()❌ failure
RefreshTokenMigrationTests.testMigrateBeaconOpaqueToJWTAndBack()❌ failure
RefreshTokenMigrationTests.testMigrateBeacon_AddMoreScopes()❌ failure
RefreshTokenMigrationTests.testMigrateCAUserAgentToBeaconWebServer()❌ failure
RefreshTokenMigrationTests.testMigrateBeaconToCA()❌ failure
RefreshTokenMigrationTests.testFlagDiversity_MigratedBeaconJwtVsNonHybridOpaque()❌ failure
RefreshTokenMigrationWithRestartTests.testMigrateBeaconScopeAddition_WithRestart()❌ failure
RefreshTokenMigrationWithRestartTests.testMigrateMultipleUsers_WithRestart()❌ failure
RefreshTokenMigrationWithRestartTests.testMigrateCAToBeacon_WithRestart()❌ failure
MultiUserLoginTests.testFlagDiversity_BeaconNonHybridJwtVsHybridOpaque()❌ failure
MultiUserLoginTests.testBeaconAndNonBeacon_MultiUser()❌ failure
MultiUserLoginTests.testAdvancedAuthUser_HasBWFlag_RegularAuthUser_DoesNot()❌ failure
BeaconLoginTests.testBeaconOpaque_SubsetScopes()❌ failure
BeaconLoginTests.testBeaconOpaque_AllScopes()❌ failure
BeaconLoginTests.testBeaconOpaque_DefaultScopes()❌ failure
BeaconLoginTests.testBeaconJwt_AllScopes()❌ failure
BeaconLoginTests.testBeaconJwt_SubsetScopes()❌ failure
BeaconLoginTests.testBeaconJwt_DefaultScopes()❌ failure
WelcomeLoginTests.testWelcomeDiscovery_AdvancedAuthLoginHost_DynamicConfig()❌ failure
WelcomeLoginTests.testWelcomeDiscovery_AdvancedAuthLoginHost()❌ failure

@codecov

codecov Bot commented Aug 26, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 71.61%. Comparing base (ada8024) to head (32e55d2).
⚠️ Report is 5 commits behind head on dev.

Additional details and impacted files
@@            Coverage Diff             @@
##              dev    #4144      +/-   ##
==========================================
- Coverage   71.80%   71.61%   -0.20%     
==========================================
  Files         254      254              
  Lines       22837    22837              
==========================================
- Hits        16399    16355      -44     
- Misses       6438     6482      +44     
Components Coverage Δ
Analytics 70.78% <ø> (ø)
Common 70.79% <ø> (-0.19%) ⬇️
Core 67.35% <ø> (-0.28%) ⬇️
SmartStore 73.45% <ø> (ø)
MobileSync 88.84% <ø> (ø)
see 4 files with indirect coverage changes
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

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