diff --git a/IdentityCore/IdentityCore.xcodeproj/project.pbxproj b/IdentityCore/IdentityCore.xcodeproj/project.pbxproj index 34576b758..06fb5a492 100644 --- a/IdentityCore/IdentityCore.xcodeproj/project.pbxproj +++ b/IdentityCore/IdentityCore.xcodeproj/project.pbxproj @@ -468,6 +468,8 @@ B253BD7A20487C8A00D07F31 /* MSIDLegacyTokenCacheIntegrationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = B23ECF041FF33AE70015FC1D /* MSIDLegacyTokenCacheIntegrationTests.m */; }; B2544EEB21684B2B00B4C108 /* MSIDCacheSchemaValidationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = B2544EEA21684B2B00B4C108 /* MSIDCacheSchemaValidationTests.m */; }; B2544EEC21684B2B00B4C108 /* MSIDCacheSchemaValidationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = B2544EEA21684B2B00B4C108 /* MSIDCacheSchemaValidationTests.m */; }; + B2561224217EA97000999876 /* MSIDB2COauth2FactoryTests.m in Sources */ = {isa = PBXBuildFile; fileRef = B2561221217EA93800999876 /* MSIDB2COauth2FactoryTests.m */; }; + B2561225217EA97000999876 /* MSIDB2COauth2FactoryTests.m in Sources */ = {isa = PBXBuildFile; fileRef = B2561221217EA93800999876 /* MSIDB2COauth2FactoryTests.m */; }; B25A356F1FC4D70300C7FD43 /* MSIDLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = B25A356B1FC4D6B600C7FD43 /* MSIDLogger.m */; }; B25A35701FC4D70300C7FD43 /* MSIDLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = B25A356B1FC4D6B600C7FD43 /* MSIDLogger.m */; }; B26A0B7D2071ADCE006BD95A /* MSIDOauth2Factory.h in Headers */ = {isa = PBXBuildFile; fileRef = B26A0B7B2071ADCE006BD95A /* MSIDOauth2Factory.h */; }; @@ -530,6 +532,15 @@ B280800B204CD81400944D89 /* MSIDLegacyCacheKeyTests.m in Sources */ = {isa = PBXBuildFile; fileRef = B2808009204CD81400944D89 /* MSIDLegacyCacheKeyTests.m */; }; B280800E204CD82100944D89 /* MSIDDefaultCredentialCacheKeyTests.m in Sources */ = {isa = PBXBuildFile; fileRef = B280800C204CD82100944D89 /* MSIDDefaultCredentialCacheKeyTests.m */; }; B2893CB11FCF6A8C00E348E9 /* NSMutableDictionary+MSIDExtensions.m in Sources */ = {isa = PBXBuildFile; fileRef = 23BDA66D1FC78B7E00FE14BE /* NSMutableDictionary+MSIDExtensions.m */; }; + B28BDA7A217E961F003E5670 /* MSIDB2COauth2Factory.h in Headers */ = {isa = PBXBuildFile; fileRef = B28BDA78217E961F003E5670 /* MSIDB2COauth2Factory.h */; }; + B28BDA7B217E961F003E5670 /* MSIDB2COauth2Factory.m in Sources */ = {isa = PBXBuildFile; fileRef = B28BDA79217E961F003E5670 /* MSIDB2COauth2Factory.m */; }; + B28BDA7C217E961F003E5670 /* MSIDB2COauth2Factory.m in Sources */ = {isa = PBXBuildFile; fileRef = B28BDA79217E961F003E5670 /* MSIDB2COauth2Factory.m */; }; + B28BDA7F217E964B003E5670 /* MSIDB2CTokenResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = B28BDA7D217E964B003E5670 /* MSIDB2CTokenResponse.h */; }; + B28BDA80217E964B003E5670 /* MSIDB2CTokenResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = B28BDA7E217E964B003E5670 /* MSIDB2CTokenResponse.m */; }; + B28BDA81217E964B003E5670 /* MSIDB2CTokenResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = B28BDA7E217E964B003E5670 /* MSIDB2CTokenResponse.m */; }; + B28BDA84217E9676003E5670 /* MSIDB2CIdTokenClaims.h in Headers */ = {isa = PBXBuildFile; fileRef = B28BDA82217E9676003E5670 /* MSIDB2CIdTokenClaims.h */; }; + B28BDA85217E9676003E5670 /* MSIDB2CIdTokenClaims.m in Sources */ = {isa = PBXBuildFile; fileRef = B28BDA83217E9676003E5670 /* MSIDB2CIdTokenClaims.m */; }; + B28BDA86217E9676003E5670 /* MSIDB2CIdTokenClaims.m in Sources */ = {isa = PBXBuildFile; fileRef = B28BDA83217E9676003E5670 /* MSIDB2CIdTokenClaims.m */; }; B2908C071FCA29EB00AFE98E /* MSIDTelemetryBaseEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = B2908C051FCA29EB00AFE98E /* MSIDTelemetryBaseEvent.h */; }; B2908C081FCA29EB00AFE98E /* MSIDTelemetryBaseEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = B2908C061FCA29EB00AFE98E /* MSIDTelemetryBaseEvent.m */; }; B2908C091FCA29EB00AFE98E /* MSIDTelemetryBaseEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = B2908C061FCA29EB00AFE98E /* MSIDTelemetryBaseEvent.m */; }; @@ -1167,6 +1178,7 @@ B251CC54204109A4005E0179 /* MSIDCredentialCacheItem.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MSIDCredentialCacheItem.m; sourceTree = ""; }; B252913A2096698100E78695 /* MSIDAADIdTokenClaimsFactoryTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MSIDAADIdTokenClaimsFactoryTests.m; sourceTree = ""; }; B2544EEA21684B2B00B4C108 /* MSIDCacheSchemaValidationTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MSIDCacheSchemaValidationTests.m; sourceTree = ""; }; + B2561221217EA93800999876 /* MSIDB2COauth2FactoryTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MSIDB2COauth2FactoryTests.m; sourceTree = ""; }; B25A35691FC4D6B600C7FD43 /* MSIDLogger+Internal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "MSIDLogger+Internal.h"; sourceTree = ""; }; B25A356A1FC4D6B600C7FD43 /* MSIDLogger.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MSIDLogger.h; sourceTree = ""; }; B25A356B1FC4D6B600C7FD43 /* MSIDLogger.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MSIDLogger.m; sourceTree = ""; }; @@ -1213,6 +1225,12 @@ B2808009204CD81400944D89 /* MSIDLegacyCacheKeyTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MSIDLegacyCacheKeyTests.m; sourceTree = ""; }; B280800C204CD82100944D89 /* MSIDDefaultCredentialCacheKeyTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MSIDDefaultCredentialCacheKeyTests.m; sourceTree = ""; }; B2893CAE1FCF68B200E348E9 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.0.sdk/System/Library/Frameworks/Security.framework; sourceTree = DEVELOPER_DIR; }; + B28BDA78217E961F003E5670 /* MSIDB2COauth2Factory.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MSIDB2COauth2Factory.h; sourceTree = ""; }; + B28BDA79217E961F003E5670 /* MSIDB2COauth2Factory.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MSIDB2COauth2Factory.m; sourceTree = ""; }; + B28BDA7D217E964B003E5670 /* MSIDB2CTokenResponse.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MSIDB2CTokenResponse.h; sourceTree = ""; }; + B28BDA7E217E964B003E5670 /* MSIDB2CTokenResponse.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MSIDB2CTokenResponse.m; sourceTree = ""; }; + B28BDA82217E9676003E5670 /* MSIDB2CIdTokenClaims.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MSIDB2CIdTokenClaims.h; sourceTree = ""; }; + B28BDA83217E9676003E5670 /* MSIDB2CIdTokenClaims.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MSIDB2CIdTokenClaims.m; sourceTree = ""; }; B2908C051FCA29EB00AFE98E /* MSIDTelemetryBaseEvent.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MSIDTelemetryBaseEvent.h; sourceTree = ""; }; B2908C061FCA29EB00AFE98E /* MSIDTelemetryBaseEvent.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MSIDTelemetryBaseEvent.m; sourceTree = ""; }; B2936F4C20AA906C0050C585 /* MSIDLegacyTokenCacheItemTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MSIDLegacyTokenCacheItemTests.m; sourceTree = ""; }; @@ -1905,6 +1923,7 @@ B210F4541FDDFA7B005A8F76 /* MSIDBrokerResponse.m */, B2CDB57A1FE33E99003A4B5C /* MSIDIdTokenClaims.h */, B2CDB57B1FE33E9A003A4B5C /* MSIDIdTokenClaims.m */, + B28BDA77217E95D9003E5670 /* b2c */, B2B1D575204369CA00DD81F0 /* account */, B251CC232041050E005E0179 /* token */, B23ECEE71FF2F3F30015FC1D /* aad_base */, @@ -2097,6 +2116,19 @@ path = keyvault; sourceTree = ""; }; + B28BDA77217E95D9003E5670 /* b2c */ = { + isa = PBXGroup; + children = ( + B28BDA78217E961F003E5670 /* MSIDB2COauth2Factory.h */, + B28BDA79217E961F003E5670 /* MSIDB2COauth2Factory.m */, + B28BDA7D217E964B003E5670 /* MSIDB2CTokenResponse.h */, + B28BDA7E217E964B003E5670 /* MSIDB2CTokenResponse.m */, + B28BDA82217E9676003E5670 /* MSIDB2CIdTokenClaims.h */, + B28BDA83217E9676003E5670 /* MSIDB2CIdTokenClaims.m */, + ); + path = b2c; + sourceTree = ""; + }; B29CB6D11FEC9B4D00F880ED /* aad_v2 */ = { isa = PBXGroup; children = ( @@ -2416,6 +2448,7 @@ B26A0B922072B824006BD95A /* MSIDAADOauth2FactoryTests.m */, B26A0B952072B9CB006BD95A /* MSIDAADV1Oauth2FactoryTests.m */, B26A0B982072BABD006BD95A /* MSIDAADV2Oauth2FactoryTests.m */, + B2561221217EA93800999876 /* MSIDB2COauth2FactoryTests.m */, 2338ECD9208A7CBD00809B9E /* MSIDAADRequestErrorHandlerTests.m */, 238EF07F208FFA4C0035ABE6 /* MSIDUrlRequestSerializerTests.m */, 238EF08220913D750035ABE6 /* MSIDAADRequestConfiguratorTests.m */, @@ -2480,6 +2513,7 @@ 96CD69521FE849C800D41938 /* MSIDTokenResponse.h in Headers */, 238E19E02086FE28004DF483 /* MSIDAADRefreshTokenGrantRequest.h in Headers */, 235480CA20DDF81000246F72 /* MSIDAuthorityFactory.h in Headers */, + B28BDA7A217E961F003E5670 /* MSIDB2COauth2Factory.h in Headers */, 23B39A8B209A53B7000AA905 /* MSIDDRSDiscoveryRequest.h in Headers */, 9641B5241FCF3EEF00AFA0EC /* MSIDMacTokenCache.h in Headers */, B2CDB5761FE2F4E2003A4B5C /* NSOrderedSet+MSIDExtensions.h in Headers */, @@ -2511,6 +2545,7 @@ 9686C72921192BCF001FFF51 /* MSIDWebOpenBrowserResponse.h in Headers */, B2B1D578204369D600DD81F0 /* MSIDAccountType.h in Headers */, 9658103120C7E1180025F4A4 /* MSIDWebviewResponse.h in Headers */, + B28BDA7F217E964B003E5670 /* MSIDB2CTokenResponse.h in Headers */, 96B8D57D20946D2600E3F4A6 /* MSIDPkce.h in Headers */, B297E1E120A1272600F370EC /* MSIDLegacyTokenCacheQuery.h in Headers */, B297E1F020A25F0C00F370EC /* MSIDLegacyTokenCacheItem.h in Headers */, @@ -2591,6 +2626,7 @@ 96F94A3320817C1A0034676C /* MSIDNTLMHandler.h in Headers */, B297E1E620A12BDE00F370EC /* MSIDDefaultAccountCacheKey.h in Headers */, B251CC3B2041058D005E0179 /* MSIDRefreshToken.h in Headers */, + B28BDA84217E9676003E5670 /* MSIDB2CIdTokenClaims.h in Headers */, 23B39AB7209BC705000AA905 /* MSIDOpenIdProviderMetadata.h in Headers */, 238A04932089A3C800989EE0 /* MSIDHttpRequestTelemetry.h in Headers */, 23B39A8120993302000AA905 /* MSIDAadAuthorityResolver.h in Headers */, @@ -2968,6 +3004,7 @@ B2936F7F20ABFF8F0050C585 /* MSIDOauth2FactoryTests.m in Sources */, 9668B6F72148796A0039AB0A /* MSIDDataExtensionsTests.m in Sources */, B252913B2096698100E78695 /* MSIDAADIdTokenClaimsFactoryTests.m in Sources */, + B2561224217EA97000999876 /* MSIDB2COauth2FactoryTests.m in Sources */, B2936F8A20AD47810050C585 /* MSIDKeychainTokenCacheIntegrationTests.m in Sources */, 6035CD8C207EA67300369E69 /* MSIDTelemetryIntegrationTests.m in Sources */, B2DD4B3D20A9270B0047A66E /* MSIDDefaultCredentialCacheQueryTests.m in Sources */, @@ -3066,6 +3103,7 @@ 606830102098E94100CCA6AB /* MSIDCertificateChooser.m in Sources */, 60B3856020A96E2700D546D0 /* MSIDWebviewUIController.m in Sources */, B251CC412041058D005E0179 /* MSIDRefreshToken.m in Sources */, + B28BDA7C217E961F003E5670 /* MSIDB2COauth2Factory.m in Sources */, 2338ECD8208A7B3200809B9E /* MSIDTestContext.m in Sources */, B2CDB56D1FE2F42B003A4B5C /* MSIDJsonSerializer.m in Sources */, 9658103320C7E1180025F4A4 /* MSIDWebviewResponse.m in Sources */, @@ -3116,6 +3154,7 @@ 966D0A8620A0E9F300EDDE94 /* MSIDNetworkConfiguration.m in Sources */, B2D5625A20CCD50E00FFF59C /* MSIDTelemetry+Cache.m in Sources */, B2A3C2802145D02E0082525C /* MSIDAadAuthorityCacheRecord.m in Sources */, + B28BDA81217E964B003E5670 /* MSIDB2CTokenResponse.m in Sources */, 9641B52B1FCF3F3A00AFA0EC /* MSIDKeyedArchiverSerializer.m in Sources */, 238E19E32086FE28004DF483 /* MSIDAADAuthorizationCodeRequest.m in Sources */, 23B39AB9209BC705000AA905 /* MSIDOpenIdProviderMetadata.m in Sources */, @@ -3158,6 +3197,7 @@ 238EF044208FE88C0035ABE6 /* MSIDAADAuthorizationCodeGrantRequest.m in Sources */, 238E19C22086FC38004DF483 /* MSIDJsonResponseSerializer.m in Sources */, 238E19C52086FC38004DF483 /* MSIDHttpResponseSerializer.m in Sources */, + B28BDA86217E9676003E5670 /* MSIDB2CIdTokenClaims.m in Sources */, B2B1D57A204369D600DD81F0 /* MSIDAccountType.m in Sources */, B210F4571FDDFA7B005A8F76 /* MSIDBrokerResponse.m in Sources */, 23B39AC8209BF9F2000AA905 /* MSIDOpenIdConfigurationInfoRequest.m in Sources */, @@ -3248,6 +3288,7 @@ 2338ECDB208A7CBD00809B9E /* MSIDAADRequestErrorHandlerTests.m in Sources */, 964FAB41213F598F00AF0EB1 /* MSIDOrderedSetExtensionsTests.m in Sources */, B2C17AF51FC7A6BD0070A514 /* MSIDTestLogger.m in Sources */, + B2561225217EA97000999876 /* MSIDB2COauth2FactoryTests.m in Sources */, B280800E204CD82100944D89 /* MSIDDefaultCredentialCacheKeyTests.m in Sources */, 23CC94482046507D00AA0551 /* MSIDMacTokenCacheIntegrationTests.m in Sources */, B2964BE620521D790000BC95 /* MSIDTokenFilteringHelperTests.m in Sources */, @@ -3355,12 +3396,14 @@ 60B3855E20A96E0600D546D0 /* MSIDWebviewUIController.m in Sources */, 238E19E22086FE28004DF483 /* MSIDAADAuthorizationCodeRequest.m in Sources */, B2964BE2205103920000BC95 /* MSIDTokenFilteringHelper.m in Sources */, + B28BDA7B217E961F003E5670 /* MSIDB2COauth2Factory.m in Sources */, 239DF9AE20DED6F7002D428B /* MSIDConstants.m in Sources */, B20657AA1FC91ECC00412B7D /* MSIDTelemetry.m in Sources */, B25A35701FC4D70300C7FD43 /* MSIDLogger.m in Sources */, B210F4321FDDE7EB005A8F76 /* MSIDTokenResponse.m in Sources */, 600D19AE20964CC00004CD43 /* MSIDRegistrationInformation.m in Sources */, B2C7B3B4213C681F009FFCC1 /* MSIDErrorConverter.m in Sources */, + B28BDA85217E9676003E5670 /* MSIDB2CIdTokenClaims.m in Sources */, B210F4381FDDEA23005A8F76 /* MSIDAADV1TokenResponse.m in Sources */, 600D19B620964D2F0004CD43 /* MSIDWorkPlaceJoinConstants.m in Sources */, 96B8D57B20946D2600E3F4A6 /* MSIDPkce.m in Sources */, @@ -3445,6 +3488,7 @@ 2321531B1FDA101900C6960D /* MSIDUserInformation.m in Sources */, 232C65842138BD11002A41FE /* MSIDAADAuthorityMetadataResponseSerializer.m in Sources */, B23ECEEB1FF2F56A0015FC1D /* MSIDAADTokenResponse.m in Sources */, + B28BDA80217E964B003E5670 /* MSIDB2CTokenResponse.m in Sources */, 600D19BC20964D8C0004CD43 /* MSIDWorkPlaceJoinUtil.m in Sources */, B251CC3C2041058D005E0179 /* MSIDAccessToken.m in Sources */, B2DD4B2220A7D2F90047A66E /* MSIDLegacyAccessToken.m in Sources */, diff --git a/IdentityCore/src/oauth2/aad_v2/MSIDAADV2Oauth2Factory.h b/IdentityCore/src/oauth2/aad_v2/MSIDAADV2Oauth2Factory.h index 30894dbd4..db518ba41 100644 --- a/IdentityCore/src/oauth2/aad_v2/MSIDAADV2Oauth2Factory.h +++ b/IdentityCore/src/oauth2/aad_v2/MSIDAADV2Oauth2Factory.h @@ -25,4 +25,8 @@ @interface MSIDAADV2Oauth2Factory : MSIDAADOauth2Factory +- (MSIDAuthority *)authorityFromURL:(NSURL *)url + tokenResponse:(MSIDTokenResponse *)response + error:(NSError **)error; + @end diff --git a/IdentityCore/src/oauth2/aad_v2/MSIDAADV2Oauth2Factory.m b/IdentityCore/src/oauth2/aad_v2/MSIDAADV2Oauth2Factory.m index 7f768d626..8c127bc63 100644 --- a/IdentityCore/src/oauth2/aad_v2/MSIDAADV2Oauth2Factory.m +++ b/IdentityCore/src/oauth2/aad_v2/MSIDAADV2Oauth2Factory.m @@ -140,10 +140,7 @@ - (BOOL)fillAccessToken:(MSIDAccessToken *)accessToken } accessToken.scopes = responseScopes; - - __auto_type authority = [self.authorityFactory authorityFromUrl:accessToken.authority.url rawTenant:response.idTokenObj.realm context:nil error:nil]; - - accessToken.authority = authority; + accessToken.authority = [self authorityFromURL:accessToken.authority.url tokenResponse:response error:nil]; return YES; } @@ -158,10 +155,8 @@ - (BOOL)fillIDToken:(MSIDIdToken *)token { return NO; } - - __auto_type authority = [self.authorityFactory authorityFromUrl:token.authority.url rawTenant:response.idTokenObj.realm context:nil error:nil]; - token.authority = authority; + token.authority = [self authorityFromURL:token.authority.url tokenResponse:response error:nil]; return YES; } @@ -181,20 +176,21 @@ - (BOOL)fillAccount:(MSIDAccount *)account { return NO; } - - __auto_type authority = [self.authorityFactory authorityFromUrl:account.authority.url rawTenant:response.idTokenObj.realm context:nil error:nil]; - - account.authority = authority; - - // AAD v2 has to return preferred_username claim - if ([NSString msidIsStringNilOrBlank:response.idTokenObj.preferredUsername]) - { - account.username = MSID_PREFERRED_USERNAME_MISSING; - } + account.authority = [self authorityFromURL:account.authority.url tokenResponse:response error:nil]; return YES; } +- (MSIDAuthority *)authorityFromURL:(NSURL *)url + tokenResponse:(MSIDTokenResponse *)response + error:(NSError **)error +{ + return [self.authorityFactory authorityFromUrl:url + rawTenant:response.idTokenObj.realm + context:nil + error:error]; +} + #pragma mark - Webview - (MSIDWebviewFactory *)webviewFactory { diff --git a/IdentityCore/src/oauth2/b2c/MSIDB2CIdTokenClaims.h b/IdentityCore/src/oauth2/b2c/MSIDB2CIdTokenClaims.h new file mode 100644 index 000000000..7632d335f --- /dev/null +++ b/IdentityCore/src/oauth2/b2c/MSIDB2CIdTokenClaims.h @@ -0,0 +1,39 @@ +//------------------------------------------------------------------------------ +// +// 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 "MSIDAADV2IdTokenClaims.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface MSIDB2CIdTokenClaims : MSIDAADV2IdTokenClaims + +// This is the name of the policy that was used to acquire the ID token. +@property (readonly) NSString *tfp; + +@end + +NS_ASSUME_NONNULL_END diff --git a/IdentityCore/src/oauth2/b2c/MSIDB2CIdTokenClaims.m b/IdentityCore/src/oauth2/b2c/MSIDB2CIdTokenClaims.m new file mode 100644 index 000000000..4cacc9a5f --- /dev/null +++ b/IdentityCore/src/oauth2/b2c/MSIDB2CIdTokenClaims.m @@ -0,0 +1,65 @@ +//------------------------------------------------------------------------------ +// +// 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 "MSIDB2CIdTokenClaims.h" +#import "MSIDHelpers.h" + +@implementation MSIDB2CIdTokenClaims + +MSID_JSON_ACCESSOR(@"tfp", tfp) + +- (void)initDerivedProperties +{ + [super initDerivedProperties]; + + // Set userId + NSString *userId = self.preferredUsername; + + if ([NSString msidIsStringNilOrBlank:userId]) + { + userId = self.subject; + _userIdDisplayable = NO; + } + else + { + _userIdDisplayable = YES; + } + + _userId = [MSIDHelpers normalizeUserId:userId]; +} + +- (NSString *)alternativeAccountId +{ + return nil; +} + +- (NSString *)realm +{ + return self.tenantId; +} + +@end diff --git a/IdentityCore/src/oauth2/b2c/MSIDB2COauth2Factory.h b/IdentityCore/src/oauth2/b2c/MSIDB2COauth2Factory.h new file mode 100644 index 000000000..bf7b4be23 --- /dev/null +++ b/IdentityCore/src/oauth2/b2c/MSIDB2COauth2Factory.h @@ -0,0 +1,36 @@ +//------------------------------------------------------------------------------ +// +// 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 "MSIDAADV2Oauth2Factory.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface MSIDB2COauth2Factory : MSIDAADV2Oauth2Factory + +@end + +NS_ASSUME_NONNULL_END diff --git a/IdentityCore/src/oauth2/b2c/MSIDB2COauth2Factory.m b/IdentityCore/src/oauth2/b2c/MSIDB2COauth2Factory.m new file mode 100644 index 000000000..9b71c9911 --- /dev/null +++ b/IdentityCore/src/oauth2/b2c/MSIDB2COauth2Factory.m @@ -0,0 +1,133 @@ +//------------------------------------------------------------------------------ +// +// 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 "MSIDB2COauth2Factory.h" +#import "MSIDB2CTokenResponse.h" +#import "MSIDOauth2Factory+Internal.h" +#import "MSIDAccessToken.h" +#import "MSIDAuthorityFactory.h" +#import "MSIDIdToken.h" + +@implementation MSIDB2COauth2Factory + +#pragma mark - Helpers + +- (BOOL)checkResponseClass:(MSIDB2CTokenResponse *)response + context:(id)context + error:(NSError **)error +{ + if (![response isKindOfClass:[MSIDB2CTokenResponse class]]) + { + if (error) + { + NSString *errorMessage = [NSString stringWithFormat:@"Wrong token response type passed, which means wrong factory is being used (expected MSIDB2CTokenResponse, passed %@", response.class]; + + *error = MSIDCreateError(MSIDErrorDomain, MSIDErrorInternal, errorMessage, nil, nil, nil, context.correlationId, nil); + } + + return NO; + } + + return YES; +} + +#pragma mark - Response + +- (MSIDB2CTokenResponse *)tokenResponseFromJSON:(NSDictionary *)json + context:(id)context + error:(NSError **)error +{ + return [[MSIDB2CTokenResponse alloc] initWithJSONDictionary:json error:error]; +} + +- (MSIDB2CTokenResponse *)tokenResponseFromJSON:(NSDictionary *)json + refreshToken:(MSIDBaseToken *)token + context:(id)context + error:(NSError * __autoreleasing *)error +{ + return [[MSIDB2CTokenResponse alloc] initWithJSONDictionary:json refreshToken:token error:error]; +} + +- (BOOL)verifyResponse:(MSIDB2CTokenResponse *)response + context:(id)context + error:(NSError * __autoreleasing *)error +{ + if (![self checkResponseClass:response context:context error:error]) + { + return NO; + } + + return [super verifyResponse:response context:context error:error]; +} + +#pragma mark - Tokens + +- (BOOL)fillAccount:(MSIDAccount *)account + fromResponse:(MSIDB2CTokenResponse *)response + configuration:(MSIDConfiguration *)configuration +{ + if (![self checkResponseClass:response context:nil error:nil]) + { + return NO; + } + + BOOL result = [super fillAccount:account fromResponse:response configuration:configuration]; + + if (!result) + { + return NO; + } + + // B2C should return preferred_username claim + if ([NSString msidIsStringNilOrBlank:response.idTokenObj.preferredUsername]) + { + account.username = MSID_PREFERRED_USERNAME_MISSING; + } + + return YES; +} + +- (MSIDAuthority *)authorityFromURL:(NSURL *)url + tokenResponse:(MSIDB2CTokenResponse *)response + error:(NSError **)error +{ + if (![self checkResponseClass:response context:nil error:error]) + { + return nil; + } + + NSString *tenantId = response.idTokenObj.realm; + + if ([NSString msidIsStringNilOrBlank:tenantId]) + { + tenantId = response.clientInfo.utid; + } + + return [self.authorityFactory authorityFromUrl:url rawTenant:tenantId context:nil error:nil]; +} + +@end diff --git a/IdentityCore/src/oauth2/b2c/MSIDB2CTokenResponse.h b/IdentityCore/src/oauth2/b2c/MSIDB2CTokenResponse.h new file mode 100644 index 000000000..5c9341952 --- /dev/null +++ b/IdentityCore/src/oauth2/b2c/MSIDB2CTokenResponse.h @@ -0,0 +1,36 @@ +//------------------------------------------------------------------------------ +// +// 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 "MSIDAADV2TokenResponse.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface MSIDB2CTokenResponse : MSIDAADV2TokenResponse + +@end + +NS_ASSUME_NONNULL_END diff --git a/IdentityCore/src/oauth2/b2c/MSIDB2CTokenResponse.m b/IdentityCore/src/oauth2/b2c/MSIDB2CTokenResponse.m new file mode 100644 index 000000000..5f9315ca9 --- /dev/null +++ b/IdentityCore/src/oauth2/b2c/MSIDB2CTokenResponse.m @@ -0,0 +1,32 @@ +//------------------------------------------------------------------------------ +// +// 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 "MSIDB2CTokenResponse.h" + +@implementation MSIDB2CTokenResponse + +@end diff --git a/IdentityCore/tests/MSIDAADV2Oauth2FactoryTests.m b/IdentityCore/tests/MSIDAADV2Oauth2FactoryTests.m index 14ddb9001..ba7f2ad5b 100644 --- a/IdentityCore/tests/MSIDAADV2Oauth2FactoryTests.m +++ b/IdentityCore/tests/MSIDAADV2Oauth2FactoryTests.m @@ -50,11 +50,11 @@ #import "NSString+MSIDTestUtil.h" #import "MSIDAccountIdentifier.h" -@interface MSIDAADV2Oauth2StartegyTests : XCTestCase +@interface MSIDAADV2Oauth2FactoryTests : XCTestCase @end -@implementation MSIDAADV2Oauth2StartegyTests +@implementation MSIDAADV2Oauth2FactoryTests #pragma mark - Token response diff --git a/IdentityCore/tests/MSIDB2COauth2FactoryTests.m b/IdentityCore/tests/MSIDB2COauth2FactoryTests.m new file mode 100644 index 000000000..8719f2f28 --- /dev/null +++ b/IdentityCore/tests/MSIDB2COauth2FactoryTests.m @@ -0,0 +1,277 @@ +// 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 "MSIDB2CTokenResponse.h" +#import "MSIDB2COauth2Factory.h" +#import "MSIDTestTokenResponse.h" +#import "MSIDTestIdentifiers.h" +#import "MSIDTestConfiguration.h" +#import "MSIDTestIdTokenUtil.h" +#import "MSIDAADV1TokenResponse.h" +#import "NSDictionary+MSIDTestUtil.h" +#import "NSString+MSIDTestUtil.h" +#import "MSIDBaseToken.h" +#import "MSIDAccessToken.h" +#import "MSIDRefreshToken.h" +#import "MSIDIdToken.h" +#import "MSIDAccount.h" +#import "MSIDAccountIdentifier.h" + +@interface MSIDB2COauth2FactoryTests : XCTestCase + +@end + +@implementation MSIDB2COauth2FactoryTests + +#pragma mark - Token response + +- (void)testTokenResponseFromJSON_whenNilJSON_shouldReturnError +{ + MSIDB2COauth2Factory *factory = [MSIDB2COauth2Factory new]; + + NSError *error = nil; + MSIDTokenResponse *response = [factory tokenResponseFromJSON:nil context:nil error:&error]; + + XCTAssertNil(response); + XCTAssertNotNil(error); + XCTAssertEqual(error.code, MSIDErrorInternal); +} + +- (void)testTokenResponseFromJSON_whenValidJSON_shouldReturnB2CTokenResponse +{ + NSDictionary *tokenResponse = @{@"access_token": @"access token", + @"refresh_token": @"refresh token" + }; + + MSIDB2COauth2Factory *factory = [MSIDB2COauth2Factory new]; + + NSError *error = nil; + MSIDTokenResponse *response = [factory tokenResponseFromJSON:tokenResponse context:nil error:&error]; + + XCTAssertNotNil(response); + XCTAssertNil(error); + + BOOL expectedClass = [response isKindOfClass:[MSIDB2CTokenResponse class]]; + XCTAssertTrue(expectedClass); + XCTAssertEqualObjects(response.accessToken, @"access token"); + XCTAssertEqualObjects(response.refreshToken, @"refresh token"); +} + +#pragma mark - Verify response + +- (void)testVerifyResponse_whenWrongResponseProvided_shouldReturnError +{ + MSIDB2COauth2Factory *factory = [MSIDB2COauth2Factory new]; + MSIDAADV1TokenResponse *response = [MSIDAADV1TokenResponse new]; + + NSError *error = nil; + BOOL result = [factory verifyResponse:response context:nil error:&error]; + + XCTAssertFalse(result); + XCTAssertNotNil(error); + XCTAssertEqual(error.code, MSIDErrorInternal); +} + +- (void)testVerifyResponse_whenValidResponseWithTokens_shouldReturnNoError +{ + MSIDB2COauth2Factory *factory = [MSIDB2COauth2Factory new]; + + NSString *rawClientInfo = [@{ @"uid" : @"1", @"utid" : @"1234-5678-90abcdefg"} msidBase64UrlJson]; + MSIDB2CTokenResponse *response = [[MSIDB2CTokenResponse alloc] initWithJSONDictionary:@{@"access_token":@"fake_access_token", + @"refresh_token":@"fake_refresh_token", + @"client_info":rawClientInfo + } + error:nil]; + NSError *error = nil; + BOOL result = [factory verifyResponse:response context:nil error:&error]; + + XCTAssertTrue(result); + XCTAssertNil(error); +} + +- (void)testVerifyResponse_whenOAuthErrorViaAuthCode_shouldReturnError +{ + MSIDB2COauth2Factory *factory = [MSIDB2COauth2Factory new]; + + MSIDB2CTokenResponse *response = [[MSIDB2CTokenResponse alloc] initWithJSONDictionary:@{@"error":@"invalid_grant"} + error:nil]; + NSError *error = nil; + BOOL result = [factory verifyResponse:response context:nil error:&error]; + + XCTAssertFalse(result); + XCTAssertEqual(error.domain, MSIDOAuthErrorDomain); + XCTAssertEqual(error.code, MSIDErrorServerInvalidGrant); + XCTAssertEqualObjects(error.userInfo[MSIDOAuthErrorKey], @"invalid_grant"); +} + +- (void)testVerifyResponse_whenNoClientInfo_shouldReturnError +{ + MSIDB2COauth2Factory *factory = [MSIDB2COauth2Factory new]; + + MSIDB2CTokenResponse *response = [[MSIDB2CTokenResponse alloc] initWithJSONDictionary:@{@"access_token":@"fake_access_token", + @"refresh_token":@"fake_refresh_token"} + error:nil]; + NSError *error = nil; + BOOL result = [factory verifyResponse:response context:nil error:&error]; + + XCTAssertFalse(result); + XCTAssertEqual(error.domain, MSIDErrorDomain); + XCTAssertEqualObjects(error.userInfo[MSIDErrorDescriptionKey], @"Client info was not returned in the server response"); +} + +#pragma mark - Tokens + +- (MSIDB2CTokenResponse *)testB2CTokenResponseWithTenantId:(NSString *)tenantId +{ + NSString *idToken = [MSIDTestIdTokenUtil idTokenWithPreferredUsername:nil + subject:@"sub" + givenName:@"name" + familyName:@"family" + name:@"name" + version:@"2.0" + tid:tenantId]; + + NSDictionary *responseDictionary = @{@"access_token":DEFAULT_TEST_ACCESS_TOKEN, + @"refresh_token":DEFAULT_TEST_REFRESH_TOKEN, + @"scope": DEFAULT_TEST_SCOPE, + @"id_token": idToken, + @"client_info": [@{ @"uid" : @"1", @"utid" : @"1234-5678-90abcdefg"} msidBase64UrlJson] + }; + + MSIDB2CTokenResponse *response = [[MSIDB2CTokenResponse alloc] initWithJSONDictionary:responseDictionary error:nil]; + return response; +} + +- (void)testAccessTokenFromResponse_whenB2CTokenResponse_withTenantId_shouldReturnToken +{ + MSIDB2COauth2Factory *factory = [MSIDB2COauth2Factory new]; + + MSIDB2CTokenResponse *response = [self testB2CTokenResponseWithTenantId:@"test_tenantid"]; + MSIDConfiguration *configuration = [MSIDTestConfiguration v2DefaultConfiguration]; + + MSIDAccessToken *token = [factory accessTokenFromResponse:response configuration:configuration]; + + XCTAssertEqualObjects(token.authority, [@"https://login.microsoftonline.com/test_tenantid" authority]); + XCTAssertEqualObjects(token.clientId, configuration.clientId); + + NSString *homeAccountId = [NSString stringWithFormat:@"%@.%@", DEFAULT_TEST_UID, DEFAULT_TEST_UTID]; + XCTAssertEqualObjects(token.accountIdentifier.homeAccountId, homeAccountId); + + XCTAssertNotNil(token.cachedAt); + XCTAssertEqualObjects(token.accessToken, DEFAULT_TEST_ACCESS_TOKEN); + NSOrderedSet *scopes = [NSOrderedSet orderedSetWithObjects:DEFAULT_TEST_SCOPE, nil]; + + XCTAssertEqualObjects(token.scopes, scopes); + XCTAssertNotNil(token.expiresOn); +} + +- (void)testAccessTokenFromResponse_whenB2CTokenResponse_withNilTenantId_shouldReturnToken +{ + MSIDB2COauth2Factory *factory = [MSIDB2COauth2Factory new]; + + MSIDB2CTokenResponse *response = [self testB2CTokenResponseWithTenantId:nil]; + MSIDConfiguration *configuration = [MSIDTestConfiguration v2DefaultConfiguration]; + + MSIDAccessToken *token = [factory accessTokenFromResponse:response configuration:configuration]; + + XCTAssertEqualObjects(token.authority, [@"https://login.microsoftonline.com/1234-5678-90abcdefg" authority]); + XCTAssertEqualObjects(token.clientId, configuration.clientId); + + NSString *homeAccountId = [NSString stringWithFormat:@"%@.%@", DEFAULT_TEST_UID, DEFAULT_TEST_UTID]; + XCTAssertEqualObjects(token.accountIdentifier.homeAccountId, homeAccountId); + + XCTAssertNotNil(token.cachedAt); + XCTAssertEqualObjects(token.accessToken, DEFAULT_TEST_ACCESS_TOKEN); + NSOrderedSet *scopes = [NSOrderedSet orderedSetWithObjects:DEFAULT_TEST_SCOPE, nil]; + + XCTAssertEqualObjects(token.scopes, scopes); + XCTAssertNotNil(token.expiresOn); +} + +- (void)testRefreshTokenFromResponse_whenB2CTokenResponse_withTenantId_shouldReturnToken +{ + MSIDB2COauth2Factory *factory = [MSIDB2COauth2Factory new]; + + MSIDB2CTokenResponse *response = [self testB2CTokenResponseWithTenantId:@"test_tenantid"]; + MSIDConfiguration *configuration = [MSIDTestConfiguration v2DefaultConfiguration]; + + MSIDRefreshToken *token = [factory refreshTokenFromResponse:response configuration:configuration]; + + XCTAssertEqualObjects(token.authority, [@"https://login.microsoftonline.com/common" authority]); + XCTAssertEqualObjects(token.clientId, configuration.clientId); + + NSString *homeAccountId = [NSString stringWithFormat:@"%@.%@", DEFAULT_TEST_UID, DEFAULT_TEST_UTID]; + XCTAssertEqualObjects(token.accountIdentifier.homeAccountId, homeAccountId); + + XCTAssertEqualObjects(token.additionalServerInfo, [NSMutableDictionary dictionary]); + XCTAssertEqualObjects(token.refreshToken, DEFAULT_TEST_REFRESH_TOKEN); + XCTAssertNil(token.familyId); +} + +- (void)testIDTokenFromResponse_whenB2CTokenResponse_withTenantId_shouldReturnToken +{ + MSIDB2COauth2Factory *factory = [MSIDB2COauth2Factory new]; + + MSIDB2CTokenResponse *response = [self testB2CTokenResponseWithTenantId:@"test_tenantid"]; + MSIDConfiguration *configuration = [MSIDTestConfiguration v2DefaultConfiguration]; + + MSIDIdToken *token = [factory idTokenFromResponse:response configuration:configuration]; + + XCTAssertEqualObjects(token.authority, [@"https://login.microsoftonline.com/test_tenantid" authority]); + XCTAssertEqualObjects(token.clientId, configuration.clientId); + + NSString *homeAccountId = [NSString stringWithFormat:@"%@.%@", DEFAULT_TEST_UID, DEFAULT_TEST_UTID]; + XCTAssertEqualObjects(token.accountIdentifier.homeAccountId, homeAccountId); + + XCTAssertEqualObjects(token.additionalServerInfo, [NSMutableDictionary dictionary]); + XCTAssertEqualObjects(token.rawIdToken, response.idToken); +} + +- (void)testAccountFromTokenResponse_whenB2CTokenResponse_withTenantId_shouldInitAccountAndSetProperties +{ + MSIDB2COauth2Factory *factory = [MSIDB2COauth2Factory new]; + + MSIDB2CTokenResponse *response = [self testB2CTokenResponseWithTenantId:@"test_tenantid"]; + + MSIDConfiguration *configuration = + + [[MSIDConfiguration alloc] initWithAuthority:[DEFAULT_TEST_AUTHORITY authority] + redirectUri:@"redirect uri" + clientId:@"client id" + target:@"target"]; + + MSIDAccount *account = [factory accountFromResponse:response configuration:configuration]; + XCTAssertNotNil(account); + XCTAssertEqualObjects(account.accountIdentifier.homeAccountId, @"1.1234-5678-90abcdefg"); + XCTAssertNotNil(account.clientInfo); + XCTAssertEqual(account.accountType, MSIDAccountTypeMSSTS); + XCTAssertEqualObjects(account.username, @"Missing from the token response"); + XCTAssertEqualObjects(account.givenName, @"name"); + XCTAssertEqualObjects(account.familyName, @"family"); + XCTAssertEqualObjects(account.name, @"name"); + XCTAssertEqualObjects(account.authority.url.absoluteString, @"https://login.microsoftonline.com/test_tenantid"); +} + + +@end diff --git a/IdentityCore/tests/integration/MSIDCacheSchemaValidationTests.m b/IdentityCore/tests/integration/MSIDCacheSchemaValidationTests.m index ebe30e5b6..90ebef9eb 100644 --- a/IdentityCore/tests/integration/MSIDCacheSchemaValidationTests.m +++ b/IdentityCore/tests/integration/MSIDCacheSchemaValidationTests.m @@ -31,6 +31,8 @@ #import "MSIDDefaultCredentialCacheKey.h" #import "MSIDDefaultAccountCacheKey.h" #import "MSIDAccountCacheItem.h" +#import "MSIDB2CTokenResponse.h" +#import "MSIDB2COauth2Factory.h" /* Those tests validate full schema compliance to test cases defined in the schema spec @@ -458,7 +460,7 @@ - (MSIDTokenResponse *)b2cTestTokenResponse NSString *jsonResponse = @"{\"access_token\":\"\",\"id_token\":\"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1Mzg4MDQ4NjAsIm5iZiI6MTUzODgwMTI2MCwidmVyIjoiMS4wIiwiaXNzIjoiaHR0cHM6Ly9sb2dpbi5taWNyb3NvZnRvbmxpbmUuY29tL2JhNmMwZDk0LWE4ZGEtNDViMi04M2FlLTMzODcxZjljMmRkOC92Mi4wLyIsInN1YiI6ImFkMDIwZjhlLWIxYmEtNDRiMi1iZDY5LWMyMmJlODY3MzdmNSIsImF1ZCI6IjBhN2Y1MmRkLTI2MGUtNDMyZi05NGRlLWI0NzgyOGMzZjM3MiIsImlhdCI6MTUzODgwMTI2MCwiYXV0aF90aW1lIjoxNTM4ODAxMjYwLCJpZHAiOiJsaXZlLmNvbSIsIm5hbWUiOiJNU0FMIFNESyBUZXN0Iiwib2lkIjoiYWQwMjBmOGUtYjFiYS00NGIyLWJkNjktYzIyYmU4NjczN2Y1IiwiZmFtaWx5X25hbWUiOiJTREsgVGVzdCIsImdpdmVuX25hbWUiOiJNU0FMIiwiZW1haWxzIjpbIm1zYWxzZGt0ZXN0QG91dGxvb2suY29tIl0sInRmcCI6IkIyQ18xX1NpZ25pbiIsImF0X2hhc2giOiJRNE8zSERDbGNhTGw3eTB1VS1iSkFnIn0.\",\"token_type\":\"Bearer\",\"not_before\":1538801260,\"expires_in\":3600,\"expires_on\":1538804860,\"resource\":\"14df2240-96cc-4f42-a133-ef0807492869\",\"client_info\":\"eyJ1aWQiOiJhZDAyMGY4ZS1iMWJhLTQ0YjItYmQ2OS1jMjJiZTg2NzM3ZjUtYjJjXzFfc2lnbmluIiwidXRpZCI6ImJhNmMwZDk0LWE4ZGEtNDViMi04M2FlLTMzODcxZjljMmRkOCJ9\",\"scope\":\"https://iosmsalb2c.onmicrosoft.com/webapitest/user.read\",\"refresh_token\":\"\",\"refresh_token_expires_in\":1209600}"; NSError *responseError = nil; - MSIDAADV2TokenResponse *response = [[MSIDAADV2TokenResponse alloc] initWithJSONData:[jsonResponse dataUsingEncoding:NSUTF8StringEncoding] error:&responseError]; + MSIDB2CTokenResponse *response = [[MSIDB2CTokenResponse alloc] initWithJSONData:[jsonResponse dataUsingEncoding:NSUTF8StringEncoding] error:&responseError]; XCTAssertNotNil(response); XCTAssertNil(responseError); @@ -481,7 +483,7 @@ - (MSIDConfiguration *)b2cTestConfiguration - (void)testSchemaComplianceForAccessToken_whenMSSTSResponse_withB2CAccount { - MSIDAADV2Oauth2Factory *factory = [MSIDAADV2Oauth2Factory new]; + MSIDB2COauth2Factory *factory = [MSIDB2COauth2Factory new]; MSIDTokenResponse *response = [self b2cTestTokenResponse]; MSIDConfiguration *configuration = [self b2cTestConfiguration]; @@ -501,7 +503,7 @@ - (void)testSchemaComplianceForAccessToken_whenMSSTSResponse_withB2CAccount @"target": @"https://iosmsalb2c.onmicrosoft.com/webapitest/user.read", @"credential_type": @"AccessToken", @"environment": @"login.microsoftonline.com", - @"realm": @"iosmsalb2c.onmicrosoft.com", + @"realm": @"ba6c0d94-a8da-45b2-83ae-33871f9c2dd8", @"expires_on": expiresOn, @"cached_at": cachedAt, @"client_id": @"0a7f52dd-260e-432f-94de-b47828c3f372", @@ -520,13 +522,13 @@ - (void)testSchemaComplianceForAccessToken_whenMSSTSResponse_withB2CAccount key.realm = credential.realm; key.target = credential.target; - NSString *expectedServiceKey = @"accesstoken-0a7f52dd-260e-432f-94de-b47828c3f372-iosmsalb2c.onmicrosoft.com-https://iosmsalb2c.onmicrosoft.com/webapitest/user.read"; + NSString *expectedServiceKey = @"accesstoken-0a7f52dd-260e-432f-94de-b47828c3f372-ba6c0d94-a8da-45b2-83ae-33871f9c2dd8-https://iosmsalb2c.onmicrosoft.com/webapitest/user.read"; XCTAssertEqualObjects(key.service, expectedServiceKey); NSString *expectedAccountKey = @"ad020f8e-b1ba-44b2-bd69-c22be86737f5-b2c_1_signin.ba6c0d94-a8da-45b2-83ae-33871f9c2dd8-login.microsoftonline.com"; XCTAssertEqualObjects(key.account, expectedAccountKey); - NSString *expectedGenericKey = @"accesstoken-0a7f52dd-260e-432f-94de-b47828c3f372-iosmsalb2c.onmicrosoft.com"; + NSString *expectedGenericKey = @"accesstoken-0a7f52dd-260e-432f-94de-b47828c3f372-ba6c0d94-a8da-45b2-83ae-33871f9c2dd8"; XCTAssertEqualObjects(key.generic, [expectedGenericKey dataUsingEncoding:NSUTF8StringEncoding]); XCTAssertEqualObjects(key.type, @2001); @@ -534,7 +536,7 @@ - (void)testSchemaComplianceForAccessToken_whenMSSTSResponse_withB2CAccount - (void)testSchemaComplianceForIDToken_whenMSSTSResponse_withB2CAccount { - MSIDAADV2Oauth2Factory *factory = [MSIDAADV2Oauth2Factory new]; + MSIDB2COauth2Factory *factory = [MSIDB2COauth2Factory new]; MSIDTokenResponse *response = [self b2cTestTokenResponse]; MSIDConfiguration *configuration = [self b2cTestConfiguration]; @@ -547,7 +549,7 @@ - (void)testSchemaComplianceForIDToken_whenMSSTSResponse_withB2CAccount @"credential_type": @"IdToken", @"environment": @"login.microsoftonline.com", @"home_account_id": @"ad020f8e-b1ba-44b2-bd69-c22be86737f5-b2c_1_signin.ba6c0d94-a8da-45b2-83ae-33871f9c2dd8", - @"realm": @"iosmsalb2c.onmicrosoft.com", + @"realm": @"ba6c0d94-a8da-45b2-83ae-33871f9c2dd8", @"client_id": @"0a7f52dd-260e-432f-94de-b47828c3f372" }; @@ -563,13 +565,13 @@ - (void)testSchemaComplianceForIDToken_whenMSSTSResponse_withB2CAccount key.realm = credential.realm; key.target = credential.target; - NSString *expectedServiceKey = @"idtoken-0a7f52dd-260e-432f-94de-b47828c3f372-iosmsalb2c.onmicrosoft.com-"; + NSString *expectedServiceKey = @"idtoken-0a7f52dd-260e-432f-94de-b47828c3f372-ba6c0d94-a8da-45b2-83ae-33871f9c2dd8-"; XCTAssertEqualObjects(key.service, expectedServiceKey); NSString *expectedAccountKey = @"ad020f8e-b1ba-44b2-bd69-c22be86737f5-b2c_1_signin.ba6c0d94-a8da-45b2-83ae-33871f9c2dd8-login.microsoftonline.com"; XCTAssertEqualObjects(key.account, expectedAccountKey); - NSString *expectedGenericKey = @"idtoken-0a7f52dd-260e-432f-94de-b47828c3f372-iosmsalb2c.onmicrosoft.com"; + NSString *expectedGenericKey = @"idtoken-0a7f52dd-260e-432f-94de-b47828c3f372-ba6c0d94-a8da-45b2-83ae-33871f9c2dd8"; XCTAssertEqualObjects(key.generic, [expectedGenericKey dataUsingEncoding:NSUTF8StringEncoding]); XCTAssertEqualObjects(key.type, @2003); @@ -577,7 +579,7 @@ - (void)testSchemaComplianceForIDToken_whenMSSTSResponse_withB2CAccount - (void)testSchemaComplianceForRefreshToken_whenMSSTSResponse_withB2CAccount { - MSIDAADV2Oauth2Factory *factory = [MSIDAADV2Oauth2Factory new]; + MSIDB2COauth2Factory *factory = [MSIDB2COauth2Factory new]; MSIDTokenResponse *response = [self b2cTestTokenResponse]; MSIDConfiguration *configuration = [self b2cTestConfiguration]; @@ -619,7 +621,7 @@ - (void)testSchemaComplianceForRefreshToken_whenMSSTSResponse_withB2CAccount - (void)testSchemaComplianceForAccount_whenMSSTSResponse_withB2CAccount { - MSIDAADV2Oauth2Factory *factory = [MSIDAADV2Oauth2Factory new]; + MSIDB2COauth2Factory *factory = [MSIDB2COauth2Factory new]; MSIDTokenResponse *response = [self b2cTestTokenResponse]; MSIDConfiguration *configuration = [self b2cTestConfiguration]; @@ -636,7 +638,7 @@ - (void)testSchemaComplianceForAccount_whenMSSTSResponse_withB2CAccount @"given_name": @"MSAL", @"environment": @"login.microsoftonline.com", @"name": @"MSAL SDK Test", - @"realm": @"iosmsalb2c.onmicrosoft.com", + @"realm": @"ba6c0d94-a8da-45b2-83ae-33871f9c2dd8", @"client_info": @"eyJ1aWQiOiJhZDAyMGY4ZS1iMWJhLTQ0YjItYmQ2OS1jMjJiZTg2NzM3ZjUtYjJjXzFfc2lnbmluIiwidXRpZCI6ImJhNmMwZDk0LWE4ZGEtNDViMi04M2FlLTMzODcxZjljMmRkOCJ9" }; @@ -651,7 +653,7 @@ - (void)testSchemaComplianceForAccount_whenMSSTSResponse_withB2CAccount key.username = account.username; - NSString *expectedServiceKey = @"iosmsalb2c.onmicrosoft.com"; + NSString *expectedServiceKey = @"ba6c0d94-a8da-45b2-83ae-33871f9c2dd8"; XCTAssertEqualObjects(key.service, expectedServiceKey); NSString *expectedAccountKey = @"ad020f8e-b1ba-44b2-bd69-c22be86737f5-b2c_1_signin.ba6c0d94-a8da-45b2-83ae-33871f9c2dd8-login.microsoftonline.com"; @@ -670,7 +672,7 @@ - (MSIDTokenResponse *)b2cTestTokenResponseWithTenantId NSString *jsonResponse = @"{\"access_token\":\"\",\"id_token\":\"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1Mzg4MDQ4NjAsIm5iZiI6MTUzODgwMTI2MCwidmVyIjoiMS4wIiwiaXNzIjoiaHR0cHM6Ly9sb2dpbi5taWNyb3NvZnRvbmxpbmUuY29tL2JhNmMwZDk0LWE4ZGEtNDViMi04M2FlLTMzODcxZjljMmRkOC92Mi4wLyIsInN1YiI6ImFkMDIwZjhlLWIxYmEtNDRiMi1iZDY5LWMyMmJlODY3MzdmNSIsImF1ZCI6IjBhN2Y1MmRkLTI2MGUtNDMyZi05NGRlLWI0NzgyOGMzZjM3MiIsImlhdCI6MTUzODgwMTI2MCwiYXV0aF90aW1lIjoxNTM4ODAxMjYwLCJpZHAiOiJsaXZlLmNvbSIsIm5hbWUiOiJNU0FMIFNESyBUZXN0Iiwib2lkIjoiYWQwMjBmOGUtYjFiYS00NGIyLWJkNjktYzIyYmU4NjczN2Y1IiwiZmFtaWx5X25hbWUiOiJTREsgVGVzdCIsImdpdmVuX25hbWUiOiJNU0FMIiwiZW1haWxzIjpbIm1zYWxzZGt0ZXN0QG91dGxvb2suY29tIl0sInRmcCI6IkIyQ18xX1NpZ25pbiIsImF0X2hhc2giOiJRNE8zSERDbGNhTGw3eTB1VS1iSkFnIiwidGlkIjoiYmE2YzBkOTQtYThkYS00NWIyLTgzYWUtMzM4NzFmOWMyZGQ4IiwicHJlZmVycmVkX3VzZXJuYW1lIjoibXNhbHNka3Rlc3RAb3V0bG9vay5jb20ifQ.\",\"token_type\":\"Bearer\",\"not_before\":1538801260,\"expires_in\":3600,\"expires_on\":1538804860,\"resource\":\"14df2240-96cc-4f42-a133-ef0807492869\",\"client_info\":\"eyJ1aWQiOiJhZDAyMGY4ZS1iMWJhLTQ0YjItYmQ2OS1jMjJiZTg2NzM3ZjUtYjJjXzFfc2lnbmluIiwidXRpZCI6ImJhNmMwZDk0LWE4ZGEtNDViMi04M2FlLTMzODcxZjljMmRkOCJ9\",\"scope\":\"https://iosmsalb2c.onmicrosoft.com/webapitest/user.read\",\"refresh_token\":\"\",\"refresh_token_expires_in\":1209600}"; NSError *responseError = nil; - MSIDAADV2TokenResponse *response = [[MSIDAADV2TokenResponse alloc] initWithJSONData:[jsonResponse dataUsingEncoding:NSUTF8StringEncoding] error:&responseError]; + MSIDB2CTokenResponse *response = [[MSIDB2CTokenResponse alloc] initWithJSONData:[jsonResponse dataUsingEncoding:NSUTF8StringEncoding] error:&responseError]; XCTAssertNotNil(response); XCTAssertNil(responseError); @@ -680,7 +682,7 @@ - (MSIDTokenResponse *)b2cTestTokenResponseWithTenantId - (void)testSchemaComplianceForAccessToken_whenMSSTSResponse_withB2CAccountAndTenantId { - MSIDAADV2Oauth2Factory *factory = [MSIDAADV2Oauth2Factory new]; + MSIDB2COauth2Factory *factory = [MSIDB2COauth2Factory new]; MSIDTokenResponse *response = [self b2cTestTokenResponseWithTenantId]; MSIDConfiguration *configuration = [self b2cTestConfiguration]; @@ -733,7 +735,7 @@ - (void)testSchemaComplianceForAccessToken_whenMSSTSResponse_withB2CAccountAndTe - (void)testSchemaComplianceForIDToken_whenMSSTSResponse_withB2CAccountAndTenantId { - MSIDAADV2Oauth2Factory *factory = [MSIDAADV2Oauth2Factory new]; + MSIDB2COauth2Factory *factory = [MSIDB2COauth2Factory new]; MSIDTokenResponse *response = [self b2cTestTokenResponseWithTenantId]; MSIDConfiguration *configuration = [self b2cTestConfiguration]; @@ -776,7 +778,7 @@ - (void)testSchemaComplianceForIDToken_whenMSSTSResponse_withB2CAccountAndTenant - (void)testSchemaComplianceForRefreshToken_whenMSSTSResponse_withB2CAccountAndTenantId { - MSIDAADV2Oauth2Factory *factory = [MSIDAADV2Oauth2Factory new]; + MSIDB2COauth2Factory *factory = [MSIDB2COauth2Factory new]; MSIDTokenResponse *response = [self b2cTestTokenResponseWithTenantId]; MSIDConfiguration *configuration = [self b2cTestConfiguration]; @@ -818,7 +820,7 @@ - (void)testSchemaComplianceForRefreshToken_whenMSSTSResponse_withB2CAccountAndT - (void)testSchemaComplianceForAccount_whenMSSTSResponse_withB2CAccountAndTenantId { - MSIDAADV2Oauth2Factory *factory = [MSIDAADV2Oauth2Factory new]; + MSIDB2COauth2Factory *factory = [MSIDB2COauth2Factory new]; MSIDTokenResponse *response = [self b2cTestTokenResponseWithTenantId]; MSIDConfiguration *configuration = [self b2cTestConfiguration]; diff --git a/IdentityCore/tests/util/MSIDTestIdTokenUtil.m b/IdentityCore/tests/util/MSIDTestIdTokenUtil.m index 03495bb43..71cd77740 100644 --- a/IdentityCore/tests/util/MSIDTestIdTokenUtil.m +++ b/IdentityCore/tests/util/MSIDTestIdTokenUtil.m @@ -181,10 +181,10 @@ + (NSString *)idTokenWithPreferredUsername:(NSString *)username @"given_name" : givenName, @"family_name" : familyName, @"name" : name, - @"preferred_username" : username, + @"preferred_username" : username ? username : @"", @"sub" : subject, @"ver": version, - @"tid": tid + @"tid": tid ? tid : @"" } msidBase64UrlJson]; return [NSString stringWithFormat:@"%@.%@.%@", idTokenp1, idTokenp2, idTokenp1]; }