Re-enable Native Auth SSPR tests with Mail.tm, Fixes AB#3729032 - #2553
Re-enable Native Auth SSPR tests with Mail.tm, Fixes AB#3729032#2553Disha Janardhan (djanardhan98) wants to merge 24 commits into
Conversation
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add a dedicated PR-branch test invocation with the Native Auth and Mail.tm inputs required by SSPRTest. Use a deterministic too-short password for the invalid-format case and update Common for Mail.tm HTTP/1.1 compatibility. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Update Common to the latest mail-tm-native-auth-e2e commit and broaden the dedicated PR test filter to the complete Native Auth E2E package, including SSPR. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
✅ Work item link check complete. Description contains link AB#3720943 to an Azure Boards work item. |
Co-authored-by: djanardhan98 <307255345+djanardhan98@users.noreply.github.com>
Co-authored-by: djanardhan98 <307255345+djanardhan98@users.noreply.github.com>
Co-authored-by: djanardhan98 <307255345+djanardhan98@users.noreply.github.com>
Co-authored-by: djanardhan98 <307255345+djanardhan98@users.noreply.github.com>
Co-authored-by: djanardhan98 <307255345+djanardhan98@users.noreply.github.com>
Co-authored-by: djanardhan98 <307255345+djanardhan98@users.noreply.github.com>
Co-authored-by: djanardhan98 <307255345+djanardhan98@users.noreply.github.com>
Point the Common submodule at the latest commit from AzureAD/microsoft-authentication-library-common-for-android#3219. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 83947e30-5bc9-4ec7-a8ed-c03d4415da92
There was a problem hiding this comment.
Pull request overview
Migrates Native Auth E2E tests to Mail.tm and re-enables SSPR coverage. The current Common submodule API is incompatible with the shared test helper, causing compilation failure.
Changes:
- Adds registered inboxes and OTP checkpoints.
- Runs Native Auth E2E tests in PR validation.
- Updates Common and AB ID extraction.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
.github/workflows/validate-pr-ab-id.yml |
Extracts explicit AB IDs. |
azure-pipelines/pull-request-validation/pr-msal.yml |
Adds Native Auth E2E validation. |
common |
Updates the Common submodule. |
NativeAuthPublicClientApplicationAbstractTest.kt |
Centralizes email service and retries. |
SSPRTest.kt |
Re-enables Mail.tm-backed SSPR tests. |
SignInEmailOTPTest.kt |
Adds OTP checkpoints. |
SignInJITTest.kt |
Creates authenticated inboxes. |
SignInMFATest.kt |
Adds MFA OTP checkpoints. |
SignUpEmailPasswordTest.kt |
Migrates signup inbox handling. |
SignUpEmailPasswordAttributesTest.kt |
Migrates attribute-flow inboxes. |
SignUpEmailOTPTest.kt |
Migrates OTP signup inboxes. |
SignUpEmailOTPAttributesTest.kt |
Migrates attributed OTP signup inboxes. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 83947e30-5bc9-4ec7-a8ed-c03d4415da92
Restore validate-pr-ab-id.yml to the dev branch version. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 4f268d2a-b8c4-4a22-826e-de2d9b9f59a6
…3219) ## Summary - Replace the Native Auth 1secmail inbox integration with authenticated Mail.tm mailboxes. - Pass the Mail.tm password through the existing Gradle `BuildConfig`/`BuildValues` pattern without committing credentials. - Add checkpoint-aware OTP polling, resend handling, MIME-aware OTP extraction, and bounded retries. - Force HTTP/1.1 for compatibility with the existing OkHttp client and Mail.tm. - Remove obsolete 1secmail response models and add regression coverage for the Mail.tm transport and inbox behavior. ## Motivation Native Auth end-to-end tests need both dynamically created signup inboxes and an authenticated persistent inbox for SSPR. Mail.tm supports both workflows, while the previous unauthenticated 1secmail integration cannot support the persistent SSPR mailbox used by the re-enabled tests. ## Validation - `.\gradlew.bat :testutils:clean :testutils:assembleDebug :testutils:testDebugUnitTest --no-daemon`: passed locally. - All MSAL tests passed after applying the corresponding MSAL changes against Common commit `ddb306a3884f9621e53b6eb3256fc14ea1497c7c`. - The corresponding MSAL changes will be submitted in a separate PR. ## Pipeline configuration - The MSAL consumer-validation task passes the secured Azure DevOps variable `EMAIL_PROVIDER_PASSWORD` from the pipeline's linked variable groups to Common as `-PemailProviderPassword=$(EMAIL_PROVIDER_PASSWORD)`; Common exposes it through generated `BuildConfig` and `BuildValues` without committing the secret. ## Related work - Fixes [AB#3720943](https://identitydivision.visualstudio.com/fac9d424-53d2-45c0-91b5-ef6ba7a6bf26/_workitems/edit/3720943) - AzureAD/microsoft-authentication-library-for-android#2553 ## Merge sequencing This PR is the expand step of a cross-repository migration: it temporarily retains `generateRandomEmailAddressLocally()` so both `dev` branches remain buildable. After AzureAD/microsoft-authentication-library-for-android#2553 migrates callers to `createRandomEmailAddress()` or `generateRandomUnregisteredEmailAddress()` and merges, the compatibility method will be removed in a Common follow-up. --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Copilot-Session: 83947e30-5bc9-4ec7-a8ed-c03d4415da92
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Resolve the Common submodule pointer in favor of the current Common dev commit containing the merged Mail.tm integration. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
| - task: Gradle@2 | ||
| displayName: Run Native Auth E2E Tests | ||
| inputs: | ||
| tasks: msal:testLocalDebugUnitTest -Plabtest -ProbolectricSdkVersion=${{variables.robolectricSdkVersion}} -PnativeAuthConfigString=$(NATIVE_AUTH_CONFIG_STRING) --tests com.microsoft.identity.client.e2e.tests.network.nativeauth.* |
There was a problem hiding this comment.
Are we gating every PR on these now? They hit mail.tm + a live tenant, and these are the same tests that were iGnOrE (@ignore)'d for OTP flakiness. I feel like unrelated PRs will start failing validation whenever mail.tm has a hiccup or the tenant throttles OTPs. Could these run on a nightly/scheduled pipeline instead of the per-PR gate?
There was a problem hiding this comment.
Fair point — a mail.tm hiccup shouldn't fail a PR that never touched Native Auth.
I went with an escape hatch rather than nightly: a skip-native-auth-e2e-tests label drops the E2E task (same thing iOS does in pr-validation.yml), plus a 30 min timeout. The label check fail-safes to skipping, so if the labels API is down it can't block anything either.
Keeping them on the gate is what makes a regression attributable to the PR that caused it. The label gives us the unblock without giving up that attribution.
Let me know if you think that's a reasonable solution
Responds to review comments on PR #2553, aligning with the equivalent iOS/ObjC implementation (microsoft-authentication-library-for-objc). - pr-msal.yml: add a "skip-native-auth-e2e-tests" label opt-out so a PR is not blocked by live mail.tm / tenant availability. The check fail-safes to skipping when the labels API is unreachable or the build is not a PR build. Also bound the E2E task with timeoutInMinutes: 30. - Replace the brittle AADSTS701014 substring match with a typed classifier (NativeAuthEmailOTPErrorClassifier), mirroring iOS MSALNativeAuthEmailOTPErrorClassifier. AssertUtils now throws NativeAuthAssertionError carrying the typed Error, so the OTP throttle is detected from Error.errorCodes first, with the description substring retained only for failures that never carry typed codes. Adds 12 unit tests for the classifier. - Reduce throttle retry cost: 5 retries with uncapped exponential backoff (~155s) becomes 3 retries with a 20s cap (~35s worst case). Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 8ace3950-0a5f-47cf-bc7e-33687e701f5f
| echo "Fetching PR labels from ${LABELS_URL}" | ||
| # Capture the body and the HTTP status separately, so that a failed API call is | ||
| # distinguishable from a successful call that simply returned no matching label. | ||
| HTTP_STATUS=$(curl -sS -o "$LABELS_FILE" -w "%{http_code}" "$LABELS_URL" || echo "000") |
There was a problem hiding this comment.
This label check hits api.github.com unauthenticated. Unauth github API is 60/hr per IP, and on the shared windows-2022 pool that egress IP is shared across a ton of jobs, so on a busy day this'll come back 403 rate-limited. The fail-safe right below then treats any non-200 as skip=true, so the native auth e2e tests we're re-enabling would just silently stop running with a green pipeline and nobody notices. kinda defeats the point of making them a PR gate.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 556e2a2c-f4a4-4c93-8aa6-e1e414b4dd8e
|
Copilot resolve the merge conflicts in this pull request, point the submodule to latest common dev branch |
Co-authored-by: djanardhan98 <307255345+djanardhan98@users.noreply.github.com>
Resolved the merge conflict and updated |
| if (errorCodes?.contains(THROTTLE_ERROR_CODE) == true) { | ||
| return true | ||
| } | ||
| return errorDescription?.contains(THROTTLE_ERROR_DESCRIPTION_MARKER) ?: false |
There was a problem hiding this comment.
I don't think the typed errorCodes path here fires for SSPR or sign-up at all. ResetPasswordChallengeApiResponse and SignUpChallengeApiResponse in common don't parse error_codes, and NativeAuthMsalController builds the APIError for those two challenge failures without errorCodes (reset password around line 1310, signup around 2025), so Error.errorCodes comes back null on both. Only signin/JIT challenge responses carry error_codes. 701014 also isn't in any of common's known-code lists.
So for the flows this PR re-enables (SSPR is right in the title) isThrottleError only ever reaches the errorDescription.contains("AADSTS701014") fallback. That's the same substring match we had before the classifier. The typed-first shape kinda implies the structured code is the primary signal, but for these two flows it's always null.
Are we ok leaning on the AADSTS701014 substring for SSPR/signup, given the typed path can't fire there?
| val actual = assertThrows(IllegalStateException::class.java) { | ||
| retryOperation(maxRetries = 1) { | ||
| attempts++ | ||
| throw expected |
There was a problem hiding this comment.
IllegalStateException isn't an AssertionError, so it never reaches the catch (e: AssertionError) in retryOperation. it just falls straight through here, so this is only really checking that a stray RuntimeException isn't swallowed, not the throttle gating.
the branch I'd want pinned is a non-701014 AssertionError getting rethrown with no retry (the isThrottleError false -> throw e path). can we add that case? attempts should still be 1 and the original error should come back out.
Summary
Motivation
Native Auth end-to-end tests need both dynamically created signup inboxes and an authenticated persistent inbox for SSPR. The Mail.tm integration in Common supports both workflows and allows the previously disabled SSPR coverage to run in CI.
Validation
ddb306a3884f9621e53b6eb3256fc14ea1497c7c.Pipeline configuration
EMAIL_PROVIDER_PASSWORDvariable to the Native Auth end-to-end test task.Dependency and merge sequencing
Merge the Common PR first, then update this PR's Common submodule reference to the merged commit before merging.
Fixes AB#3729032