feat(telemetry): add A1-A5/TM/JT/OT/BN per-user feature flag markers (W-23762053) - #2980
Merged
wmathurin merged 17 commits intoAug 11, 2026
Merged
Conversation
Generated by 🚫 Danger |
…all sites (W-23762053) Adds AppConfig.isBeacon (derived from app name prefix), then threads isJwt and isBeacon into loginAndValidate, restartAndValidateUser, and migrateAndValidate in AuthFlowTest so every login assertion also validates JT/OT and BN. Migration tests pass expectedAMarker matching the original login's A-marker (preserved unchanged during migration).
… auth surface (W-23762053) registerAuthTypeFeatureGlobal() was called at LoginActivity.onCreate() but not when Login Options disabled web server flow and reloadWebView() ran on resume. The stale A2 global persisted into the completed login. Adding the call in the loginDevMenuReload block ensures the global reflects the effective flow type (A3/A4 for user agent) by the time auth completes.
…ath (W-23762053) NativeLoginManager.suspendFinishAuthFlow calls onAuthFlowComplete directly, bypassing LoginActivity.onAuthFlowSuccess where A-marker promotion normally happens. Added equivalent promotion block inside onAuthFlowComplete for the nativeLogin path: promotes active A-marker global per-user (A5 in the happy path), clears all A-marker globals, writes JT/OT/BN, and clears TM.
…gin Options (W-23762053) loginAndValidate only called disableWebServerFlow/disableHybridAuthToken/enableDPoP when the flag was false/true respectively, leaving stale toggle state from a prior login in the same test run. Multi-user tests where User A disables hybrid and User B re-enables it (default) would see User B inherit A's A1 instead of A2. Explicitly set all three toggles to the desired state on every Login Options visit.
…er state (W-23762053) Three issues found running the expanded test list: 1. Login Options toggles left stale: loginAndValidate only disabled web-server/hybrid toggles when requested off, never re-enabled them for the next user. Multi-user tests where User A disables hybrid and User B uses the default hybrid=true inherited the wrong toggle state. Fix: explicitly set all three toggles to the requested value on every Login Options visit. 2. ensureRegularAuthServer fast-path skipped stale SDK flag: the fast path (expectCustomTab=true, alreadyOnRegularAuth=true) assumed the SDK forceAdvancedAuthentication flag matched the caller's intent, but a prior loginAndValidate call with forceAdvancedAuthentication=false left it cleared. Added an SDK-state check to the fast-path guard and replaced the conditional setForcedAdvancedAuthEnabled(false) with an unconditional setForcedAdvancedAuthEnabled(forceAdvancedAuthentication) in the general path. 3. testMultiUser_A4OT_BN_vs_A2JT used impossible combinations: BN (beacon child key) is only returned by web-server flow's token endpoint, not user-agent flow's URL-fragment redirect. Redesigned to use web-server hybrid beacon (A2+OT+BN) vs web-server non-hybrid ECA opaque (A1+OT, no BN). 4. testAdvancedAuthUser_HasBWFlag_RegularAuthUser_DoesNot used REGULAR_AUTH vs ADVANCED_AUTH users who may share orgId/userId (same Salesforce org accessed via two auth domains), collapsing per-user feature isolation. Redesigned to use REGULAR_AUTH for both users, distinguishing them by forced-advanced-auth vs user-agent flow. Also fixed the final validateUserAgent to expect A4 (user-agent hybrid) instead of A3 (non-hybrid).
testFlagDiversity_A1OtVsA2Jt: User A=A1+OT, User B=A2+JT; asserts A-marker and token-format are isolated across user switches and survive after User B logout. testFlagDiversity_A1JtBnVsA2OtNoBn: User A=A1+JT+BN, User B=A2+OT no BN; three flags differ simultaneously. Uses ECA_OPAQUE for User B (not CA_OPAQUE) to force needsLoginOptions=true so the HybridAuthToken toggle is explicitly re-enabled after User A disabled it.
…W-23762053) Add two new rows to the MultiUserLoginTests table and a new "Multi-user flag leakage detection tests" subsection explaining how per-user flag storage works, what failure modes the tests catch, and the per-test details including the ECA_OPAQUE-vs-CA_OPAQUE boot-config fast-path note for testFlagDiversity_A1JtBnVsA2OtNoBn.
…names (W-23762053)
…sh helpers; fix admin A-marker registration - adminLoginAndValidate(): resolve appConfig and pass isJwt/isBeacon to validateUser so JWT/Beacon apps no longer fail the OT/BN assertions - assertRevokeAndRefreshWorks(): add isJwt param and thread it through to validateUserAgent; update JWT-config callers in DPoPLoginTests and RTRLoginTests - switchToUserAndValidateUser(): add isJwt param and thread it through to validateUser; moved definition after assertRevokeAndRefreshWorks for logical grouping; update LoginWithRestartTests (ECA_OPAQUE→isJwt=false, ECA_JWT→isJwt=true) and DPoPLoginTests (ECA_JWT_DPOP→isJwt=true) - LoginActivity.registerAuthTypeFeatureGlobal(): use webServer = viewModel.useWebServerFlow() || completedViaAdminCustomTab so the admin Custom Tab path always registers a web-server A-marker (A2) even when useWebServerAuthentication=false
…In (W-23762053) Add com.android.chrome:id/skip_button, "Skip", and "Not now" to dismissOneFreControl so the "Set Chrome as default" FRE page introduced in newer Chrome versions is dismissed and the Custom Tab can render. Without this, testAdvancedAuth_WithRestart fails because skipGoogleSignIn exhausts its 30s budget without clearing the FRE, leaving setUsername with no username field to find.
…ns, test renames (W-23762053) UserAgentFlow tests must set forceAdvancedAuthentication=false: Custom Tab always uses web-server grant, making user-agent flow impossible with the default true. Multi-user flag assertion fixes: - testFirstDynamic_SecondStatic_DifferentApps: pass isJwt=true (User A = ECA_JWT) - testDifferentApps_differentScopes: pass isBeacon=true for User A (BEACON_OPAQUE), isJwt=true for User B (ECA_JWT) - testMultiUser_tokenMigration: pass isJwt=true, isBeacon=true (User A = BEACON_JWT) Rename flag-diversity tests to descriptive flow names (already done in prior commit for Android; README updated to match the renamed tests and add detail sections).
Generated by 🚫 Danger |
…sertions (W-23762053) TM is per-user only but the global features set was never cleared of it, causing TM to bleed into all users' UA strings. Fix: after writing TM per-user on migration (AuthenticationUtilities) and after clearing TM per-user on full login (LoginActivity), unconditionally remove TM from the global set — same pattern as iOS SFUserAccountManager. Test fixes (switchToUserAndValidate missing isJwt/isBeacon/wasMigrated): - testSameApp_ECA_DifferentScopes: add isJwt=true (both users are ECA_JWT) - testSameApp_Beacon_DifferentScopes: add isBeacon=true (both users are BEACON_OPAQUE) - testFirstStatic_SecondDynamic_DifferentApps: add isJwt=true,isBeacon=true for otherUser (BEACON_JWT) - testMultiUser_tokenMigration_backgroundUser: add isJwt=true,wasMigrated=true for user post-migration (ECA_JWT)
…ion logins (W-23762053) testMigrateCAUserAgent_To_ECAExtendedWebServer and _To_BeaconExtendedWebServer both use useWebServerFlow=false to get A3 (user-agent non-hybrid), but without forceAdvancedAuthentication=false the Custom Tab is opened and always uses the web-server grant, producing A1 instead of A3.
Resolved conflict in LoginActivity.kt: added FEATURE_APP_ATTESTATION import (from upstream) alongside the new FEATURE_AUTH_TYPE_* and FEATURE_BEACON imports (from this branch), keeping all in alphabetical order.
brandonpage
reviewed
Aug 11, 2026
Comment on lines
+198
to
+199
| // Newer Chrome FRE "Set Chrome as default" page uses skip_button. | ||
| "com.android.chrome:id/skip_button", |
Contributor
There was a problem hiding this comment.
Great for local testing.
brandonpage
approved these changes
Aug 11, 2026
Resolve single conflict in LoginActivity.kt: keep registerAuthTypeFeatureGlobal() alongside the @OptIn(ExperimentalInitialNavigationCanLeaveBrowser::class) annotation added upstream before loadLoginPageInCustomTab.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
certAuthOrLogin()/loadLoginPageInCustomTab(), promoted inonAuthFlowSuccess()and global clearedSalesforceSDKManager.useNativeLogin(); A-marker per-user promotion for the native path happens inAuthenticationUtilities.ktforceAdvancedAuthentication = falseto get A3/A4AuthenticationUtilities.kt(tokenMigration == truebranch); cleared on full login inonAuthFlowSuccess()LoginActivity.onAuthFlowSuccessandAuthenticationUtilities.ktnow unconditionally clear TM from the globalfeaturesset after every auth completion, preventing it from bleeding into other users' UA stringsAuthFlowTesterPageObject.ktvalidateUserAgentto assert all new flags (all new params default to non-asserting so existing call sites compile unchanged)SalesforceSDKManagerTests.kt; extensive multi-user and migration UI test fixesGUS story
W-23762053
Key behavioral rules
Test plan
./gradlew :libs:SalesforceSDK:testDebugUnitTest— BUILD SUCCESSFUL./gradlew :native:NativeSampleApps:AuthFlowTester:assembleDebugAndroidTest— BUILD SUCCESSFUL