[Major] [Mobile Onboarding]: Mobile Onboarding Framework#1734
[Major] [Mobile Onboarding]: Mobile Onboarding Framework#1734swasti29 wants to merge 19 commits into
Conversation
…ps://github.com/AzureAD/microsoft-authentication-library-common-for-objc into maagubuzo/ufic/introduce_ufic_into_api_contract
ero "exit merge editor" | git merge --continue 2>/dev/null || git log --oneline -3 t branch e branch 'dev' into maagubuzo/ufic/introduce_ufic_into_api_contract
| @@ -1873,6 +1873,9 @@ | |||
| B41163B929BAC9BF00E64619 /* MSIDWKNavigationActionMock.m in Sources */ = {isa = PBXBuildFile; fileRef = B41163B829BAC9BF00E64619 /* MSIDWKNavigationActionMock.m */; }; | |||
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Pull request overview
Adds new embedded-webview navigation infrastructure to support “Mobile Onboarding” flows, including special msauth:// redirect handling and transitions from WKWebView to ASWebAuthenticationSession with optional iOS 18+ request headers.
Changes:
- Extended
MSIDASWebAuthenticationSessionHandlerto accept iOS 18+/macOS 15+additionalHeadersand apply them toASWebAuthenticationSession. - Introduced new navigation helper/action/util types to centralize handling of special redirects and MDM/profile-install flows.
- Added a new
MSIDWebviewTransitionHandlerto coordinate suspend/resume of embedded webviews while launching system webview sessions.
Reviewed changes
Copilot reviewed 13 out of 13 changed files in this pull request and generated 21 comments.
Show a summary per file
| File | Description |
|---|---|
| IdentityCore/src/webview/systemWebview/session/MSIDASWebAuthenticationSessionHandler.m | Adds support for passing iOS 18+/macOS 15+ additional header fields into ASWebAuthenticationSession. |
| IdentityCore/src/webview/systemWebview/session/MSIDASWebAuthenticationSessionHandler.h | Adds a new API-available initializer for additional headers. |
| IdentityCore/src/webview/embeddedWebview/MSIDWebviewNavigationDelegateHelper.m | New helper implementation for configuring embedded webviews and handling special redirects/transitions. |
| IdentityCore/src/webview/embeddedWebview/MSIDWebviewNavigationDelegateHelper.h | New helper interface for shared navigation delegate logic. |
| IdentityCore/src/webview/embeddedWebview/MSIDWebviewNavigationDelegate.h | New protocol for controllers to intercept special redirects and transition events. |
| IdentityCore/src/webview/embeddedWebview/MSIDWebviewNavigationActionUtil.m | New URL parsing/routing utility for msauth:// host actions (enroll/compliance/installprofile). |
| IdentityCore/src/webview/embeddedWebview/MSIDWebviewNavigationActionUtil.h | Declares the new action resolution utility API. |
| IdentityCore/src/webview/embeddedWebview/MSIDWebviewNavigationAction.m | New navigation-action value object (load request / open ASWebAuth / fail / etc.). |
| IdentityCore/src/webview/embeddedWebview/MSIDWebviewNavigationAction.h | Declares action types and system webview “purpose” enum. |
| IdentityCore/src/webview/embeddedWebview/MSIDOAuth2EmbeddedWebviewController.h | Adds a navigationDelegate property intended for special redirect handling. |
| IdentityCore/src/webview/MSIDWebviewTransitionHandler.m | New coordinator to suspend an embedded webview and launch ASWebAuthenticationSession. |
| IdentityCore/src/webview/MSIDWebviewTransitionHandler.h | Declares the new transition coordinator API. |
| IdentityCore/IdentityCore.xcodeproj/project.pbxproj | Adds new files to build phases/groups. |
| MSIDAADOAuthEmbeddedWebviewController *aadWebviewController = | ||
| (MSIDAADOAuthEmbeddedWebviewController *)webviewController; | ||
|
|
||
| aadWebviewController.navigationDelegate = delegate; |
There was a problem hiding this comment.
The type check is for MSIDOAuth2EmbeddedWebviewController, but the value is cast to MSIDAADOAuthEmbeddedWebviewController. If a non-AAD MSIDOAuth2EmbeddedWebviewController instance is passed, this cast is unsafe. Cast to MSIDOAuth2EmbeddedWebviewController (or check for MSIDAADOAuthEmbeddedWebviewController explicitly) before setting navigationDelegate.
| MSIDAADOAuthEmbeddedWebviewController *aadWebviewController = | |
| (MSIDAADOAuthEmbeddedWebviewController *)webviewController; | |
| aadWebviewController.navigationDelegate = delegate; | |
| MSIDOAuth2EmbeddedWebviewController *oauth2WebviewController = | |
| (MSIDOAuth2EmbeddedWebviewController *)webviewController; | |
| oauth2WebviewController.navigationDelegate = delegate; |
| - (MSIDWebviewNavigationAction *)resolveActionForMSAuthURL:(NSURL *)url | ||
| webviewController:(id<MSIDWebviewInteracting>)webviewController | ||
| responseHeaders:(NSDictionary<NSString *,NSString *> * _Nullable)responseHeaders | ||
| isBrokerContext:(BOOL)isBrokerContext | ||
| externalNavigationBlock:(MSIDExternalDecidePolicyForBrowserActionBlock)externalNavigationBlock | ||
| { |
There was a problem hiding this comment.
This PR introduces substantial new URL parsing/routing behavior for msauth:// hosts (enroll/compliance/installprofile) but there are no accompanying unit tests. Given existing webview controller tests in this repo, please add focused tests for MSIDWebviewNavigationActionUtil covering each host, missing params/headers, and the requireASWebAuthenticationSession branch to prevent regressions.
| _url = url; | ||
| _purpose = purpose; | ||
| _error = error; | ||
| _additionalHeaders = additionalHeaders; |
There was a problem hiding this comment.
additionalHeaders is stored without copying, so a mutable dictionary passed in could be mutated after the action is created. Consider copying (and ideally declaring the property as copy) to keep MSIDWebviewNavigationAction immutable and safer to share across components.
| _additionalHeaders = additionalHeaders; | |
| _additionalHeaders = [additionalHeaders copy]; |
| typedef NS_ENUM(NSInteger, MSIDSystemWebviewPurpose); | ||
|
|
There was a problem hiding this comment.
typedef NS_ENUM(NSInteger, MSIDSystemWebviewPurpose); is not a valid forward declaration and will not compile. Import the header that defines MSIDSystemWebviewPurpose (e.g., MSIDWebviewNavigationAction.h) or define the enum here instead of trying to forward-declare it with NS_ENUM.
| return [MSIDWebviewNavigationAction loadRequestAction:request]; | ||
| } | ||
|
|
||
| - (MSIDWebviewNavigationAction *)actionForInstallProfileURL:(NSURL *)url |
There was a problem hiding this comment.
actionForInstallProfileURL doesn’t use the url parameter, which will fail the build due to unused-parameter warnings being treated as errors. Mark it __unused or remove it from the signature if it’s not needed.
| - (MSIDWebviewNavigationAction *)actionForInstallProfileURL:(NSURL *)url | |
| - (MSIDWebviewNavigationAction *)actionForInstallProfileURL:(__unused NSURL *)url |
| webviewController:(id<MSIDWebviewInteracting>)webviewController | ||
| responseHeaders:(NSDictionary<NSString *, NSString *> * _Nullable)responseHeaders | ||
| isBrokerContext:(BOOL)isBrokerContext | ||
| externalNavigationBlock:(MSIDExternalDecidePolicyForBrowserActionBlock)externalNavigationBlock; |
There was a problem hiding this comment.
externalNavigationBlock is declared nonnull, but callers may legitimately pass nil (and the implementation checks for it). Passing nil to a nonnull parameter will produce a nullability warning (treated as an error). Mark this parameter as _Nullable in the header (and match in the implementation).
| externalNavigationBlock:(MSIDExternalDecidePolicyForBrowserActionBlock)externalNavigationBlock; | |
| externalNavigationBlock:(MSIDExternalDecidePolicyForBrowserActionBlock _Nullable)externalNavigationBlock; |
There was a problem hiding this comment.
externalNavigationBlock is optional param right ? so may be make it nullable ?
| brtEvaluator:(nullable BOOL(^)(void))brtEvaluator | ||
| brtHandler:(nullable void(^)(void(^)(BOOL success, NSError * _Nullable error)))brtHandler | ||
| isBrokerContext:(BOOL)isBrokerContext | ||
| externalNavigationBlock:(nullable id)externalNavigationBlock; |
There was a problem hiding this comment.
externalNavigationBlock is typed as id, but it's passed to APIs that expect MSIDExternalDecidePolicyForBrowserActionBlock. This will trigger an incompatible-pointer-types warning (treated as an error) and loses type safety. Change the parameter type in both the header and implementation to MSIDExternalDecidePolicyForBrowserActionBlock _Nullable (or remove it if not needed).
| externalNavigationBlock:(nullable id)externalNavigationBlock; | |
| externalNavigationBlock:(nullable MSIDExternalDecidePolicyForBrowserActionBlock)externalNavigationBlock; |
| @property (nonatomic, readonly) NSDictionary<NSString *, NSString *> *customHeaders; | ||
| @property (nonatomic, copy) MSIDNavigationResponseBlock navigationResponseBlock; | ||
| @property (nonatomic, copy) MSIDExternalDecidePolicyForBrowserActionBlock externalDecidePolicyForBrowserAction; | ||
| @property (nonatomic, weak) id<MSIDWebviewNavigationDelegate> navigationDelegate; |
There was a problem hiding this comment.
navigationDelegate is introduced on MSIDOAuth2EmbeddedWebviewController, but there is no usage of this property anywhere in the implementation (only assignments). As-is, it adds API surface without behavior and will likely confuse call sites. Either wire it into decidePolicyForNavigationAction: (and/or response handling) or remove the property until it’s actually used.
|
|
||
| @interface MSIDWebviewNavigationDelegateHelper() | ||
|
|
||
| @property (nonatomic) id<MSIDRequestContext> context; |
There was a problem hiding this comment.
Header declares context as weak, readonly, but the class extension redeclares it as strong/readwrite (@property (nonatomic) ...). This defeats the documented retain-cycle avoidance and can also produce attribute-mismatch warnings (warnings are errors in this repo). Redeclare it in the extension as weak, readwrite (or keep it weak and store a separate strong local when needed).
| @property (nonatomic) id<MSIDRequestContext> context; | |
| @property (nonatomic, weak, readwrite) id<MSIDRequestContext> context; |
| MSIDWebviewNavigationActionTypeLoadRequestInWebview, | ||
|
|
||
| /// Open the URL in ASWebAuthenticationSession (system webview) | ||
| MSIDWebviewNavigationActionTypeOpenInASWebAuthenticationSession, |
There was a problem hiding this comment.
lets revisit this based on the design discussion we are having for ASWebAuth handoff
| * Purpose for opening a system webview. | ||
| * Used to provide context about for ASWebAuthenticationSession. | ||
| */ | ||
| typedef NS_ENUM(NSInteger, MSIDSystemWebviewPurpose) |
There was a problem hiding this comment.
you might not need this if we go with the response header logic, lets revisit once we conclude
| /*! | ||
| Additional HTTP headers to include when executing the action. | ||
|
|
||
| For OpenASWebAuthenticationSession actions, these headers (e.g., X-Intune-AuthToken) |
There was a problem hiding this comment.
additional headers could also be used for WKwebiew based requests too
| * @param headers Additional HTTP headers (e.g., X-Intune-AuthToken) to pass to the handler | ||
| * @return Action object with type OpenASWebAuthenticationSession | ||
| */ | ||
| + (instancetype)openInASWebAuthSessionAction:(NSURL *)url |
|
|
||
| #pragma mark - Validation | ||
|
|
||
| - (BOOL)isValid |
There was a problem hiding this comment.
where is isValid API used ?
| { | ||
| // Extract intuneUrl from query parameters | ||
| // URL format: msauth://enroll?intuneUrl=https://go.microsoft.com/fwlink?LinkId=396941 | ||
| NSString *intuneUrl = params[@"intuneUrl"]; |
There was a problem hiding this comment.
Marking for update based on the qp from CA redirect
Proposed changes
Mobile Onboarding Framework Changes
Type of change
Risk
Additional information