Skip to content

Add resource-tenant enrollment lookup for guest/MTO MAM (AB#3673091)#1873

Draft
antonioalwan wants to merge 12 commits into
devfrom
antonio_alwan/mto_resource_tenant_enrollment
Draft

Add resource-tenant enrollment lookup for guest/MTO MAM (AB#3673091)#1873
antonioalwan wants to merge 12 commits into
devfrom
antonio_alwan/mto_resource_tenant_enrollment

Conversation

@antonioalwan

@antonioalwan antonioalwan commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Work item

AB#3673091 — CommonCore layer of the Guest/MTO cross-tenant MAM fix.

Summary

When a guest user (home in Tenant A) accesses a MAM-protected app in resource Tenant B, the broker currently resolves Intune enrollment by the home tenant, so the resource tenant's MAM policy is never enforced. This PR adds the CommonCore primitives needed to resolve enrollment by resource tenant.

Changes

  • MSIDError.h/.m: new MSIDResourceTenantIdKey error userInfo constant.
  • MSIDIntuneEnrollmentIdsCache.h/.m: new enrollmentIdForUserObjectId:resourceTenantId:context:error: lookup that matches enrollment entries by OID + resource tenant.
  • MSIDDefaultBrokerResponseHandler.m: map resource_tenant_id to MSIDResourceTenantIdKey in _userInfoKeyMapping so MSAL can extract it from broker error responses.
  • Unit tests: 6 new enrollment-lookup tests + response-handler assertion.

Testing

IdentityCore iOS unit tests pass (73 tests in the two affected suites, 0 failures).

Related PRs (merge order)

  1. This PR (CommonCore)
  2. MSAL — AzureAD/microsoft-authentication-library-for-objc antonio_alwan/mto_msal_resource_tenant_id
  3. Broker — AzureAD/azure-activedirectory-tokenbroker-for-objc antonio_alwan/mto_guest_mam_resource_tenant

Note: end-to-end behavior also depends on the Intune MAM SDK writing enrollment entries keyed to the resource tenant (external dependency).

Swasti Gupta and others added 11 commits June 12, 2026 10:40
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
- Replace @{ @"mdm_enrollment_status": status } userInfo with nil
- Embed status in error description: "MDM enrollment failed with status: <status>"
- Add nil-completionBlock unit test
- Expose handleWebMDMEnrollmentCompletionResponse:completion: in Internal.h
- Use @Class forward declaration to reduce coupling

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add MSID_BROKER_NEW_MOBILE_ONBOARDING_FLOW_KEY constant
- Serialize/deserialize flag in MSIDBrokerOperationInteractiveTokenRequest
- Set flag in MSIDAADOAuthEmbeddedWebviewController on msauth://enroll detection
- Add property to MSIDInteractiveRequestParameters
- Update MSIDLocalInteractiveController for enrollment completion handling
- Expose delegate property in MSIDOAuth2EmbeddedWebviewController

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Update testJsonDictionary_whenAllPropertiesSet to verify the flag
serializes as "new_mobile_onboarding_flow": "1" in JSON output.
Update testInitWithJSONDictionary_whenAllProperties to verify the
flag deserializes correctly from JSON input.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add braces to single-line if statements in MSIDLocalInteractiveController
and MSIDInteractiveControllerIntegrationTests per .clinerules guidelines.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Match existing Doxygen-style block comments used throughout the codebase.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Adds MSIDResourceTenantIdKey error userInfo constant, a new
enrollmentIdForUserObjectId:resourceTenantId:context:error: lookup on
MSIDIntuneEnrollmentIdsCache that matches Intune enrollment entries by
OID + resource tenant, and a resource_tenant_id -> MSIDResourceTenantIdKey
mapping in MSIDDefaultBrokerResponseHandler so MSAL can extract it from
broker error responses. Includes unit tests.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 extends IdentityCore to support cross-tenant Intune MAM enrollment resolution for Guest/MTO scenarios by carrying the resource tenant id through broker error surfaces and adding a cache lookup that matches enrollment entries by OID + resource tenant. In addition, the PR also introduces new mobile onboarding / MDM enrollment completion plumbing that affects embedded webview navigation and interactive controller retry behavior.

Changes:

  • Add MSIDResourceTenantIdKey and map broker resource_tenant_id into error userInfo so downstream (e.g., MSAL) can resolve enrollment against the resource tenant.
  • Add enrollmentIdForUserObjectId:resourceTenantId:context:error: to MSIDIntuneEnrollmentIdsCache and corresponding unit tests.
  • Introduce “new mobile onboarding flow” state propagation and MDM enrollment completion retry via MSIDRequestControllerFactory, plus associated webview navigation API/test updates.

Reviewed changes

Copilot reviewed 27 out of 27 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
IdentityCore/tests/MSIDWebviewNavigationHandlerTests.m Updates tests to match the simplified special-redirect handler signature.
IdentityCore/tests/MSIDWebviewNavigationDecisionResolverTests.m Updates resolver tests for new headers derived from MSIDVersion and signature changes.
IdentityCore/tests/MSIDIntuneEnrollmentIdsCacheTests.m Adds tests for OID + resource-tenant enrollment lookup.
IdentityCore/tests/MSIDBrokerOperationInteractiveTokenRequestTests.m Updates broker request JSON tests for the new onboarding-flow flag field.
IdentityCore/tests/integration/MSIDInteractiveControllerIntegrationTests.m Adds integration coverage for MDM enrollment completion handling and controller-factory retry behavior.
IdentityCore/tests/integration/ios/MSIDDefaultBrokerResponseHandlerTests.m Adds assertion that resource_tenant_id is surfaced via MSIDResourceTenantIdKey.
IdentityCore/src/webview/embeddedWebview/MSIDWebviewNavigationHandler.m Removes appName/appVersion parameters and forwards to resolver using the new API.
IdentityCore/src/webview/embeddedWebview/MSIDWebviewNavigationHandler.h Updates handler API/docs to remove appName/appVersion parameters.
IdentityCore/src/webview/embeddedWebview/MSIDWebviewNavigationDecisionResolver.m Derives enrollment request headers from MSIDVersion and updates resolver API.
IdentityCore/src/webview/embeddedWebview/MSIDWebviewNavigationDecisionResolver.h Updates resolver API/docs to remove appName/appVersion parameters.
IdentityCore/src/webview/embeddedWebview/MSIDOAuth2EmbeddedWebviewController.m Switches mobile onboarding gating to MSIDInteractiveRequestParameters.isNewMobileOnboardingFlow.
IdentityCore/src/webview/embeddedWebview/MSIDOAuth2EmbeddedWebviewController.h Removes isMobileOnboardingEnabled state from the controller surface.
IdentityCore/src/webview/embeddedWebview/MSIDAADOAuthEmbeddedWebviewController.m Sets/reads the new onboarding-flow flag based on server redirects and flighting checks.
IdentityCore/src/requests/sdk/msal/MSIDDefaultBrokerResponseHandler.m Maps broker resource_tenant_id into MSIDResourceTenantIdKey.
IdentityCore/src/parameters/MSIDInteractiveRequestParameters.h Adds isNewMobileOnboardingFlow flag to interactive request parameters.
IdentityCore/src/MSIDError.m Defines the new MSIDResourceTenantIdKey constant.
IdentityCore/src/MSIDError.h Declares MSIDResourceTenantIdKey and documents its Guest/MTO purpose.
IdentityCore/src/MSIDBrokerConstants.m Adds the broker IPC key new_mobile_onboarding_flow.
IdentityCore/src/MSIDBrokerConstants.h Declares the broker IPC key new_mobile_onboarding_flow.
IdentityCore/src/intune/MSIDIntuneEnrollmentIdsCache.m Implements enrollment lookup by OID + resource tenant id.
IdentityCore/src/intune/MSIDIntuneEnrollmentIdsCache.h Declares and documents the new OID + resource-tenant lookup API.
IdentityCore/src/controllers/MSIDLocalInteractiveController+Internal.h Exposes an internal handler for MDM enrollment completion response.
IdentityCore/src/controllers/MSIDLocalInteractiveController.m Wires webview navigation handling + adds MDM completion handling and retry via controller factory.
IdentityCore/src/controllers/MSIDLocalInteractiveController.h Makes the controller conform to MSIDWebviewNavigationDelegate.
IdentityCore/src/broker_operation/request/interactive_token_request/MSIDBrokerOperationInteractiveTokenRequest.m Round-trips onboarding-flow flag through broker IPC JSON.
IdentityCore/src/broker_operation/request/interactive_token_request/MSIDBrokerOperationInteractiveTokenRequest.h Adds the onboarding-flow flag property with documentation.
changelog.txt Adds a changelog entry for the Guest/MTO resource-tenant enrollment lookup feature.

Comment on lines +195 to +199
NSString *objectId;
NSString *resourceTenantId = @"fda5d5d9-17c3-4c29-9cf9-a27c3d3f03e1";

NSError *error;
__auto_type enrollmentId = [self.cache enrollmentIdForUserObjectId:objectId resourceTenantId:resourceTenantId context:nil error:&error];
Comment on lines +207 to +211
NSString *objectId = @"d3444455-mike-4271-b6ea-e499cc0cab46";
NSString *resourceTenantId;

NSError *error;
__auto_type enrollmentId = [self.cache enrollmentIdForUserObjectId:objectId resourceTenantId:resourceTenantId context:nil error:&error];
Comment on lines +70 to +81
// Wire the navigation handler into the webview controller once it's created.
__weak typeof(self) weakSelf = self;
parameters.webviewConfigurationBlock = ^(id<MSIDWebviewInteracting> webviewController) {
__strong typeof(self) strongSelf = weakSelf;
if (!strongSelf)
{
return;
}

[strongSelf.navigationHandler configureWebviewController:webviewController
delegate:strongSelf];
};
Comment on lines +50 to +54
/* Marks the current request as part of the new mobile onboarding flow.
Set to YES when the server issues `msauth://enroll` during the embedded
webview leg, so the bit survives the hop into the broker SSO extension
where the broker can branch on it during device-registration bootstrap. */
@property (nonatomic) BOOL isNewMobileOnboardingFlow;
* dev:
  [minor][tests]: Add a automation health tracker (#1865)
  Add MSIDMobileOnboardingState for shared-reference flag propagation (#1868)
  Record PkeyAuth PRT execution-flow tag when correlation id is available
  [Minor][Engg]: Final Lab Update (#1870)
  Apply suggestions from code review
  Merge Back Main branch into Dev
  Add changelog entry for PkeyAuth PRT known AAD hosts restriction
  Only attach PRT header to PkeyAuth response for known AAD hosts
  CC Release 1.25.0
  Mobile Onboarding Non Broker Enrollment (#1862)

# Conflicts:
#	IdentityCore/src/broker_operation/request/interactive_token_request/MSIDBrokerOperationInteractiveTokenRequest.h
#	IdentityCore/src/parameters/MSIDInteractiveRequestParameters.h
#	changelog.txt
@antonioalwan
antonioalwan marked this pull request as draft June 24, 2026 22:15
NSArray *enrollIds = [jsonDictionary objectForKey:MSID_INTUNE_ENROLLMENT_ID_ARRAY];
for (NSDictionary *enrollIdDic in enrollIds)
{
if ([enrollIdDic[MSID_INTUNE_OID] isEqualToString:userObjectId] &&

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Could we normalize the OID and tenant ID before comparing them? MSIDAccountIdentifier.uid preserves the input casing, while the enrollment cache may store GUIDs with different casing, so this exact comparison can miss a valid resource-tenant enrollment and fall back to the home tenant.

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.

5 participants