From df6bd3bbe25c3e3d4a0cb4c6d5b90a1403cf85ce Mon Sep 17 00:00:00 2001 From: Olga Dalton Date: Sun, 21 Oct 2018 14:59:08 -0700 Subject: [PATCH 1/3] Added app name and version change to MSAL --- MSAL/IdentityCore | 2 +- MSAL/src/requests/MSALRequestParameters.h | 1 + MSAL/src/requests/MSALRequestParameters.m | 31 +++++++++++ MSAL/test/unit/MSALAcquireTokenTests.m | 5 +- MSAL/test/unit/MSALInteractiveRequestTests.m | 22 ++------ MSAL/test/unit/MSALSilentRequestTests.m | 32 +++-------- MSAL/test/unit/ios/unit-test-host/Info.plist | 2 + .../telemetry/MSALTelemetryDispatcherTests.m | 6 +++ .../unit/utils/MSIDTestURLResponse+MSAL.h | 2 + .../unit/utils/MSIDTestURLResponse+MSAL.m | 54 +++++++++---------- 10 files changed, 83 insertions(+), 74 deletions(-) diff --git a/MSAL/IdentityCore b/MSAL/IdentityCore index d18b6e4b11..553b2cdca2 160000 --- a/MSAL/IdentityCore +++ b/MSAL/IdentityCore @@ -1 +1 @@ -Subproject commit d18b6e4b1170a0421bb6880fc55046aaaa494d77 +Subproject commit 553b2cdca257d82c0e70c6651c2605d57289eac9 diff --git a/MSAL/src/requests/MSALRequestParameters.h b/MSAL/src/requests/MSALRequestParameters.h index 7ae30e53a9..7979b78a96 100644 --- a/MSAL/src/requests/MSALRequestParameters.h +++ b/MSAL/src/requests/MSALRequestParameters.h @@ -61,6 +61,7 @@ @property NSUUID *correlationId; @property NSString *logComponent; @property NSString *telemetryRequestId; +@property NSDictionary *appRequestMetadata; @property (readonly) MSIDConfiguration *msidConfiguration; @property MSIDOauth2Factory *msidOAuthFactory; diff --git a/MSAL/src/requests/MSALRequestParameters.m b/MSAL/src/requests/MSALRequestParameters.m index bbf4de9368..2d89331c97 100644 --- a/MSAL/src/requests/MSALRequestParameters.m +++ b/MSAL/src/requests/MSALRequestParameters.m @@ -32,9 +32,40 @@ #import "NSOrderedSet+MSIDExtensions.h" #import "MSIDAuthorityFactory.h" #import "MSALAuthority.h" +#import "MSIDConstants.h" @implementation MSALRequestParameters +- (instancetype)init +{ + self = [super init]; + + if (self) + { + [self initDefaultAppMetadata]; + } + + return self; +} + +- (void)initDefaultAppMetadata +{ + NSDictionary *metadata = [[NSBundle mainBundle] infoDictionary]; + + NSString *appName = metadata[@"CFBundleDisplayName"]; + + if (!appName) + { + appName = metadata[@"CFBundleName"]; + } + + NSString *appVer = metadata[@"CFBundleShortVersionString"]; + + _appRequestMetadata = @{MSID_VERSION_KEY: @MSAL_VERSION_STRING, + MSID_APP_NAME_KEY: appName ? appName : @"", + MSID_APP_VER_KEY: appVer ? appVer : @""}; +} + - (void)setScopesFromArray:(NSArray *)scopes { NSMutableArray *scopesLowercase = [NSMutableArray new]; diff --git a/MSAL/test/unit/MSALAcquireTokenTests.m b/MSAL/test/unit/MSALAcquireTokenTests.m index ad19ca92d8..914dc48d0a 100644 --- a/MSAL/test/unit/MSALAcquireTokenTests.m +++ b/MSAL/test/unit/MSALAcquireTokenTests.m @@ -1099,11 +1099,8 @@ - (void)addTestTokenResponseWithResponseScopes:(NSString *)responseScopes NSDictionary *clientInfo = @{ @"uid" : @"1", @"utid" : [MSALTestIdTokenUtil defaultTenantId]}; // Token request response. - NSMutableDictionary *reqHeaders = [[MSIDDeviceId deviceId] mutableCopy]; - [reqHeaders setObject:@"true" forKey:@"return-client-request-id"]; + NSMutableDictionary *reqHeaders = [[MSIDTestURLResponse msalDefaultRequestHeaders] mutableCopy]; [reqHeaders setObject:@"application/x-www-form-urlencoded" forKey:@"Content-Type"]; - [reqHeaders setObject:@"application/json" forKey:@"Accept"]; - [reqHeaders setObject:[MSIDTestRequireValueSentinel new] forKey:@"client-request-id"]; NSString *url = [NSString stringWithFormat:@"%@/oauth2/v2.0/token", authority]; diff --git a/MSAL/test/unit/MSALInteractiveRequestTests.m b/MSAL/test/unit/MSALInteractiveRequestTests.m index acce26e3f9..3c1982bbe4 100644 --- a/MSAL/test/unit/MSALInteractiveRequestTests.m +++ b/MSAL/test/unit/MSALInteractiveRequestTests.m @@ -153,12 +153,9 @@ - (void)testInteractiveRequestFlow_whenValid_shouldReturnResultWithNoError completionHandler(oauthResponse, nil); }]; - NSMutableDictionary *reqHeaders = [[MSIDDeviceId deviceId] mutableCopy]; - [reqHeaders setObject:@"true" forKey:@"return-client-request-id"]; + NSMutableDictionary *reqHeaders = [[MSIDTestURLResponse msalDefaultRequestHeaders] mutableCopy]; [reqHeaders setObject:@"application/x-www-form-urlencoded" forKey:@"Content-Type"]; - [reqHeaders setObject:@"application/json" forKey:@"Accept"]; - [reqHeaders setObject:correlationId.UUIDString forKey:@"client-request-id"]; - + NSString *url = @"https://login.microsoftonline.com/common/oauth2/v2.0/token"; MSIDTestURLResponse *response = @@ -379,11 +376,8 @@ - (void)testInteractiveRequestFlow_whenValidWithUser_shouldReturnResultWithNoErr completionHandler(oauthResponse, nil); }]; - NSMutableDictionary *reqHeaders = [[MSIDDeviceId deviceId] mutableCopy]; - [reqHeaders setObject:@"true" forKey:@"return-client-request-id"]; + NSMutableDictionary *reqHeaders = [[MSIDTestURLResponse msalDefaultRequestHeaders] mutableCopy]; [reqHeaders setObject:@"application/x-www-form-urlencoded" forKey:@"Content-Type"]; - [reqHeaders setObject:@"application/json" forKey:@"Accept"]; - [reqHeaders setObject:correlationId.UUIDString forKey:@"client-request-id"]; NSString *url = @"https://login.microsoftonline.com/common/oauth2/v2.0/token"; @@ -499,11 +493,8 @@ - (void)testInteractiveRequestFlow_whenUserMismatch_shouldReturnNilResultWithErr completionHandler(oauthResponse, nil); }]; - NSMutableDictionary *reqHeaders = [[MSIDDeviceId deviceId] mutableCopy]; - [reqHeaders setObject:@"true" forKey:@"return-client-request-id"]; + NSMutableDictionary *reqHeaders = [[MSIDTestURLResponse msalDefaultRequestHeaders] mutableCopy]; [reqHeaders setObject:@"application/x-www-form-urlencoded" forKey:@"Content-Type"]; - [reqHeaders setObject:@"application/json" forKey:@"Accept"]; - [reqHeaders setObject:correlationId.UUIDString forKey:@"client-request-id"]; NSString *url = @"https://login.microsoftonline.com/common/oauth2/v2.0/token"; @@ -592,11 +583,8 @@ - (void)testInteractiveRequestFlow_whenNoAccessTokenReturned_shouldReturnError completionHandler(oauthResponse, nil); }]; - NSMutableDictionary *reqHeaders = [[MSIDDeviceId deviceId] mutableCopy]; - [reqHeaders setObject:@"true" forKey:@"return-client-request-id"]; + NSMutableDictionary *reqHeaders = [[MSIDTestURLResponse msalDefaultRequestHeaders] mutableCopy]; [reqHeaders setObject:@"application/x-www-form-urlencoded" forKey:@"Content-Type"]; - [reqHeaders setObject:@"application/json" forKey:@"Accept"]; - [reqHeaders setObject:correlationId.UUIDString forKey:@"client-request-id"]; NSString *url = @"https://login.microsoftonline.com/common/oauth2/v2.0/token"; diff --git a/MSAL/test/unit/MSALSilentRequestTests.m b/MSAL/test/unit/MSALSilentRequestTests.m index a7ee91052c..c8cf77f048 100644 --- a/MSAL/test/unit/MSALSilentRequestTests.m +++ b/MSAL/test/unit/MSALSilentRequestTests.m @@ -262,10 +262,8 @@ - (void)testAtsAuthorityATExpired error:nil]; XCTAssertTrue(result); - NSMutableDictionary *reqHeaders = [[MSIDDeviceId deviceId] mutableCopy]; - [reqHeaders setObject:@"true" forKey:@"return-client-request-id"]; + NSMutableDictionary *reqHeaders = [[MSIDTestURLResponse msalDefaultRequestHeaders] mutableCopy]; [reqHeaders setObject:@"application/x-www-form-urlencoded" forKey:@"Content-Type"]; - [reqHeaders setObject:@"application/json" forKey:@"Accept"]; [reqHeaders setObject:correlationId.UUIDString forKey:@"client-request-id"]; NSString *url = @"https://login.microsoftonline.com/common/oauth2/v2.0/token?slice=myslice"; @@ -366,10 +364,8 @@ - (void)testAtsAuthority_whenATExpiresIn50WithinExpirationBuffer100_shouldReAcqu error:nil]; XCTAssertTrue(result); - NSMutableDictionary *reqHeaders = [[MSIDDeviceId deviceId] mutableCopy]; - [reqHeaders setObject:@"true" forKey:@"return-client-request-id"]; + NSMutableDictionary *reqHeaders = [[MSIDTestURLResponse msalDefaultRequestHeaders] mutableCopy]; [reqHeaders setObject:@"application/x-www-form-urlencoded" forKey:@"Content-Type"]; - [reqHeaders setObject:@"application/json" forKey:@"Accept"]; [reqHeaders setObject:correlationId.UUIDString forKey:@"client-request-id"]; NSString *url = @"https://login.microsoftonline.com/common/oauth2/v2.0/token?slice=myslice"; @@ -469,10 +465,8 @@ - (void)testAtsHomeAuthorityATExpired error:nil]; XCTAssertTrue(result); - NSMutableDictionary *reqHeaders = [[MSIDDeviceId deviceId] mutableCopy]; - [reqHeaders setObject:@"true" forKey:@"return-client-request-id"]; + NSMutableDictionary *reqHeaders = [[MSIDTestURLResponse msalDefaultRequestHeaders] mutableCopy]; [reqHeaders setObject:@"application/x-www-form-urlencoded" forKey:@"Content-Type"]; - [reqHeaders setObject:@"application/json" forKey:@"Accept"]; [reqHeaders setObject:correlationId.UUIDString forKey:@"client-request-id"]; NSString *url = @"https://login.microsoftonline.com/1234-5678-90abcdefg/oauth2/v2.0/token"; @@ -652,10 +646,8 @@ - (void)testAtsAuthorityForceUpdate result = [self.tokenCacheAccessor removeToken:accessToken context:nil error:nil]; XCTAssertTrue(result); - NSMutableDictionary *reqHeaders = [[MSIDDeviceId deviceId] mutableCopy]; - [reqHeaders setObject:@"true" forKey:@"return-client-request-id"]; + NSMutableDictionary *reqHeaders = [[MSIDTestURLResponse msalDefaultRequestHeaders] mutableCopy]; [reqHeaders setObject:@"application/x-www-form-urlencoded" forKey:@"Content-Type"]; - [reqHeaders setObject:@"application/json" forKey:@"Accept"]; [reqHeaders setObject:correlationId.UUIDString forKey:@"client-request-id"]; NSString *url = @"https://login.microsoftonline.com/common/oauth2/v2.0/token"; @@ -807,10 +799,8 @@ - (void)testAtsAuthorityForceUpdateUserNotMatch result = [self.tokenCacheAccessor removeToken:accessToken context:nil error:nil]; XCTAssertTrue(result); - NSMutableDictionary *reqHeaders = [[MSIDDeviceId deviceId] mutableCopy]; - [reqHeaders setObject:@"true" forKey:@"return-client-request-id"]; + NSMutableDictionary *reqHeaders = [[MSIDTestURLResponse msalDefaultRequestHeaders] mutableCopy]; [reqHeaders setObject:@"application/x-www-form-urlencoded" forKey:@"Content-Type"]; - [reqHeaders setObject:@"application/json" forKey:@"Accept"]; [reqHeaders setObject:correlationId.UUIDString forKey:@"client-request-id"]; NSString *url = @"https://login.microsoftonline.com/common/oauth2/v2.0/token"; @@ -918,10 +908,8 @@ - (void)testSilentRequest_whenForceUpdateAndNoATReturned_shouldReturnError result = [self.tokenCacheAccessor removeToken:accessToken context:nil error:nil]; XCTAssertTrue(result); - NSMutableDictionary *reqHeaders = [[MSIDDeviceId deviceId] mutableCopy]; - [reqHeaders setObject:@"true" forKey:@"return-client-request-id"]; + NSMutableDictionary *reqHeaders = [[MSIDTestURLResponse msalDefaultRequestHeaders] mutableCopy]; [reqHeaders setObject:@"application/x-www-form-urlencoded" forKey:@"Content-Type"]; - [reqHeaders setObject:@"application/json" forKey:@"Accept"]; [reqHeaders setObject:correlationId.UUIDString forKey:@"client-request-id"]; NSString *url = @"https://login.microsoftonline.com/common/oauth2/v2.0/token"; @@ -1028,10 +1016,8 @@ - (void)testSilentRequest_whenResiliencyErrorReturned_shouldRetryRequestOnceAndS MSIDTestURLResponse *oidcResponse = [MSIDTestURLResponse oidcResponseForAuthority:@"https://login.microsoftonline.com/common"]; [MSIDTestURLSession addResponses:@[discoveryResponse, oidcResponse]]; - NSMutableDictionary *reqHeaders = [[MSIDDeviceId deviceId] mutableCopy]; - [reqHeaders setObject:@"true" forKey:@"return-client-request-id"]; + NSMutableDictionary *reqHeaders = [[MSIDTestURLResponse msalDefaultRequestHeaders] mutableCopy]; [reqHeaders setObject:@"application/x-www-form-urlencoded" forKey:@"Content-Type"]; - [reqHeaders setObject:@"application/json" forKey:@"Accept"]; [reqHeaders setObject:correlationId.UUIDString forKey:@"client-request-id"]; // Create failing response first @@ -1154,10 +1140,8 @@ - (void)testSilentRequest_when429ThrottledErrorReturned_shouldReturnAllHeadersAn MSIDTestURLResponse *oidcResponse = [MSIDTestURLResponse oidcResponseForAuthority:@"https://login.microsoftonline.com/common"]; [MSIDTestURLSession addResponses:@[discoveryResponse, oidcResponse]]; - NSMutableDictionary *reqHeaders = [[MSIDDeviceId deviceId] mutableCopy]; - [reqHeaders setObject:@"true" forKey:@"return-client-request-id"]; + NSMutableDictionary *reqHeaders = [[MSIDTestURLResponse msalDefaultRequestHeaders] mutableCopy]; [reqHeaders setObject:@"application/x-www-form-urlencoded" forKey:@"Content-Type"]; - [reqHeaders setObject:@"application/json" forKey:@"Accept"]; [reqHeaders setObject:correlationId.UUIDString forKey:@"client-request-id"]; NSString *url = @"https://login.microsoftonline.com/common/oauth2/v2.0/token?slice=myslice"; diff --git a/MSAL/test/unit/ios/unit-test-host/Info.plist b/MSAL/test/unit/ios/unit-test-host/Info.plist index d052473868..6168538f7f 100644 --- a/MSAL/test/unit/ios/unit-test-host/Info.plist +++ b/MSAL/test/unit/ios/unit-test-host/Info.plist @@ -4,6 +4,8 @@ CFBundleDevelopmentRegion en + CFBundleDisplayName + UnitTestHost CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier diff --git a/MSAL/test/unit/telemetry/MSALTelemetryDispatcherTests.m b/MSAL/test/unit/telemetry/MSALTelemetryDispatcherTests.m index 2102696356..96040e6798 100644 --- a/MSAL/test/unit/telemetry/MSALTelemetryDispatcherTests.m +++ b/MSAL/test/unit/telemetry/MSALTelemetryDispatcherTests.m @@ -73,6 +73,12 @@ - (NSString *)logComponent return nil; } +- (NSDictionary *)appRequestMetadata +{ + return nil; +} + + - (NSURLSession *)urlSession { return nil; diff --git a/MSAL/test/unit/utils/MSIDTestURLResponse+MSAL.h b/MSAL/test/unit/utils/MSIDTestURLResponse+MSAL.h index 7b43530b85..8928117793 100644 --- a/MSAL/test/unit/utils/MSIDTestURLResponse+MSAL.h +++ b/MSAL/test/unit/utils/MSIDTestURLResponse+MSAL.h @@ -31,6 +31,8 @@ @interface MSIDTestURLResponse (MSAL) ++ (NSDictionary *)msalDefaultRequestHeaders; + + (MSIDTestURLResponse *)discoveryResponseForAuthority:(NSString *)authority; + (MSIDTestURLResponse *)oidcResponseForAuthority:(NSString *)authority; diff --git a/MSAL/test/unit/utils/MSIDTestURLResponse+MSAL.m b/MSAL/test/unit/utils/MSIDTestURLResponse+MSAL.m index fb15f11eb2..ea1f2d2235 100644 --- a/MSAL/test/unit/utils/MSIDTestURLResponse+MSAL.m +++ b/MSAL/test/unit/utils/MSIDTestURLResponse+MSAL.m @@ -37,12 +37,28 @@ @implementation MSIDTestURLResponse (MSAL) ++ (NSDictionary *)msalDefaultRequestHeaders +{ + static NSDictionary *s_msalHeaders = nil; + static dispatch_once_t headersOnce; + + dispatch_once(&headersOnce, ^{ + NSMutableDictionary *headers = [[MSIDDeviceId deviceId] mutableCopy]; + headers[@"return-client-request-id"] = @"true"; + headers[@"client-request-id"] = [MSIDTestRequireValueSentinel sentinel]; + headers[@"Accept"] = @"application/json"; + headers[@"x-app-name"] = @"UnitTestHost"; + headers[@"x-app-ver"] = @"1.0"; + + s_msalHeaders = [headers copy]; + }); + + return s_msalHeaders; +} + + (MSIDTestURLResponse *)oidcResponseForAuthority:(NSString *)authority { - NSMutableDictionary *oidcReqHeaders = [[MSIDDeviceId deviceId] mutableCopy]; - [oidcReqHeaders setObject:@"true" forKey:@"return-client-request-id"]; - [oidcReqHeaders setObject:[MSIDTestRequireValueSentinel new] forKey:@"client-request-id"]; - [oidcReqHeaders setObject:@"application/json" forKey:@"Accept"]; + NSDictionary *oidcReqHeaders = [self msalDefaultRequestHeaders]; NSDictionary *oidcJson = @{ @"token_endpoint" : [NSString stringWithFormat:@"%@/oauth2/v2.0/token", authority], @@ -75,11 +91,8 @@ + (MSIDTestURLResponse *)discoveryResponseForAuthority:(NSString *)authority MSIDTestURLResponse *discoveryResponse = [MSIDTestURLResponse request:[NSURL URLWithString:requestUrl] reponse:httpResponse]; - NSMutableDictionary *headers = [[MSIDDeviceId deviceId] mutableCopy]; - headers[@"Accept"] = @"application/json"; - headers[@"return-client-request-id"] = @"true"; - headers[@"client-request-id"] = [MSIDTestRequireValueSentinel new]; - discoveryResponse->_requestHeaders = headers; + NSDictionary *headers = [self msalDefaultRequestHeaders]; + discoveryResponse->_requestHeaders = [headers mutableCopy]; NSString *tenantDiscoveryEndpoint = [NSString stringWithFormat:@"%@/v2.0/.well-known/openid-configuration", authority]; @@ -106,10 +119,7 @@ + (MSIDTestURLResponse *)oidcResponseForAuthority:(NSString *)authority responseUrl:(NSString *)responseAuthority query:(NSString *)query { - NSMutableDictionary *oidcReqHeaders = [[MSIDDeviceId deviceId] mutableCopy]; - [oidcReqHeaders setObject:@"true" forKey:@"return-client-request-id"]; - [oidcReqHeaders setObject:[MSIDTestRequireValueSentinel new] forKey:@"client-request-id"]; - [oidcReqHeaders setObject:@"application/json" forKey:@"Accept"]; + NSDictionary *oidcReqHeaders = [self msalDefaultRequestHeaders]; NSString *queryString = query ? [NSString stringWithFormat:@"?%@", query] : @""; @@ -136,11 +146,7 @@ + (MSIDTestURLResponse *)rtResponseForScopes:(MSALScopes *)scopes tenantId:(NSString *)tid user:(MSALAccount *)user { - NSMutableDictionary *tokenReqHeaders = [[MSIDDeviceId deviceId] mutableCopy]; - [tokenReqHeaders setObject:@"application/json" forKey:@"Accept"]; - [tokenReqHeaders setObject:[MSIDTestRequireValueSentinel new] forKey:@"client-request-id"]; - [tokenReqHeaders setObject:@"true" forKey:@"return-client-request-id"]; - [tokenReqHeaders setObject:@"application/x-www-form-urlencoded" forKey:@"Content-Type"]; + NSDictionary *tokenReqHeaders = [self msalDefaultRequestHeaders]; MSIDTestURLResponse *tokenResponse = [MSIDTestURLResponse requestURLString:[NSString stringWithFormat:@"%@/oauth2/v2.0/token", authority] @@ -175,11 +181,7 @@ + (MSIDTestURLResponse *)errorRtResponseForScopes:(MSALScopes *)scopes errorDescription:(NSString *)errorDescription subError:(NSString *)subError { - NSMutableDictionary *tokenReqHeaders = [[MSIDDeviceId deviceId] mutableCopy]; - [tokenReqHeaders setObject:@"application/json" forKey:@"Accept"]; - [tokenReqHeaders setObject:[MSIDTestRequireValueSentinel new] forKey:@"client-request-id"]; - [tokenReqHeaders setObject:@"true" forKey:@"return-client-request-id"]; - [tokenReqHeaders setObject:@"application/x-www-form-urlencoded" forKey:@"Content-Type"]; + NSDictionary *tokenReqHeaders = [self msalDefaultRequestHeaders]; MSIDTestURLResponse *tokenResponse = [MSIDTestURLResponse requestURLString:[NSString stringWithFormat:@"%@/oauth2/v2.0/token", authority] @@ -220,11 +222,7 @@ + (MSIDTestURLResponse *)authCodeResponse:(NSString *)authcode scopes:(MSALScopes *)scopes clientInfo:(NSDictionary *)clientInfo { - NSMutableDictionary *tokenReqHeaders = [[MSIDDeviceId deviceId] mutableCopy]; - [tokenReqHeaders setObject:@"application/json" forKey:@"Accept"]; - [tokenReqHeaders setObject:[MSIDTestRequireValueSentinel new] forKey:@"client-request-id"]; - [tokenReqHeaders setObject:@"true" forKey:@"return-client-request-id"]; - [tokenReqHeaders setObject:@"application/x-www-form-urlencoded" forKey:@"Content-Type"]; + NSDictionary *tokenReqHeaders = [self msalDefaultRequestHeaders]; NSMutableDictionary *tokenQPs = [NSMutableDictionary new]; if (query) From 96f29e2be7aadfdaf4de637adc4da8736c3b1e72 Mon Sep 17 00:00:00 2001 From: Olga Dalton Date: Mon, 22 Oct 2018 14:12:17 -0700 Subject: [PATCH 2/3] Updated identitycore submodule --- MSAL/IdentityCore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MSAL/IdentityCore b/MSAL/IdentityCore index 553b2cdca2..a98d6ed570 160000 --- a/MSAL/IdentityCore +++ b/MSAL/IdentityCore @@ -1 +1 @@ -Subproject commit 553b2cdca257d82c0e70c6651c2605d57289eac9 +Subproject commit a98d6ed57059b061b4bf9267fdec278a0090cb82 From 91432231f498fdadb825fd093cc258b5b58d26e8 Mon Sep 17 00:00:00 2001 From: Olga Dalton Date: Mon, 22 Oct 2018 18:17:25 -0700 Subject: [PATCH 3/3] Separate B2C logic --- MSAL/IdentityCore | 2 +- MSAL/MSAL.xcodeproj/project.pbxproj | 18 ++++ MSAL/src/MSALPublicClientApplication.m | 24 ++++-- MSAL/src/instance/MSALOauth2FactoryProducer.h | 38 +++++++++ MSAL/src/instance/MSALOauth2FactoryProducer.m | 62 ++++++++++++++ MSAL/src/requests/MSALBaseRequest.h | 2 +- MSAL/src/requests/MSALBaseRequest.m | 17 +++- .../interactive/MSALB2CInteractiveTests.m | 8 +- MSAL/test/unit/MSALInteractiveRequestTests.m | 9 +- .../unit/MSALOauth2FactoryProducerTests.m | 83 +++++++++++++++++++ MSAL/test/unit/MSALSilentRequestTests.m | 16 ++++ 11 files changed, 261 insertions(+), 18 deletions(-) create mode 100644 MSAL/src/instance/MSALOauth2FactoryProducer.h create mode 100644 MSAL/src/instance/MSALOauth2FactoryProducer.m create mode 100644 MSAL/test/unit/MSALOauth2FactoryProducerTests.m diff --git a/MSAL/IdentityCore b/MSAL/IdentityCore index d18b6e4b11..85066b0798 160000 --- a/MSAL/IdentityCore +++ b/MSAL/IdentityCore @@ -1 +1 @@ -Subproject commit d18b6e4b1170a0421bb6880fc55046aaaa494d77 +Subproject commit 85066b0798c5eac12765883f3fed9dc04437480d diff --git a/MSAL/MSAL.xcodeproj/project.pbxproj b/MSAL/MSAL.xcodeproj/project.pbxproj index b66c981077..6021da4a7c 100644 --- a/MSAL/MSAL.xcodeproj/project.pbxproj +++ b/MSAL/MSAL.xcodeproj/project.pbxproj @@ -107,6 +107,8 @@ B221CEEC20C0AF0B002F5E94 /* MSALAccountId+Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = B221CEEA20C0AF0B002F5E94 /* MSALAccountId+Internal.h */; }; B2341A2A21507CA1008E93FC /* AuthenticationServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 963C89A6214BA1760051AFEE /* AuthenticationServices.framework */; }; B2341A2B21507CA7008E93FC /* AuthenticationServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 963C89A6214BA1760051AFEE /* AuthenticationServices.framework */; }; + B256121B217EA44900999876 /* MSALOauth2FactoryProducerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = B256121A217EA44900999876 /* MSALOauth2FactoryProducerTests.m */; }; + B256121C217EA44900999876 /* MSALOauth2FactoryProducerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = B256121A217EA44900999876 /* MSALOauth2FactoryProducerTests.m */; }; B25F1BBB1EC3DB3200474D1B /* MSIDTokenCacheItem+Automation.m in Sources */ = {isa = PBXBuildFile; fileRef = B25F1BBA1EC3DB3200474D1B /* MSIDTokenCacheItem+Automation.m */; }; B25F1BC11EC3DD3200474D1B /* MSALUser+Automation.m in Sources */ = {isa = PBXBuildFile; fileRef = B25F1BC01EC3DD3200474D1B /* MSALUser+Automation.m */; }; B25F1BC41EC3E44500474D1B /* MSALResult+Automation.m in Sources */ = {isa = PBXBuildFile; fileRef = B25F1BC31EC3E44500474D1B /* MSALResult+Automation.m */; }; @@ -115,6 +117,10 @@ B2734C1C21253AD300DAB1CD /* MSALMultiAppCacheCoexistenceTests.m in Sources */ = {isa = PBXBuildFile; fileRef = B2734C1B21253AD300DAB1CD /* MSALMultiAppCacheCoexistenceTests.m */; }; B2734C1E21253B1B00DAB1CD /* MSALDotNetCacheCoexistenceTests.m in Sources */ = {isa = PBXBuildFile; fileRef = B2734C1D21253B1B00DAB1CD /* MSALDotNetCacheCoexistenceTests.m */; }; B277241E1EAE97D700375C53 /* MSALStressTestHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = B277241D1EAE97D700375C53 /* MSALStressTestHelper.m */; }; + B28BDA8E217E9EAB003E5670 /* MSALOauth2FactoryProducer.h in Headers */ = {isa = PBXBuildFile; fileRef = B28BDA8C217E9EAB003E5670 /* MSALOauth2FactoryProducer.h */; }; + B28BDA8F217E9EAB003E5670 /* MSALOauth2FactoryProducer.h in Headers */ = {isa = PBXBuildFile; fileRef = B28BDA8C217E9EAB003E5670 /* MSALOauth2FactoryProducer.h */; }; + B28BDA90217E9EAB003E5670 /* MSALOauth2FactoryProducer.m in Sources */ = {isa = PBXBuildFile; fileRef = B28BDA8D217E9EAB003E5670 /* MSALOauth2FactoryProducer.m */; }; + B28BDA91217E9EAB003E5670 /* MSALOauth2FactoryProducer.m in Sources */ = {isa = PBXBuildFile; fileRef = B28BDA8D217E9EAB003E5670 /* MSALOauth2FactoryProducer.m */; }; B29E2AC221238DCD00B170ED /* libIdentityCore.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D6A206231FC50A4D00755A51 /* libIdentityCore.a */; }; B29E2AC321238DFC00B170ED /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 96902DEC20E1574F00200E6F /* WebKit.framework */; }; B29E2AC521238E0000B170ED /* SafariServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B29E2AC421238E0000B170ED /* SafariServices.framework */; }; @@ -556,6 +562,7 @@ B221CED920C0AC60002F5E94 /* MSALAccountId.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MSALAccountId.h; sourceTree = ""; }; B221CEDA20C0AC60002F5E94 /* MSALAccountId.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MSALAccountId.m; sourceTree = ""; }; B221CEEA20C0AF0B002F5E94 /* MSALAccountId+Internal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "MSALAccountId+Internal.h"; sourceTree = ""; }; + B256121A217EA44900999876 /* MSALOauth2FactoryProducerTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MSALOauth2FactoryProducerTests.m; sourceTree = ""; }; B25F1BB21EC257F900474D1B /* MSALB2CPolicyTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MSALB2CPolicyTests.m; sourceTree = ""; }; B25F1BB91EC3DB3200474D1B /* MSIDTokenCacheItem+Automation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MSIDTokenCacheItem+Automation.h"; sourceTree = ""; }; B25F1BBA1EC3DB3200474D1B /* MSIDTokenCacheItem+Automation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MSIDTokenCacheItem+Automation.m"; sourceTree = ""; }; @@ -571,6 +578,8 @@ B2734C1D21253B1B00DAB1CD /* MSALDotNetCacheCoexistenceTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MSALDotNetCacheCoexistenceTests.m; sourceTree = ""; }; B277241C1EAE97D700375C53 /* MSALStressTestHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MSALStressTestHelper.h; sourceTree = ""; }; B277241D1EAE97D700375C53 /* MSALStressTestHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MSALStressTestHelper.m; sourceTree = ""; }; + B28BDA8C217E9EAB003E5670 /* MSALOauth2FactoryProducer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MSALOauth2FactoryProducer.h; sourceTree = ""; }; + B28BDA8D217E9EAB003E5670 /* MSALOauth2FactoryProducer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MSALOauth2FactoryProducer.m; sourceTree = ""; }; B29E2AC421238E0000B170ED /* SafariServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SafariServices.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.4.sdk/System/Library/Frameworks/SafariServices.framework; sourceTree = DEVELOPER_DIR; }; B29E2AC821238F2200B170ED /* MSALNonUnifiedADALCoexistenceCacheTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MSALNonUnifiedADALCoexistenceCacheTests.m; sourceTree = ""; }; B29E2ACE21238F5200B170ED /* MultiAppiOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MultiAppiOSTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -861,6 +870,8 @@ 23A68A7F20F538DE0071E435 /* MSALADFSAuthority.m */, 23A68A8B20F57A440071E435 /* MSALAuthorityFactory.h */, 23A68A8C20F57A440071E435 /* MSALAuthorityFactory.m */, + B28BDA8C217E9EAB003E5670 /* MSALOauth2FactoryProducer.h */, + B28BDA8D217E9EAB003E5670 /* MSALOauth2FactoryProducer.m */, ); path = instance; sourceTree = ""; @@ -1260,6 +1271,7 @@ B25F1BB21EC257F900474D1B /* MSALB2CPolicyTests.m */, 04D32CCF1FD8AFF3000B123E /* MSALErrorConverterTests.m */, B210E3E21FC23D4700E7A325 /* MSALErrorTests.m */, + B256121A217EA44900999876 /* MSALOauth2FactoryProducerTests.m */, ); path = unit; sourceTree = ""; @@ -1467,6 +1479,7 @@ 23F32F071FF4787600B2905E /* MSIDTestURLResponse+MSAL.h in Headers */, D65A6FB21E3FF41D00C69FBA /* MSALError.h in Headers */, 9682624C20E304F30080694D /* MSALWebviewType.h in Headers */, + B28BDA8E217E9EAB003E5670 /* MSALOauth2FactoryProducer.h in Headers */, D65A6FB41E3FF41D00C69FBA /* MSALPublicClientApplication.h in Headers */, B2A3C29621460D290082525C /* MSALAuthority.h in Headers */, B21E07B1210E542C007E3A3C /* MSALRedirectUriVerifier.h in Headers */, @@ -1496,6 +1509,7 @@ B2B5F08C1FCA61EB00F6AFAD /* MSALTelemetryDefaultEvent.h in Headers */, D673F0791E4A633B0018BA91 /* MSALError_Internal.h in Headers */, B21E07B2210E542C007E3A3C /* MSALRedirectUriVerifier.h in Headers */, + B28BDA8F217E9EAB003E5670 /* MSALOauth2FactoryProducer.h in Headers */, 94E876DF1E495F2700FB96ED /* MSALUIBehavior.h in Headers */, D65A6FA91E3FF3D900C69FBA /* MSALError.h in Headers */, 96D9A5451E4AB1DC00674A85 /* MSALTelemetry.h in Headers */, @@ -2107,6 +2121,7 @@ D61BD2AF1EBD09F90007E484 /* MSALLogger.m in Sources */, D61BD2BF1EBD0A010007E484 /* MSALDefaultDispatcher.m in Sources */, D61BD2B81EBD0A010007E484 /* MSALTelemetryAPIEvent.m in Sources */, + B28BDA90217E9EAB003E5670 /* MSALOauth2FactoryProducer.m in Sources */, D61BD2B01EBD09F90007E484 /* MSALPublicClientApplication.m in Sources */, D61BD2AD1EBD09F90007E484 /* MSALError.m in Sources */, 963377C1211E14C600943EE0 /* MSALWebviewType.m in Sources */, @@ -2141,6 +2156,7 @@ D673F08F1E4CE6D70018BA91 /* MSALError.m in Sources */, 23A68A8320F538DE0071E435 /* MSALADFSAuthority.m in Sources */, 23A68A7720F5386A0071E435 /* MSALAADAuthority.m in Sources */, + B28BDA91217E9EAB003E5670 /* MSALOauth2FactoryProducer.m in Sources */, D673F0951E4CE6DB0018BA91 /* MSALRequestParameters.m in Sources */, D673F0981E4CE6DB0018BA91 /* MSALInteractiveRequest.m in Sources */, D673F0911E4CE6D70018BA91 /* MSALLogger.m in Sources */, @@ -2170,6 +2186,7 @@ D61F5BC01E5913BE00912CB8 /* SFSafariViewController+TestOverrides.m in Sources */, D69ADB351E516F9B00952049 /* MSALTestBundle.m in Sources */, D69ADB3F1E516F9B00952049 /* MSALTestURLSessionDataTask.m in Sources */, + B256121B217EA44900999876 /* MSALOauth2FactoryProducerTests.m in Sources */, D62746D91E9B5F1E00EFCE99 /* MSALUserTests.m in Sources */, D69ADB3D1E516F9B00952049 /* MSIDTestURLSession+MSAL.m in Sources */, 2364C74B1FB3E5CB00835428 /* XCTestCase+HelperMethods.m in Sources */, @@ -2201,6 +2218,7 @@ B21E07C3210E5C3C007E3A3C /* MSALRedirectUriVerifierTests.m in Sources */, D69ADB401E516F9B00952049 /* MSALTestURLSessionDataTask.m in Sources */, D62746DA1E9B5F1E00EFCE99 /* MSALUserTests.m in Sources */, + B256121C217EA44900999876 /* MSALOauth2FactoryProducerTests.m in Sources */, D69ADB3C1E516F9B00952049 /* MSALTestSwizzle.m in Sources */, D69ADB381E516F9B00952049 /* MSALTestCase.m in Sources */, 04D32CD11FD8AFF3000B123E /* MSALErrorConverterTests.m in Sources */, diff --git a/MSAL/src/MSALPublicClientApplication.m b/MSAL/src/MSALPublicClientApplication.m index a1ef6ebcd1..0acb699153 100644 --- a/MSAL/src/MSALPublicClientApplication.m +++ b/MSAL/src/MSALPublicClientApplication.m @@ -54,6 +54,7 @@ #import "MSIDAADAuthority.h" #import "MSIDAuthorityFactory.h" #import "MSALAADAuthority.h" +#import "MSALOauth2FactoryProducer.h" static NSString *const s_defaultAuthorityUrlString = @"https://login.microsoftonline.com/common"; @@ -71,6 +72,7 @@ @interface MSALPublicClientApplication() { WKWebView *_customWebview; NSString *_defaultKeychainGroup; + MSIDOauth2Factory *_oauth2Factory; } @property (nonatomic) MSIDDefaultTokenCacheAccessor *tokenCache; @@ -205,6 +207,14 @@ - (id)initWithClientId:(NSString *)clientId _authority = [[MSALAADAuthority alloc] initWithURL:authorityURL context:nil error:error]; } + _oauth2Factory = [MSALOauth2FactoryProducer msidOauth2FactoryForAuthority:_authority.url context:nil error:error]; + + if (!_oauth2Factory) + { + MSID_LOG_ERROR(nil, @"Couldn't create Oauth2 factory"); + return nil; + } + BOOL redirectUriValid = [self verifyRedirectUri:redirectUri clientId:clientId error:error]; if (!redirectUriValid) return nil; @@ -220,11 +230,9 @@ - (id)initWithClientId:(NSString *)clientId } dataSource = [[MSIDKeychainTokenCache alloc] initWithGroup:_keychainGroup]; - - MSIDOauth2Factory *factory = [MSIDAADV2Oauth2Factory new]; - - MSIDLegacyTokenCacheAccessor *legacyAccessor = [[MSIDLegacyTokenCacheAccessor alloc] initWithDataSource:dataSource otherCacheAccessors:nil factory:factory]; - MSIDDefaultTokenCacheAccessor *defaultAccessor = [[MSIDDefaultTokenCacheAccessor alloc] initWithDataSource:dataSource otherCacheAccessors:@[legacyAccessor] factory:factory]; + + MSIDLegacyTokenCacheAccessor *legacyAccessor = [[MSIDLegacyTokenCacheAccessor alloc] initWithDataSource:dataSource otherCacheAccessors:nil factory:_oauth2Factory]; + MSIDDefaultTokenCacheAccessor *defaultAccessor = [[MSIDDefaultTokenCacheAccessor alloc] initWithDataSource:dataSource otherCacheAccessors:@[legacyAccessor] factory:_oauth2Factory]; self.tokenCache = defaultAccessor; @@ -233,7 +241,7 @@ - (id)initWithClientId:(NSString *)clientId #else __auto_type dataSource = MSIDMacTokenCache.defaultCache; - MSIDDefaultTokenCacheAccessor *defaultAccessor = [[MSIDDefaultTokenCacheAccessor alloc] initWithDataSource:dataSource otherCacheAccessors:nil factory:[MSIDAADV2Oauth2Factory new]]; + MSIDDefaultTokenCacheAccessor *defaultAccessor = [[MSIDDefaultTokenCacheAccessor alloc] initWithDataSource:dataSource otherCacheAccessors:nil factory:_oauth2Factory]; self.tokenCache = defaultAccessor; _webviewType = MSALWebviewTypeWKWebView; @@ -550,7 +558,7 @@ - (void)acquireTokenForScopes:(NSArray *)scopes { MSALRequestParameters *params = [MSALRequestParameters new]; - params.msidOAuthFactory = [MSIDAADV2Oauth2Factory new]; + params.msidOAuthFactory = _oauth2Factory; params.correlationId = correlationId ? correlationId : [NSUUID new]; params.logComponent = _component; params.apiId = apiId; @@ -637,7 +645,7 @@ - (void)acquireTokenSilentForScopes:(NSArray *)scopes msidAuthority = [authorityFactory authorityFromUrl:msidAuthority.url rawTenant:account.homeAccountId.tenantId context:nil error:nil]; MSALRequestParameters* params = [MSALRequestParameters new]; - params.msidOAuthFactory = [MSIDAADV2Oauth2Factory new]; + params.msidOAuthFactory = _oauth2Factory; params.correlationId = correlationId ? correlationId : [NSUUID new]; params.account = account; params.apiId = apiId; diff --git a/MSAL/src/instance/MSALOauth2FactoryProducer.h b/MSAL/src/instance/MSALOauth2FactoryProducer.h new file mode 100644 index 0000000000..536be8b674 --- /dev/null +++ b/MSAL/src/instance/MSALOauth2FactoryProducer.h @@ -0,0 +1,38 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) Microsoft Corporation. +// All rights reserved. +// +// This code is licensed under the MIT License. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files(the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions : +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// 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 +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +//------------------------------------------------------------------------------ + +#import + +@class MSIDOauth2Factory; + +@interface MSALOauth2FactoryProducer : NSObject + ++ (nullable MSIDOauth2Factory *)msidOauth2FactoryForAuthority:(nonnull NSURL *)authority + context:(nullable id)context + error:(NSError * _Nullable __autoreleasing * _Nullable)error; + +@end diff --git a/MSAL/src/instance/MSALOauth2FactoryProducer.m b/MSAL/src/instance/MSALOauth2FactoryProducer.m new file mode 100644 index 0000000000..8d73cf9a9b --- /dev/null +++ b/MSAL/src/instance/MSALOauth2FactoryProducer.m @@ -0,0 +1,62 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) Microsoft Corporation. +// All rights reserved. +// +// This code is licensed under the MIT License. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files(the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions : +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// 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 +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +//------------------------------------------------------------------------------ + +#import "MSALOauth2FactoryProducer.h" +#import "MSIDOauth2Factory.h" +#import "MSIDB2CAuthority.h" +#import "MSIDAADAuthority.h" +#import "MSIDAADV2Oauth2Factory.h" +#import "MSIDB2COauth2Factory.h" + +@implementation MSALOauth2FactoryProducer + ++ (MSIDOauth2Factory *)msidOauth2FactoryForAuthority:(NSURL *)authority + context:(id)context + error:(NSError **)error +{ + if (!authority) + { + if (error) + { + *error = MSIDCreateError(MSALErrorDomain, MSALErrorInvalidParameter, @"Provided authority url is not a valid authority.", nil, nil, nil, nil, nil); + MSID_LOG_ERROR(context, @"Provided authority url is not a valid authority."); + } + + return nil; + } + + if ([MSIDB2CAuthority isAuthorityFormatValid:authority context:context error:nil]) + { + return [MSIDB2COauth2Factory new]; + } + + // Create AAD v2 factory for everything else, but in future we might want to further separate this out + // (e.g. ADFS, Google, Oauth2 etc...) + return [MSIDAADV2Oauth2Factory new]; +} + +@end diff --git a/MSAL/src/requests/MSALBaseRequest.h b/MSAL/src/requests/MSALBaseRequest.h index 61c9b37409..14e065304b 100644 --- a/MSAL/src/requests/MSALBaseRequest.h +++ b/MSAL/src/requests/MSALBaseRequest.h @@ -48,7 +48,7 @@ typedef void(^MSALAuthorityCompletion)(BOOL resolved, NSError * _Nullable error) @property (nullable) MSALTokenCacheItem *accessTokenItem; @property (nonnull, readonly) MSALRequestParameters *parameters; @property (nullable, nonatomic, readonly) MSIDDefaultTokenCacheAccessor *tokenCache; -@property (nullable, nonatomic, readonly) MSIDAADV2Oauth2Factory *oauth2Factory; +@property (nullable, nonatomic, readonly) MSIDOauth2Factory *oauth2Factory; /* Returns the complete set of scopes to be sent out with a token request */ - (nonnull MSALScopes *)requestScopes:(nullable MSALScopes *)extraScopes; diff --git a/MSAL/src/requests/MSALBaseRequest.m b/MSAL/src/requests/MSALBaseRequest.m index f5c7f264a8..45e9bcd054 100644 --- a/MSAL/src/requests/MSALBaseRequest.m +++ b/MSAL/src/requests/MSALBaseRequest.m @@ -54,7 +54,7 @@ @interface MSALBaseRequest() @property (nullable, nonatomic) MSIDDefaultTokenCacheAccessor *tokenCache; -@property (nullable, nonatomic) MSIDAADV2Oauth2Factory *oauth2Factory; +@property (nullable, nonatomic) MSIDOauth2Factory *oauth2Factory; @end @@ -97,7 +97,20 @@ - (id)initWithParameters:(MSALRequestParameters *)parameters } _tokenCache = tokenCache; - _oauth2Factory = [MSIDAADV2Oauth2Factory new]; + + if (!_tokenCache) + { + REQUIRED_PARAMETER_ERROR(tokenCache, _parameters); + return nil; + } + + _oauth2Factory = _parameters.msidOAuthFactory; + + if (!_oauth2Factory) + { + REQUIRED_PARAMETER_ERROR(_parameters.msidOAuthFactory, _parameters); + return nil; + } MSIDAADNetworkConfiguration.defaultConfiguration.aadApiVersion = @"v2.0"; diff --git a/MSAL/test/automation/tests/interactive/MSALB2CInteractiveTests.m b/MSAL/test/automation/tests/interactive/MSALB2CInteractiveTests.m index 63d26d76c1..76b9e2c5f2 100644 --- a/MSAL/test/automation/tests/interactive/MSALB2CInteractiveTests.m +++ b/MSAL/test/automation/tests/interactive/MSALB2CInteractiveTests.m @@ -122,7 +122,7 @@ - (void)testInteractiveB2CLogin_withEmbeddedWebView_withoutLoginHint_withSigninP request.accountIdentifier = homeAccountId; // B2C currently doesn't return "tid" claim in the id_token, so MSAL will use tenantId from the provided authority - request.cacheAuthority = [NSString stringWithFormat:@"https://login.microsoftonline.com/%@", self.primaryAccount.tenantName]; + request.cacheAuthority = [NSString stringWithFormat:@"https://login.microsoftonline.com/%@", self.primaryAccount.homeTenantId]; // 4. Run silent login request.testAccount = nil; [self runSharedSilentAADLoginWithTestRequest:request]; @@ -192,7 +192,7 @@ - (void)testInteractiveB2CLogin_withSafariViewController_withoutLoginHint_withSi [self runSharedAuthUIAppearsStepWithTestRequest:request]; request.accountIdentifier = homeAccountId; - request.cacheAuthority = [NSString stringWithFormat:@"https://login.microsoftonline.com/%@", self.primaryAccount.tenantName]; + request.cacheAuthority = [NSString stringWithFormat:@"https://login.microsoftonline.com/%@", self.primaryAccount.homeTenantId]; // 4. Run silent login request.testAccount = nil; [self runSharedSilentAADLoginWithTestRequest:request]; @@ -251,14 +251,14 @@ - (void)testInteractiveB2CLogin_withPassedInWebView_withoutLoginHint_withSigninA // 5. Get token silently for the first request request.accountIdentifier = homeAccountId; // B2C currently doesn't return "tid" claim in the id_token, so MSAL will use tenantId from the provided authority - request.cacheAuthority = [NSString stringWithFormat:@"https://login.microsoftonline.com/%@", self.primaryAccount.tenantName]; + request.cacheAuthority = [NSString stringWithFormat:@"https://login.microsoftonline.com/%@", self.primaryAccount.homeTenantId]; request.testAccount = nil; [self runSharedSilentAADLoginWithTestRequest:request]; // 6. Get token silently for the second request profileRequest.accountIdentifier = profileHomeAccountId; // B2C currently doesn't return "tid" claim in the id_token, so MSAL will use tenantId from the provided authority - profileRequest.cacheAuthority = [NSString stringWithFormat:@"https://login.microsoftonline.com/%@", self.primaryAccount.tenantName]; + profileRequest.cacheAuthority = [NSString stringWithFormat:@"https://login.microsoftonline.com/%@", self.primaryAccount.homeTenantId]; profileRequest.testAccount = nil; [self runSharedSilentAADLoginWithTestRequest:profileRequest]; diff --git a/MSAL/test/unit/MSALInteractiveRequestTests.m b/MSAL/test/unit/MSALInteractiveRequestTests.m index acce26e3f9..44f83be260 100644 --- a/MSAL/test/unit/MSALInteractiveRequestTests.m +++ b/MSAL/test/unit/MSALInteractiveRequestTests.m @@ -100,12 +100,13 @@ - (void)testInitWithParameters_whenValidParams_shouldInit parameters.extraQueryParameters = @{ @"eqp1" : @"val1", @"eqp2" : @"val2" }; parameters.loginHint = @"fakeuser@contoso.com"; parameters.correlationId = correlationId; + parameters.msidOAuthFactory = [MSIDAADV2Oauth2Factory new]; MSALInteractiveRequest *request = [[MSALInteractiveRequest alloc] initWithParameters:parameters - extraScopesToConsent:@[@"fakescope3"] + extraScopesToConsent:@[@"fakescope3"] behavior:MSALForceConsent - tokenCache:nil + tokenCache:[MSIDDefaultTokenCacheAccessor new] error:&error]; XCTAssertNotNil(request); @@ -127,6 +128,7 @@ - (void)testInteractiveRequestFlow_whenValid_shouldReturnResultWithNoError parameters.loginHint = @"fakeuser@contoso.com"; parameters.correlationId = correlationId; parameters.webviewType = MSALWebviewTypeWKWebView; + parameters.msidOAuthFactory = [MSIDAADV2Oauth2Factory new]; __block MSALInteractiveRequest *request = [[MSALInteractiveRequest alloc] initWithParameters:parameters @@ -345,6 +347,7 @@ - (void)testInteractiveRequestFlow_whenValidWithUser_shouldReturnResultWithNoErr parameters.extraQueryParameters = @{ @"eqp1" : @"val1", @"eqp2" : @"val2" }; parameters.correlationId = correlationId; parameters.webviewType = MSALWebviewTypeWKWebView; + parameters.msidOAuthFactory = [MSIDAADV2Oauth2Factory new]; MSALAccount *account = [[MSALAccount alloc] initWithUsername:@"User" name:@"user@contoso.com" @@ -465,6 +468,7 @@ - (void)testInteractiveRequestFlow_whenUserMismatch_shouldReturnNilResultWithErr parameters.extraQueryParameters = @{ @"eqp1" : @"val1", @"eqp2" : @"val2" }; parameters.correlationId = correlationId; parameters.webviewType = MSALWebviewTypeWKWebView; + parameters.msidOAuthFactory = [MSIDAADV2Oauth2Factory new]; MSALAccount *account = [[MSALAccount alloc] initWithUsername:@"User" name:@"user@contoso.com" @@ -566,6 +570,7 @@ - (void)testInteractiveRequestFlow_whenNoAccessTokenReturned_shouldReturnError parameters.loginHint = @"fakeuser@contoso.com"; parameters.correlationId = correlationId; parameters.webviewType = MSALWebviewTypeWKWebView; + parameters.msidOAuthFactory = [MSIDAADV2Oauth2Factory new]; __block MSALInteractiveRequest *request = [[MSALInteractiveRequest alloc] initWithParameters:parameters diff --git a/MSAL/test/unit/MSALOauth2FactoryProducerTests.m b/MSAL/test/unit/MSALOauth2FactoryProducerTests.m new file mode 100644 index 0000000000..7e47e4d384 --- /dev/null +++ b/MSAL/test/unit/MSALOauth2FactoryProducerTests.m @@ -0,0 +1,83 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) Microsoft Corporation. +// All rights reserved. +// +// This code is licensed under the MIT License. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files(the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions : +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// 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 +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +//------------------------------------------------------------------------------ + +#import +#import "MSALOauth2FactoryProducer.h" +#import "MSIDOauth2Factory.h" +#import "MSIDAADV2Oauth2Factory.h" +#import "MSIDB2COauth2Factory.h" + +@interface MSALOauth2FactoryProducerTests : XCTestCase + +@end + +@implementation MSALOauth2FactoryProducerTests + +- (void)testOauth2FactoryForAuthority_whenNilAuthority_shouldReturnNilAndError +{ + NSError *error = nil; + NSURL *authorityURL = nil; + MSIDOauth2Factory *factory = [MSALOauth2FactoryProducer msidOauth2FactoryForAuthority:authorityURL context:nil error:&error]; + + XCTAssertNil(factory); + XCTAssertNotNil(error); +} + +- (void)testOauth2FactoryForAuthority_whenB2CAuthority_shouldReturnB2CFactoryNilError +{ + NSError *error = nil; + NSURL *authorityURL = [NSURL URLWithString:@"https://login.microsoftonline.com/tfp/contoso.com/B2C_1_Signin"]; + MSIDOauth2Factory *factory = [MSALOauth2FactoryProducer msidOauth2FactoryForAuthority:authorityURL context:nil error:&error]; + + XCTAssertNotNil(factory); + XCTAssertNil(error); + XCTAssertTrue([factory isKindOfClass:[MSIDB2COauth2Factory class]]); +} + +- (void)testOauth2FactoryForAuthority_whenAADAuthority_shouldReturnAADV2FactoryNilError +{ + NSError *error = nil; + NSURL *authorityURL = [NSURL URLWithString:@"https://login.microsoftonline.com/contoso.com/"]; + MSIDOauth2Factory *factory = [MSALOauth2FactoryProducer msidOauth2FactoryForAuthority:authorityURL context:nil error:&error]; + + XCTAssertNotNil(factory); + XCTAssertNil(error); + XCTAssertTrue([factory isKindOfClass:[MSIDAADV2Oauth2Factory class]]); +} + +- (void)testOauth2FactoryForAuthority_whenADFSAuthority_shouldReturnAADV2FactoryNilError +{ + NSError *error = nil; + NSURL *authorityURL = [NSURL URLWithString:@"https://contoso.com/adfs"]; + MSIDOauth2Factory *factory = [MSALOauth2FactoryProducer msidOauth2FactoryForAuthority:authorityURL context:nil error:&error]; + + XCTAssertNotNil(factory); + XCTAssertNil(error); + XCTAssertTrue([factory isKindOfClass:[MSIDAADV2Oauth2Factory class]]); +} + +@end diff --git a/MSAL/test/unit/MSALSilentRequestTests.m b/MSAL/test/unit/MSALSilentRequestTests.m index a7ee91052c..8336eb714b 100644 --- a/MSAL/test/unit/MSALSilentRequestTests.m +++ b/MSAL/test/unit/MSALSilentRequestTests.m @@ -104,6 +104,7 @@ - (void)testInit parameters.clientId = UNIT_TEST_CLIENT_ID; parameters.loginHint = @"fakeuser@contoso.com"; parameters.correlationId = correlationId; + parameters.msidOAuthFactory = [MSIDAADV2Oauth2Factory new]; MSALSilentRequest *request = [[MSALSilentRequest alloc] initWithParameters:parameters forceRefresh:NO tokenCache:self.tokenCacheAccessor expirationBuffer:300 error:&error]; @@ -124,6 +125,7 @@ - (void)testAtsNoUser parameters.clientId = UNIT_TEST_CLIENT_ID; parameters.loginHint = @"fakeuser@contoso.com"; parameters.correlationId = correlationId; + parameters.msidOAuthFactory = [MSIDAADV2Oauth2Factory new]; MSALSilentRequest *request = [[MSALSilentRequest alloc] initWithParameters:parameters forceRefresh:NO tokenCache:self.tokenCacheAccessor expirationBuffer:300 error:&error]; @@ -162,6 +164,7 @@ - (void)testAtsATFound parameters.clientId = UNIT_TEST_CLIENT_ID; parameters.loginHint = @"fakeuser@contoso.com"; parameters.correlationId = correlationId; + parameters.msidOAuthFactory = [MSIDAADV2Oauth2Factory new]; NSDictionary* idTokenClaims = @{ @"home_oid" : @"29f3807a-4fb0-42f2-a44a-236aa0cb3f97", @"preferred_username": @"fakeuser@contoso.com"}; NSDictionary* clientInfoClaims = @{ @"uid" : @"29f3807a-4fb0-42f2-a44a-236aa0cb3f97", @"utid" : @"0287f963-2d72-4363-9e3a-5705c5b0f031"}; @@ -226,6 +229,7 @@ - (void)testAtsAuthorityATExpired parameters.loginHint = @"fakeuser@contoso.com"; parameters.correlationId = correlationId; parameters.sliceParameters = @{ @"slice" : @"myslice" }; + parameters.msidOAuthFactory = [MSIDAADV2Oauth2Factory new]; NSDictionary* clientInfoClaims = @{ @"uid" : @"1", @"utid" : @"1234-5678-90abcdefg"}; MSALAccount *account = [[MSALAccount alloc] initWithUsername:@"preferredUserName" @@ -330,6 +334,7 @@ - (void)testAtsAuthority_whenATExpiresIn50WithinExpirationBuffer100_shouldReAcqu parameters.loginHint = @"fakeuser@contoso.com"; parameters.correlationId = correlationId; parameters.sliceParameters = @{ @"slice" : @"myslice" }; + parameters.msidOAuthFactory = [MSIDAADV2Oauth2Factory new]; NSDictionary* clientInfoClaims = @{ @"uid" : @"1", @"utid" : @"1234-5678-90abcdefg"}; MSALAccount *account = [[MSALAccount alloc] initWithUsername:@"preferredUserName" @@ -433,6 +438,7 @@ - (void)testAtsHomeAuthorityATExpired parameters.loginHint = @"fakeuser@contoso.com"; parameters.correlationId = correlationId; parameters.sliceParameters = @{ UT_SLICE_PARAMS_DICT }; + parameters.msidOAuthFactory = [MSIDAADV2Oauth2Factory new]; NSDictionary* clientInfoClaims = @{ @"uid" : @"1", @"utid" : @"1234-5678-90abcdefg"}; @@ -538,6 +544,7 @@ - (void)testAtsAuthorityATExpiredAndRTNotFound parameters.clientId = UNIT_TEST_CLIENT_ID; parameters.loginHint = @"fakeuser@contoso.com"; parameters.correlationId = correlationId; + parameters.msidOAuthFactory = [MSIDAADV2Oauth2Factory new]; NSDictionary* clientInfoClaims = @{ @"uid" : @"1", @"utid" : @"1234-5678-90abcdefg"}; @@ -610,6 +617,8 @@ - (void)testAtsAuthorityForceUpdate parameters.clientId = UNIT_TEST_CLIENT_ID; parameters.loginHint = @"fakeuser@contoso.com"; parameters.correlationId = correlationId; + parameters.msidOAuthFactory = [MSIDAADV2Oauth2Factory new]; + NSDictionary* clientInfoClaims = @{ @"uid" : @"1", @"utid" : @"1234-5678-90abcdefg"}; MSALAccount *account = [[MSALAccount alloc] initWithUsername:@"preferredUserName" @@ -719,6 +728,7 @@ - (void)testAtsAuthorityForceUpdateRTNotFound parameters.clientId = UNIT_TEST_CLIENT_ID; parameters.loginHint = @"fakeuser@contoso.com"; parameters.correlationId = correlationId; + parameters.msidOAuthFactory = [MSIDAADV2Oauth2Factory new]; MSALAccount *account = [[MSALAccount alloc] initWithUsername:@"preferredUserName" name:@"user@contoso.com" @@ -765,6 +775,7 @@ - (void)testAtsAuthorityForceUpdateUserNotMatch parameters.clientId = UNIT_TEST_CLIENT_ID; parameters.loginHint = @"fakeuser@contoso.com"; parameters.correlationId = correlationId; + parameters.msidOAuthFactory = [MSIDAADV2Oauth2Factory new]; NSDictionary* clientInfoClaims = @{ @"uid" : @"1", @"utid" : @"1234-5678-90abcdefg"}; @@ -875,6 +886,7 @@ - (void)testSilentRequest_whenForceUpdateAndNoATReturned_shouldReturnError parameters.clientId = UNIT_TEST_CLIENT_ID; parameters.loginHint = @"fakeuser@contoso.com"; parameters.correlationId = correlationId; + parameters.msidOAuthFactory = [MSIDAADV2Oauth2Factory new]; NSDictionary* idTokenClaims = @{ @"home_oid" : @"29f3807a-4fb0-42f2-a44a-236aa0cb3f97", @"preferred_username": @"fakeuser@contoso.com"}; NSDictionary* clientInfoClaims = @{ @"uid" : @"1", @"utid" : @"1234-5678-90abcdefg"}; @@ -987,6 +999,8 @@ - (void)testSilentRequest_whenResiliencyErrorReturned_shouldRetryRequestOnceAndS parameters.loginHint = @"fakeuser@contoso.com"; parameters.correlationId = correlationId; parameters.sliceParameters = @{ @"slice" : @"myslice" }; + parameters.msidOAuthFactory = [MSIDAADV2Oauth2Factory new]; + NSDictionary* clientInfoClaims = @{ @"uid" : @"1", @"utid" : @"1234-5678-90abcdefg"}; MSALAccount *account = [[MSALAccount alloc] initWithUsername:@"preferredUserName" @@ -1113,6 +1127,8 @@ - (void)testSilentRequest_when429ThrottledErrorReturned_shouldReturnAllHeadersAn parameters.loginHint = @"fakeuser@contoso.com"; parameters.correlationId = correlationId; parameters.sliceParameters = @{ @"slice" : @"myslice" }; + parameters.msidOAuthFactory = [MSIDAADV2Oauth2Factory new]; + NSDictionary* clientInfoClaims = @{ @"uid" : @"1", @"utid" : @"1234-5678-90abcdefg"}; MSALAccount *account = [[MSALAccount alloc] initWithUsername:@"preferredUserName"