Skip to content

Add AuthTab support for MSAL browser auth and Broker DUNA flows, Fixes AB#3533538#2998

Draft
Copilot wants to merge 2 commits intodevfrom
copilot/add-auth-tab-support-again
Draft

Add AuthTab support for MSAL browser auth and Broker DUNA flows, Fixes AB#3533538#2998
Copilot wants to merge 2 commits intodevfrom
copilot/add-auth-tab-support-again

Conversation

Copy link
Contributor

Copilot AI commented Mar 4, 2026

Chrome 137+ introduces AuthTabIntent (androidx.browser:browser:1.9.0), which returns auth results via ActivityResultCallback instead of intent-based redirects — improving security and simplifying redirect handling. This PR wires up AuthTab support behind an ENABLE_AUTH_TAB feature flag (default false) for two flows: MSAL interactive browser auth and Broker Switch Browser (DUNA).

Changes

Feature Flag

  • CommonFlight.ENABLE_AUTH_TAB("EnableAuthTab", false) added to CommonFlight.java

Dependency

  • browserVersion: 1.7.01.9.0 in gradle/versions.gradle

Telemetry (AttributeName.java)

  • New attributes: is_auth_tab_used, auth_tab_result_code, auth_tab_supported

New: AuthTabAuthorizationFragment (MSAL browser flow)

Extends AuthorizationFragment; replaces BrowserAuthorizationFragment when ENABLE_AUTH_TAB is on.

  • Registers ActivityResultLauncher in onCreate() (required before STARTED state)
  • Launches AuthTabIntent in onResume() with requestUrl/redirectScheme from arguments
  • Handles all result codes: RESULT_OK, RESULT_CANCELED, RESULT_VERIFICATION_FAILED, RESULT_VERIFICATION_TIMED_OUT
  • Second onResume() without a callback result → treated as user cancellation
mAuthTabLauncher = AuthTabIntent.registerActivityResultLauncher(this) { handleAuthResult(it) }
// ...
val authTabIntent = AuthTabIntent.Builder().build()
authTabIntent.launch(launcher, Uri.parse(requestUrl), redirectScheme)

AuthorizationActivityFactory update

  • Non-WebView, non-current-task path: if ENABLE_AUTH_TAB is enabled → returns AuthTabAuthorizationFragment() instead of BrowserAuthorizationFragment()

SwitchBrowserActivity update (DUNA flow)

  • Registers AuthTabIntent.ActivityResultLauncher in onCreate()
  • launchBrowser() pre-checks ENABLE_AUTH_TAB flag + CustomTabsManager.isAuthTabSupported() before the existing Custom Tabs path
  • handleAuthTabResult(): RESULT_OK → passes URI via WebViewAuthorizationFragment.setSwitchBrowserBundle() + finishAndRemoveTask(); cancel/error → finishAndRemoveTask()

CustomTabsManager.isAuthTabSupported() helper

Static method wrapping CustomTabsClient.isAuthTabSupported(context, browserPackage) with null-safety and logging.

Tests (AuthorizationActivityFactoryTest)

  • ENABLE_AUTH_TAB = truegetAuthorizationFragmentFromStartIntent() returns AuthTabAuthorizationFragment
  • ENABLE_AUTH_TAB = false → returns BrowserAuthorizationFragment (existing behavior unchanged)

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:

  • dl.google.com
    • Triggering command: /usr/lib/jvm/temurin-17-jdk-amd64/bin/java /usr/lib/jvm/temurin-17-jdk-amd64/bin/java --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.lang.invoke=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.prefs/java.util.prefs=ALL-UNNAMED --add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED --add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.prefs/java.util.prefs=ALL-UNNAMED --add-opens=java.base/java.nio.charset=ALL-UNNAMED --add-opens=java.base/java.net=ALL-UNNAMED --add-opens=java.base/java.util.concurrent.atomic=ALL-UNNAMED --add-opens=java.xml/javax.xml.namespace=ALL-UNNAMED -XX:MaxMetaspaceSize=1024m -XX:+HeapDumpOnOutOfMemoryError -Xmx3072m -Dfile.encoding=UTF-8 -Duser.country -Duser.language=en -Duser.variant (dns block)
  • identitydivision.pkgs.visualstudio.com
    • Triggering command: /usr/lib/jvm/temurin-17-jdk-amd64/bin/java /usr/lib/jvm/temurin-17-jdk-amd64/bin/java --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.lang.invoke=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.prefs/java.util.prefs=ALL-UNNAMED --add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED --add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.prefs/java.util.prefs=ALL-UNNAMED --add-opens=java.base/java.nio.charset=ALL-UNNAMED --add-opens=java.base/java.net=ALL-UNNAMED --add-opens=java.base/java.util.concurrent.atomic=ALL-UNNAMED --add-opens=java.xml/javax.xml.namespace=ALL-UNNAMED -XX:MaxMetaspaceSize=1024m -XX:+HeapDumpOnOutOfMemoryError -Xmx3072m -Dfile.encoding=UTF-8 -Duser.country -Duser.language=en -Duser.variant (dns block)
  • www.puppycrawl.com
    • Triggering command: /opt/hostedtoolcache/CodeQL/2.24.2/x64/codeql/tools/linux64/java/bin/java /opt/hostedtoolcache/CodeQL/2.24.2/x64/codeql/tools/linux64/java/bin/java -jar /opt/hostedtoolcache/CodeQL/2.24.2/x64/codeql/xml/tools/xml-extractor.jar --fileList=/tmp/codeql-scratch-b2678d0398b00160/dbs/java/working/files-to-index8780552885994131758.list --sourceArchiveDir=/tmp/codeql-scratch-b2678d0398b00160/dbs/java/src --outputDir=/tmp/codeql-scratch-b2678d0398b00160/dbs/java/trap/java /opt/hostedtoolcache/CodeQL/2.24.2/x64/codeql/java/tools/setup-proxy.gradle --init-script /opt/hostedtoolcache/CodeQL/2.24.2/x64/codeql/java/tools/dep-graph.gradle ForceDependencyResolutionPlugin_resolveAllDependencies --stacktrace -DGITHUB_DEPENDENCY_GRAPH_JOB_CORRELATOR=dep-graph (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Original prompt

Fixes AB#3533538

Objective

Implement full AuthTab support in the Common repo: add the ENABLE_AUTH_TAB feature flag to CommonFlight, create a new AuthTabAuthorizationFragment for MSAL browser flows, update AuthorizationActivityFactory to route to it, update SwitchBrowserActivity for DUNA flows, add an isAuthTabSupported() helper in CustomTabsManager, and bump androidx.browser to 1.9.0.

Target Repository

  • Repo: AzureAD/microsoft-authentication-library-common-for-android
  • Base Branch: dev
  • Module: common4j + common

Context

Chrome 137+ introduces AuthTab (AuthTabIntent from androidx.browser:browser:1.9.0), a specialized Custom Tab for authentication. AuthTab returns results via ActivityResultCallback instead of intent-based redirects, improving security and simplifying the flow. This PBI implements AuthTab support for two paths:

  1. MSAL interactive browser auth - A new AuthTabAuthorizationFragment replaces BrowserAuthorizationFragment when AuthTab is enabled and supported.
  2. Broker Switch Browser (DUNA) - SwitchBrowserActivity gains an AuthTab launch path alongside its existing Custom Tabs path.

Both paths fall back to standard Custom Tabs when the browser doesn't support AuthTab.

Feature Flag

Create a new ENABLE_AUTH_TAB enum value in CommonFlight.java (common4j module) with config key "EnableAuthTab" and default false. Follow the pattern of SWITCH_BROWSER_PROTOCOL_REQUIRES_STATE. Then gate all new behavior behind CommonFlightsManager.getFlightsProvider().isFlightEnabled(CommonFlight.ENABLE_AUTH_TAB).

Technical Requirements

1. Feature Flag (common4j)

  • Add ENABLE_AUTH_TAB("EnableAuthTab", false) to CommonFlight.java
  • Add JavaDoc: enables Chrome AuthTab (Chrome 137+) for browser-based auth flows

2. Dependency Bump

  • Change browserVersion = "1.7.0" to browserVersion = "1.9.0" in gradle/versions.gradle

3. New AuthTabAuthorizationFragment.kt (common)

  • Create in common/src/main/java/com/microsoft/identity/common/internal/providers/oauth2/
  • Extends AuthorizationFragment
  • In onCreate(), register ActivityResultLauncher via AuthTabIntent.registerActivityResultLauncher(this, ::handleAuthResult) - MUST be before STARTED state
  • In onResume(), build AuthTabIntent.Builder().build() and call authTabIntent.launch(launcher, uri, redirectScheme)
  • Extract requestUrl and redirectScheme from fragment arguments (same pattern as BrowserAuthorizationFragment gets mAuthIntent)
  • Handle AuthResult: RESULT_OK -> sendResult(RawAuthorizationResult.fromRedirectUri(...)), RESULT_CANCELED -> cancelAuthorization(true), RESULT_VERIFICATION_FAILED/TIMED_OUT -> send exception result
  • Add telemetry span attributes: is_auth_tab_used, auth_tab_result_code, auth_tab_supported
  • Log all decision points via Logger class
  • Handle onSaveInstanceState/extractState for authFlowStarted flag

4. Update AuthorizationActivityFactory.kt

  • In getAuthorizationFragmentFromStartIntent(), when agent is NOT WEBVIEW, check CommonFlight.ENABLE_AUTH_TAB. If true, return AuthTabAuthorizationFragment()
  • Runtime browser support check happens inside the fragment itself

5. Update SwitchBrowserActivity.kt

  • In launchBrowser(), before existing Custom Tabs check: if AuthTab flag on + CustomTabsClient.isAuthTabSupported() returns true, launch via AuthTabIntent
  • Register ActivityResultLauncher in onCreate() (must be before onStart)
  • Handle result: RESULT_OK -> pass URI to WebViewAuthorizationFragment.setSwitchBrowserBundle() + finishAndRemoveTask(); cancel/error -> finishAndRemoveTask()

6. Add isAuthTabSupported() to CustomTabsManager.java

  • Static method: public static boolean isAuthTabSupported(@NonNull Context context, @NonNull String browserPackage)
  • Wraps CustomTabsClient.isAuthTabSupported() with null-safety and logging

Files to Modify/Create

  • common4j/src/main/com/microsoft/identity/common/java/flighting/CommonFlight.java - Add ENABLE_AUTH_TAB enum
  • gradle/versions.gradle - browserVersion = "1.9.0"
  • common/src/main/java/com/microsoft/identity/common/internal/providers/oauth2/AuthTabAuthorizationFragment.kt - NEW: AuthTab authorization fragment
  • common/src/main/java/com/microsoft/identity/common/internal/providers/oauth2/AuthorizationActivityFactory.kt - Add AuthTab branch
  • common/src/main/java/com/microsoft/identity/common/internal/providers/oauth2/SwitchBrowserActivity.kt - Add AuthTab launch path
  • common/src/main/java/com/microsoft/identity/common/internal/ui/browser/CustomTabsManager.java - Add isAuthTabSupported()
  • common/src/test/java/com/microsoft/identity/common/internal/providers/oauth2/AuthTabAuthorizationFragmentTest.kt - NEW: Unit tests
  • common/src/test/java/com/microsoft/identity/common/internal/providers/oauth2/AuthorizationActivityFactoryTest.java - Add AuthTab tests

Acceptance Criteria

  • CommonFlight.ENABLE_AUTH_TAB exists w...

💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

@github-actions
Copy link

github-actions bot commented Mar 4, 2026

✅ Work item link check complete. Description contains link AB#3533538 to an Azure Boards work item.

@github-actions github-actions bot changed the title [WIP] Implement full AuthTab support in Common repo [WIP] Implement full AuthTab support in Common repo, Fixes AB#3533538 Mar 4, 2026
…rowserActivity, CustomTabsManager helper, and tests

Co-authored-by: shahzaibj <37125644+shahzaibj@users.noreply.github.com>
Copilot AI changed the title [WIP] Implement full AuthTab support in Common repo, Fixes AB#3533538 Add AuthTab support for MSAL browser auth and Broker DUNA flows Mar 4, 2026
@github-actions github-actions bot changed the title Add AuthTab support for MSAL browser auth and Broker DUNA flows Add AuthTab support for MSAL browser auth and Broker DUNA flows, Fixes AB#3533538 Mar 4, 2026
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