From 9bd55568013dd74cf80fb84ff8b35b7b77900a51 Mon Sep 17 00:00:00 2001 From: Kai Song Date: Wed, 26 Feb 2025 09:09:10 -0800 Subject: [PATCH] Add enum to enabl/disable XPC service --- IdentityCore/src/MSIDConstants.h | 7 + .../MSIDRequestControllerFactory.m | 13 +- .../src/parameters/MSIDRequestParameters.h | 4 +- .../src/util/MSIDXpcSingleSignOnProvider.m | 2 +- .../tests/MSIDRequestControllerFactoryTests.m | 136 +++++++++++++++++- 5 files changed, 154 insertions(+), 8 deletions(-) diff --git a/IdentityCore/src/MSIDConstants.h b/IdentityCore/src/MSIDConstants.h index c5651b0a8..569577e0a 100644 --- a/IdentityCore/src/MSIDConstants.h +++ b/IdentityCore/src/MSIDConstants.h @@ -93,6 +93,13 @@ typedef NS_ENUM(NSInteger, MSIDHeaderType) MSIDHeaderTypeDeviceRegistration }; +typedef NS_ENUM(NSUInteger, MSIDXpcMode) +{ + MSIDXpcModeDisable = 0, + MSIDXpcModeBackup, + MSIDXpcModeFull +}; + typedef void (^MSIDRequestCompletionBlock)(MSIDTokenResult * _Nullable result, NSError * _Nullable error); typedef void (^MSIDSignoutRequestCompletionBlock)(BOOL success, NSError * _Nullable error); typedef void (^MSIDGetAccountsRequestCompletionBlock)(NSArray * _Nullable accounts, BOOL returnBrokerAccountsOnly, NSError * _Nullable error); diff --git a/IdentityCore/src/controllers/MSIDRequestControllerFactory.m b/IdentityCore/src/controllers/MSIDRequestControllerFactory.m index ca6073212..7a71ca0a2 100644 --- a/IdentityCore/src/controllers/MSIDRequestControllerFactory.m +++ b/IdentityCore/src/controllers/MSIDRequestControllerFactory.m @@ -162,14 +162,21 @@ @implementation MSIDRequestControllerFactory fallbackController.isLocalFallbackMode = YES; } + MSIDSilentController *xpcController = nil; #if TARGET_OS_OSX - if (parameters.enableXpcFlow && [MSIDXpcSilentTokenRequestController canPerformRequest]) + if (parameters.xpcMode != MSIDXpcModeDisable && [MSIDXpcSilentTokenRequestController canPerformRequest]) { - fallbackController = [[MSIDXpcSilentTokenRequestController alloc] initWithRequestParameters:parameters + xpcController = [[MSIDXpcSilentTokenRequestController alloc] initWithRequestParameters:parameters forceRefresh:forceRefresh tokenRequestProvider:tokenRequestProvider fallbackInteractiveController:fallbackController error:error]; + if (parameters.xpcMode == MSIDXpcModeFull) + { + // If in Xpc full mode, the XPCController will work as a isolated controller when SsoExtension cannotPerformRequest + fallbackController = xpcController; + xpcController = nil; + } } #endif @@ -178,7 +185,7 @@ @implementation MSIDRequestControllerFactory fallbackController = [[MSIDSSOExtensionSilentTokenRequestController alloc] initWithRequestParameters:parameters forceRefresh:forceRefresh tokenRequestProvider:tokenRequestProvider - fallbackInteractiveController:fallbackController + fallbackInteractiveController:xpcController?:fallbackController error:error]; } } diff --git a/IdentityCore/src/parameters/MSIDRequestParameters.h b/IdentityCore/src/parameters/MSIDRequestParameters.h index 35cdb2f78..79be19c91 100644 --- a/IdentityCore/src/parameters/MSIDRequestParameters.h +++ b/IdentityCore/src/parameters/MSIDRequestParameters.h @@ -73,7 +73,6 @@ @property (nonatomic) NSUInteger tokenExpirationBuffer; @property (nonatomic) BOOL extendedLifetimeEnabled; @property (nonatomic) BOOL instanceAware; -@property (nonatomic) BOOL enableXpcFlow; @property (nonatomic) BOOL allowUsingLocalCachedRtWhenSsoExtFailed; @property (nonatomic) BOOL clientBrokerKeyCapabilityNotSupported; @property (nonatomic) NSString *intuneApplicationIdentifier; @@ -109,6 +108,9 @@ #pragma mark - SSO context @property (nonatomic) MSIDExternalSSOContext *ssoContext; +#pragma mark - Xpc Mode +@property (nonatomic) MSIDXpcMode xpcMode; + - (NSURL *)tokenEndpoint; #pragma mark Methods diff --git a/IdentityCore/src/util/MSIDXpcSingleSignOnProvider.m b/IdentityCore/src/util/MSIDXpcSingleSignOnProvider.m index 2e4a93397..1c1ce62ac 100644 --- a/IdentityCore/src/util/MSIDXpcSingleSignOnProvider.m +++ b/IdentityCore/src/util/MSIDXpcSingleSignOnProvider.m @@ -142,7 +142,7 @@ - (void)handleRequestParam:(NSDictionary *)requestParam + (BOOL)canPerformRequest { - // This will be upgraded in item: xxx + // TODO: The full implementation will be done in 3166516 // Synchronously entering this class method @synchronized (self) { dispatch_group_t group = dispatch_group_create(); diff --git a/IdentityCore/tests/MSIDRequestControllerFactoryTests.m b/IdentityCore/tests/MSIDRequestControllerFactoryTests.m index af5230fb5..1a86f123a 100644 --- a/IdentityCore/tests/MSIDRequestControllerFactoryTests.m +++ b/IdentityCore/tests/MSIDRequestControllerFactoryTests.m @@ -198,14 +198,76 @@ - (void)testWhenUseLocalRt_isUnDefined_shouldSkip_whenFallBackController_isValid XCTAssertTrue([(MSIDSilentController *)controller skipLocalRt]); } + #if TARGET_OS_OSX -- (void)testWhenSsoExtensionIsEnabled_andXPCIsEnabled_controllersOrder_areCorrect +- (void)testWhenSsoExtensionIsEnabled_andXpcIsPartiallyEnabled_andSsoExtensionIsDisabled_controllersOrder_areCorrect { MSIDTestTokenRequestProvider *provider = [[MSIDTestTokenRequestProvider alloc] initWithTestResponse:nil testError:nil testWebMSAuthResponse:nil]; MSIDRequestParameters *parameters = [self requestParameters]; - parameters.enableXpcFlow = YES; + parameters.xpcMode = MSIDXpcModeBackup; + parameters.allowUsingLocalCachedRtWhenSsoExtFailed = YES; + + NSError *error; + SEL selectorForMSIDSSOExtensionSilentTokenRequestController = NSSelectorFromString(@"canPerformRequest"); + [MSIDTestSwizzle classMethod:selectorForMSIDSSOExtensionSilentTokenRequestController + class:[MSIDSSOExtensionSilentTokenRequestController class] + block:(id)^(void) + { + return NO; + }]; + + SEL selectorForMSIDXpcSilentTokenRequestController = NSSelectorFromString(@"canPerformRequest"); + [MSIDTestSwizzle classMethod:selectorForMSIDXpcSilentTokenRequestController + class:[MSIDXpcSilentTokenRequestController class] + block:(id)^(void) + { + return YES; + }]; + + SEL selectorForMSIDRequestParameters = NSSelectorFromString(@"shouldUseBroker"); + [MSIDTestSwizzle instanceMethod:selectorForMSIDRequestParameters + class:[MSIDRequestParameters class] + block:(id)^(void) + { + return YES; + }]; + + id controller = [MSIDRequestControllerFactory silentControllerForParameters:parameters + forceRefresh:NO + skipLocalRt:MSIDSilentControllerForceSkippingLocalRt + tokenRequestProvider:provider + error:&error]; + // 1. Start with local signin controller to read cached tokens + if (![controller isMemberOfClass:MSIDSilentController.class]) + { + XCTFail(); + } + + XCTAssertTrue([(MSIDSilentController *)controller skipLocalRt]); + XCTAssertFalse([(MSIDSilentController *)controller forceRefresh]); + + MSIDBaseRequestController *baseController = (MSIDBaseRequestController *)controller; + + // 2. When SsoExtension controller disabled, use local signin controller to refresh. XPC is ignore as it is in XPC backup mode + if (![baseController.fallbackController isMemberOfClass:MSIDSilentController.class]) + { + XCTFail(); + } + + baseController = (MSIDSilentController *)baseController.fallbackController; + XCTAssertTrue([(MSIDSilentController *)baseController forceRefresh]); + XCTAssertTrue([(MSIDSilentController *)baseController isLocalFallbackMode]); +} + +- (void)testWhenSsoExtensionIsEnabled_andXpcIsPartiallyEnabled_andSsoExtensionIsEnabled_controllersOrder_areCorrect +{ + MSIDTestTokenRequestProvider *provider = [[MSIDTestTokenRequestProvider alloc] initWithTestResponse:nil + testError:nil + testWebMSAuthResponse:nil]; + MSIDRequestParameters *parameters = [self requestParameters]; + parameters.xpcMode = MSIDXpcModeBackup; parameters.allowUsingLocalCachedRtWhenSsoExtFailed = YES; NSError *error; @@ -272,9 +334,77 @@ - (void)testWhenSsoExtensionIsEnabled_andXPCIsEnabled_controllersOrder_areCorrec XCTAssertTrue([(MSIDSilentController *)baseController forceRefresh]); XCTAssertTrue([(MSIDSilentController *)baseController isLocalFallbackMode]); } + +- (void)testWhenSsoExtensionIsEnabled_andXpcIsFullyEnabled_andSsoExtensionIsDisabled_controllersOrder_areCorrect +{ + MSIDTestTokenRequestProvider *provider = [[MSIDTestTokenRequestProvider alloc] initWithTestResponse:nil + testError:nil + testWebMSAuthResponse:nil]; + MSIDRequestParameters *parameters = [self requestParameters]; + parameters.xpcMode = MSIDXpcModeFull; + parameters.allowUsingLocalCachedRtWhenSsoExtFailed = YES; + + NSError *error; + SEL selectorForMSIDSSOExtensionSilentTokenRequestController = NSSelectorFromString(@"canPerformRequest"); + [MSIDTestSwizzle classMethod:selectorForMSIDSSOExtensionSilentTokenRequestController + class:[MSIDSSOExtensionSilentTokenRequestController class] + block:(id)^(void) + { + return NO; + }]; + + SEL selectorForMSIDXpcSilentTokenRequestController = NSSelectorFromString(@"canPerformRequest"); + [MSIDTestSwizzle classMethod:selectorForMSIDXpcSilentTokenRequestController + class:[MSIDXpcSilentTokenRequestController class] + block:(id)^(void) + { + return YES; + }]; + + SEL selectorForMSIDRequestParameters = NSSelectorFromString(@"shouldUseBroker"); + [MSIDTestSwizzle instanceMethod:selectorForMSIDRequestParameters + class:[MSIDRequestParameters class] + block:(id)^(void) + { + return YES; + }]; + + id controller = [MSIDRequestControllerFactory silentControllerForParameters:parameters + forceRefresh:NO + skipLocalRt:MSIDSilentControllerForceSkippingLocalRt + tokenRequestProvider:provider + error:&error]; + // 1. Start with local signin controller to read cached tokens + if (![controller isMemberOfClass:MSIDSilentController.class]) + { + XCTFail(); + } + + XCTAssertTrue([(MSIDSilentController *)controller skipLocalRt]); + XCTAssertFalse([(MSIDSilentController *)controller forceRefresh]); + + // 2. When local signin controller failed, use SsoExtension controller + MSIDBaseRequestController *baseController = (MSIDBaseRequestController *)controller; + if (![baseController.fallbackController isMemberOfClass:MSIDXpcSilentTokenRequestController.class]) + { + XCTFail(); + } + + // 2. When SsoExtension controller failed, use Xpc Controller + baseController = (MSIDXpcSilentTokenRequestController *)baseController.fallbackController; + if (![baseController.fallbackController isMemberOfClass:MSIDSilentController.class]) + { + XCTFail(); + } + + // 3. When Xpc controller failed, use local signin controller to refresh + baseController = (MSIDSilentController *)baseController.fallbackController; + XCTAssertTrue([(MSIDSilentController *)baseController forceRefresh]); + XCTAssertTrue([(MSIDSilentController *)baseController isLocalFallbackMode]); +} #endif -- (void)testWhenSsoExtensionIsEnabled_andXPCIsDisabled_controllersOrder_areCorrect +- (void)testWhenSsoExtensionIsEnabled_andXpcIsDisabled_controllersOrder_areCorrect { MSIDTestTokenRequestProvider *provider = [[MSIDTestTokenRequestProvider alloc] initWithTestResponse:nil testError:nil