Skip to content

@W-24269743 refactor: Consolidate iOS RTR account lookups - #4179

Merged
wmathurin merged 3 commits into
forcedotcom:devfrom
wmathurin:optimize-ios-rtr-account-lookups
Sep 23, 2026
Merged

wmathurin merged 3 commits into
forcedotcom:devfrom
wmathurin:optimize-ios-rtr-account-lookups

Conversation

@wmathurin

Copy link
Copy Markdown
Contributor

Description

Consolidates the adjacent post-response account lookups in SFOAuthSessionRefresher.

The request-time lookup remains separate so the request uses the credential owner's User-Agent.
After the asynchronous refresh completes, the refresher resolves the account once from the updated
credentials and reuses that fresh account for both RTR feature registration and the successful
refresh notification. This preserves account-removal behavior while removing one account lookup
from rotated-token successes.

Adds focused regression coverage for rotated and unchanged refresh tokens and for an account being
removed while refresh is in flight.

Spec: SalesforceMobileSDK-Workspace PR #109

Resolves

W-24269743

Testing

Tests in the PR

  • Manual Tests
  • Unit Tests
  • Integration Tests

Manual Tests

No manual UI behavior is changed.

  • SFOAuthSessionRefresherTests deterministic set: 6 passed, 0 failed on an iPhone 16 Pro / iOS 18.6 simulator.
  • Rotated, unchanged, and in-flight account-removal regressions: 3 passed, 0 failed.
  • The existing real-network testFailedRefresh was excluded from the clean run after exceeding its two-second timeout; the test build and all deterministic refresher tests succeeded.

@wmathurin wmathurin self-assigned this Sep 22, 2026
@github-actions

Copy link
Copy Markdown
TestsPassedSkippedFailed ❌️
AuthFlowTester UI Test Results all1 ran1 ❌
TestResult
AuthFlowTester UI Test Results all
AuthFlowTesterUITests.xctest
LegacyLoginTests.testCAOpaque_DefaultScopes_WebServerFlow()❌ failure

@codecov

codecov Bot commented Sep 22, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 67.95%. Comparing base (56b708f) to head (c28eb34).
⚠️ Report is 1 commits behind head on dev.

Additional details and impacted files
@@            Coverage Diff             @@
##              dev    #4179      +/-   ##
==========================================
+ Coverage   67.94%   67.95%   +0.01%     
==========================================
  Files         254      254              
  Lines       23083    23086       +3     
==========================================
+ Hits        15684    15689       +5     
+ Misses       7399     7397       -2     
Components Coverage Δ
Analytics 71.17% <ø> (ø)
Common 71.76% <ø> (ø)
Core 61.87% <100.00%> (+0.02%) ⬆️
SmartStore 73.45% <ø> (ø)
MobileSync 88.90% <ø> (ø)
Files with missing lines Coverage Δ
...rceSDKCore/Classes/OAuth/SFOAuthSessionRefresher.m 93.68% <100.00%> (+0.20%) ⬆️

... and 2 files with indirect coverage changes

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

@github-actions

github-actions Bot commented Sep 22, 2026

Copy link
Copy Markdown
TestsPassed ☑️SkippedFailed ❌️
SalesforceSDKCore iOS ^18 Test Results1062 ran1061 ✅1 ❌
TestResult
SalesforceSDKCore iOS ^18 Test Results
testPasswordValidation()❌ failure

@JohnsonEricAtSalesforce JohnsonEricAtSalesforce 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.

Reviewed the consolidation of the post-response account lookups in SFOAuthSessionRefresher.

What changed: the request-time lookup (used only to build the outbound User-Agent) stays separate and unchanged. After the refresh response comes back, the two previously-separate post-response lookups (one for refresh-token-rotation feature registration, one for the success notification) are now resolved once and reused for both.

Verification performed:

  • Traced the full flow end to end: confirmed the rotated-token path now performs two accountForCredentials: lookups (one at request time, one post-response) instead of three, and the unchanged-token path stays at two — matching the PR description's claim.
  • Confirmed there's no stale-reference window between the single post-response resolve and its two uses (feature registration, then notification): both happen in straight-line synchronous code with no thread hop in between.
  • Traced accountForCredentials: and deleteAccountForUser: in SFUserAccountManager to confirm that an account removed while the refresh is in flight causes the post-response lookup to correctly return nil (the identity is removed from userAccountMap under the same lock before the post-response lookup would ever see it), which drives the existing nil-account branch — notification still posts, account key omitted, RTR flag not registered. The new test_givenAccountRemovedDuringRefresh_whenRotatedTokenSucceeds_thenNotificationOmitsAccount test exercises this scenario (via a beforeCompletion hook that deletes the account before the stub's completion fires) rather than only the happy path.
  • Confirmed the PR's approach diverges from the literal suggested fix (resolve once at the very top and reuse everywhere) for good reason: doing that would reuse a pre-refresh snapshot for the post-response feature-registration/notification and would reintroduce exactly the staleness the removal-during-refresh test now guards against. Keeping two resolves (one pre-, one post-refresh) is the correct design here, not a shortcut.
  • Confirmed the identity match used by the post-response lookup (userId/orgId) is never mutated by the credential update that happens earlier in the same completion block, so the consolidated lookup can't be destabilized by the very refresh it's resolving against.
  • Read through the new/changed tests against a test-correctness checklist: names, setup, and assertions line up; the network boundary is stubbed (not the class under test); cleanup (account deletion, feature-marker unregistration, auth-client factory restore) is present in every new/changed test.

Related work: there's a same-shape finding tracked for the Android side (a different subsystem area, redundant account re-decryption in its RTR refresh path), currently in an earlier triage state with no PR yet — noted for awareness, not a blocker for this PR.

No blocking findings.

This review was generated by an AI agent on behalf of @JohnsonEricAtSalesforce.

@wmathurin
wmathurin merged commit d514ebd into forcedotcom:dev Sep 23, 2026
27 of 31 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