Skip to content

Veena/mob onb2#1689

Draft
swasti29 wants to merge 14 commits intodevfrom
veena/mob_onb2
Draft

Veena/mob onb2#1689
swasti29 wants to merge 14 commits intodevfrom
veena/mob_onb2

Conversation

@swasti29
Copy link
Contributor

@swasti29 swasti29 commented Feb 5, 2026

PR Title Format

Required Format: [Keyword1] [Keyword2]: Description

  • Keyword1: major, minor, or patch (case-insensitive)
  • Keyword2: feature, bugfix, engg, or tests (case-insensitive)

Examples:

  • [MAJOR] [Feature]: new API
  • [minor] [bugfix]: fix crash
  • [PATCH][tests]:add coverage

Proposed changes

Describe what this PR is trying to do.

Type of change

  • Feature work
  • Bug fix
  • Documentation
  • Engineering change
  • Test
  • Logging/Telemetry

Risk

  • High – Errors could cause MAJOR regression of many scenarios. (Example: new large features or high level infrastructure changes)
  • Medium – Errors could cause regression of 1 or more scenarios. (Example: somewhat complex bug fixes, small new features)
  • Small – No issues are expected. (Example: Very small bug fixes, string changes, or configuration settings changes)

Additional information

Copilot AI and others added 11 commits February 3, 2026 05:10
…activeController actions

- Created MSIDWebInstallProfileResponse class to detect and parse msauth://profileInstalled URLs
- Added response detection in MSIDAADWebviewFactory response chain
- Updated MSIDInteractiveAuthorizationCodeRequest to pass through profile installed responses
- Added handleWebInstallProfileResponse method in MSIDLocalInteractiveController
- Controller can now perform custom actions before continuing authentication flow
- Created comprehensive unit tests for the new response type

Co-authored-by: Veena11 <9446116+Veena11@users.noreply.github.com>
- Created MSIDWebviewTransitionCoordinator to manage state-preserving transitions
- Added MSIDWebProfileInstallTriggerResponse to detect msauth://profileInstall with HTTP headers
- Updated MSIDAADOAuthEmbeddedWebviewController to:
  - Capture HTTP response headers via navigationResponseBlock
  - Detect profile install trigger (msauth://profileInstall)
  - Extract profile installation URL from X-Profile-Install-URL header
  - Suspend embedded webview (hide UI but keep alive)
  - Launch ASWebAuthenticationSession with extracted URL
  - Wait for msauth://profileInstalled callback
  - Resume suspended embedded webview seamlessly
  - Continue authentication flow without cancellation
- Created comprehensive tests for trigger response detection

Co-authored-by: Veena11 <9446116+Veena11@users.noreply.github.com>
Corrected URL scheme names to match requirements:
- First 302: msauth://installProfile - triggers transition FROM embedded webview TO ASWebAuthenticationSession
- Second 302: msauth://profileInstalled - happens IN ASWebAuthenticationSession, triggers transition BACK to embedded webview

Changes:
- Updated MSIDWebProfileInstallTriggerResponse to detect msauth://installProfile
- Changed constant from PROFILE_INSTALL to INSTALL_PROFILE
- Updated all references to use installProfile instead of profileInstall
- Updated tests to use correct URL msauth://installProfile
- Updated comments and log messages for clarity
- Verified MSIDWebInstallProfileResponse correctly detects msauth://profileInstalled

Co-authored-by: Veena11 <9446116+Veena11@users.noreply.github.com>
…tiveController

- Removed profile installation handling from MSIDAADOAuthEmbeddedWebviewController
- Embedded webview now only detects msauth://installProfile and returns it via completion handler
- MSIDLocalInteractiveController now orchestrates the entire profile installation flow
- Added handleProfileInstallTrigger method to controller
- Added handleProfileInstallationCompletion method to controller
- Controller now manages MSIDWebviewTransitionCoordinator
- Controller suspends/resumes webview and launches ASWebAuthenticationSession
- Follows existing pattern used for MSIDWebWPJResponse
- Maintains separation of concerns: view detects, controller orchestrates

Co-authored-by: Veena11 <9446116+Veena11@users.noreply.github.com>
- Updated MSIDWebProfileInstallTriggerResponse to extract x-intune-url and x-intune-token headers
- Replaced profileInstallURL property with intuneURL
- Added intuneToken property for authentication
- Added extractHeaderValue helper for case-insensitive header matching
- Updated MSIDASWebAuthenticationSessionHandler to support additionalHeaders parameter (iOS 18+)
- Added new initializer with additionalHeaders support
- Use additionalHeaderFields property when iOS 18+ available
- Updated MSIDWebviewTransitionCoordinator to pass additional headers
- Updated MSIDLocalInteractiveController to build headers dictionary with x-intune-token
- Updated all tests to use new header names (x-intune-url, x-intune-token)
- Added tests for both headers extraction and case-insensitive matching

Co-authored-by: Veena11 <9446116+Veena11@users.noreply.github.com>
…ctory access

- Added lastHTTPResponse property to MSIDWebviewSession
- Updated MSIDAADOAuthEmbeddedWebviewController to store HTTP response in session
- Updated MSIDWebviewAuthorization to pass httpResponse to factory
- Added new overload methods to configuration classes accepting httpResponse parameter
- Added new overload to MSIDWebviewFactory.oAuthResponseWithURL with httpResponse
- Updated MSIDAADWebviewFactory to create MSIDWebProfileInstallTriggerResponse with HTTP headers
- HTTP response now flows: Webview → Session → Authorization → Factory → Response
- Intune URL and token now properly extracted from HTTP headers
- Controller receives response with both intuneURL and intuneToken populated
- Backward compatible: New methods with default implementations

Co-authored-by: Veena11 <9446116+Veena11@users.noreply.github.com>
…AuthenticationSession flow

- Renamed profileSessionHandler → externalSessionHandler (generic naming)
- Renamed launchProfileInstallationSession → launchExternalSession (generic naming)
- Renamed dismissProfileInstallationSession → dismissExternalSession (generic naming)
- Updated all method parameters to be generic (profileURL → url)
- Updated documentation to describe generic external session flows
- Updated log messages to be generic (external session vs profile installation)
- Updated error messages to be generic
- Updated MSIDLocalInteractiveController to use new method names
- Coordinator is now reusable for ANY flow requiring ASWebAuthenticationSession transition
- No functional changes, only naming improvements for reusability

Co-authored-by: Veena11 <9446116+Veena11@users.noreply.github.com>
@swasti29
Copy link
Contributor Author

swasti29 commented Feb 5, 2026

@copilot can you create the design doc for this change

Copy link
Contributor

Copilot AI commented Feb 5, 2026

@swasti29 I've opened a new pull request, #1690, to work on those changes. Once the pull request is ready, I'll request review from you.

@@ -729,8 +729,24 @@
60F94D332210E8BD0035D956 /* MSIDV1IdToken.m in Sources */ = {isa = PBXBuildFile; fileRef = 60F94D312210E8BD0035D956 /* MSIDV1IdToken.m */; };

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This pull request does not update changelog.txt.

Please consider if this change would be noticeable to a partner or user and either update changelog.txt or resolve this conversation.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR implements Mobile Device Management (MDM) profile installation support for iOS applications. It introduces a sophisticated webview transition mechanism that allows seamless switching between embedded webviews and ASWebAuthenticationSession during the authentication flow, specifically to handle Intune MDM profile installation.

Changes:

  • Adds new response classes (MSIDWebMDMInstallProfileResponse, MSIDWebMDMEnrollmentCompletionResponse) for handling MDM enrollment flows
  • Implements MSIDWebviewTransitionCoordinator to manage transitions between embedded webview and ASWebAuthenticationSession
  • Introduces navigation action system (MSIDWebviewNavigationAction, MSIDWebviewNavigationActionUtil) for handling special URL schemes (msauth://, browser://)
  • Extends ASWebAuthenticationSession to support additional HTTP headers (iOS 17.4+)
  • Adds BRT (Broker Refresh Token) acquisition logic placeholder in MSIDLocalInteractiveController

Reviewed changes

Copilot reviewed 38 out of 38 changed files in this pull request and generated 29 comments.

Show a summary per file
File Description
MSIDWebProfileInstallTriggerResponseTests.m Test file for profile install trigger response (references non-existent class)
MSIDWebInstallProfileResponseTests.m Test file for profile installed response (references non-existent class)
MSIDASWebAuthenticationSessionHandler.m Adds additional headers support for ASWebAuthenticationSession
MSIDASWebAuthenticationSessionHandler.h New initializer with additionalHeaders parameter
MSIDWebMDMInstallProfileResponse.m Implementation for detecting profile install trigger URLs
MSIDWebMDMInstallProfileResponse.h Header for profile install trigger response class
MSIDWebMDMEnrollmentCompletionResponse.m Implementation for profile installation completion response
MSIDWebMDMEnrollmentCompletionResponse.h Header for enrollment completion response class
MSIDWebviewSpecialNavigationDelegate.h Protocol for handling special navigation redirects
MSIDWebviewNavigationAction.m Implementation of navigation action types and factory methods
MSIDWebviewNavigationAction.h Header defining navigation action types and enum
MSIDOAuth2EmbeddedWebviewController.h Adds specialNavigationDelegate property
MSIDAADOAuthEmbeddedWebviewController.m Implements special redirect handling and action execution
MSIDAADOAuthEmbeddedWebviewController.h Documentation for special navigation delegate
MSIDWebviewTransitionCoordinator.m Coordinates webview transitions with suspend/resume logic
MSIDWebviewTransitionCoordinator.h Header for webview transition coordinator
MSIDWebviewNavigationActionUtil.m Utility for resolving actions from msauth URLs
MSIDWebviewNavigationActionUtil.h Header for navigation action utility
MSIDLocalInteractiveController.m Orchestrates MDM flow, BRT acquisition, and webview configuration
MSIDLocalInteractiveController.h Adds MSIDWebviewSpecialNavigationDelegate conformance
MSIDLocalInteractiveController+Internal.h Internal properties for BRT state tracking
MSIDInteractiveTokenRequest.m Updates completion block type to use MSIDWebviewResponse
MSIDInteractiveTokenRequest+Internal.h Forward declaration for webview interacting protocol
MSIDInteractiveRequestControlling.h Updates completion block type signature
MSIDInteractiveAuthorizationCodeRequest.m Adds webview configuration, handles MDM responses
MSIDInteractiveAuthorizationCodeRequest.h Adds currentWebview property, updates completion block
MSIDInteractiveTokenRequestParameters.h Adds webviewConfigurationBlock property
MSIDAADWebviewFactory.m Adds MDM response creation in factory
MSIDWebviewFactory.m Adds responseHeaders parameter support
MSIDWebviewFactory.h New method signature with responseHeaders
MSIDBaseWebRequestConfiguration.m Implements responseHeaders parameter support
MSIDBaseWebRequestConfiguration.h Declares method with responseHeaders parameter
MSIDAuthorizeWebRequestConfiguration.m Forwards responseHeaders to factory
MSIDWebviewSession.h Adds lastResponseHeaders property
MSIDWebviewAuthorization.m Passes response headers to configuration
MSIDError.m Adds error code description for MDM enrollment
MSIDError.h Defines MSIDErrorMDMEnrollmentCompletedNeedsRetry constant
project.pbxproj Adds new files to Xcode project

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +123 to +130
if (@available(iOS 17.4, macOS 15.0, *))
{
self.webAuthSession.additionalHeaderFields = self.additionalHeaders;
MSID_LOG_WITH_CTX(MSIDLogLevelInfo, nil, @"Set %lu additional headers for ASWebAuthenticationSession", (unsigned long)self.additionalHeaders.count);
}
else
{
MSID_LOG_WITH_CTX(MSIDLogLevelWarning, nil, @"Additional headers provided but iOS 18+ required. Headers will be ignored.");
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The availability check uses iOS 17.4, but the log message warns about iOS 18+ being required. This is inconsistent. According to Apple documentation, ASWebAuthenticationSession.additionalHeaderFields was introduced in iOS 17.4, not iOS 18. Update the log message to match the actual availability check or vice versa.

Copilot uses AI. Check for mistakes.
- Acquired on FIRST msauth:// or browser:// redirect if needed
- Only ONE attempt per session (no retry)

Check before acquisition: !brtAcquired && !brtAttemptAttempted
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment has a typo: "Attemptted" should be "Attempted" (double 't' should be single 't').

Suggested change
Check before acquisition: !brtAcquired && !brtAttemptAttempted
Check before acquisition: !brtAcquired && !brtAttempted

Copilot uses AI. Check for mistakes.
Comment on lines +246 to +266
if (@available(iOS 18.0, macOS 15.0, *))
{
self.aSWebAuthenticationSessionHandler = [[MSIDASWebAuthenticationSessionHandler alloc] initWithParentController:parentController
startURL:url
callbackScheme:callbackScheme
useEmpheralSession:NO
additionalHeaders:additionalHeaders];
}
else
{
// Fallback for older OS versions (shouldn't happen since minimum is iOS 18 ?)
self.aSWebAuthenticationSessionHandler = [[MSIDASWebAuthenticationSessionHandler alloc] initWithParentController:parentController
startURL:url
callbackScheme:callbackScheme
useEmpheralSession:NO];

if (additionalHeaders && additionalHeaders.count > 0)
{
MSID_LOG_WITH_CTX(MSIDLogLevelWarning, nil, @"[MSIDWebviewTransitionCoordinator] Additional headers ignored - iOS 18+ required");
}
}
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same version check issue: line 246 uses iOS 18.0 but should use iOS 17.4 to match the actual availability of additionalHeaderFields. This is duplicated logic from the first method and should be corrected.

Copilot uses AI. Check for mistakes.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing space after period in license header: "NONINFRINGEMENT.IN NO EVENT" should be "NONINFRINGEMENT. IN NO EVENT".

Suggested change
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE

Copilot uses AI. Check for mistakes.
// THE SOFTWARE.

#import <XCTest/XCTest.h>
#import "MSIDWebInstallProfileResponse.h"
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test file imports MSIDWebInstallProfileResponse which doesn't exist in the implementation files. The actual implementation uses MSIDWebMDMEnrollmentCompletionResponse instead. This will cause compilation errors.

Copilot uses AI. Check for mistakes.
Comment on lines +255 to +289
case MSIDWebviewNavigationActionTypeOpenInASWebAuthenticationSession:
{
if (action.url)
{
MSID_LOG_WITH_CTX_PII(MSIDLogLevelInfo, self.context, @"URL needs to be opened in ASWebAuthenticationSession, calling CompleteWebauth with URL so controller can handle this via response: %@", MSID_PII_LOG_MASKABLE(action.url));
[self completeWebAuthWithURL:action.url]; // should we complete request or invoke a delegate method to handoff to ASWebAuthSession ?
}
else
{
MSID_LOG_WITH_CTX(MSIDLogLevelError, self.context, @"OpenASWebAuthSession action has nil URL");
[self completeWebAuthWithURL:requestURL];
}
// alternatively replace above action with the delegate method to handoff to ASWebAuthSession
id<MSIDWebviewSpecialNavigationDelegate> strongSpecialNavigationDelegate = self.specialNavigationDelegate;
if (strongSpecialNavigationDelegate)
{
if ([strongSpecialNavigationDelegate respondsToSelector:@selector(webviewController:handleSpecialRedirect:completion:)])
{
MSID_LOG_WITH_CTX(MSIDLogLevelInfo, self.context,
@"Detected special redirect scheme: %@. Delegating to navigationDelegate.", requestURL.scheme);

// Call delegate on main thread
__weak typeof(self) weakSelf = self;
dispatch_async(dispatch_get_main_queue(), ^{
__strong typeof(self) strongSelf = weakSelf;
if (!strongSelf) return;

[strongSpecialNavigationDelegate handleASWebAuthenticationTransitionWithUrl:action.url embeddedWebview:strongSelf additionalHeaders:action.additionalHeaders MSIDSystemWebviewPurpose:action.purpose completion:^(MSIDWebviewNavigationAction * _Nonnull navigationAction, NSError * _Nonnull aswebAuthError) {
[strongSelf executeViewNavigationAction:navigationAction requestURL:requestURL error:aswebAuthError]; //need to test if this recursion could cause any issue
}];
});
}
}
break;
}
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing break statement at the end of this case. While the closing brace on line 289 ends the case block, the code structure is confusing because the delegate call and its closing brace are outside the main if statement. This could lead to fall-through issues if the switch statement is modified later.

Copilot uses AI. Check for mistakes.
nil, nil, error,
self.context.correlationId,
nil, NO);
[self endWebAuthWithURL:nil error:localerror]; //endWebAuth or do completeWebAuth ?
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment on line 232 has a typo or unclear syntax: "endWebAuth or do completeWebAuth ?" should either be formatted as a proper question with consistent capitalization, or rephrased as a statement. Consider: "TODO: Should this call endWebAuth or completeWebAuth?"

Suggested change
[self endWebAuthWithURL:nil error:localerror]; //endWebAuth or do completeWebAuth ?
[self endWebAuthWithURL:nil error:localerror]; // TODO: Should this call endWebAuth or completeWebAuth?

Copilot uses AI. Check for mistakes.
@@ -4669,6 +4702,9 @@
60B3856D20AB3CDC00D546D0 /* ui */,
96235FA0207D786A007EAB36 /* challangeHandlers */,
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spelling error: "challangeHandlers" should be "challengeHandlers" (single 'l').

Suggested change
96235FA0207D786A007EAB36 /* challangeHandlers */,
96235FA0207D786A007EAB36 /* challengeHandlers */,

Copilot uses AI. Check for mistakes.
@@ -0,0 +1,195 @@
// Copyright (c) Microsoft Corporation.
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR title "Veena/mob onb2" doesn't follow the required format specified in the PR description. According to the description, the title should be in the format "[Keyword1] [Keyword2]: Description" where Keyword1 is major/minor/patch and Keyword2 is feature/bugfix/engg/tests. Examples: "[MAJOR] [Feature]: new API" or "[minor] [bugfix]: fix crash". The current title needs to be updated to match this format.

Copilot uses AI. Check for mistakes.
// THE SOFTWARE.

#import <XCTest/XCTest.h>
#import "MSIDWebProfileInstallTriggerResponse.h"
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test files reference classes MSIDWebProfileInstallTriggerResponse and MSIDWebInstallProfileResponse that don't exist in the implementation. The actual implementation uses MSIDWebMDMInstallProfileResponse and MSIDWebMDMEnrollmentCompletionResponse instead. Either the test files are outdated or the class names in tests need to be updated to match the implementation.

Copilot uses AI. Check for mistakes.
@Veena11 Veena11 marked this pull request as draft February 6, 2026 18:40
Copilot AI and others added 2 commits February 6, 2026 19:59
Co-authored-by: Veena11 <9446116+Veena11@users.noreply.github.com>
…t Flow (#1691)

Documents the architecture and implementation details of PR #1689's
in-app MDM profile installation and enrollment support for MSAL
Objective-C.

## Added

- **Design document** at `docs/design/mobile-mdm-onboarding-design.md`
covering:
- Architecture flow for embedded WKWebView → ASWebAuthenticationSession
transitions
- New components: navigation action resolver, transition coordinator,
MDM response models
- Modified components: local interactive controller, AAD webview
controller, request/response pipeline
- `msauth://` URL scheme routing for profile installation and enrollment
completion
  - Broker Refresh Token (BRT) acquisition strategy
  - Post-enrollment handoff to SSO Extension
- Risk assessment and known incomplete items (BRT placeholder, dual
transition paths, no tests)

## Structure

```
docs/
└── design/
    └── mobile-mdm-onboarding-design.md  # 266 lines, 11 sections
```

Document includes flow diagrams, component tables, and files changed
summary for the 38-file, +2,814/-37 line change in PR #1689.

<!-- START COPILOT ORIGINAL PROMPT -->



<details>

<summary>Original prompt</summary>

Add a comprehensive design document as a markdown file to the repository
that documents the changes introduced in PR #1689 (`veena/mob_onb2`
branch). The design doc should be placed at
`docs/design/mobile-mdm-onboarding-design.md` and contain the following
content exactly:

---

# Design Document: Mobile MDM Onboarding & In-App Enrollment Flow

**PR:** [#1689 – Veena/mob
onb2](#1689)
**Branch:** `veena/mob_onb2` → `dev`
**Repository:**
`AzureAD/microsoft-authentication-library-common-for-objc`
**Author:** @swasti29
**Status:** Draft, Open
**Stats:** +2,814 additions, -37 deletions across 38 files

---

## 1. Executive Summary

This change introduces **in-app MDM (Mobile Device Management) profile
installation and enrollment** support into the MSAL common library for
Objective-C. It enables an interactive authentication flow where, when
the AAD server signals that an Intune management profile must be
installed, the embedded webview (WKWebView) seamlessly transitions to an
`ASWebAuthenticationSession` for profile installation, then returns to
the embedded webview to complete the original authentication.
Additionally, it introduces **Broker Refresh Token (BRT)** acquisition
logic triggered on special `msauth://` and `browser://` redirects.

---

## 2. Problem Statement

Currently, when AAD determines that a device requires MDM enrollment
(Intune profile installation) before authentication can complete, the
library lacks the ability to:

1. **Detect** an MDM profile installation trigger
(`msauth://installProfile`) from the server.
2. **Orchestrate** a seamless transition from the embedded webview to
`ASWebAuthenticationSession` for profile download (which requires
system-level handling).
3. **Resume** the embedded webview after profile installation completes
(`msauth://in_app_enrollment_complete`).
4. **Acquire a Broker Refresh Token (BRT)** opportunistically on special
redirect schemes.
5. **Hand off to the broker** (SSO Extension) after successful
enrollment for final token acquisition.

---

## 3. Architecture Overview

### 3.1 High-Level Flow

```
┌──────────────┐     ┌─────────────────────┐     ┌──────────────────────────┐
│  App calls   │────▶│ LocalInteractive     │────▶│ Embedded WKWebview       │
│ acquireToken │     │ Controller           │     │ (AAD login page)         │
└──────────────┘     └─────────────────────┘     └──────────┬───────────────┘
                                                            │
                         ┌──────────────────────────────────┤
                         │ Server returns msauth://          │
                         │ installProfile redirect           │
                         ▼                                   │
              ┌──────────────────────┐                       │
              │ SpecialNavigation    │ Delegate intercepts   │
              │ Delegate callback    │◀──────────────────────┘
              └──────┬───────────────┘
                     │ 1. Acquire BRT (first time only)
                     │ 2. Resolve navigation action
                     ▼
              ┌──────────────────────┐
              │ NavigationActionUtil │  Parses msauth:// URL
              │ resolves action      │  + HTTP response headers
              └──────┬───────────────┘
                     │ Returns: OpenInASWebAuthSession
                     ▼
              ┌──────────────────────┐     ┌─────────────────────────┐
              │ TransitionCoordinator│────▶│ ASWebAuthenticationSession│
              │ - Suspend WKWebview  │     │ (Profile installation)   │
              │ - Launch ASWebAuth   │     └──────────┬──────────────┘
              └──────────────────────┘                │
                                                      │ Callback:
                                                      │ msauth://in_app_enrollment_complete
                                                      ▼
              ┌──────────────────────┐     ┌──────────────────────────┐
              │ TransitionCoordinator│────▶│ Resume WKWebview         │
              │ - Resume webview     │     │ Load enrollment callback │
              │ - Clean up ASWebAuth │     └──────────┬───────────────┘
              └──────────────────────┘                │
                                                      │ WKWebview processes
                                                      │ enrollment completion
                                                      ▼
              ┌──────────────────────────────────────────────────────┐
              │ Controller handles MDMEnrollmentCompletionResponse   │
              │ → Creates BrokerInteractiveController               │
              │ → Delegates to SSO Extension for final token        │
              └─────────────────────────────────────────────────────┘
```

---

## 4. New Components

### 4.1 New Classes

| Class | Location | Purpose |
|---|---|---|
| **`...

</details>



<!-- START COPILOT CODING AGENT SUFFIX -->

*This pull request was created from Copilot chat.*
>

<!-- START COPILOT CODING AGENT TIPS -->
---

💬 We'd love your input! Share your thoughts on Copilot coding agent in
our [2 minute survey](https://gh.io/copilot-coding-agent-survey).
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.

3 participants