Add NativeAuthRequestInterceptor for custom per-request headers and UI Automation, Fixes AB#3600652#3112
Conversation
Implement custom HTTP headers request interceptor for native auth CIAM requests, matching the iOS PR (microsoft-authentication-library-for-objc#2862). - Add NativeAuthRequestInterceptor interface for injecting custom x-* headers - Add NativeAuthHeaderValidator to enforce header naming rules - Pass interceptor through the full config propagation chain: OAuth2StrategyParameters → NativeAuthCIAMAuthority → NativeAuthOAuth2Configuration → NativeAuthOAuth2StrategyFactory → all 4 interactors (SignIn, SignUp, ResetPassword, JIT) - Add interceptor field to BaseNativeAuthCommandParameters - Wire interceptor in NativeAuthMsalController.createOAuth2Strategy() - Add unit tests for header validation (11 tests) - Add integration tests for interceptor in SignInInteractor (6 tests) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
@copilot resolve the merge conflicts in this pull request |
Co-authored-by: spetrescu84 <111577419+spetrescu84@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Adds a NativeAuthRequestInterceptor extension point that lets applications inject custom x-* HTTP headers (e.g., Akamai/fraud signals) into native-auth (CIAM) network requests. The interceptor is threaded from BaseNativeAuthCommandParameters through OAuth2StrategyParameters → NativeAuthCIAMAuthority → NativeAuthOAuth2Configuration → NativeAuthOAuth2StrategyFactory and into all four interactors (SignIn, SignUp, ResetPassword, JIT). A NativeAuthHeaderValidator enforces the x- prefix and rejects reserved prefixes (x-ms-, x-client-, x-broker-, x-app-).
Changes:
- New
NativeAuthRequestInterceptorinterface andNativeAuthHeaderValidator(with unit tests) for additive, validated headers. - Interceptor field added to
OAuth2StrategyParameters,BaseNativeAuthCommandParameters,NativeAuthOAuth2Configuration, and the four interactors;NativeAuthMsalController.createOAuth2Strategypropagates it; identicalapplyInterceptorHeadershelper duplicated in each interactor. - Integration tests for
SignInInteractor(only) covering merge, null/empty interceptor, reserved-prefix filtering, URL passthrough; changelog entry added.
Reviewed changes
Copilot reviewed 15 out of 15 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| common4j/.../providers/NativeAuthRequestInterceptor.kt | New SAM-style interface for per-request additional headers. |
| common4j/.../providers/NativeAuthHeaderValidator.kt | New validator filtering headers by prefix rules. |
| common4j/.../providers/NativeAuthOAuth2Configuration.kt | Adds nullable requestInterceptor config field. |
| common4j/.../providers/NativeAuthOAuth2StrategyFactory.kt | Passes interceptor into all four interactors. |
| common4j/.../providers/interactors/SignInInteractor.kt | Adds interceptor field + applyInterceptorHeaders and applies to 4 calls. |
| common4j/.../providers/interactors/SignUpInteractor.kt | Same interceptor wiring as SignIn (no tests added). |
| common4j/.../providers/interactors/ResetPasswordInteractor.kt | Same interceptor wiring (no tests added). |
| common4j/.../providers/interactors/JITInteractor.kt | Same interceptor wiring (no tests added). |
| common4j/.../authorities/NativeAuthCIAMAuthority.kt | Threads interceptor from strategy params into config; uses fully-qualified type name. |
| common4j/.../providers/oauth2/OAuth2StrategyParameters.java | Adds mRequestInterceptor; introduces dependency from generic OAuth2 layer to nativeauth package. |
| common4j/.../commands/parameters/BaseNativeAuthCommandParameters.java | Adds transient requestInterceptor field (excluded from equals/hash). |
| common/.../controllers/NativeAuthMsalController.kt | Forwards parameters.requestInterceptor into the strategy params builder. |
| common4j/.../NativeAuthHeaderValidatorTest.kt | New unit tests for the prefix validator. |
| common4j/.../SignInInteractorRequestInterceptorTest.kt | New tests for interceptor behavior, only covering SignIn. |
| changelog.txt | Adds entry with empty PR number (#) and misleading "HttpRequest interceptor" wording. |
Comments suppressed due to low confidence (1)
common4j/src/main/com/microsoft/identity/common/java/nativeauth/providers/interactors/SignInInteractor.kt:74
additionalHeadersis invoked from inside the network call path with notry/catcharound it (seeapplyInterceptorHeadersin each interactor). A buggy interceptor implementation that throws (e.g., NPE while computing a fraud signal) will tear down the entire token request with an unrelated exception type that the existing native-auth error mapping is not designed to handle. Consider catchingThrowablefrom the interceptor invocation, logging it, and falling back to no extra headers so an interceptor crash cannot break sign-in/sign-up/reset-password/JIT for end users.
private fun applyInterceptorHeaders(requestUrl: URL, headers: Map<String, String?>): Map<String, String?> {
if (requestInterceptor == null) return headers
val additionalHeaders = requestInterceptor.additionalHeaders(requestUrl) ?: return headers
val validHeaders = NativeAuthHeaderValidator.filterValidHeaders(additionalHeaders)
if (validHeaders.isEmpty()) return headers
val mergedHeaders = headers.toMutableMap()
mergedHeaders.putAll(validHeaders)
return mergedHeaders
}
| @@ -61,6 +62,12 @@ public class OAuth2StrategyParameters { | |||
| @Nullable | |||
| public final List<String> mCapabilities; | |||
|
|
|||
| /** | |||
| * An optional interceptor for injecting custom HTTP headers into native auth requests. | |||
| */ | |||
| @Nullable | |||
| public final transient NativeAuthRequestInterceptor mRequestInterceptor; | |||
Resolved and pushed. I merged |
|
@copilot apply changes based on the comments in this thread |
Agent-Logs-Url: https://github.com/AzureAD/microsoft-authentication-library-common-for-android/sessions/3a466cba-db2f-42cd-afa9-92e96cef6792 Co-authored-by: spetrescu84 <111577419+spetrescu84@users.noreply.github.com>
Agent-Logs-Url: https://github.com/AzureAD/microsoft-authentication-library-common-for-android/sessions/3a466cba-db2f-42cd-afa9-92e96cef6792 Co-authored-by: spetrescu84 <111577419+spetrescu84@users.noreply.github.com>
Applied the linked review-thread updates in Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
- Add SignUpInteractorRequestInterceptorTest (8 tests) - Add ResetPasswordInteractorRequestInterceptorTest (7 tests) - Add JITInteractorRequestInterceptorTest (5 tests) - Expand SignInInteractorRequestInterceptorTest to cover all 7 methods (12 tests) - Total: 43 tests (32 interactor + 11 validator), all passing Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
❌ Work item link check failed. Description does not contain AB#{ID}. Click here to Learn more. |
|
@copilot apply changes based on the comments in this thread |
Applied. The review-thread items are implemented in the latest commits, including shared interceptor header handling, case-insensitive header normalization/merge behavior, generic OAuth2 interceptor decoupling, and follow-up docs/guards/tests ( |
|
@copilot apply changes based on the comments in this thread |
Applied; the linked review-thread changes are already in the branch via |
Switches Maven publishing from the AndroidADAL feed to the NewAndroid feed to eliminate the upstream-feed traversal latency that occurs when downstream pipeline stages resolve freshly-published artifacts. Background: - Builds publish to AndroidADAL but consumers fetch from NewAndroid. - NewAndroid resolves AndroidADAL only via its upstream chain, after walking Maven Central, Google, etc., causing first-fetch latency on every newly published version (which CI agents always pay due to ephemeral caches). - AndroidADAL will be added as an upstream of NewAndroid (done outside this change) so any external consumers still resolving from AndroidADAL keep working transparently. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
| override fun createOAuth2Strategy(parameters: OAuth2StrategyParameters): NativeAuthOAuth2Strategy { | ||
| val config = createNativeAuthOAuth2Configuration(parameters.mChallengeTypes, parameters.mCapabilities) | ||
| if (parameters.mRequestInterceptor != null && parameters.mRequestInterceptor !is NativeAuthRequestInterceptor) { | ||
| Logger.warn(TAG, "Ignoring non-native OAuth2RequestInterceptor for NativeAuthCIAMAuthority.") |
There was a problem hiding this comment.
I think WARN message is misleading the situation.
There was a problem hiding this comment.
I've changed how this works, please take a look
Each test now uses the actual production endpoint URL for its method (e.g., /signup/v1.0/challenge for performChallenge) instead of a single shared URL per file. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The publishing block in testutils and uiautomationutilities iterates
implementation dependencies to populate the generated POM. For project
deps like project(':keyvault'), it.version reads project(':keyvault').version
-- which Gradle defaults to the string 'unspecified' if that sibling
project hasn't been configured yet.
With Gradle configure-on-demand enabled, the publish task for common
may run without configuring sibling projects like :keyvault, :labapi,
:common, etc. The published POM then contained 'keyvault:unspecified',
which caused downstream consumers (AADAuthenticator distDebugUnitTest)
to fail at dependency resolution.
Fix: for project dependencies, write the current artifact's version
(getAppVersionName()) since all sibling library projects share the same
version. External dependencies still use it.version as before.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
thentication-library-common-for-android into fadi/publish-libraries-to-newandroid-feed
Replace all usages of NativeAuthRequestInterceptor in common with the base OAuth2RequestInterceptor type. The NativeAuthRequestInterceptor interface is a public-facing API that customers implement, so it belongs in the MSAL module (com.microsoft.identity.nativeauth package) following the established pattern for public nativeauth types. Common now uses OAuth2RequestInterceptor internally, which is the parent interface with the same contract. Any MSAL-level NativeAuthRequestInterceptor implementation will satisfy this type since it extends OAuth2RequestInterceptor. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
mustafamizrak
left a comment
There was a problem hiding this comment.
Why did you move NativeAuthRequestInterceptor to MSAL module? What are the reasons?
We use NativeAuthRequestInterceptor in public api, that is why we moved it to the main MSAL module. Common core code should not be exposed in the public api. |
…t) to resolve MSAL submodule conflict Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…xes AB#3618269 (#3146) [AB#3618269](https://identitydivision.visualstudio.com/fac9d424-53d2-45c0-91b5-ef6ba7a6bf26/_workitems/edit/3618269) When release-integration/24.3.0 was back-merged into dev (#3131), some entries that were merged to dev *after* the 24.3.0 RC cut got listed under `Version 24.3.0`. They actually shipped in dev *after* 24.3.0 was finalized, so they belong under `vNext` for the next release. This PR moves 5 entries from `Version 24.3.0` to `vNext`: - #3133 SwitchBrowserRedirectActivity for non-broker Switch Browser flows - #3125 Update OpenTelemetry to 1.62.0 - #3135 Disabling GetCookies API from webapps APIs - #3132 Enable passkey registration by default in CommonFlight - #3112 Add NativeAuthRequestInterceptor for native auth flows Note: #3128 (Fix Token Endpoint Server Telemetry Parsing) correctly stays under Version 24.3.0 because it was cherry-picked into the release branch before the RC cut. ### Verification Identified by diffing the current dev `changelog.txt` against the file at commit `e80117451` (final 24.3.0 "remove RC" cut). Any entry currently listed under Version 24.3.0 that wasn't present at the RC cut must have arrived via the back-merge. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Implement custom HTTP headers request interceptor for native auth CIAM requests
UI Automation Test Support
NativeAuthSampleApp.java— App model class for UI automation (package name, APK filename constants, no-ophandleFirstRun()/initialiseAppImpl())CopyFileRule.java— AddedNativeAuthSampleApp.NATIVE_AUTH_SAMPLE_APKto the list of APKs copied from/sdcard/to/data/local/tmp/at test runtimeLabConstants.java— AddedCIAMuser type constantUserType.java— AddedCIAMenum value for lab queriesAPI Change: NativeAuthRequestInterceptor moved to MSAL
The
NativeAuthRequestInterceptorinterface has been moved to the MSAL module (com.microsoft.identity.nativeauthpackage) as it is a public-facing type that customers implement. Common now uses the baseOAuth2RequestInterceptortype internally, whichNativeAuthRequestInterceptorextends. This follows the established pattern where public nativeauth types live in MSAL.AB#3600652