diff --git a/CHANGELOG.md b/CHANGELOG.md index 5508e73e..e68e92fd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,23 @@ +# Version 1.6.00 + +### Bug fixes +- `MASAuthCredentialsJWT` credentials was marked as re-usable, so the Mobile SDK tried to consume the same credentials for a certain period of time. JWT credentials can now be consumed only one time, and is not reusable. [DE324462] +- Device deregistration was removing all credentials from the Mobile SDK regardless of the result of deregistration request. Now, the Mobile SDK removes credentials only when the deregistration request succeeds. [DE324142] +- Mobile SDK was changing `MASGrantFlow` to client credentials in a specific scenario with Cordova SDK. The Mobile SDK no longer switches the `MASGrantFlow` by itself. [DE311841] +- Mobile SDK enhances the device registration flow so it handles the device registration record more smoothly. This removes the hassle of developers seeing "This device has already been registered and has not been configured to accept updates" error message in development phase. [US406920] +- `MASConfiguration` was not properly updating the updated endpoint values when switching to a different configuration. It is fixed. [DE321925] +- `MASConfiguration` had some hard-coded values for client credentials device registration endpoint. `MASConfiguration` now reads the value from the configuration. [DE321921] +- `MASMQTTClient` was unable to reestablish MQTT connection when the user session was logged out, and logged in with a different account. Mobile SDK now properly handles session changes for MQTT connection. [US408725] +- Mobile SDK now stores all credentials only to the device. Data will not be backed-up or transferred with iCloud unless `[MAS setKeychainSynchroizable:]` is explicitly set to `YES`. [US388853] +- Mobile SDK's MQTT connection was unable to establish mutual SSL connection with public CA certificate. The Mobile SDK now establishes mutual SSL with public CA certificate when **entire certificate chain** is exported in JSON configuration. [US399506] + +### New features +- Mobile SDK introduces a secure way of storing and sharing data across multiple applications using same keychain sharing group with MASFoundation's `MASSharedStorage` class. [US416558] +- Mobile SDK introduces a new way of building API CRUD request with `MASRequestBuilder` and `MASRequest` classes to provide seamless developer experience Android SDK. [US374082] + +### Deprecated methods +- `[MASConfiguration setSecurityConfiguration:]` is deprecated. Please use `[MASSecurityConfiguration setSecurityConfiguration:error:]` for better handling of error cases when setting the security configuration object. [DE328373] + # Version 1.5.00 NOTE: From this version on the frameworks changed to Dynamic instead of Static library @@ -12,14 +32,14 @@ NOTE: From this version on the frameworks changed to Dynamic instead of Static l - The SDK no longer requires Keychain Sharing to be enabled in Xcode. However, to establish SSO across multiple applications, Keychain Sharing must be enabled. [US320771] - Mobile SDK now only validates against the leaf certificate for SSL pinning validation by default. The configuration can be changed to validate against entire certificate chain through `MASSecurityConfiguration`. [US374086] -### New Features +### New features - Mobile SDK introduces an ability to configure security configuration for external APIs (such as SSL pinning), so that Mobile SDK can securely connect to external API (other than primary Gateway). [US344780] - The SDK handles multiple concurrent API requests with proper authentication processes. [US362800] - The SDK supports dynamic framework. All you need to do is update your Xcode settings. [US367604] - The SDK introduces more flexible and extensible authentication with different types of credentials. For details, see `MASAuthCredentials`. [US349497] - The SDK introduces the ability to digitally sign the request as JWT. See `MASClaims` to sign the request. [US313137] -### Deprecated Methods +### Deprecated methods - `[MAS setUserLoginBlock:]` is deprecated. Please use `[MAS setAuthCredentials:]` block to perform implicit authentication with `MASAuthCredentials` object. diff --git a/MASFoundation.xcodeproj/project.pbxproj b/MASFoundation.xcodeproj/project.pbxproj index aab8da93..acacfdcc 100644 --- a/MASFoundation.xcodeproj/project.pbxproj +++ b/MASFoundation.xcodeproj/project.pbxproj @@ -293,6 +293,10 @@ A4F671331BAFC345000E2223 /* NSString+MASPrivate.m in Sources */ = {isa = PBXBuildFile; fileRef = A4F671311BAFC345000E2223 /* NSString+MASPrivate.m */; }; A858C6651D0978A6001FB9AD /* MASOTPService.h in Headers */ = {isa = PBXBuildFile; fileRef = A858C6631D0978A6001FB9AD /* MASOTPService.h */; }; A858C6661D0978A6001FB9AD /* MASOTPService.m in Sources */ = {isa = PBXBuildFile; fileRef = A858C6641D0978A6001FB9AD /* MASOTPService.m */; }; + C81CC3CC1FC2EA190058718E /* MASBrowserBasedAuthentication.h in Headers */ = {isa = PBXBuildFile; fileRef = C81CC3CA1FC2EA190058718E /* MASBrowserBasedAuthentication.h */; }; + C81CC3CD1FC2EA190058718E /* MASBrowserBasedAuthentication.m in Sources */ = {isa = PBXBuildFile; fileRef = C81CC3CB1FC2EA190058718E /* MASBrowserBasedAuthentication.m */; }; + C81CC3D01FC2EFBB0058718E /* UIAlertController+MAS.h in Headers */ = {isa = PBXBuildFile; fileRef = C81CC3CE1FC2EFBB0058718E /* UIAlertController+MAS.h */; }; + C81CC3D11FC2EFBB0058718E /* UIAlertController+MAS.m in Sources */ = {isa = PBXBuildFile; fileRef = C81CC3CF1FC2EFBB0058718E /* UIAlertController+MAS.m */; }; CB0A8ADF1D01F64F00B1DCCC /* MASProximityLogin.h in Headers */ = {isa = PBXBuildFile; fileRef = CB0A8ADD1D01F64F00B1DCCC /* MASProximityLogin.h */; settings = {ATTRIBUTES = (Public, ); }; }; CB0A8AE01D01F64F00B1DCCC /* MASProximityLogin.m in Sources */ = {isa = PBXBuildFile; fileRef = CB0A8ADE1D01F64F00B1DCCC /* MASProximityLogin.m */; }; CB0B58591E258C2A00BC0163 /* MASAuthorizationResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = CB0B58571E258C2A00BC0163 /* MASAuthorizationResponse.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -310,6 +314,8 @@ CB1907F91C17950700A5EF16 /* MASAccessService.m in Sources */ = {isa = PBXBuildFile; fileRef = CB1907F71C17950700A5EF16 /* MASAccessService.m */; }; CB1C151E1E450109002B31A5 /* NSURL+MASPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = CB1C151C1E450109002B31A5 /* NSURL+MASPrivate.h */; }; CB1C151F1E450109002B31A5 /* NSURL+MASPrivate.m in Sources */ = {isa = PBXBuildFile; fileRef = CB1C151D1E450109002B31A5 /* NSURL+MASPrivate.m */; }; + CB1FD14B1FB23701000AFA25 /* MASSharedStorage.h in Headers */ = {isa = PBXBuildFile; fileRef = CB1FD1491FB23701000AFA25 /* MASSharedStorage.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CB1FD14C1FB23701000AFA25 /* MASSharedStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = CB1FD14A1FB23701000AFA25 /* MASSharedStorage.m */; }; CB2357921F0EF53600D4C420 /* MASURLSessionManager.h in Headers */ = {isa = PBXBuildFile; fileRef = CB2357901F0EF53600D4C420 /* MASURLSessionManager.h */; }; CB2357931F0EF53600D4C420 /* MASURLSessionManager.m in Sources */ = {isa = PBXBuildFile; fileRef = CB2357911F0EF53600D4C420 /* MASURLSessionManager.m */; }; CB2357961F0EFDEA00D4C420 /* MASSessionTaskOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = CB2357941F0EFDEA00D4C420 /* MASSessionTaskOperation.h */; }; @@ -718,6 +724,10 @@ A4F671311BAFC345000E2223 /* NSString+MASPrivate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+MASPrivate.m"; sourceTree = ""; }; A858C6631D0978A6001FB9AD /* MASOTPService.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MASOTPService.h; sourceTree = ""; }; A858C6641D0978A6001FB9AD /* MASOTPService.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MASOTPService.m; sourceTree = ""; }; + C81CC3CA1FC2EA190058718E /* MASBrowserBasedAuthentication.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MASBrowserBasedAuthentication.h; sourceTree = ""; }; + C81CC3CB1FC2EA190058718E /* MASBrowserBasedAuthentication.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MASBrowserBasedAuthentication.m; sourceTree = ""; }; + C81CC3CE1FC2EFBB0058718E /* UIAlertController+MAS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIAlertController+MAS.h"; sourceTree = ""; }; + C81CC3CF1FC2EFBB0058718E /* UIAlertController+MAS.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIAlertController+MAS.m"; sourceTree = ""; }; CB0A8ADD1D01F64F00B1DCCC /* MASProximityLogin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MASProximityLogin.h; sourceTree = ""; }; CB0A8ADE1D01F64F00B1DCCC /* MASProximityLogin.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MASProximityLogin.m; sourceTree = ""; }; CB0B58571E258C2A00BC0163 /* MASAuthorizationResponse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MASAuthorizationResponse.h; sourceTree = ""; }; @@ -735,6 +745,8 @@ CB1907F71C17950700A5EF16 /* MASAccessService.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MASAccessService.m; sourceTree = ""; }; CB1C151C1E450109002B31A5 /* NSURL+MASPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSURL+MASPrivate.h"; sourceTree = ""; }; CB1C151D1E450109002B31A5 /* NSURL+MASPrivate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSURL+MASPrivate.m"; sourceTree = ""; }; + CB1FD1491FB23701000AFA25 /* MASSharedStorage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MASSharedStorage.h; sourceTree = ""; }; + CB1FD14A1FB23701000AFA25 /* MASSharedStorage.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MASSharedStorage.m; sourceTree = ""; }; CB2357901F0EF53600D4C420 /* MASURLSessionManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MASURLSessionManager.h; sourceTree = ""; }; CB2357911F0EF53600D4C420 /* MASURLSessionManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MASURLSessionManager.m; sourceTree = ""; }; CB2357941F0EFDEA00D4C420 /* MASSessionTaskOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MASSessionTaskOperation.h; sourceTree = ""; }; @@ -1342,6 +1354,10 @@ CB14D2181D02266D004F772E /* MASProximityLoginQRCode.m */, CBA3EB2C1E945F2400E64D9D /* MASClaims.h */, CBA3EB2D1E945F2400E64D9D /* MASClaims.m */, + CB1FD1491FB23701000AFA25 /* MASSharedStorage.h */, + CB1FD14A1FB23701000AFA25 /* MASSharedStorage.m */, + C81CC3CA1FC2EA190058718E /* MASBrowserBasedAuthentication.h */, + C81CC3CB1FC2EA190058718E /* MASBrowserBasedAuthentication.m */, ); path = models; sourceTree = ""; @@ -1396,6 +1412,8 @@ A4F6712F1BAFC321000E2223 /* categories */ = { isa = PBXGroup; children = ( + C81CC3CE1FC2EFBB0058718E /* UIAlertController+MAS.h */, + C81CC3CF1FC2EFBB0058718E /* UIAlertController+MAS.m */, CB1907ED1C1794F400A5EF16 /* MASIKeyChainStore+MASPrivate.h */, CB1907EE1C1794F400A5EF16 /* MASIKeyChainStore+MASPrivate.m */, A483C1FF1BE6D0C5007572CE /* CBCentralManager+MASPrivate.h */, @@ -1677,6 +1695,7 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( + CB1FD14B1FB23701000AFA25 /* MASSharedStorage.h in Headers */, 69B7DF6A1F9675600056DD3A /* MASRequestBuilder.h in Headers */, 69B7DF681F9675600056DD3A /* MASRequest.h in Headers */, CBAFD24C1F2BD46C0034DF02 /* MASSecurityConfiguration.h in Headers */, @@ -1717,9 +1736,11 @@ 105B2F4B1CA6B3EA0005A2D0 /* ripemd.h in Headers */, A46F49F11C2F5FC500A4C370 /* MASINTULocationRequestDefines.h in Headers */, CB5E4C641C1D1B56001B3B8A /* MASGetURLRequest.h in Headers */, + C81CC3CC1FC2EA190058718E /* MASBrowserBasedAuthentication.h in Headers */, 105B2F471CA6B3EA0005A2D0 /* pqueue.h in Headers */, 105B2F371CA6B3EA0005A2D0 /* kssl.h in Headers */, 105B2F511CA6B3EA0005A2D0 /* srtp.h in Headers */, + C81CC3D01FC2EFBB0058718E /* UIAlertController+MAS.h in Headers */, CBFA70F41F1ED5D6006D025D /* MASSecurityPolicy.h in Headers */, CBD25AF51E78C47C00DFB47F /* JWTCryptoKeyExtractor.h in Headers */, 105B2F5F1CA6B3EA0005A2D0 /* x509_vfy.h in Headers */, @@ -2085,12 +2106,14 @@ A4150EFC1BF16EE200037E27 /* MASKeyChainService.m in Sources */, A47F12811C1D73530008E3F2 /* MASBluetoothPeripheral.m in Sources */, CBD25B061E78C47C00DFB47F /* JWTCoding+VersionThree.m in Sources */, + C81CC3D11FC2EFBB0058718E /* UIAlertController+MAS.m in Sources */, CBD25AED1E78C47C00DFB47F /* JWTAlgorithmDataHolderChain.m in Sources */, A46F49DA1C2F5FC500A4C370 /* MASINetworkActivityIndicatorManager.m in Sources */, A4831AAE1BD1A551007B4AE6 /* MASConfiguration.m in Sources */, CBA3EB2F1E945F2400E64D9D /* MASClaims.m in Sources */, CBD25B151E7A0A9200DFB47F /* MF_Base64Additions.m in Sources */, 10738A3B1C711C2F00B7E87E /* util_mosq.c in Sources */, + CB1FD14C1FB23701000AFA25 /* MASSharedStorage.m in Sources */, 10E027A71F72B10100EAB103 /* RNEncryptor.m in Sources */, 10738A2F1C711C2F00B7E87E /* read_handle.c in Sources */, CB9975571EDF5986006CEBB1 /* MASAuthCredentialsClientCredentials.m in Sources */, @@ -2144,6 +2167,7 @@ A46F49C51C2F5FC500A4C370 /* MASIHTTPRequestOperation.m in Sources */, A4150E701BF1643900037E27 /* MASIJSONResponseSerializer+MASPrivate.m in Sources */, A417BA521BF033C300EC9BCB /* CLLocation+MASPrivate.m in Sources */, + C81CC3CD1FC2EA190058718E /* MASBrowserBasedAuthentication.m in Sources */, 69B7DF6D1F96756B0056DD3A /* MASRequest+MASPrivate.m in Sources */, A4831AB21BD1A551007B4AE6 /* MASFile.m in Sources */, CB0B585A1E258C2A00BC0163 /* MASAuthorizationResponse.m in Sources */, @@ -2310,7 +2334,7 @@ buildSettings = { CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - CURRENT_PROJECT_VERSION = 1.5.00; + CURRENT_PROJECT_VERSION = 1.6.00; DEAD_CODE_STRIPPING = YES; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = ""; @@ -2355,7 +2379,7 @@ buildSettings = { CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - CURRENT_PROJECT_VERSION = 1.5.00; + CURRENT_PROJECT_VERSION = 1.6.00; DEAD_CODE_STRIPPING = YES; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = ""; diff --git a/MASFoundation/Classes/MAS.h b/MASFoundation/Classes/MAS.h index 8d290576..65d8de1c 100644 --- a/MASFoundation/Classes/MAS.h +++ b/MASFoundation/Classes/MAS.h @@ -111,6 +111,16 @@ +/** + * Sets Bool indicator of Browser Based Authentication (templatized login) enabled or not for authorization process. + * By default, it is disabled. + + @param enable BOOL value indicating whether Browser Based Authentication is enabled or not. + */ ++ (void)enableBrowserBasedAuthentication:(BOOL)enable; + + + /** * Sets the gateway monitoring block defined by the GatewayMonitorStatusBlock type. * This block will be triggered when any change to the current monitoring status diff --git a/MASFoundation/Classes/MAS.m b/MASFoundation/Classes/MAS.m index db17fbab..ddda9014 100644 --- a/MASFoundation/Classes/MAS.m +++ b/MASFoundation/Classes/MAS.m @@ -92,6 +92,12 @@ + (void)setOTPCredentialsBlock:(MASOTPCredentialsBlock)oneTimePassword } ++ (void)enableBrowserBasedAuthentication:(BOOL)enable +{ + [MASModelService setBrowserBasedAuthentication:enable]; +} + + + (void)setGatewayMonitor:(MASGatewayMonitorStatusBlock)monitor { [MASNetworkingService setGatewayMonitor:monitor]; @@ -206,7 +212,7 @@ + (void)start:(MASCompletionErrorBlock)completion // // If the device is registered, and id_token exists, which means MSSO can be used for this application // - else if ([MASDevice currentDevice].isRegistered && [[MASAccessService sharedService] getAccessValueStringWithType:MASAccessValueTypeIdToken]) + else if ([MASDevice currentDevice].isRegistered && [[MASAccessService sharedService] getAccessValueStringWithStorageKey:MASKeychainStorageKeyIdToken]) { // // Make sure to register the client (application) @@ -1641,7 +1647,7 @@ + (NSString * _Nullable)signWithClaims:(MASClaims *_Nonnull)claims error:(NSErro // // Retrieve private key from registered device's client certificate // - SecKeyRef pemPrivateRef = [[MASAccessService sharedService] getAccessValueCryptoKeyWithType:MASAccessValueTypePrivateKey]; + SecKeyRef pemPrivateRef = [[MASAccessService sharedService] getAccessValueCryptoKeyWithStorageKey:MASKeychainStorageKeyPrivateKey]; NSData *privateKeyData = [NSData converKeyRefToNSData:pemPrivateRef]; return [self signWithClaims:claims privateKey:privateKeyData error:error]; diff --git a/MASFoundation/Classes/MASConstants.h b/MASFoundation/Classes/MASConstants.h index 003e0284..00303ee1 100644 --- a/MASFoundation/Classes/MASConstants.h +++ b/MASFoundation/Classes/MASConstants.h @@ -91,6 +91,27 @@ typedef void (^MASOTPChannelSelectionBlock)(NSArray *_Nonnull supportedOTPChanne typedef void (^MASOTPCredentialsBlock)(MASOTPFetchCredentialsBlock _Nonnull otpBlock, NSError *_Nullable otpError); +/** + * The Selected Biometric modalities (NSArray *_Nullable biometricModalities, BOOL cancel, MASCompletionErrorBlock _Nullable) + * block. + */ +typedef void (^MASBiometricModalitiesBlock)(NSArray *_Nullable biometricModalities, BOOL cancel, MASCompletionErrorBlock _Nullable); + + +/** + * The Biometric registration with available modalities (NSArray *_Nonnull availableModalities, MASBiometricModalitiesBlock + * _Nonnull biometricModalitiesBlock) block. + */ +typedef void (^MASBiometricRegistrationModalitiesSelectionBlock)(NSArray *_Nonnull availableModalities, MASBiometricModalitiesBlock _Nonnull biometricModalitiesBlock); + + +/** + * The Biometric deregistration with available modalities (NSArray *_Nonnull availableModalities, MASBiometricModalitiesBlock + * _Nonnull biometricModalitiesBlock) block. + */ +typedef void (^MASBiometricDeregistrationModalitiesSelectionBlock)(NSArray *_Nonnull availableModalities, MASBiometricModalitiesBlock _Nonnull biometricModalitiesBlock); + + ///-------------------------------------- /// @name MAS Constants ///-------------------------------------- @@ -329,6 +350,12 @@ typedef NS_ENUM(NSInteger, MASFoundationErrorCode) MASFoundationErrorCodeConfigurationLoadingFailedJsonValidation = 100203, MASFoundationErrorCodeConfigurationInvalidEndpoint = 100204, + // + // Security Configuration + // + MASFoundationErrorCodeConfigurationInvalidHostForSecurityConfiguration = 100211, + MASFoundationErrorCodeConfigurationInvalidPinningInfoForSecurityConfiguration = 100212, + // // Geolocation // @@ -459,6 +486,15 @@ typedef NS_ENUM(NSInteger, MASFoundationErrorCode) MASFoundationErrorCodeJWTUnexpectedClassType = 170002, MASFoundationErrorCodeJWTSerializationError = 170003, + // + // Browser Based Login + // + MASFoundationErrorCodeBBANotEnabled = 180000, + // + // SharedStorage + // + MASFoundationErrorCodeSharedStorageNotNilKey = 180001, + MASFoundationErrorCodeCount = -999999 }; diff --git a/MASFoundation/Classes/MQTT/MASMQTTHelper.m b/MASFoundation/Classes/MQTT/MASMQTTHelper.m index cbe88579..56a5acb1 100644 --- a/MASFoundation/Classes/MQTT/MASMQTTHelper.m +++ b/MASFoundation/Classes/MQTT/MASMQTTHelper.m @@ -29,7 +29,7 @@ + (void)showLogMessage:(NSString *)message debugMode:(BOOL)debugMode + (NSString *)mqttClientId { - NSString *magIdentifier = [[MASAccessService sharedService] getAccessValueStringWithType:MASAccessValueTypeMAGIdentifier]; + NSString *magIdentifier = [[MASAccessService sharedService] getAccessValueStringWithStorageKey:MASKeychainStorageKeyMAGIdentifier]; //MQTT ClientId is: :::: NSString *clientId = [NSString stringWithFormat:@"%@::%@::%@",magIdentifier,[MASApplication currentApplication].identifier,[MASUser currentUser].objectId]; diff --git a/MASFoundation/Classes/_private_/MASConstantsPrivate.h b/MASFoundation/Classes/_private_/MASConstantsPrivate.h index 3e0ff215..b0c98fe9 100644 --- a/MASFoundation/Classes/_private_/MASConstantsPrivate.h +++ b/MASFoundation/Classes/_private_/MASConstantsPrivate.h @@ -212,6 +212,11 @@ static NSString *_Nonnull const MASGrantTypeRefreshToken = @"refresh_token"; // static int const MASExceptionErrorCodeInvalidCertificate = 9999; // integer +# pragma mark - MASSharedStorage custom prefix + +static NSString *_Nonnull const MASSharedStorageCustomPrefix = @"MAS.customSharedStorage"; + + ///-------------------------------------- /// @name Location Monitoring Constants ///-------------------------------------- diff --git a/MASFoundation/Classes/_private_/categories/NSError+MASPrivate.h b/MASFoundation/Classes/_private_/categories/NSError+MASPrivate.h index b20b0bb4..a41079e6 100644 --- a/MASFoundation/Classes/_private_/categories/NSError+MASPrivate.h +++ b/MASFoundation/Classes/_private_/categories/NSError+MASPrivate.h @@ -644,9 +644,17 @@ /** * Create MASFoundationErrorDomainLocal NSError for MASFoundationErrorCodeProximityLoginInvalidAuthorizeURL. * - * @return REturns an NSError instance with the domain MASFoundationErrorDomainLocal and + * @return Returns an NSError instance with the domain MASFoundationErrorDomainLocal and * error MASFoundationErrorCodeProximityLoginInvalidAuthorizeURL */ + (NSError *)errorProximityLoginInvalidAuthroizeURL; + +/** + * Create MASFoundationErrorDomainLocal NSError for MASFoundationErrorCodeBBANotEnabled. + * + * @return Returns an NSError instance with the domain MASFoundationErrorDomainLocal and + * error MASFoundationErrorCodeBBANotEnabled + */ ++ (NSError *)errorBrowserBasedAuthenticaionNotEnabled; @end diff --git a/MASFoundation/Classes/_private_/categories/NSError+MASPrivate.m b/MASFoundation/Classes/_private_/categories/NSError+MASPrivate.m index cfd4c0e4..9362038c 100644 --- a/MASFoundation/Classes/_private_/categories/NSError+MASPrivate.m +++ b/MASFoundation/Classes/_private_/categories/NSError+MASPrivate.m @@ -835,6 +835,11 @@ + (NSError *)errorProximityLoginInvalidAuthroizeURL } ++ (NSError *)errorBrowserBasedAuthenticaionNotEnabled +{ + return [self errorForFoundationCode:MASFoundationErrorCodeBBANotEnabled errorDomain:MASFoundationErrorDomainLocal]; +} + # pragma mark - Foundation Errors Private + (MASFoundationErrorCode)foundationErrorCodeForApiCode:(MASApiErrorCode)apiCode @@ -984,6 +989,12 @@ + (NSString *)descriptionForFoundationErrorCode:(MASFoundationErrorCode)errorCod case MASFoundationErrorCodeConfigurationLoadingFailedJsonValidation: return @"The configuration was successfully loaded, but the configuration is invalid for the following reason\n\n'%@'"; case MASFoundationErrorCodeConfigurationInvalidEndpoint: return @"Invalid endpoint"; + // + // Security Configuration + // + case MASFoundationErrorCodeConfigurationInvalidHostForSecurityConfiguration: return @"Invalid host information for security configuration. NSURL host or port cannot be nil."; + case MASFoundationErrorCodeConfigurationInvalidPinningInfoForSecurityConfiguration: return @"Invalid pinning information for security configuration. At least one pinning information should be provided or public PKI should be trusted."; + // // Device // @@ -1102,7 +1113,16 @@ + (NSString *)descriptionForFoundationErrorCode:(MASFoundationErrorCode)errorCod case MASFoundationErrorCodeJWTInvalidClaims: return @"MASClaims cannot be nil."; case MASFoundationErrorCodeJWTUnexpectedClassType: return @"Mis-match of reserved JWT claim value's type (%@)"; case MASFoundationErrorCodeJWTSerializationError: return @"Claim value (%@) cannot be serialized"; - + + // + // Shared Storage + // + case MASFoundationErrorCodeSharedStorageNotNilKey: return @"Data key cannot be nil or empty string."; + + // + // Browser Based Authentication + // + case MASFoundationErrorCodeBBANotEnabled : return @"MAS Browser Based Authentication is Not Enabled"; // // Default // diff --git a/MASFoundation/Classes/_private_/categories/UIAlertController+MAS.h b/MASFoundation/Classes/_private_/categories/UIAlertController+MAS.h new file mode 100644 index 00000000..ec8de498 --- /dev/null +++ b/MASFoundation/Classes/_private_/categories/UIAlertController+MAS.h @@ -0,0 +1,23 @@ +// +// UIAlertController+MAS.h +// MASFoundation +// +// Created by nimma01 on 11/10/17. +// Copyright © 2017 CA Technologies. All rights reserved. +// + +#import + +@interface UIAlertController (MAS) + +///-------------------------------------- +/// @name Public +///------------------------------------- + +# pragma mark - Public + +/** + * Retrieve the currently visible UIViewController. + */ ++ (UIViewController *)rootViewController; +@end diff --git a/MASFoundation/Classes/_private_/categories/UIAlertController+MAS.m b/MASFoundation/Classes/_private_/categories/UIAlertController+MAS.m new file mode 100644 index 00000000..cbd86f3e --- /dev/null +++ b/MASFoundation/Classes/_private_/categories/UIAlertController+MAS.m @@ -0,0 +1,59 @@ +// +// UIAlertController+MAS.m +// MASFoundation +// +// Created by nimma01 on 11/10/17. +// Copyright © 2017 CA Technologies. All rights reserved. +// + +#import "UIAlertController+MAS.h" +#import "MASUser.h" +@implementation UIAlertController (MAS) + +# pragma mark - Error Alert + ++ (UIViewController *) presentedViewController:(id)viewController +{ + if ([viewController isKindOfClass:[UINavigationController class]]) + { + UINavigationController *navigationController = (UINavigationController *)viewController; + return [self presentedViewController:navigationController.topViewController]; + } + if ([viewController isKindOfClass:[UIViewController class]]) + { + if ([viewController presentedViewController]) + { + if ([[viewController presentedViewController] isKindOfClass:[UINavigationController class]]) + { + UINavigationController *navigationController = (UINavigationController *)[viewController presentedViewController]; + + if (navigationController.isBeingDismissed) + { + return viewController; + } + } + + return [self presentedViewController:[viewController presentedViewController]]; + } + else { + return viewController; + } + } + else if ([viewController isKindOfClass:[UITabBarController class]]) + { + UITabBarController *tabBarController = (UITabBarController *)viewController; + return [self presentedViewController:tabBarController.presentedViewController]; + } + else { + return nil; + } +} + + +# pragma mark - Public + ++ (UIViewController *)rootViewController +{ + return [self presentedViewController:[UIApplication sharedApplication].keyWindow.rootViewController]; +} +@end diff --git a/MASFoundation/Classes/_private_/models/AuthCredentials/MASAuthCredentials+MASPrivate.m b/MASFoundation/Classes/_private_/models/AuthCredentials/MASAuthCredentials+MASPrivate.m index 8673246c..79067d7f 100644 --- a/MASFoundation/Classes/_private_/models/AuthCredentials/MASAuthCredentials+MASPrivate.m +++ b/MASFoundation/Classes/_private_/models/AuthCredentials/MASAuthCredentials+MASPrivate.m @@ -333,7 +333,7 @@ - (void)loginWithCredential:(MASCompletionErrorBlock)completion { NSError *idTokenValidationError = nil; BOOL isIdTokenValid = [MASAccessService validateIdToken:[bodyInfo objectForKey:MASIdTokenBodyRequestResponseKey] - magIdentifier:[[MASAccessService sharedService] getAccessValueStringWithType:MASAccessValueTypeMAGIdentifier] + magIdentifier:[[MASAccessService sharedService] getAccessValueStringWithStorageKey:MASKeychainStorageKeyMAGIdentifier] error:&idTokenValidationError]; if (!isIdTokenValid && idTokenValidationError) @@ -355,7 +355,7 @@ - (void)loginWithCredential:(MASCompletionErrorBlock)completion // // Persist current authCredentials type // - [[MASAccessService sharedService] setAccessValueString:self.credentialsType withAccessValueType:MASAccessValueTypeCurrentAuthCredentialsGrantType]; + [[MASAccessService sharedService] setAccessValueString:self.credentialsType storageKey:MASKeychainStorageKeyCurrentAuthCredentialsGrantType]; // // Create a new instance of MASUser if not client credentials @@ -371,7 +371,7 @@ - (void)loginWithCredential:(MASCompletionErrorBlock)completion // set authenticated timestamp // NSNumber *authenticatedTimestamp = [NSNumber numberWithDouble:[[NSDate date] timeIntervalSince1970]]; - [[MASAccessService sharedService] setAccessValueNumber:authenticatedTimestamp withAccessValueType:MASAccessValueTypeAuthenticatedTimestamp]; + [[MASAccessService sharedService] setAccessValueNumber:authenticatedTimestamp storageKey:MASKeychainStorageKeyAuthenticatedTimestamp]; // // Store credential information into keychain diff --git a/MASFoundation/Classes/_private_/models/AuthCredentials/MASAuthCredentialsClientCredentials.m b/MASFoundation/Classes/_private_/models/AuthCredentials/MASAuthCredentialsClientCredentials.m index 305ce1e2..b6d85197 100644 --- a/MASFoundation/Classes/_private_/models/AuthCredentials/MASAuthCredentialsClientCredentials.m +++ b/MASFoundation/Classes/_private_/models/AuthCredentials/MASAuthCredentialsClientCredentials.m @@ -109,14 +109,14 @@ - (NSDictionary *)getParameters else { // ClientId - NSString *clientId = [[MASAccessService sharedService] getAccessValueStringWithType:MASAccessValueTypeClientId]; + NSString *clientId = [[MASAccessService sharedService] getAccessValueStringWithStorageKey:MASKeychainStorageKeyClientId]; if (clientId) { parameterInfo[MASClientIdentifierRequestResponseKey] = clientId; } // ClientSecret - NSString *clientSecret = [[MASAccessService sharedService] getAccessValueStringWithType:MASAccessValueTypeClientSecret]; + NSString *clientSecret = [[MASAccessService sharedService] getAccessValueStringWithStorageKey:MASKeychainStorageKeyClientSecret]; if (clientSecret) { parameterInfo[MASClientSecretRequestResponseKey] = clientSecret; diff --git a/MASFoundation/Classes/_private_/models/MASAccess.m b/MASFoundation/Classes/_private_/models/MASAccess.m index 3401a4e9..a3b7457b 100644 --- a/MASFoundation/Classes/_private_/models/MASAccess.m +++ b/MASFoundation/Classes/_private_/models/MASAccess.m @@ -60,14 +60,14 @@ + (MASAccess *)instanceFromStorage // // retrieve all values from keychain and initialize with dictionary as those values shouold be read only. // - NSString *accessToken = [[MASAccessService sharedService] getAccessValueStringWithType:MASAccessValueTypeAccessToken]; - NSString *tokenType = [[MASAccessService sharedService] getAccessValueStringWithType:MASAccessValueTypeTokenType]; - NSString *refreshToken = [[MASAccessService sharedService] getAccessValueStringWithType:MASAccessValueTypeRefreshToken]; - NSString *idToken = [[MASAccessService sharedService] getAccessValueStringWithType:MASAccessValueTypeIdToken]; - NSString *idTokenType = [[MASAccessService sharedService] getAccessValueStringWithType:MASAccessValueTypeIdTokenType]; - NSNumber *expiresIn = [[MASAccessService sharedService] getAccessValueNumberWithType:MASAccessValueTypeExpiresIn]; - NSString *scopeAsString = [[MASAccessService sharedService] getAccessValueStringWithType:MASAccessValueTypeScope]; - NSString *authCredentialsType = [[MASAccessService sharedService] getAccessValueStringWithType:MASAccessValueTypeCurrentAuthCredentialsGrantType]; + NSString *accessToken = [[MASAccessService sharedService] getAccessValueStringWithStorageKey:MASKeychainStorageKeyAccessToken]; + NSString *tokenType = [[MASAccessService sharedService] getAccessValueStringWithStorageKey:MASKeychainStorageKeyTokenType]; + NSString *refreshToken = [[MASAccessService sharedService] getAccessValueStringWithStorageKey:MASKeychainStorageKeyRefreshToken]; + NSString *idToken = [[MASAccessService sharedService] getAccessValueStringWithStorageKey:MASKeychainStorageKeyIdToken]; + NSString *idTokenType = [[MASAccessService sharedService] getAccessValueStringWithStorageKey:MASKeychainStorageKeyIdTokenType]; + NSNumber *expiresIn = [[MASAccessService sharedService] getAccessValueNumberWithStorageKey:MASKeychainStorageKeyExpiresIn]; + NSString *scopeAsString = [[MASAccessService sharedService] getAccessValueStringWithStorageKey:MASKeychainStorageKeyScope]; + NSString *authCredentialsType = [[MASAccessService sharedService] getAccessValueStringWithStorageKey:MASKeychainStorageKeyCurrentAuthCredentialsGrantType]; NSMutableDictionary *accessDictionary = [NSMutableDictionary dictionary]; @@ -149,14 +149,14 @@ - (void)saveToStorage // // Save to the keychain // - [[MASAccessService sharedService] setAccessValueString:self.accessToken withAccessValueType:MASAccessValueTypeAccessToken]; - [[MASAccessService sharedService] setAccessValueString:self.tokenType withAccessValueType:MASAccessValueTypeTokenType]; - [[MASAccessService sharedService] setAccessValueString:self.refreshToken withAccessValueType:MASAccessValueTypeRefreshToken]; - [[MASAccessService sharedService] setAccessValueString:self.idToken withAccessValueType:MASAccessValueTypeIdToken]; - [[MASAccessService sharedService] setAccessValueString:self.idTokenType withAccessValueType:MASAccessValueTypeIdTokenType]; - [[MASAccessService sharedService] setAccessValueNumber:self.expiresIn withAccessValueType:MASAccessValueTypeExpiresIn]; - [[MASAccessService sharedService] setAccessValueString:self.scopeAsString withAccessValueType:MASAccessValueTypeScope]; - [[MASAccessService sharedService] setAccessValueString:self.authCredentialsType withAccessValueType:MASAccessValueTypeCurrentAuthCredentialsGrantType]; + [[MASAccessService sharedService] setAccessValueString:self.accessToken storageKey:MASKeychainStorageKeyAccessToken]; + [[MASAccessService sharedService] setAccessValueString:self.tokenType storageKey:MASKeychainStorageKeyTokenType]; + [[MASAccessService sharedService] setAccessValueString:self.refreshToken storageKey:MASKeychainStorageKeyRefreshToken]; + [[MASAccessService sharedService] setAccessValueString:self.idToken storageKey:MASKeychainStorageKeyIdToken]; + [[MASAccessService sharedService] setAccessValueString:self.idTokenType storageKey:MASKeychainStorageKeyIdTokenType]; + [[MASAccessService sharedService] setAccessValueNumber:self.expiresIn storageKey:MASKeychainStorageKeyExpiresIn]; + [[MASAccessService sharedService] setAccessValueString:self.scopeAsString storageKey:MASKeychainStorageKeyScope]; + [[MASAccessService sharedService] setAccessValueString:self.authCredentialsType storageKey:MASKeychainStorageKeyCurrentAuthCredentialsGrantType]; } @@ -262,7 +262,7 @@ - (void)saveWithUpdatedInfo:(NSDictionary *)info // // authCredentialsType // - NSString *authCredentialsType = [[MASAccessService sharedService] getAccessValueStringWithType:MASAccessValueTypeCurrentAuthCredentialsGrantType]; + NSString *authCredentialsType = [[MASAccessService sharedService] getAccessValueStringWithStorageKey:MASKeychainStorageKeyCurrentAuthCredentialsGrantType]; if (authCredentialsType) { _authCredentialsType = authCredentialsType; @@ -278,29 +278,29 @@ - (void)saveWithUpdatedInfo:(NSDictionary *)info - (void)refresh { _accessToken = nil; - _accessToken = [[MASAccessService sharedService] getAccessValueStringWithType:MASAccessValueTypeAccessToken]; + _accessToken = [[MASAccessService sharedService] getAccessValueStringWithStorageKey:MASKeychainStorageKeyAccessToken]; _tokenType = nil; - _tokenType = [[MASAccessService sharedService] getAccessValueStringWithType:MASAccessValueTypeTokenType]; + _tokenType = [[MASAccessService sharedService] getAccessValueStringWithStorageKey:MASKeychainStorageKeyTokenType]; _refreshToken = nil; - _refreshToken = [[MASAccessService sharedService] getAccessValueStringWithType:MASAccessValueTypeRefreshToken]; + _refreshToken = [[MASAccessService sharedService] getAccessValueStringWithStorageKey:MASKeychainStorageKeyRefreshToken]; _idToken = nil; - _idToken = [[MASAccessService sharedService] getAccessValueStringWithType:MASAccessValueTypeIdToken]; + _idToken = [[MASAccessService sharedService] getAccessValueStringWithStorageKey:MASKeychainStorageKeyIdToken]; _idTokenType = nil; - _idTokenType = [[MASAccessService sharedService] getAccessValueStringWithType:MASAccessValueTypeIdTokenType]; + _idTokenType = [[MASAccessService sharedService] getAccessValueStringWithStorageKey:MASKeychainStorageKeyIdTokenType]; _expiresIn = nil; - _expiresIn = [[MASAccessService sharedService] getAccessValueNumberWithType:MASAccessValueTypeExpiresIn]; + _expiresIn = [[MASAccessService sharedService] getAccessValueNumberWithStorageKey:MASKeychainStorageKeyExpiresIn]; _scope = nil; _scopeAsString = nil; - _scopeAsString = [[MASAccessService sharedService] getAccessValueStringWithType:MASAccessValueTypeScope]; + _scopeAsString = [[MASAccessService sharedService] getAccessValueStringWithStorageKey:MASKeychainStorageKeyScope]; _authCredentialsType = nil; - _authCredentialsType = [[MASAccessService sharedService] getAccessValueStringWithType:MASAccessValueTypeCurrentAuthCredentialsGrantType]; + _authCredentialsType = [[MASAccessService sharedService] getAccessValueStringWithStorageKey:MASKeychainStorageKeyCurrentAuthCredentialsGrantType]; } @@ -328,7 +328,6 @@ - (void)reset } - - (void)deleteAll { @@ -336,40 +335,39 @@ - (void)deleteAll // remove all data from the keychain // _accessToken = nil; - [[MASAccessService sharedService] setAccessValueString:nil withAccessValueType:MASAccessValueTypeAccessToken]; + [[MASAccessService sharedService] setAccessValueString:nil storageKey:MASKeychainStorageKeyAccessToken]; - [[MASAccessService sharedService] setAccessValueString:nil withAccessValueType:MASAccessValueTypeAuthenticatedUserObjectId]; + [[MASAccessService sharedService] setAccessValueString:nil storageKey:MASKeychainStorageKeyAuthenticatedUserObjectId]; - [[MASAccessService sharedService] setAccessValueNumber:nil withAccessValueType:MASAccessValueTypeAuthenticatedTimestamp]; + [[MASAccessService sharedService] setAccessValueNumber:nil storageKey:MASKeychainStorageKeyAuthenticatedTimestamp]; _tokenType = nil; - [[MASAccessService sharedService] setAccessValueString:nil withAccessValueType:MASAccessValueTypeTokenType]; + [[MASAccessService sharedService] setAccessValueString:nil storageKey:MASKeychainStorageKeyTokenType]; _refreshToken = nil; - [[MASAccessService sharedService] setAccessValueString:nil withAccessValueType:MASAccessValueTypeRefreshToken]; + [[MASAccessService sharedService] setAccessValueString:nil storageKey:MASKeychainStorageKeyRefreshToken]; _idToken = nil; - [[MASAccessService sharedService] setAccessValueString:nil withAccessValueType:MASAccessValueTypeIdToken]; + [[MASAccessService sharedService] setAccessValueString:nil storageKey:MASKeychainStorageKeyIdToken]; _idTokenType = nil; - [[MASAccessService sharedService] setAccessValueString:nil withAccessValueType:MASAccessValueTypeIdTokenType]; + [[MASAccessService sharedService] setAccessValueString:nil storageKey:MASKeychainStorageKeyIdTokenType]; _expiresIn = nil; - [[MASAccessService sharedService] setAccessValueNumber:nil withAccessValueType:MASAccessValueTypeExpiresIn]; + [[MASAccessService sharedService] setAccessValueNumber:nil storageKey:MASKeychainStorageKeyExpiresIn]; _scope = nil; _scopeAsString = nil; - [[MASAccessService sharedService] setAccessValueString:nil withAccessValueType:MASAccessValueTypeScope]; + [[MASAccessService sharedService] setAccessValueString:nil storageKey:MASKeychainStorageKeyScope]; // // Clena up the tokens from Local Authentication protected keychain storage // - [[MASAccessService sharedService] setAccessValueString:nil withAccessValueType:MASAccessValueTypeSecuredIdToken]; - [[MASAccessService sharedService] setAccessValueNumber:nil withAccessValueType:MASAccessValueTypeIsDeviceLocked]; + [[MASAccessService sharedService] setAccessValueString:nil storageKey:MASKeychainStorageKeySecuredIdToken]; + [[MASAccessService sharedService] setAccessValueNumber:nil storageKey:MASKeychainStorageKeyIsDeviceLocked]; } - - (void)deleteForLogOff { @@ -377,24 +375,24 @@ - (void)deleteForLogOff // remove all data from the keychain // _accessToken = nil; - [[MASAccessService sharedService] setAccessValueString:nil withAccessValueType:MASAccessValueTypeAccessToken]; + [[MASAccessService sharedService] setAccessValueString:nil storageKey:MASKeychainStorageKeyAccessToken]; - [[MASAccessService sharedService] setAccessValueString:nil withAccessValueType:MASAccessValueTypeAuthenticatedUserObjectId]; + [[MASAccessService sharedService] setAccessValueString:nil storageKey:MASKeychainStorageKeyAuthenticatedUserObjectId]; - [[MASAccessService sharedService] setAccessValueNumber:nil withAccessValueType:MASAccessValueTypeAuthenticatedTimestamp]; + [[MASAccessService sharedService] setAccessValueNumber:nil storageKey:MASKeychainStorageKeyAuthenticatedTimestamp]; _tokenType = nil; - [[MASAccessService sharedService] setAccessValueString:nil withAccessValueType:MASAccessValueTypeTokenType]; + [[MASAccessService sharedService] setAccessValueString:nil storageKey:MASKeychainStorageKeyTokenType]; _refreshToken = nil; - [[MASAccessService sharedService] setAccessValueString:nil withAccessValueType:MASAccessValueTypeRefreshToken]; + [[MASAccessService sharedService] setAccessValueString:nil storageKey:MASKeychainStorageKeyRefreshToken]; _expiresIn = nil; - [[MASAccessService sharedService] setAccessValueNumber:nil withAccessValueType:MASAccessValueTypeExpiresIn]; + [[MASAccessService sharedService] setAccessValueNumber:nil storageKey:MASKeychainStorageKeyExpiresIn]; _scope = nil; _scopeAsString = nil; - [[MASAccessService sharedService] setAccessValueString:nil withAccessValueType:MASAccessValueTypeScope]; + [[MASAccessService sharedService] setAccessValueString:nil storageKey:MASKeychainStorageKeyScope]; } @@ -404,19 +402,19 @@ - (void)deleteForTokenExpiration // remove all data from the keychain // _accessToken = nil; - [[MASAccessService sharedService] setAccessValueString:nil withAccessValueType:MASAccessValueTypeAccessToken]; + [[MASAccessService sharedService] setAccessValueString:nil storageKey:MASKeychainStorageKeyAccessToken]; - [[MASAccessService sharedService] setAccessValueNumber:nil withAccessValueType:MASAccessValueTypeAuthenticatedTimestamp]; + [[MASAccessService sharedService] setAccessValueNumber:nil storageKey:MASKeychainStorageKeyAuthenticatedTimestamp]; _tokenType = nil; - [[MASAccessService sharedService] setAccessValueString:nil withAccessValueType:MASAccessValueTypeTokenType]; + [[MASAccessService sharedService] setAccessValueString:nil storageKey:MASKeychainStorageKeyTokenType]; _expiresIn = nil; - [[MASAccessService sharedService] setAccessValueNumber:nil withAccessValueType:MASAccessValueTypeExpiresIn]; + [[MASAccessService sharedService] setAccessValueNumber:nil storageKey:MASKeychainStorageKeyExpiresIn]; _scope = nil; _scopeAsString = nil; - [[MASAccessService sharedService] setAccessValueString:nil withAccessValueType:MASAccessValueTypeScope]; + [[MASAccessService sharedService] setAccessValueString:nil storageKey:MASKeychainStorageKeyScope]; } @@ -491,7 +489,7 @@ - (BOOL)isSessionLocked // MASAccessService *accessService = [MASAccessService sharedService]; - NSNumber *isLocked = [accessService getAccessValueNumberWithType:MASAccessValueTypeIsDeviceLocked]; + NSNumber *isLocked = [accessService getAccessValueNumberWithStorageKey:MASKeychainStorageKeyIsDeviceLocked]; return [isLocked boolValue]; } @@ -576,7 +574,7 @@ - (NSDate *)expiresInDate } // Authentication timestamp - NSNumber *authenticatedTimestamp = [[MASAccessService sharedService] getAccessValueNumberWithType:MASAccessValueTypeAuthenticatedTimestamp]; + NSNumber *authenticatedTimestamp = [[MASAccessService sharedService] getAccessValueNumberWithStorageKey:MASKeychainStorageKeyAuthenticatedTimestamp]; double expiresInDateNumber = [authenticatedTimestamp doubleValue] + [_expiresIn doubleValue]; NSDate *expiresInDate = [NSDate dateWithTimeIntervalSince1970:expiresInDateNumber]; @@ -589,7 +587,7 @@ - (NSDate *)clientCertificateExpirationDate { if (!_clientCertificateExpirationDate) { - NSNumber *clientCertExpTimestamp = [[MASAccessService sharedService] getAccessValueNumberWithType:MASAccessValueTypeSignedPublicCertificateExpirationDate]; + NSNumber *clientCertExpTimestamp = [[MASAccessService sharedService] getAccessValueNumberWithStorageKey:MASKeychainStorageKeyPublicCertificateExpirationDate]; if (clientCertExpTimestamp) { @@ -600,7 +598,7 @@ - (NSDate *)clientCertificateExpirationDate // // Extracting signed client certificate expiration date // - NSArray * cert = [[MASAccessService sharedService] getAccessValueCertificateWithType:MASAccessValueTypeSignedPublicCertificate]; + NSArray * cert = [[MASAccessService sharedService] getAccessValueCertificateWithStorageKey:MASKeychainStorageKeySignedPublicCertificate]; SecCertificateRef certificate = (__bridge SecCertificateRef)([cert objectAtIndex:0]); // @@ -608,7 +606,7 @@ - (NSDate *)clientCertificateExpirationDate // _clientCertificateExpirationDate = [[MASAccessService sharedService] extractExpirationDateFromCertificate:certificate]; [[MASAccessService sharedService] setAccessValueNumber:[NSNumber numberWithDouble:[_clientCertificateExpirationDate timeIntervalSince1970]] - withAccessValueType:MASAccessValueTypeSignedPublicCertificateExpirationDate]; + storageKey:MASKeychainStorageKeyPublicCertificateExpirationDate]; } } diff --git a/MASFoundation/Classes/_private_/models/MASApplication+MASPrivate.m b/MASFoundation/Classes/_private_/models/MASApplication+MASPrivate.m index 2c2291d3..8c4a9d2f 100644 --- a/MASFoundation/Classes/_private_/models/MASApplication+MASPrivate.m +++ b/MASFoundation/Classes/_private_/models/MASApplication+MASPrivate.m @@ -56,25 +56,24 @@ - (id)initWithConfiguration nil) forKey:@"redirectUri"]; MASAccessService *accessService = [MASAccessService sharedService]; - - NSData *trustedServerCertificate = [accessService getAccessValueDataWithType:MASAccessValueTypeTrustedServerCertificate]; - if(!trustedServerCertificate) + NSData *trustedServerCertificate = [accessService getAccessValueDataWithStorageKey:MASKeychainStorageKeyTrustedServerCertificate]; + if (!trustedServerCertificate) { // // Trusted Server Certificate (not sure if this really belongs here, think about that) // NSArray *certificates = [MASConfiguration currentConfiguration].gatewayCertificatesAsPEMData; - if(certificates && certificates.count > 0) + if (certificates && certificates.count > 0) { trustedServerCertificate = certificates[0]; - [accessService setAccessValueData:trustedServerCertificate withAccessValueType:MASAccessValueTypeTrustedServerCertificate]; + [accessService setAccessValueData:trustedServerCertificate storageKey:MASKeychainStorageKeyTrustedServerCertificate]; } } // // If the credentials are NOT dynamic set them here // - if(!configuration.applicationCredentialsAreDynamic) + if (!configuration.applicationCredentialsAreDynamic) { NSDictionary *credentialsFromConfiguration = @ { @@ -108,7 +107,7 @@ + (MASApplication *)instanceFromStorage // Attempt to retrieve from keychain // NSData *data = [[MASIKeyChainStore keyChainStoreWithService:[MASConfiguration currentConfiguration].gatewayUrl.absoluteString] dataForKey:[MASApplication.class description]]; - if(data) + if (data) { application = (MASApplication *)[NSKeyedUnarchiver unarchiveObjectWithData:data]; } @@ -160,14 +159,14 @@ - (void)saveToStorage // Save to the keychain // NSData *data = [NSKeyedArchiver archivedDataWithRootObject:self]; - if(data) + if (data) { NSError *error; [[MASIKeyChainStore keyChainStoreWithService:[MASConfiguration currentConfiguration].gatewayUrl.absoluteString] setData:data forKey:[MASApplication.class description] error:&error]; - if(error) + if (error) { DLog(@"Error attempting to save data: %@", [error localizedDescription]); return; @@ -198,27 +197,27 @@ - (void)saveWithUpdatedInfo:(NSDictionary *)info // Client Expiration // NSNumber *clientExpiration = bodyInfo[MASClientExpirationRequestResponseKey]; - if(clientExpiration) + if (clientExpiration) { - [accessService setAccessValueNumber:clientExpiration withAccessValueType:MASAccessValueTypeClientExpiration]; + [accessService setAccessValueNumber:clientExpiration storageKey:MASKeychainStorageKeyClientExpiration]; } // // Client Key // NSString *clientId = bodyInfo[MASClientKeyRequestResponseKey]; - if(clientId) + if (clientId) { - [accessService setAccessValueString:clientId withAccessValueType:MASAccessValueTypeClientId]; + [accessService setAccessValueString:clientId storageKey:MASKeychainStorageKeyClientId]; } // // Client Secret // NSString *clientSecret = bodyInfo[MASClientSecretRequestResponseKey]; - if(clientSecret) + if (clientSecret) { - [accessService setAccessValueString:clientSecret withAccessValueType:MASAccessValueTypeClientSecret]; + [accessService setAccessValueString:clientSecret storageKey:MASKeychainStorageKeyClientSecret]; } // @@ -232,9 +231,9 @@ - (void)reset { MASAccessService *accessService = [MASAccessService sharedService]; - [accessService setAccessValueString:nil withAccessValueType:MASAccessValueTypeClientId]; - [accessService setAccessValueString:nil withAccessValueType:MASAccessValueTypeClientSecret]; - [accessService setAccessValueNumber:nil withAccessValueType:MASAccessValueTypeClientExpiration]; + [accessService setAccessValueString:nil storageKey:MASKeychainStorageKeyClientId]; + [accessService setAccessValueString:nil storageKey:MASKeychainStorageKeyClientSecret]; + [accessService setAccessValueNumber:nil storageKey:MASKeychainStorageKeyClientExpiration]; [[MASIKeyChainStore keyChainStoreWithService:[MASConfiguration currentConfiguration].gatewayUrl.absoluteString] removeItemForKey:[MASApplication.class description]]; } @@ -245,7 +244,7 @@ - (id)initWithEnterpriseInfo:(NSDictionary *)info //DLog(@"\n\ncalled with info: %@\n\n", info); self = [super init]; - if(self) + if (self) { [self setValue:info[MASApplicationIdRequestResponseKey] forKey:@"identifier"]; [self setValue:info[MASApplicationNameRequestResponseKey] forKey:@"name"]; @@ -268,8 +267,8 @@ + (NSDate *)expirationAsDate // MASAccessService *accessService = [MASAccessService sharedService]; - NSNumber *clientExpiration = [accessService getAccessValueNumberWithType:MASAccessValueTypeClientExpiration]; - if(!clientExpiration) + NSNumber *clientExpiration = [accessService getAccessValueNumberWithStorageKey:MASKeychainStorageKeyClientExpiration]; + if (!clientExpiration) { return nil; } @@ -291,8 +290,8 @@ - (NSString *)clientAuthorizationBasicHeaderValue // MASAccessService *accessService = [MASAccessService sharedService]; - NSString *clientId = [accessService getAccessValueStringWithType:MASAccessValueTypeClientId]; - NSString *clientSecret = [accessService getAccessValueStringWithType:MASAccessValueTypeClientSecret]; + NSString *clientId = [accessService getAccessValueStringWithStorageKey:MASKeychainStorageKeyClientId]; + NSString *clientSecret = [accessService getAccessValueStringWithStorageKey:MASKeychainStorageKeyClientSecret]; NSString *clientAuthStr = [NSString stringWithFormat:@"%@:%@", clientId, clientSecret]; NSData *clientAuthData = [clientAuthStr dataUsingEncoding:NSUTF8StringEncoding]; @@ -310,14 +309,14 @@ - (BOOL)isExpired // MASAccessService *accessService = [MASAccessService sharedService]; - NSNumber *clientExpiration = [accessService getAccessValueNumberWithType:MASAccessValueTypeClientExpiration]; - NSString *clientId = [accessService getAccessValueStringWithType:MASAccessValueTypeClientId]; - NSString *clientSecret = [accessService getAccessValueStringWithType:MASAccessValueTypeClientSecret]; + NSNumber *clientExpiration = [accessService getAccessValueNumberWithStorageKey:MASKeychainStorageKeyClientExpiration]; + NSString *clientId = [accessService getAccessValueStringWithStorageKey:MASKeychainStorageKeyClientId]; + NSString *clientSecret = [accessService getAccessValueStringWithStorageKey:MASKeychainStorageKeyClientSecret]; // // Expiration is nil, then it is considered expired // - if(!clientExpiration) + if (!clientExpiration) { isExpired = YES; } @@ -326,7 +325,7 @@ - (BOOL)isExpired // If the value is zero AND both the client id and secret are set then it is not expired and // the expiry is actually infinite // - else if([clientExpiration doubleValue] == 0 && clientId && clientSecret) + else if ([clientExpiration doubleValue] == 0 && clientId && clientSecret) { isExpired = NO; } @@ -334,7 +333,7 @@ - (BOOL)isExpired // // If a positive time interval remains compared to the current time and date then it is not expired // - else if([[MASApplication expirationAsDate] timeIntervalSinceNow] > 0) + else if ([[MASApplication expirationAsDate] timeIntervalSinceNow] > 0) { isExpired = NO; } @@ -349,7 +348,7 @@ - (NSString *)authenticationStatusAsString // // Detect status and respond appropriately // - switch([self authenticationStatus]) + switch ([self authenticationStatus]) { // // Not Logged In @@ -382,7 +381,7 @@ - (NSString *)scopeTypeToString:(MASScopeType)scopeType // // Detect type and respond appropriately // - switch(scopeType) + switch (scopeType) { // // OpenId diff --git a/MASFoundation/Classes/_private_/models/MASClaims+MASPrivate.m b/MASFoundation/Classes/_private_/models/MASClaims+MASPrivate.m index da45ebad..ccb5e2c8 100644 --- a/MASFoundation/Classes/_private_/models/MASClaims+MASPrivate.m +++ b/MASFoundation/Classes/_private_/models/MASClaims+MASPrivate.m @@ -48,8 +48,8 @@ - (NSString * __nullable)buildWithPrivateKey:(NSData * __nonnull)privateKey erro // If iss was not prepare upon MASClaims object construction which most likley happened due to registration status of the client, // re-prepare iss with registered client id // - NSString *magIdentifier = [[MASAccessService sharedService] getAccessValueStringWithType:MASAccessValueTypeMAGIdentifier]; - NSString *clientId = [[MASAccessService sharedService] getAccessValueStringWithType:MASAccessValueTypeClientId]; + NSString *magIdentifier = [[MASAccessService sharedService] getAccessValueStringWithStorageKey:MASKeychainStorageKeyMAGIdentifier]; + NSString *clientId = [[MASAccessService sharedService] getAccessValueStringWithStorageKey:MASKeychainStorageKeyClientId]; if (magIdentifier && clientId) { diff --git a/MASFoundation/Classes/_private_/models/MASDevice+MASPrivate.m b/MASFoundation/Classes/_private_/models/MASDevice+MASPrivate.m index 48dab8cf..5972031a 100644 --- a/MASFoundation/Classes/_private_/models/MASDevice+MASPrivate.m +++ b/MASFoundation/Classes/_private_/models/MASDevice+MASPrivate.m @@ -96,28 +96,28 @@ - (void)saveWithUpdatedInfo:(NSDictionary *)info NSString *jwt = headerInfo[MASJwtRequestResponseKey]; if (jwt) { - [accessService setAccessValueString:jwt withAccessValueType:MASAccessValueTypeJWT]; + [accessService setAccessValueString:jwt storageKey:MASKeychainStorageKeyJWT]; } // Mag Identifier NSString *magIdentifier = headerInfo[MASMagIdentifierRequestResponseKey]; if (magIdentifier) { - [accessService setAccessValueString:magIdentifier withAccessValueType:MASAccessValueTypeMAGIdentifier]; + [accessService setAccessValueString:magIdentifier storageKey:MASKeychainStorageKeyMAGIdentifier]; } // Id token NSString *idToken = headerInfo[MASIdTokenHeaderRequestResponseKey]; if (idToken) { - [accessService setAccessValueString:idToken withAccessValueType:MASAccessValueTypeIdToken]; + [accessService setAccessValueString:idToken storageKey:MASKeychainStorageKeyIdToken]; } // Id token type NSString *idTokenType = headerInfo[MASIdTokenTypeHeaderRequestResponseKey]; if (idTokenType) { - [accessService setAccessValueString:idTokenType withAccessValueType:MASAccessValueTypeIdTokenType]; + [accessService setAccessValueString:idTokenType storageKey:MASKeychainStorageKeyIdTokenType]; } // @@ -129,20 +129,20 @@ - (void)saveWithUpdatedInfo:(NSDictionary *)info if (certificateData) { - [accessService setAccessValueCertificate:certificateData withAccessValueType:MASAccessValueTypeSignedPublicCertificate]; - [accessService setAccessValueData:certificateData withAccessValueType:MASAccessValueTypeSignedPublicCertificateData]; + [accessService setAccessValueCertificate:certificateData storageKey:MASKeychainStorageKeySignedPublicCertificate]; + [accessService setAccessValueData:certificateData storageKey:MASKeychainStorageKeyPublicCertificateData]; // // Extracting signed client certificate expiration date // - NSArray * cert = [accessService getAccessValueCertificateWithType:MASAccessValueTypeSignedPublicCertificate]; + NSArray * cert = [accessService getAccessValueCertificateWithStorageKey:MASKeychainStorageKeySignedPublicCertificate]; SecCertificateRef certificate = (__bridge SecCertificateRef)([cert objectAtIndex:0]); // // Store client certificate expiration date into shared keychain storage // NSDate *expirationDate = [accessService extractExpirationDateFromCertificate:certificate]; - [accessService setAccessValueNumber:[NSNumber numberWithDouble:[expirationDate timeIntervalSince1970]] withAccessValueType:MASAccessValueTypeSignedPublicCertificateExpirationDate]; + [accessService setAccessValueNumber:[NSNumber numberWithDouble:[expirationDate timeIntervalSince1970]] storageKey:MASKeychainStorageKeyPublicCertificateExpirationDate]; } // @@ -151,7 +151,7 @@ - (void)saveWithUpdatedInfo:(NSDictionary *)info NSString *deviceVendorId = [MASDevice deviceVendorId]; if (deviceVendorId) { - [accessService setAccessValueString:deviceVendorId withAccessValueType:MASAccessValueTypeDeviceVendorId]; + [accessService setAccessValueString:deviceVendorId storageKey:MASKeychainStorageKeyDeviceVendorId]; } // diff --git a/MASFoundation/Classes/_private_/models/MASUser+MASPrivate.m b/MASFoundation/Classes/_private_/models/MASUser+MASPrivate.m index 630acfcd..567efc1f 100644 --- a/MASFoundation/Classes/_private_/models/MASUser+MASPrivate.m +++ b/MASFoundation/Classes/_private_/models/MASUser+MASPrivate.m @@ -29,7 +29,7 @@ @implementation MASUser (MASPrivate) - (id)initWithInfo:(NSDictionary *)info { self = [super init]; - if(self) + if (self) { [self saveWithUpdatedInfo:info]; } @@ -46,9 +46,9 @@ + (MASUser *)instanceFromStorage // Attempt to retrieve from keychain // - NSData *data = [[MASAccessService sharedService] getAccessValueDataWithType:MASAccessValueTypeMASUserObjectData]; + NSData *data = [[MASAccessService sharedService] getAccessValueDataWithStorageKey:MASKeychainStorageKeyMASUserObjectData]; - if(data) + if (data) { user = (MASUser *)[NSKeyedUnarchiver unarchiveObjectWithData:data]; } @@ -63,9 +63,9 @@ - (void)saveToStorage // Save to the keychain // NSData *data = [NSKeyedArchiver archivedDataWithRootObject:self]; - if(data) + if (data) { - [[MASAccessService sharedService] setAccessValueData:data withAccessValueType:MASAccessValueTypeMASUserObjectData]; + [[MASAccessService sharedService] setAccessValueData:data storageKey:MASKeychainStorageKeyMASUserObjectData]; } } @@ -88,13 +88,19 @@ - (void)saveWithUpdatedInfo:(NSDictionary *)info // Uid --> ObjectId // NSString *uid = bodyInfo[MASUserPreferredNameRequestResponseKey]; - if(uid && ![uid isKindOfClass:[NSNull class]]) [self setValue:uid forKey:@"objectId"]; + if (uid && ![uid isKindOfClass:[NSNull class]]) + { + [self setValue:uid forKey:@"objectId"]; + } // // Preferred UserName // NSString *userName = bodyInfo[MASUserPreferredNameRequestResponseKey]; - if(userName && ![userName isKindOfClass:[NSNull class]]) [self setValue:userName forKey:@"userName"]; + if (userName && ![userName isKindOfClass:[NSNull class]]) + { + [self setValue:userName forKey:@"userName"]; + } // // Family Name @@ -116,24 +122,33 @@ - (void)saveWithUpdatedInfo:(NSDictionary *)info NSMutableString *mutableCopy = [NSMutableString new]; // Given name, if any - if(self.givenName && ![self.givenName isKindOfClass:[NSNull class]]) [mutableCopy appendString:self.givenName]; + if (self.givenName && ![self.givenName isKindOfClass:[NSNull class]]) + { + [mutableCopy appendString:self.givenName]; + } // Family name, if any - if(self.familyName && ![self.familyName isKindOfClass:[NSNull class]]) + if (self.familyName && ![self.familyName isKindOfClass:[NSNull class]]) { // Check if there was a given name first, if so add a space - if(mutableCopy.length > 0) [mutableCopy appendString:MASDefaultEmptySpace]; + if (mutableCopy.length > 0) + { + [mutableCopy appendString:MASDefaultEmptySpace]; + } [mutableCopy appendString:self.familyName]; } - if(mutableCopy.length > 0) [self setValue:mutableCopy forKey:@"formattedName"]; + if (mutableCopy.length > 0) + { + [self setValue:mutableCopy forKey:@"formattedName"]; + } // // Email Addresses // NSString *emailValue = bodyInfo[MASUserEmailRequestResponseKey]; - if(emailValue && ![emailValue isKindOfClass:[NSNull class]]) + if (emailValue && ![emailValue isKindOfClass:[NSNull class]]) { [self setValue:@{ MASInfoTypeWork : emailValue } forKey:@"emailAddresses"]; } @@ -142,7 +157,7 @@ - (void)saveWithUpdatedInfo:(NSDictionary *)info // Phone Numbers // NSString *phoneValue = bodyInfo[MASUserPhoneRequestResponseKey]; - if(phoneValue && ![phoneValue isKindOfClass:[NSNull class]]) + if (phoneValue && ![phoneValue isKindOfClass:[NSNull class]]) { [self setValue:@{ MASInfoTypeWork : phoneValue } forKey:@"phoneNumbers"]; } @@ -151,7 +166,7 @@ - (void)saveWithUpdatedInfo:(NSDictionary *)info // Addresses // NSDictionary *addressInfo = bodyInfo[MASUserAddressRequestResponseKey]; - if(addressInfo && ![addressInfo isKindOfClass:[NSNull class]]) + if (addressInfo && ![addressInfo isKindOfClass:[NSNull class]]) { [self setValue:@{ MASInfoTypeWork : addressInfo } forKey:@"addresses"]; } @@ -160,7 +175,7 @@ - (void)saveWithUpdatedInfo:(NSDictionary *)info // Picture // NSString *imageUriAsString = bodyInfo[MASUserPictureRequestResponseKey]; - if(imageUriAsString && ![imageUriAsString isKindOfClass:[NSNull class]]) + if (imageUriAsString && ![imageUriAsString isKindOfClass:[NSNull class]]) { NSURL *imageUrl = [NSURL URLWithString:imageUriAsString]; NSData *imageData = [NSData dataWithContentsOfURL:imageUrl]; @@ -172,12 +187,12 @@ - (void)saveWithUpdatedInfo:(NSDictionary *)info // set authenticated timestamp // NSNumber *authenticatedTimestamp = [NSNumber numberWithDouble:[[NSDate date] timeIntervalSince1970]]; - [accessService setAccessValueNumber:authenticatedTimestamp withAccessValueType:MASAccessValueTypeAuthenticatedTimestamp]; + [accessService setAccessValueNumber:authenticatedTimestamp storageKey:MASKeychainStorageKeyAuthenticatedTimestamp]; // // set authenticated user's objectId // - [accessService setAccessValueString:self.objectId withAccessValueType:MASAccessValueTypeAuthenticatedUserObjectId]; + [accessService setAccessValueString:self.objectId storageKey:MASKeychainStorageKeyAuthenticatedUserObjectId]; // // storing access information into keychain @@ -203,7 +218,7 @@ - (void)reset { [self resetPartial]; - [[MASAccessService sharedService] setAccessValueData:nil withAccessValueType:MASAccessValueTypeMASUserObjectData]; + [[MASAccessService sharedService] setAccessValueData:nil storageKey:MASKeychainStorageKeyMASUserObjectData]; } - (void)resetPartial @@ -223,7 +238,10 @@ - (void)setWasLoggedOffAndSave:(BOOL)wasLoggedOff // // If was logged off remove the keychain stored values // - if(wasLoggedOff) [self resetPartial]; + if (wasLoggedOff) + { + [self resetPartial]; + } // // Save diff --git a/MASFoundation/Classes/_private_/services/MASServiceRegistry.h b/MASFoundation/Classes/_private_/services/MASServiceRegistry.h index 694f9508..d2c18078 100644 --- a/MASFoundation/Classes/_private_/services/MASServiceRegistry.h +++ b/MASFoundation/Classes/_private_/services/MASServiceRegistry.h @@ -187,4 +187,15 @@ typedef NS_ENUM(NSInteger, MASRegistryState) - (BOOL)uiServiceWillHandleOTPChannelSelection:(NSArray *)supportedChannels otpGenerationBlock:(MASOTPGenerationBlock)generationBlock; + +/** + * Calling this method will attempt to launch a browser which handles the user authentication steps. + * For this method to handle authentication it requires browser based login to be enabled. + * @see enableBrowserBasedAuthentication + * + * @param bbaLoginBlock The MASAuthCredentialsBlock to receive login result. + * @return Return YES if handled, NO if not. + */ +- (BOOL)browserBasedLoginWillHandleAuthentication : (MASAuthCredentialsBlock)bbaLoginBlock; + @end diff --git a/MASFoundation/Classes/_private_/services/MASServiceRegistry.m b/MASFoundation/Classes/_private_/services/MASServiceRegistry.m index 9c375214..f0b11b73 100644 --- a/MASFoundation/Classes/_private_/services/MASServiceRegistry.m +++ b/MASFoundation/Classes/_private_/services/MASServiceRegistry.m @@ -15,6 +15,8 @@ #import "MASConfigurationService.h" #import "MASModelService.h" #import "MASService.h" +#import "MASServiceRegistry.h" +#import "MASBrowserBasedAuthentication.h" // @@ -932,4 +934,17 @@ - (BOOL)uiServiceWillHandleOTPChannelSelection:(NSArray *)supportedChannels return YES; } + +- (BOOL)browserBasedLoginWillHandleAuthentication : (MASAuthCredentialsBlock)bbaLoginBlock +{ + if(![MASModelService browserBasedAuthentication]) + { + return NO; + } + + [[MASBrowserBasedAuthentication sharedInstance] loadWebLoginTemplate:bbaLoginBlock]; + return YES; + +} + @end diff --git a/MASFoundation/Classes/_private_/services/access/MASAccessService.h b/MASFoundation/Classes/_private_/services/access/MASAccessService.h index 077e6038..dfb9c3f0 100644 --- a/MASFoundation/Classes/_private_/services/access/MASAccessService.h +++ b/MASFoundation/Classes/_private_/services/access/MASAccessService.h @@ -16,43 +16,38 @@ @class MASIKeyChainStore; - -/** - * The enumerated MASAccessValueType - */ -typedef NS_ENUM(NSInteger, MASAccessValueType) -{ - MASAccessValueTypeUknonw = -1, - MASAccessValueTypeAccessToken, - MASAccessValueTypeAuthenticatedTimestamp, - MASAccessValueTypeAuthenticatedUserObjectId, - MASAccessValueTypeConfiguration, - MASAccessValueTypeClientExpiration, - MASAccessValueTypeClientId, - MASAccessValueTypeClientSecret, - MASAccessValueTypeExpiresIn, - MASAccessValueTypeIdToken, - MASAccessValueTypeIdTokenType, - MASAccessValueTypeIsDeviceLocked, - MASAccessValueTypeJWT, - MASAccessValueTypeMAGIdentifier, - MASAccessValueTypeMSSOEnabled, - MASAccessValueTypePrivateKey, - MASAccessValueTypePrivateKeyBits, - MASAccessValueTypePublicKey, - MASAccessValueTypeRefreshToken, - MASAccessValueTypeScope, - MASAccessValueTypeSecuredIdToken, - MASAccessValueTypeSignedPublicCertificate, - MASAccessValueTypeSignedPublicCertificateData, - MASAccessValueTypeSignedPublicCertificateExpirationDate, - MASAccessValueTypeTokenExpiration, - MASAccessValueTypeTokenType, - MASAccessValueTypeTrustedServerCertificate, - MASAccessValueTypeCurrentAuthCredentialsGrantType, - MASAccessValueTypeMASUserObjectData, - MASAccessValueTypeDeviceVendorId, -}; +// +// List of constant NSString values for reserved storage keys +// +extern NSString * const MASKeychainStorageKeyConfiguration; +extern NSString * const MASKeychainStorageKeyAccessToken; +extern NSString * const MASKeychainStorageKeyAuthenticatedUserObjectId; +extern NSString * const MASKeychainStorageKeyRefreshToken; +extern NSString * const MASKeychainStorageKeyScope; +extern NSString * const MASKeychainStorageKeyTokenType; +extern NSString * const MASKeychainStorageKeyExpiresIn; +extern NSString * const MASKeychainStorageKeyTokenExpiration; +extern NSString * const MASKeychainStorageKeySecuredIdToken; +extern NSString * const MASKeychainStorageKeyIdToken; +extern NSString * const MASKeychainStorageKeyIdTokenType; +extern NSString * const MASKeychainStorageKeyClientExpiration; +extern NSString * const MASKeychainStorageKeyClientId; +extern NSString * const MASKeychainStorageKeyClientSecret; +extern NSString * const MASKeychainStorageKeyJWT; +extern NSString * const MASKeychainStorageKeyMAGIdentifier; +extern NSString * const MASKeychainStorageKeyMSSOEnabled; +extern NSString * const MASKeychainStorageKeyPrivateKey; +extern NSString * const MASKeychainStorageKeyPrivateKeyBits; +extern NSString * const MASKeychainStorageKeyPublicKey; +extern NSString * const MASKeychainStorageKeyTrustedServerCertificate; +extern NSString * const MASKeychainStorageKeySignedPublicCertificate; +extern NSString * const MASKeychainStorageKeyPublicCertificateData; +extern NSString * const MASKeychainStorageKeyPublicCertificateExpirationDate; +extern NSString * const MASKeychainStorageKeyAuthenticatedTimestamp; +extern NSString * const MASKeychainStorageKeyIsDeviceLocked; +extern NSString * const MASKeychainStorageKeyCurrentAuthCredentialsGrantType; +extern NSString * const MASKeychainStorageKeyMASUserObjectData; +extern NSString * const MASKeychainStorageKeyDeviceVendorId; /** @@ -133,6 +128,10 @@ typedef NS_ENUM(NSInteger, MASAccessValueType) +///-------------------------------------- +/// @name MASAccess object +///-------------------------------------- + # pragma mark - MASAccess object /** @@ -145,9 +144,11 @@ typedef NS_ENUM(NSInteger, MASAccessValueType) -# pragma mark - Storage methods - +///-------------------------------------- +/// @name Storage methods +///-------------------------------------- +# pragma mark - Storage methods /** * Retrieve list of identities in keychain @@ -162,41 +163,65 @@ typedef NS_ENUM(NSInteger, MASAccessValueType) * Store the certificate as data format into keychain * * @param certificate NSData form of certificate - * @param type MASAccessValueType enum specifying the value key + * @param storageKey NSString value for the data key */ -- (void)setAccessValueCertificate:(NSData *)certificate withAccessValueType:(MASAccessValueType)type; +- (void)setAccessValueCertificate:(NSData *)certificate storageKey:(NSString *)storageKey; /** * Retrieve the certificate data by the value key * - * @param type MASAccessValueType enum value for key + * @param storageKey NSString value for the data key * * @return Certificate value by the specified value key */ -- (id)getAccessValueCertificateWithType:(MASAccessValueType)type; +- (id)getAccessValueCertificateWithStorageKey:(NSString *)storageKey; /** - * Store NSData of access value into keychain - * - * @param data NSData to store into keychain - * @param type MASAccessValueType enum value for the value key + Store NSData of access value into keychain + + @param data NSData to be stored into keychain + @param storageKey NSString value for the data key + @return BOOL result of operation */ -- (void)setAccessValueData:(NSData *)data withAccessValueType:(MASAccessValueType)type; +- (BOOL)setAccessValueData:(NSData *)data storageKey:(NSString *)storageKey; + + + +/** + Store NSData of access value into keychain + + @param data NSData to be stored into keychain + @param storageKey NSString value for the data key + @param error NSError reference object to notify if there is any error while keychain operation + @return BOOL result of operation + */ +- (BOOL)setAccessValueData:(NSData *)data storageKey:(NSString *)storageKey error:(NSError **)error; /** * Retrieve NSData of access value from keychain * - * @param type MASAccessValueType enum value for the value key + * @param storageKey NSString value for the data key * * @return NSData of the access data by the specified value key */ -- (NSData *)getAccessValueDataWithType:(MASAccessValueType)type; +- (NSData *)getAccessValueDataWithStorageKey:(NSString *)storageKey; + + + +/** + Retrieve NSData of access value from keychain + + @param storageKey NSString value for the data key + @param error NSError reference object to notify if there is any error while keychain operation + @return NSData of the access data by the specified value key + */ +- (NSData *)getAccessValueDataWithStorageKey:(NSString *)storageKey error:(NSError **)error; @@ -204,20 +229,44 @@ typedef NS_ENUM(NSInteger, MASAccessValueType) * Store NSString of access value into keychain * * @param string NSString to store into keychain - * @param type MASAccessValueType enum value for the value key + * @param storageKey NSString value for the data key + * @return BOOL result of operation */ -- (void)setAccessValueString:(NSString *)string withAccessValueType:(MASAccessValueType)type; +- (BOOL)setAccessValueString:(NSString *)string storageKey:(NSString *)storageKey; + + + +/** + Store NSString of access value into keychain + + @param string NSString to store into keychain + @param storageKey NSString value for the data key + @param error NSError reference object to notify if there is any error while keychain operation + @return BOOL result of operation + */ +- (BOOL)setAccessValueString:(NSString *)string storageKey:(NSString *)storageKey error:(NSError **)error; /** * Retrieve NSString of access value from keychain * - * @param type MASAccessValueType enum value for the value key + * @param storageKey NSString value for the data key * * @return NSString of the access data by the specified value key */ -- (NSString *)getAccessValueStringWithType:(MASAccessValueType)type; +- (NSString *)getAccessValueStringWithStorageKey:(NSString *)storageKey; + + + +/** + Retrieve NSString of access value from keychain + + @param storageKey NSString value for the data key + @param error NSError reference object to notify if there is any error while keychain operation + @return NSString of the access data by the specified value key + */ +- (NSString *)getAccessValueStringWithStorageKey:(NSString *)storageKey error:(NSError **)error; @@ -225,20 +274,20 @@ typedef NS_ENUM(NSInteger, MASAccessValueType) * Store NSDictionary of access value into keychain * * @param dictionary NSDictionary to store into keychain - * @param type MASAccessValueType enum value for the value key + * @param storageKey NSString value for the data key */ -- (void)setAccessValueDictionary:(NSDictionary *)dictionary withAccessValueType:(MASAccessValueType)type; +- (BOOL)setAccessValueDictionary:(NSDictionary *)dictionary storageKey:(NSString *)storageKey; /** * Retrieve NSDictionary of access value from keychain * - * @param type MASAccessValueType enum value for the value key + * @param storageKey NSString value for the data key * * @return NSDictionary of the access data by the specified value key */ -- (NSDictionary *)getAccessValueDictionaryWithType:(MASAccessValueType)type; +- (NSDictionary *)getAccessValueDictionaryWithStorageKey:(NSString *)storageKey; @@ -246,20 +295,20 @@ typedef NS_ENUM(NSInteger, MASAccessValueType) * Store NSNumber of access value into keychain * * @param number NSNumber to store into keychain - * @param type MASAccessValueType enum value for the value key + * @param storageKey NSString value for the data key */ -- (void)setAccessValueNumber:(NSNumber *)number withAccessValueType:(MASAccessValueType)type; +- (BOOL)setAccessValueNumber:(NSNumber *)number storageKey:(NSString *)storageKey; /** * Retrieve NSNumber of access value from keychain * - * @param type MASAccessValueType enum value for the value key + * @param storageKey NSString value for the data key * * @return NSNumber of the access data by the specified value key */ -- (NSNumber *)getAccessValueNumberWithType:(MASAccessValueType)type; +- (NSNumber *)getAccessValueNumberWithStorageKey:(NSString *)storageKey; @@ -271,9 +320,9 @@ typedef NS_ENUM(NSInteger, MASAccessValueType) * Other access type value will not be stored. * * @param cryptoKey SecKeyRef to store into keychain - * @param type MASAccessValueType enum value for the value key + * @param storageKey NSString value for the data key */ -- (void)setAccessValueCryptoKey:(SecKeyRef)cryptoKey withAccessValueType:(MASAccessValueType)type; +- (void)setAccessValueCryptoKey:(SecKeyRef)cryptoKey storageKey:(NSString *)storageKey; @@ -284,12 +333,27 @@ typedef NS_ENUM(NSInteger, MASAccessValueType) * MASAccessValueTypePublicKey and MASAccessValueTypePrivateKey. * Other access type value will not be retrieved. * - * @param type MASAccessValueType enum value for the value key + * @param storageKey NSString value for the data key * * @return SecKeyRef of the access data by the specified value key */ -- (SecKeyRef)getAccessValueCryptoKeyWithType:(MASAccessValueType)type; +- (SecKeyRef)getAccessValueCryptoKeyWithStorageKey:(NSString *)storageKey; + + + +/** + Deletes keychain storage item based on storage key + + @param storageKey NSString of storage key. + @param error NSError object reference. + */ +- (void)deleteForStorageKey:(NSString *)storageKey error:(NSError **)error; + + +///-------------------------------------- +/// @name Public +///-------------------------------------- # pragma mark - Public @@ -303,6 +367,8 @@ typedef NS_ENUM(NSInteger, MASAccessValueType) */ + (BOOL)validateIdToken:(NSString *)idToken magIdentifier:(NSString *)magIdentifier error:(NSError *__autoreleasing *)error; + + /** * Validate the expiration date in id_token * @@ -313,6 +379,13 @@ typedef NS_ENUM(NSInteger, MASAccessValueType) + (BOOL)isIdTokenExpired:(NSString *)idToken error:(NSError *__autoreleasing *)error; + +/** + Extracts the expiration date from the SecCertificateRef + + @param certificate SecCertificateRef of the certificate + @return NSDate of the expiration date from SecCertificateRef + */ - (NSDate *)extractExpirationDateFromCertificate:(SecCertificateRef)certificate; @@ -328,7 +401,6 @@ typedef NS_ENUM(NSInteger, MASAccessValueType) - /** Unlock id_token, access_token, and refresh_token from secure keychain storage protected by device's local authentication (passcode and/or fingerprint) @@ -348,6 +420,16 @@ typedef NS_ENUM(NSInteger, MASAccessValueType) +/** + Internal method to determine whether the key is reserved for internal system data or not + + @param storageKey NSString of key to be stored + @return BOOL result of whether the key is reserved or not by internal system data + */ +- (BOOL)isInternalDataForStorageKey:(NSString *)storageKey; + + + # pragma mark - Debug only - (void)clearLocal; diff --git a/MASFoundation/Classes/_private_/services/access/MASAccessService.m b/MASFoundation/Classes/_private_/services/access/MASAccessService.m index a03e0d4b..cedf6246 100644 --- a/MASFoundation/Classes/_private_/services/access/MASAccessService.m +++ b/MASFoundation/Classes/_private_/services/access/MASAccessService.m @@ -25,9 +25,43 @@ static NSString *const kMASAccessSharedStorageKey = @"sharedStorage"; static NSString *const kMASAccessLocalStorageKey = @"localStorage"; +static NSString *const kMASAccessCustomSharedStorageKey = @"customSharedStorage"; static NSString *const kMASAccessIsNotFreshInstallFlag = @"isNotFreshInstall"; +# pragma mark - Keychain Storage Key + +NSString * const MASKeychainStorageKeyConfiguration = @"kMASKeyChainConfiguration"; +NSString * const MASKeychainStorageKeyAccessToken = @"kMASKeyChainAccessToken"; +NSString * const MASKeychainStorageKeyAuthenticatedUserObjectId = @"MASAccessValueTypeAuthenticatedUserObjectId"; +NSString * const MASKeychainStorageKeyRefreshToken = @"kMASKeyChainRefreshToken"; +NSString * const MASKeychainStorageKeyScope = @"kMASKeyChainScope"; +NSString * const MASKeychainStorageKeyTokenType = @"kMASKeyChainTokenType"; +NSString * const MASKeychainStorageKeyExpiresIn = @"kMASKeyChainExpiresIn"; +NSString * const MASKeychainStorageKeyTokenExpiration = @"kMASKeyChainTokenExpiration"; +NSString * const MASKeychainStorageKeySecuredIdToken = @"kMASKeyChainSecuredIdToken"; +NSString * const MASKeychainStorageKeyIdToken = @"kMASKeyChainIdToken"; +NSString * const MASKeychainStorageKeyIdTokenType = @"kMASKeyChainIdTokenType"; +NSString * const MASKeychainStorageKeyClientExpiration = @"kMASKeyChainClientExpiration"; +NSString * const MASKeychainStorageKeyClientId = @"kMASKeyChainClientId"; +NSString * const MASKeychainStorageKeyClientSecret = @"kMASKeyChainClientSecret"; +NSString * const MASKeychainStorageKeyJWT = @"kMASKeyChainJwt"; +NSString * const MASKeychainStorageKeyMAGIdentifier = @"kMASKeyChainMagIdentifier"; +NSString * const MASKeychainStorageKeyMSSOEnabled = @"kMASAccessValueTypeMSSOEnabled"; +NSString * const MASKeychainStorageKeyPrivateKey = @"kMASKeyChainPrivateKey"; +NSString * const MASKeychainStorageKeyPrivateKeyBits = @"kMASKeyChainPrivateKeyBits"; +NSString * const MASKeychainStorageKeyPublicKey = @"kMASKeyChainPublicKey"; +NSString * const MASKeychainStorageKeyTrustedServerCertificate = @"kMASKeyChainTrustedServerCertificate"; +NSString * const MASKeychainStorageKeySignedPublicCertificate = @"kMASKeyChainSignedPublicCertificate"; +NSString * const MASKeychainStorageKeyPublicCertificateData = @"kMASKeyChainSignedPublicCertificateData"; +NSString * const MASKeychainStorageKeyPublicCertificateExpirationDate = @"kMASAccessValueTypeSignedPublicCertificateExpirationDate"; +NSString * const MASKeychainStorageKeyAuthenticatedTimestamp = @"kMASAccessValueTypeAuthenticatedTimestamp"; +NSString * const MASKeychainStorageKeyIsDeviceLocked = @"kMASAccessValueTypeIsDeviceLocked"; +NSString * const MASKeychainStorageKeyCurrentAuthCredentialsGrantType = @"kMASAccessValueTypeCurrentAuthCredentialsGrantType"; +NSString * const MASKeychainStorageKeyMASUserObjectData = @"kMASAccessValueTypeMASUserObjectData"; +NSString * const MASKeychainStorageKeyDeviceVendorId = @"kMASKeyChainDeviceVendorId"; + + @interface MASAccessService () # pragma mark - Properties @@ -36,12 +70,17 @@ @interface MASAccessService () @property (strong, nonatomic, readwrite) NSString *sharedStorageServiceName; @property (strong, nonatomic, readwrite) NSString *localStorageServiceName; +@property (strong, nonatomic, readwrite) NSString *customSharedStorageServiceName; @property (strong, nonatomic, readwrite) NSString *gatewayHostName; @property (strong, nonatomic, readwrite) NSString *gatewayIdentifier; @property (assign) BOOL isSharedKeychainEnabled; +@property (strong, nonatomic, readwrite) NSArray *sharedStorageKeys; +@property (strong, nonatomic, readwrite) NSArray *localStorageKeys; +@property (strong, nonatomic, readwrite) NSArray *secureStorageKeys; + @end @@ -102,13 +141,54 @@ + (NSString *)serviceUUID - (void)serviceDidLoad { - [super serviceDidLoad]; } - (void)serviceWillStart { + // + // Define a list of keys for secured storage + // + _secureStorageKeys = @[MASKeychainStorageKeySecuredIdToken]; + + // + // Define a list of keys to be stored in local keychain storage + // + _localStorageKeys = @[MASKeychainStorageKeyConfiguration, + MASKeychainStorageKeyAccessToken, + MASKeychainStorageKeyRefreshToken, + MASKeychainStorageKeyScope, + MASKeychainStorageKeyTokenType, + MASKeychainStorageKeyExpiresIn, + MASKeychainStorageKeyTokenExpiration, + MASKeychainStorageKeyClientExpiration, + MASKeychainStorageKeyClientId, + MASKeychainStorageKeyClientSecret, + MASKeychainStorageKeyAuthenticatedTimestamp]; + + // + // Define a list of keys to be stored in shared keychain storage + // + _sharedStorageKeys = @[MASKeychainStorageKeyAuthenticatedUserObjectId, + MASKeychainStorageKeySecuredIdToken, + MASKeychainStorageKeyIdToken, + MASKeychainStorageKeyIdTokenType, + MASKeychainStorageKeyJWT, + MASKeychainStorageKeyMAGIdentifier, + MASKeychainStorageKeyMSSOEnabled, + MASKeychainStorageKeyPrivateKey, + MASKeychainStorageKeyPrivateKeyBits, + MASKeychainStorageKeyPublicKey, + MASKeychainStorageKeyTrustedServerCertificate, + MASKeychainStorageKeySignedPublicCertificate, + MASKeychainStorageKeyPublicCertificateData, + MASKeychainStorageKeyPublicCertificateExpirationDate, + MASKeychainStorageKeyCurrentAuthCredentialsGrantType, + MASKeychainStorageKeyIsDeviceLocked, + MASKeychainStorageKeyMASUserObjectData, + MASKeychainStorageKeyDeviceVendorId]; + // // Retrieve gatewayUrl which is combination of hostname, port number, and prefix of the gateway. // The gatewayUrl can be unique identifier for each server. @@ -116,8 +196,14 @@ - (void)serviceWillStart _gatewayIdentifier = [MASConfiguration currentConfiguration].gatewayUrl.absoluteString; _localStorageServiceName = [NSString stringWithFormat:@"%@.%@", _gatewayIdentifier, kMASAccessLocalStorageServiceName]; - _sharedStorageServiceName = [NSString stringWithFormat:@"%@.%@", _gatewayIdentifier, kMASAccessSharedStorageServiceName]; + _customSharedStorageServiceName = [NSString stringWithFormat:@"MAS.%@", kMASAccessCustomSharedStorageKey]; + + // + // Custom shared storage + // + MASIKeyChainStore *customSharedStorage = [MASIKeyChainStore keyChainStoreWithService:_customSharedStorageServiceName accessGroup:self.accessGroup]; + customSharedStorage.synchronizable = _isKeychainSynchronizable_; // // Local storage @@ -136,13 +222,13 @@ - (void)serviceWillStart // // storage dictionary property // - _storages = [NSDictionary dictionaryWithObjectsAndKeys:localStorage, kMASAccessLocalStorageKey, sharedStorage, kMASAccessSharedStorageKey, nil]; + _storages = [NSDictionary dictionaryWithObjectsAndKeys:localStorage, kMASAccessLocalStorageKey, sharedStorage, kMASAccessSharedStorageKey, customSharedStorage, kMASAccessCustomSharedStorageKey, nil]; } else { // // storage dictionary property // - _storages = [NSDictionary dictionaryWithObjectsAndKeys:localStorage, kMASAccessLocalStorageKey, localStorage, kMASAccessSharedStorageKey, nil]; + _storages = [NSDictionary dictionaryWithObjectsAndKeys:localStorage, kMASAccessLocalStorageKey, localStorage, kMASAccessSharedStorageKey, customSharedStorage, kMASAccessCustomSharedStorageKey, nil]; } @@ -215,7 +301,7 @@ - (void)saveAccessValuesWithDictionary:(NSDictionary *)dictionary forceToOverwri // // if the user chooses to overwite whatever SDK contains with the provided dictionary, reset the object // - if(forceToOverwrite) + if (forceToOverwrite) { [_currentAccessObj reset]; _currentAccessObj = nil; @@ -240,11 +326,22 @@ - (void)saveAccessValuesWithDictionary:(NSDictionary *)dictionary forceToOverwri # pragma mark - Storage methods -- (void)setAccessValueCertificate:(NSData *)certificate withAccessValueType:(MASAccessValueType)type +- (id)getAccessValueIdentities +{ + //DLog(@"\n\ncalled\n\n"); + + MASIKeyChainStore *keychainStore = [MASIKeyChainStore keyChainStore]; + NSArray *identities = [keychainStore identitiesWithCertificateLabel:[self convertKeyString:MASKeychainStorageKeySignedPublicCertificate]]; + + return identities; +} + + +- (void)setAccessValueCertificate:(NSData *)certificate storageKey:(NSString *)storageKey { - NSString *storageKey = [self getStorageKeyWithAccessValueType:type]; - NSString *accessValueAsString = [self convertAccessTypeToString:type]; - MASIKeyChainStore *destinationStorage = _storages[storageKey]; + NSString *storageType = [self getStorageTypeWithKey:storageKey]; + NSString *accessValueAsString = [self convertKeyString:storageKey]; + MASIKeyChainStore *destinationStorage = _storages[storageType]; NSData * certData = nil; @@ -269,35 +366,31 @@ - (void)setAccessValueCertificate:(NSData *)certificate withAccessValueType:(MAS } -- (id)getAccessValueCertificateWithType:(MASAccessValueType)type +- (id)getAccessValueCertificateWithStorageKey:(NSString *)storageKey { - NSString *storageKey = [self getStorageKeyWithAccessValueType:type]; - NSString *accessValueAsString = [self convertAccessTypeToString:type]; - MASIKeyChainStore *destinationStorage = _storages[storageKey]; + NSString *storageType = [self getStorageTypeWithKey:storageKey]; + NSString *accessValueAsString = [self convertKeyString:storageKey]; + MASIKeyChainStore *destinationStorage = _storages[storageType]; return [destinationStorage certificateForKey:accessValueAsString]; } -- (id)getAccessValueIdentities +- (BOOL)setAccessValueData:(NSData *)data storageKey:(NSString *)storageKey { - //DLog(@"\n\ncalled\n\n"); - - MASIKeyChainStore *keychainStore = [MASIKeyChainStore keyChainStore]; - NSArray *identities = [keychainStore identitiesWithCertificateLabel:[self convertAccessTypeToString:MASAccessValueTypeSignedPublicCertificate]]; - - return identities; + return [self setAccessValueData:data storageKey:storageKey error:nil]; } -- (void)setAccessValueData:(NSData *)data withAccessValueType:(MASAccessValueType)type +- (BOOL)setAccessValueData:(NSData *)data storageKey:(NSString *)storageKey error:(NSError **)error { + NSString *storageType = [self getStorageTypeWithKey:storageKey]; + NSString *accessValueAsString = [self convertKeyString:storageKey]; + MASIKeyChainStore *destinationStorage = _storages[storageType]; + NSError *operationError = nil; - NSString *storageKey = [self getStorageKeyWithAccessValueType:type]; - NSString *accessValueAsString = [self convertAccessTypeToString:type]; - MASIKeyChainStore *destinationStorage = _storages[storageKey]; - - BOOL isSecuredData = [self isSecuredData:type]; + BOOL isSecuredData = [self isSecureData:storageKey]; + BOOL result = NO; if (isSecuredData) { @@ -309,50 +402,70 @@ - (void)setAccessValueData:(NSData *)data withAccessValueType:(MASAccessValueTyp // if (data) { - [destinationStorage setData:data forKey:accessValueAsString]; + result = [destinationStorage setData:data forKey:accessValueAsString error:&operationError]; } // // Removal // else { - [destinationStorage removeItemForKey:accessValueAsString]; + result = [destinationStorage removeItemForKey:accessValueAsString error:&operationError]; } if (isSecuredData) { [destinationStorage setAccessibility:MASIKeyChainStoreAccessibilityAfterFirstUnlock authenticationPolicy:0]; } + + if (error) + { + *error = operationError; + } + + return result; +} + + +- (NSData *)getAccessValueDataWithStorageKey:(NSString *)storageKey +{ + return [self getAccessValueDataWithStorageKey:storageKey error:nil]; } -- (NSData *)getAccessValueDataWithType:(MASAccessValueType)type +- (NSData *)getAccessValueDataWithStorageKey:(NSString *)storageKey error:(NSError **)error { + NSString *storageType = [self getStorageTypeWithKey:storageKey]; + NSString *accessValueAsString = [self convertKeyString:storageKey]; + MASIKeyChainStore *destinationStorage = _storages[storageType]; + NSError *operationError = nil; - NSString *storageKey = [self getStorageKeyWithAccessValueType:type]; - NSString *accessValueAsString = [self convertAccessTypeToString:type]; - MASIKeyChainStore *destinationStorage = _storages[storageKey]; + NSData *keychainData = [destinationStorage dataForKey:accessValueAsString error:&operationError]; + + if (error) + { + *error = operationError; + } - NSData *keychainData = [destinationStorage dataForKey:accessValueAsString]; - return keychainData; } -- (void)setAccessValueString:(NSString *)string withAccessValueType:(MASAccessValueType)type +- (BOOL)setAccessValueString:(NSString *)string storageKey:(NSString *)storageKey { - [self setAccessValueString:string withAccessValueType:type error:nil]; + return [self setAccessValueString:string storageKey:storageKey error:nil]; } -- (BOOL)setAccessValueString:(NSString *)string withAccessValueType:(MASAccessValueType)type error:(NSError * __nullable __autoreleasing * __nullable)error +- (BOOL)setAccessValueString:(NSString *)string storageKey:(NSString *)storageKey error:(NSError **)error { - NSString *storageKey = [self getStorageKeyWithAccessValueType:type]; - NSString *accessValueAsString = [self convertAccessTypeToString:type]; - MASIKeyChainStore *destinationStorage = _storages[storageKey]; + NSString *storageType = [self getStorageTypeWithKey:storageKey]; + NSString *accessValueAsString = [self convertKeyString:storageKey]; + MASIKeyChainStore *destinationStorage = _storages[storageType]; + NSError *operationError = nil; - BOOL isSecuredData = [self isSecuredData:type]; + BOOL result = NO; + BOOL isSecuredData = [self isSecureData:storageKey]; if (isSecuredData) { @@ -364,14 +477,14 @@ - (BOOL)setAccessValueString:(NSString *)string withAccessValueType:(MASAccessVa // if (string) { - [destinationStorage setString:string forKey:accessValueAsString error:error]; + result = [destinationStorage setString:string forKey:accessValueAsString error:&operationError]; } // // Removal // else { - [destinationStorage removeItemForKey:accessValueAsString error:error]; + result = [destinationStorage removeItemForKey:accessValueAsString error:&operationError]; } if (isSecuredData) @@ -381,70 +494,82 @@ - (BOOL)setAccessValueString:(NSString *)string withAccessValueType:(MASAccessVa if (error) { - return NO; - } - else { - return YES; + *error = operationError; } + + return result; } -- (NSString *)getAccessValueStringWithType:(MASAccessValueType)type +- (NSString *)getAccessValueStringWithStorageKey:(NSString *)storageKey { - - return [self getAccessValueStringWithType:type error:nil]; + return [self getAccessValueStringWithStorageKey:storageKey error:nil]; } -- (NSString *)getAccessValueStringWithType:(MASAccessValueType)type userOperationPrompt:(NSString *)userOperationPrompt error:(NSError * __nullable __autoreleasing * __nullable)error +- (NSString *)getAccessValueStringWithStorageKey:(NSString *)storageKey userOperationPrompt:(NSString *)userOperationPrompt error:(NSError **)error { - NSString *storageKey = [self getStorageKeyWithAccessValueType:type]; - NSString *accessValueAsString = [self convertAccessTypeToString:type]; - MASIKeyChainStore *destinationStorage = _storages[storageKey]; + NSString *storageType = [self getStorageTypeWithKey:storageKey]; + NSString *accessValueAsString = [self convertKeyString:storageKey]; + MASIKeyChainStore *destinationStorage = _storages[storageType]; + NSError *operationError = nil; - NSString *securedString = [destinationStorage stringForKey:accessValueAsString userOperationPrompt:userOperationPrompt error:error]; + NSString *securedString = [destinationStorage stringForKey:accessValueAsString userOperationPrompt:userOperationPrompt error:&operationError]; + + if (error) + { + *error = operationError; + } return securedString; } -- (NSString *)getAccessValueStringWithType:(MASAccessValueType)type error:(NSError * __nullable __autoreleasing * __nullable)error +- (NSString *)getAccessValueStringWithStorageKey:(NSString *)storageKey error:(NSError **)error { + NSString *storageType = [self getStorageTypeWithKey:storageKey]; + NSString *accessValueAsString = [self convertKeyString:storageKey]; + MASIKeyChainStore *destinationStorage = _storages[storageType]; + NSError *operationError = nil; - NSString *storageKey = [self getStorageKeyWithAccessValueType:type]; - NSString *accessValueAsString = [self convertAccessTypeToString:type]; - MASIKeyChainStore *destinationStorage = _storages[storageKey]; + NSString *securedString = [destinationStorage stringForKey:accessValueAsString error:&operationError]; - NSString *securedString = [destinationStorage stringForKey:accessValueAsString error:error]; + if (error) + { + *error = operationError; + } return securedString; } -- (void)setAccessValueDictionary:(NSDictionary *)dictionary withAccessValueType:(MASAccessValueType)type +- (BOOL)setAccessValueDictionary:(NSDictionary *)dictionary storageKey:(NSString *)storageKey { // // convert dictionary to data // NSData *thisData = [NSKeyedArchiver archivedDataWithRootObject:dictionary]; + BOOL result = NO; // // make sure the data exists // - if(thisData) + if (thisData) { - [self setAccessValueData:thisData withAccessValueType:type]; + result = [self setAccessValueData:thisData storageKey:storageKey]; } + + return result; } -- (NSDictionary *)getAccessValueDictionaryWithType:(MASAccessValueType)type +- (NSDictionary *)getAccessValueDictionaryWithStorageKey:(NSString *)storageKey { // // get data from keychain as NSData first // - NSData *thisData = [self getAccessValueDataWithType:type]; + NSData *thisData = [self getAccessValueDataWithStorageKey:storageKey]; // // return nil if NSData is nil @@ -453,28 +578,31 @@ - (NSDictionary *)getAccessValueDictionaryWithType:(MASAccessValueType)type } -- (void)setAccessValueNumber:(NSNumber *)number withAccessValueType:(MASAccessValueType)type +- (BOOL)setAccessValueNumber:(NSNumber *)number storageKey:(NSString *)storageKey { // convert dictionary to data // NSData *thisData = [NSKeyedArchiver archivedDataWithRootObject:number]; + BOOL result = NO; // // make sure the data exists // - if(thisData) + if (thisData) { - [self setAccessValueData:thisData withAccessValueType:type]; + result = [self setAccessValueData:thisData storageKey:storageKey]; } + + return result; } -- (NSNumber *)getAccessValueNumberWithType:(MASAccessValueType)type +- (NSNumber *)getAccessValueNumberWithStorageKey:(NSString *)storageKey { // // get data from keychain as NSData first // - NSData *thisData = [self getAccessValueDataWithType:type]; + NSData *thisData = [self getAccessValueDataWithStorageKey:storageKey]; // // return nil if NSData is nil @@ -483,19 +611,20 @@ - (NSNumber *)getAccessValueNumberWithType:(MASAccessValueType)type } -- (void)setAccessValueCryptoKey:(SecKeyRef)cryptoKey withAccessValueType:(MASAccessValueType)type +- (void)setAccessValueCryptoKey:(SecKeyRef)cryptoKey storageKey:(NSString *)storageKey { - NSString *storageKey = [self getStorageKeyWithAccessValueType:type]; + NSString *storageType = [self getStorageTypeWithKey:storageKey]; - MASIKeyChainStore *destinationStorage = _storages[storageKey]; + MASIKeyChainStore *destinationStorage = _storages[storageType]; NSString *keyIdentifierStr = nil; - if (type == MASAccessValueTypePublicKey) + + if ([storageKey isEqualToString:MASKeychainStorageKeyPublicKey]) { keyIdentifierStr = [NSString stringWithFormat:@"%@.%@", [MASConfiguration currentConfiguration].gatewayUrl.absoluteString, @"publicKey"]; } - else if (type == MASAccessValueTypePrivateKey) + else if ([storageKey isEqualToString:MASKeychainStorageKeyPrivateKey]) { keyIdentifierStr = [NSString stringWithFormat:@"%@.%@", [MASConfiguration currentConfiguration].gatewayUrl.absoluteString, @"privateKey"]; } @@ -510,20 +639,20 @@ - (void)setAccessValueCryptoKey:(SecKeyRef)cryptoKey withAccessValueType:(MASAcc } -- (SecKeyRef)getAccessValueCryptoKeyWithType:(MASAccessValueType)type +- (SecKeyRef)getAccessValueCryptoKeyWithStorageKey:(NSString *)storageKey { - NSString *storageKey = [self getStorageKeyWithAccessValueType:type]; - MASIKeyChainStore *destinationStorage = _storages[storageKey]; + NSString *storageType = [self getStorageTypeWithKey:storageKey]; + MASIKeyChainStore *destinationStorage = _storages[storageType]; NSString *keyIdentifierStr = nil; - if (type == MASAccessValueTypePublicKey) + if ([storageKey isEqualToString:MASKeychainStorageKeyPublicKey]) { keyIdentifierStr = [NSString stringWithFormat:@"%@.%@", [MASConfiguration currentConfiguration].gatewayUrl.absoluteString, @"publicKey"]; } - else if (type == MASAccessValueTypePrivateKey) + else if ([storageKey isEqualToString:MASKeychainStorageKeyPrivateKey]) { keyIdentifierStr = [NSString stringWithFormat:@"%@.%@", [MASConfiguration currentConfiguration].gatewayUrl.absoluteString, @"privateKey"]; } @@ -542,9 +671,26 @@ - (SecKeyRef)getAccessValueCryptoKeyWithType:(MASAccessValueType)type } +- (void)deleteForStorageKey:(NSString *)storageKey error:(NSError **)error +{ + NSString *storageType = [self getStorageTypeWithKey:storageKey]; + NSString *accessValueAsString = [self convertKeyString:storageKey]; + MASIKeyChainStore *destinationStorage = _storages[storageType]; + + NSError *operationError = nil; + + [destinationStorage removeItemForKey:accessValueAsString error:&operationError]; + + if (operationError && error) + { + *error = operationError; + } +} + + #pragma mark - Private -+ (NSString *)padding: (NSString *) encodedString{ ++ (NSString *)padding:(NSString *)encodedString{ unsigned long lengthtRequired = (int)(4 * ceil((float)[encodedString length] / 4.0)); long numPaddings = lengthtRequired - [encodedString length]; @@ -562,6 +708,7 @@ + (NSString *)padding: (NSString *) encodedString{ return encodedString; } + + (NSDictionary *)getIdTokenSegments:(NSString *)idToken error:(NSError *__autoreleasing *)error { NSDictionary *segmentsDict = nil; @@ -598,6 +745,7 @@ + (NSDictionary *)getIdTokenSegments:(NSString *)idToken error:(NSError *__autor return segmentsDict; } + + (NSDictionary *)unwrap:(NSString *)data { NSDictionary *dictionary = nil; @@ -615,284 +763,59 @@ + (NSDictionary *)unwrap:(NSString *)data return dictionary; } -- (BOOL)isSecuredData:(MASAccessValueType)type + +- (NSString *)convertKeyString:(NSString *)key { - BOOL isSecuredData = NO; + NSString *accessTypeToString = nil; - switch (type) { - case MASAccessValueTypeSecuredIdToken: - isSecuredData = YES; - break; + // + // Internal system data + // + if ([_sharedStorageKeys containsObject:key] || [_localStorageKeys containsObject:key]) + { + accessTypeToString = [NSString stringWithFormat:@"%@.%@", _gatewayIdentifier, key]; - default: - isSecuredData = NO; - break; + // + // When access gruop is not accessiable, differentiate the key to make sure there is no conflict of device registration record in the future + // + if (![self isAccessGroupAccessible]) + { + accessTypeToString = [NSString stringWithFormat:@"_%@", accessTypeToString]; + } + } + // + // External custom data in shared keychain storage + // + else { + accessTypeToString = key; } - return isSecuredData; + return accessTypeToString; } -- (NSString *)getStorageKeyWithAccessValueType:(MASAccessValueType)type +- (BOOL)isSecureData:(NSString *)key { - NSString *storageKey = @""; - - switch (type) { - //Configuration - case MASAccessValueTypeConfiguration: - storageKey = kMASAccessLocalStorageKey; - break; - //AccessToken - case MASAccessValueTypeAccessToken: - storageKey = kMASAccessLocalStorageKey; - break; - //Authenticated username - case MASAccessValueTypeAuthenticatedUserObjectId: - storageKey = kMASAccessSharedStorageKey; - break; - //RefreshToken - case MASAccessValueTypeRefreshToken: - storageKey = kMASAccessLocalStorageKey; - break; - //Scope - case MASAccessValueTypeScope: - storageKey = kMASAccessLocalStorageKey; - break; - //TokenType - case MASAccessValueTypeTokenType: - storageKey = kMASAccessLocalStorageKey; - break; - //ExpiresIn - case MASAccessValueTypeExpiresIn: - storageKey = kMASAccessLocalStorageKey; - break; - //TokenExpiration - case MASAccessValueTypeTokenExpiration: - storageKey = kMASAccessLocalStorageKey; - break; - //IdToken with secured local authentication - case MASAccessValueTypeSecuredIdToken: - storageKey = kMASAccessSharedStorageKey; - break; - //IdToken - case MASAccessValueTypeIdToken: - storageKey = kMASAccessSharedStorageKey; - break; - //IdTokenType - case MASAccessValueTypeIdTokenType: - storageKey = kMASAccessSharedStorageKey; - break; - //ClientExpiration - case MASAccessValueTypeClientExpiration: - storageKey = kMASAccessLocalStorageKey; - break; - //ClientId - case MASAccessValueTypeClientId: - storageKey = kMASAccessLocalStorageKey; - break; - //ClientSecret - case MASAccessValueTypeClientSecret: - storageKey = kMASAccessLocalStorageKey; - break; - //JWT - case MASAccessValueTypeJWT: - storageKey = kMASAccessSharedStorageKey; - break; - //MAGIdentifier - case MASAccessValueTypeMAGIdentifier: - storageKey = kMASAccessSharedStorageKey; - break; - case MASAccessValueTypeMSSOEnabled: - storageKey = kMASAccessSharedStorageKey; - break; - //PrivateKey - case MASAccessValueTypePrivateKey: - storageKey = kMASAccessSharedStorageKey; - break; - case MASAccessValueTypePrivateKeyBits: - storageKey = kMASAccessSharedStorageKey; - break; - //PublicKey - case MASAccessValueTypePublicKey: - storageKey = kMASAccessSharedStorageKey; - break; - //TrustedServerCertificate - case MASAccessValueTypeTrustedServerCertificate: - storageKey = kMASAccessSharedStorageKey; - break; - //PublicCertificate - case MASAccessValueTypeSignedPublicCertificate: - storageKey = kMASAccessSharedStorageKey; - break; - //PublicCertificate as NSData - case MASAccessValueTypeSignedPublicCertificateData: - storageKey = kMASAccessSharedStorageKey; - break; - //PublicCertificate Expiration Date - case MASAccessValueTypeSignedPublicCertificateExpirationDate: - storageKey = kMASAccessSharedStorageKey; - break; - //authentication timestamp - case MASAccessValueTypeAuthenticatedTimestamp: - storageKey = kMASAccessLocalStorageKey; - break; - case MASAccessValueTypeCurrentAuthCredentialsGrantType: - storageKey = kMASAccessSharedStorageKey; - break; - case MASAccessValueTypeIsDeviceLocked: - storageKey = kMASAccessSharedStorageKey; - break; - case MASAccessValueTypeMASUserObjectData: - storageKey = kMASAccessSharedStorageKey; - break; - case MASAccessValueTypeDeviceVendorId: - storageKey = kMASAccessSharedStorageKey; - break; - default: - // - // MASAccessValueTypeUknonw - // - break; - } - - return storageKey; + return [_secureStorageKeys containsObject:key]; } -- (NSString *)convertAccessTypeToString:(MASAccessValueType)type +- (NSString *)getStorageTypeWithKey:(NSString *)key { - - NSString *accessTypeToString = @""; - - switch (type) { - //Configuration - case MASAccessValueTypeConfiguration: - accessTypeToString = [NSString stringWithFormat:@"%@.%@", _gatewayIdentifier, @"kMASKeyChainConfiguration"]; - break; - //AccessToken - case MASAccessValueTypeAccessToken: - accessTypeToString = [NSString stringWithFormat:@"%@.%@", _gatewayIdentifier, @"kMASKeyChainAccessToken"]; - break; - //Authenticated username - case MASAccessValueTypeAuthenticatedUserObjectId: - accessTypeToString = [NSString stringWithFormat:@"%@.%@", _gatewayIdentifier, @"MASAccessValueTypeAuthenticatedUserObjectId"]; - break; - //RefreshToken - case MASAccessValueTypeRefreshToken: - accessTypeToString = [NSString stringWithFormat:@"%@.%@", _gatewayIdentifier, @"kMASKeyChainRefreshToken"]; - break; - //Scope - case MASAccessValueTypeScope: - accessTypeToString = [NSString stringWithFormat:@"%@.%@", _gatewayIdentifier, @"kMASKeyChainScope"]; - break; - //TokenType - case MASAccessValueTypeTokenType: - accessTypeToString = [NSString stringWithFormat:@"%@.%@", _gatewayIdentifier, @"kMASKeyChainTokenType"]; - break; - //ExpiresIn - case MASAccessValueTypeExpiresIn: - accessTypeToString = [NSString stringWithFormat:@"%@.%@", _gatewayIdentifier, @"kMASKeyChainExpiresIn"]; - break; - //TokenExpiration - case MASAccessValueTypeTokenExpiration: - accessTypeToString = [NSString stringWithFormat:@"%@.%@", _gatewayIdentifier, @"kMASKeyChainTokenExpiration"]; - break; - //IdToken with secured local authentication - case MASAccessValueTypeSecuredIdToken: - accessTypeToString = [NSString stringWithFormat:@"%@.%@", _gatewayIdentifier, @"kMASKeyChainSecuredIdToken"]; - break; - //IdToken - case MASAccessValueTypeIdToken: - accessTypeToString = [NSString stringWithFormat:@"%@.%@", _gatewayIdentifier, @"kMASKeyChainIdToken"]; - break; - //IdTokenType - case MASAccessValueTypeIdTokenType: - accessTypeToString = [NSString stringWithFormat:@"%@.%@", _gatewayIdentifier, @"kMASKeyChainIdTokenType"]; - break; - //ClientExpiration - case MASAccessValueTypeClientExpiration: - accessTypeToString = [NSString stringWithFormat:@"%@.%@", _gatewayIdentifier, @"kMASKeyChainClientExpiration"]; - break; - //ClientId - case MASAccessValueTypeClientId: - accessTypeToString = [NSString stringWithFormat:@"%@.%@", _gatewayIdentifier, @"kMASKeyChainClientId"]; - break; - //ClientSecret - case MASAccessValueTypeClientSecret: - accessTypeToString = [NSString stringWithFormat:@"%@.%@", _gatewayIdentifier, @"kMASKeyChainClientSecret"]; - break; - //JWT - case MASAccessValueTypeJWT: - accessTypeToString = [NSString stringWithFormat:@"%@.%@", _gatewayIdentifier, @"kMASKeyChainJwt"]; - break; - //MAGIdentifier - case MASAccessValueTypeMAGIdentifier: - accessTypeToString = [NSString stringWithFormat:@"%@.%@", _gatewayIdentifier, @"kMASKeyChainMagIdentifier"]; - break; - case MASAccessValueTypeMSSOEnabled: - accessTypeToString = [NSString stringWithFormat:@"%@.%@", _gatewayIdentifier, @"kMASAccessValueTypeMSSOEnabled"]; - break; - //PrivateKey - case MASAccessValueTypePrivateKey: - accessTypeToString = [NSString stringWithFormat:@"%@.%@", _gatewayIdentifier, @"kMASKeyChainPrivateKey"]; - break; - //PrivateKeyBits - case MASAccessValueTypePrivateKeyBits: - accessTypeToString = [NSString stringWithFormat:@"%@.%@", _gatewayIdentifier, @"kMASKeyChainPrivateKeyBits"]; - break; - //PublicKey - case MASAccessValueTypePublicKey: - accessTypeToString = [NSString stringWithFormat:@"%@.%@", _gatewayIdentifier, @"kMASKeyChainPublicKey"]; - break; - //TrustedServerCertificate - case MASAccessValueTypeTrustedServerCertificate: - accessTypeToString = [NSString stringWithFormat:@"%@.%@", _gatewayIdentifier, @"kMASKeyChainTrustedServerCertificate"]; - break; - //PublicCertificate - case MASAccessValueTypeSignedPublicCertificate: - accessTypeToString = [NSString stringWithFormat:@"%@.%@", _gatewayIdentifier, @"kMASKeyChainSignedPublicCertificate"]; - break; - //PublicCertificate as NSData - case MASAccessValueTypeSignedPublicCertificateData: - accessTypeToString = [NSString stringWithFormat:@"%@.%@", _gatewayIdentifier, @"kMASKeyChainSignedPublicCertificateData"]; - break; - //PublicCertificate Expiration Date - case MASAccessValueTypeSignedPublicCertificateExpirationDate: - accessTypeToString = [NSString stringWithFormat:@"%@.%@", _gatewayIdentifier, @"kMASAccessValueTypeSignedPublicCertificateExpirationDate"]; - break; - //AuthenticatedTimestamp - case MASAccessValueTypeAuthenticatedTimestamp: - accessTypeToString = [NSString stringWithFormat:@"%@.%@", _gatewayIdentifier, @"kMASAccessValueTypeAuthenticatedTimestamp"]; - break; - //IsDeviceLocked: - case MASAccessValueTypeIsDeviceLocked: - accessTypeToString = [NSString stringWithFormat:@"%@.%@", _gatewayIdentifier, @"kMASAccessValueTypeIsDeviceLocked"]; - break; - //CurrentAuthCredentialsGrantType - case MASAccessValueTypeCurrentAuthCredentialsGrantType: - accessTypeToString = [NSString stringWithFormat:@"%@.%@", _gatewayIdentifier, @"kMASAccessValueTypeCurrentAuthCredentialsGrantType"]; - break; - //MASUserObjectData - case MASAccessValueTypeMASUserObjectData: - accessTypeToString = [NSString stringWithFormat:@"%@.%@", _gatewayHostName, @"kMASAccessValueTypeMASUserObjectData"]; - break; - //DeviceVendorId - case MASAccessValueTypeDeviceVendorId: - accessTypeToString = [NSString stringWithFormat:@"%@.%@", _gatewayHostName, @"kMASKeyChainDeviceVendorId"]; - break; - default: - // - // MASAccessValueTypeUknonw - // - break; + if ([_sharedStorageKeys containsObject:key]) + { + return kMASAccessSharedStorageKey; } - - if (![self isAccessGroupAccessible]) + else if ([_localStorageKeys containsObject:key]) { - accessTypeToString = [NSString stringWithFormat:@"_%@", accessTypeToString]; + return kMASAccessLocalStorageKey; + } + // + // If the key is not defined in either of shared nor local storage, the key must be custom data which will always be stored in shared + // + else { + return kMASAccessCustomSharedStorageKey; } - - return accessTypeToString; } @@ -931,7 +854,7 @@ - (NSString *)accessGroup // // if accessGroup is not defined // - if(!_accessGroup) + if (!_accessGroup) { NSString *groupSuffix = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"MSSOSDKKeychainGroup"]; @@ -1034,7 +957,7 @@ - (BOOL)lockSession:(NSError * __nullable __autoreleasing * __nullable)error // if (!localError) { - [self setAccessValueString:idToken withAccessValueType:MASAccessValueTypeSecuredIdToken error:&localError]; + [self setAccessValueString:idToken storageKey:MASKeychainStorageKeySecuredIdToken error:&localError]; } } @@ -1048,7 +971,7 @@ - (BOOL)lockSession:(NSError * __nullable __autoreleasing * __nullable)error // if (![MASUser currentUser].isSessionLocked) { - [self setAccessValueString:nil withAccessValueType:MASAccessValueTypeSecuredIdToken]; + [self setAccessValueString:nil storageKey:MASKeychainStorageKeySecuredIdToken]; } if (error != NULL) @@ -1061,10 +984,10 @@ - (BOOL)lockSession:(NSError * __nullable __autoreleasing * __nullable)error // else { - [self setAccessValueString:nil withAccessValueType:MASAccessValueTypeAccessToken]; - [self setAccessValueString:nil withAccessValueType:MASAccessValueTypeRefreshToken]; - [self setAccessValueString:nil withAccessValueType:MASAccessValueTypeIdToken]; - [self setAccessValueNumber:[NSNumber numberWithBool:YES] withAccessValueType:MASAccessValueTypeIsDeviceLocked]; + [self setAccessValueString:nil storageKey:MASKeychainStorageKeyAccessToken]; + [self setAccessValueString:nil storageKey:MASKeychainStorageKeyRefreshToken]; + [self setAccessValueString:nil storageKey:MASKeychainStorageKeyIdToken]; + [self setAccessValueNumber:[NSNumber numberWithBool:YES] storageKey:MASKeychainStorageKeyIsDeviceLocked]; // // Refresh the currentAccessObj to reflect the current status @@ -1120,7 +1043,7 @@ - (BOOL)unlockSessionWithUserOperationPromptMessage:(NSString *)userOperationPro // if (!localError) { - idToken = [self getAccessValueStringWithType:MASAccessValueTypeSecuredIdToken userOperationPrompt:userOperationPrompt error:&localError]; + idToken = [self getAccessValueStringWithStorageKey:MASKeychainStorageKeySecuredIdToken userOperationPrompt:userOperationPrompt error:&localError]; } if (idToken) @@ -1129,7 +1052,7 @@ - (BOOL)unlockSessionWithUserOperationPromptMessage:(NSString *)userOperationPro // Validate id_token whether it is valid or not // BOOL isIdTokenValid = [MASAccessService validateIdToken:idToken - magIdentifier:[[MASAccessService sharedService] getAccessValueStringWithType:MASAccessValueTypeMAGIdentifier] + magIdentifier:[[MASAccessService sharedService] getAccessValueStringWithStorageKey:MASKeychainStorageKeyMAGIdentifier] error:&localError]; if (localError && localError.code != MASFoundationErrorCodeTokenIdTokenExpired) @@ -1151,9 +1074,9 @@ - (BOOL)unlockSessionWithUserOperationPromptMessage:(NSString *)userOperationPro // if (!localError) { - [self setAccessValueString:idToken withAccessValueType:MASAccessValueTypeIdToken]; - [self setAccessValueString:nil withAccessValueType:MASAccessValueTypeSecuredIdToken]; - [self setAccessValueNumber:[NSNumber numberWithBool:NO] withAccessValueType:MASAccessValueTypeIsDeviceLocked]; + [self setAccessValueString:idToken storageKey:MASKeychainStorageKeyIdToken]; + [self setAccessValueString:nil storageKey:MASKeychainStorageKeySecuredIdToken]; + [self setAccessValueNumber:[NSNumber numberWithBool:NO] storageKey:MASKeychainStorageKeyIsDeviceLocked]; // // Refresh the currentAccessObj to reflect the current status @@ -1175,8 +1098,8 @@ - (BOOL)unlockSessionWithUserOperationPromptMessage:(NSString *)userOperationPro - (void)removeSessionLock { - [self setAccessValueString:nil withAccessValueType:MASAccessValueTypeSecuredIdToken]; - [self setAccessValueNumber:[NSNumber numberWithBool:NO] withAccessValueType:MASAccessValueTypeIsDeviceLocked]; + [self setAccessValueString:nil storageKey:MASKeychainStorageKeySecuredIdToken]; + [self setAccessValueNumber:[NSNumber numberWithBool:NO] storageKey:MASKeychainStorageKeyIsDeviceLocked]; // // Refresh the currentAccessObj to reflect the current status @@ -1213,7 +1136,8 @@ + (BOOL)validateIdToken:(NSString *)idToken magIdentifier:(NSString *)magIdentif // NSDictionary *headerDisctionary = [MASAccessService unwrap:headerString]; - if ([[headerDisctionary objectForKey:@"alg"] isEqualToString:@"HS256"]){ + if ([[headerDisctionary objectForKey:@"alg"] isEqualToString:@"HS256"]) + { // // check signature @@ -1223,7 +1147,7 @@ + (BOOL)validateIdToken:(NSString *)idToken magIdentifier:(NSString *)magIdentif [signatureSegments addObject:payload]; NSString *signingInput = [signatureSegments componentsJoinedByString:@"."]; - NSString *clientSecret = [[MASAccessService sharedService] getAccessValueStringWithType:MASAccessValueTypeClientSecret]; + NSString *clientSecret = [[MASAccessService sharedService] getAccessValueStringWithStorageKey:MASKeychainStorageKeyClientSecret]; NSData *signedInput = [NSData sign:signingInput key:clientSecret]; NSString *encodedSignedInput = [signedInput base64Encoding]; @@ -1249,7 +1173,8 @@ + (BOOL)validateIdToken:(NSString *)idToken magIdentifier:(NSString *)magIdentif NSString *azp = [payloadDictionary valueForKey:@"azp"]; NSDate *exp = [NSDate dateWithTimeIntervalSince1970:[[payloadDictionary valueForKey:@"exp"] floatValue]]; - if (!aud || !azp || !exp){ + if (!aud || !azp || !exp) + { if (error) { @@ -1261,7 +1186,8 @@ + (BOOL)validateIdToken:(NSString *)idToken magIdentifier:(NSString *)magIdentif // // case 2: aud doesn't match with clientId // - if (![aud isEqualToString:[[MASAccessService sharedService] getAccessValueStringWithType:MASAccessValueTypeClientId]]){ + if (![aud isEqualToString:[[MASAccessService sharedService] getAccessValueStringWithStorageKey:MASKeychainStorageKeyClientId]]) + { if (error) { @@ -1273,7 +1199,8 @@ + (BOOL)validateIdToken:(NSString *)idToken magIdentifier:(NSString *)magIdentif // // case 3: azp doesn't match with mag-identifier // - if (![azp isEqualToString:magIdentifier]){ + if (![azp isEqualToString:magIdentifier]) + { if (error) { @@ -1285,7 +1212,8 @@ + (BOOL)validateIdToken:(NSString *)idToken magIdentifier:(NSString *)magIdentif // // case 4: JWT expired // - if ([exp timeIntervalSinceNow] < 0){ + if ([exp timeIntervalSinceNow] < 0) + { if (error) { @@ -1358,9 +1286,11 @@ - (NSDate *)extractExpirationDateFromCertificate:(SecCertificateRef)certificate if (certificateX509 != NULL) { ASN1_TIME *certificateExpiryASN1 = X509_get_notAfter(certificateX509); - if (certificateExpiryASN1 != NULL) { + if (certificateExpiryASN1 != NULL) + { ASN1_GENERALIZEDTIME *certificateExpiryASN1Generalized = ASN1_TIME_to_generalizedtime(certificateExpiryASN1, NULL); - if (certificateExpiryASN1Generalized != NULL) { + if (certificateExpiryASN1Generalized != NULL) + { unsigned char *certificateExpiryData = ASN1_STRING_data(certificateExpiryASN1Generalized); // ASN1 generalized times look like this: "20131114230046Z" @@ -1393,6 +1323,19 @@ - (NSDate *)extractExpirationDateFromCertificate:(SecCertificateRef)certificate } +- (BOOL)isInternalDataForStorageKey:(NSString *)storageKey +{ + BOOL isInternalData = NO; + + if ([_localStorageKeys containsObject:storageKey] || [_sharedStorageKeys containsObject:storageKey]) + { + isInternalData = YES; + } + + return isInternalData; +} + + # pragma mark - Debug only - (void)clearLocal @@ -1405,13 +1348,13 @@ - (void)clearLocal - (void)clearShared; { - [[MASAccessService sharedService] setAccessValueString:nil withAccessValueType:MASAccessValueTypeMAGIdentifier]; + [[MASAccessService sharedService] setAccessValueString:nil storageKey:MASKeychainStorageKeyMAGIdentifier]; [_storages[kMASAccessSharedStorageKey] removeAllItems]; // // Retrieve the key for certificate // - NSString *certificateKey = [self convertAccessTypeToString:MASAccessValueTypeSignedPublicCertificate]; + NSString *certificateKey = [self convertKeyString:MASKeychainStorageKeySignedPublicCertificate]; [[MASIKeyChainStore keyChainStore] clearCertificatesAndIdentitiesWithCertificateLabelKey:certificateKey]; // @@ -1431,7 +1374,7 @@ - (NSString *)debugSecuredDescription NSString *value = [NSString stringWithFormat:@"\n\n(MASAccessService)\n\n Local (%@):\n", kMASAccessLocalStorageServiceName]; NSMutableString *keychainDescription = [[NSMutableString alloc] initWithString:value]; - for(NSString *key in [_storages[kMASAccessLocalStorageKey] allKeys]) + for (NSString *key in [_storages[kMASAccessLocalStorageKey] allKeys]) { [keychainDescription appendString:[NSString stringWithFormat:@"\n key: %@", key]]; } @@ -1442,7 +1385,18 @@ - (NSString *)debugSecuredDescription value = [NSString stringWithFormat:@"\n\n Shared (%@):\n", kMASAccessSharedStorageServiceName]; [keychainDescription appendString:value]; - for(NSString *key in [_storages[kMASAccessSharedStorageKey] allKeys]) + for (NSString *key in [_storages[kMASAccessSharedStorageKey] allKeys]) + { + [keychainDescription appendString:[NSString stringWithFormat:@"\n key: %@", key]]; + } + + // + // Custom + // + value = [NSString stringWithFormat:@"\n\n Custom (%@):\n", kMASAccessCustomSharedStorageKey]; + [keychainDescription appendString:value]; + + for (NSString *key in [_storages[kMASAccessCustomSharedStorageKey] allKeys]) { [keychainDescription appendString:[NSString stringWithFormat:@"\n key: %@", key]]; } diff --git a/MASFoundation/Classes/_private_/services/model/MASModelService.h b/MASFoundation/Classes/_private_/services/model/MASModelService.h index 50b63377..d2c356cd 100644 --- a/MASFoundation/Classes/_private_/services/model/MASModelService.h +++ b/MASFoundation/Classes/_private_/services/model/MASModelService.h @@ -82,6 +82,25 @@ - (void)setUserObject:(MASUser *)user; + +/** + * Sets the browser based authentication property. Default is NO. + * + * @param browserBasedLogin The state of browser based authentication. + * If this is set to true, a URL which has a templatized login is launched in a browser and this would disable the Social Login, Proximity Login and also prevents the launch of MASUI. + */ ++ (void)setBrowserBasedAuthentication:(BOOL)browserBasedAuthentication; + + + +/** + * The current state of browser based login. + * + * @return BOOL value is returned. + */ ++ (BOOL)browserBasedAuthentication; + + ///-------------------------------------- /// @name Application ///-------------------------------------- diff --git a/MASFoundation/Classes/_private_/services/model/MASModelService.m b/MASFoundation/Classes/_private_/services/model/MASModelService.m index 0aa71154..205ce5e3 100644 --- a/MASFoundation/Classes/_private_/services/model/MASModelService.m +++ b/MASFoundation/Classes/_private_/services/model/MASModelService.m @@ -30,6 +30,7 @@ @interface MASModelService () @property (nonatomic, strong, readwrite) MASAuthenticationProviders *currentProviders; + @end @@ -38,8 +39,7 @@ @implementation MASModelService static MASGrantFlow _grantFlow_ = MASGrantFlowClientCredentials; static MASUserLoginWithUserCredentialsBlock _userLoginBlock_ = nil; static MASUserAuthCredentialsBlock _userAuthCredentialsBlock_ = nil; - - +static BOOL _isBrowserBasedAuthentication_ = NO; # pragma mark - Properties @@ -71,6 +71,19 @@ - (void)setUserObject:(MASUser *)user _currentUser = user; } + ++ (void)setBrowserBasedAuthentication : (BOOL)browserBasedAuthentication +{ + _isBrowserBasedAuthentication_ = browserBasedAuthentication; +} + + ++ (BOOL)browserBasedAuthentication +{ + return _isBrowserBasedAuthentication_; +} + + # pragma mark - Shared Service + (instancetype)sharedService @@ -155,9 +168,9 @@ - (void)serviceWillStart // if (![keychainApplication.identifier isEqualToString:_currentApplication.identifier]) { - [[MASAccessService sharedService] setAccessValueString:nil withAccessValueType:MASAccessValueTypeClientId]; - [[MASAccessService sharedService] setAccessValueString:nil withAccessValueType:MASAccessValueTypeClientSecret]; - [[MASAccessService sharedService] setAccessValueString:nil withAccessValueType:MASAccessValueTypeClientExpiration]; + [[MASAccessService sharedService] setAccessValueString:nil storageKey:MASKeychainStorageKeyClientId]; + [[MASAccessService sharedService] setAccessValueString:nil storageKey:MASKeychainStorageKeyClientSecret]; + [[MASAccessService sharedService] setAccessValueString:nil storageKey:MASKeychainStorageKeyClientExpiration]; [[MASModelService sharedService] clearCurrentUserForLogout]; } @@ -367,7 +380,7 @@ - (void)retrieveAuthenticationProviders:(MASObjectResponseErrorBlock)completion // // If the user was already authenticated, we don't have to retrieve the authentication provider // - if (([MASApplication currentApplication].isAuthenticated && [MASApplication currentApplication].authenticationStatus == MASAuthenticationStatusLoginWithUser) || [MASAccess currentAccess].isSessionLocked) + if (([MASApplication currentApplication].isAuthenticated && [MASApplication currentApplication].authenticationStatus == MASAuthenticationStatusLoginWithUser) || [MASAccess currentAccess].isSessionLocked || _isBrowserBasedAuthentication_) { // @@ -396,7 +409,7 @@ - (void)retrieveAuthenticationProviders:(MASObjectResponseErrorBlock)completion MASIMutableOrderedDictionary *parameterInfo = [MASIMutableOrderedDictionary new]; // ClientId - parameterInfo[MASClientKeyRequestResponseKey] = [[MASAccessService sharedService] getAccessValueStringWithType:MASAccessValueTypeClientId]; + parameterInfo[MASClientKeyRequestResponseKey] = [[MASAccessService sharedService] getAccessValueStringWithStorageKey:MASKeychainStorageKeyClientId]; // RedirectUri parameterInfo[MASRedirectUriRequestResponseKey] = [[MASApplication currentApplication].redirectUri absoluteString]; @@ -906,9 +919,15 @@ - (void)registerDeviceWithCompletion:(MASCompletionErrorBlock)completion @"\n\n********************************************************\n\n\n"); // - // If the UI handling framework is present and will handle this stop here + // If the UI handling framework or browser based login is present and will handle this stop here // MASServiceRegistry *serviceRegistry = [MASServiceRegistry sharedRegistry]; + + if([serviceRegistry browserBasedLoginWillHandleAuthentication:authCredentialsBlock]) + { + return; + } + if([serviceRegistry uiServiceWillHandleWithAuthCredentialsBlock:authCredentialsBlock]) { return; @@ -1308,9 +1327,9 @@ - (void)renewClientCertificateWithCompletion:(MASCompletionErrorBlock)completion // // Remove signed client certificate from the keychain storage // - [[MASAccessService sharedService] setAccessValueData:nil withAccessValueType:MASAccessValueTypeSignedPublicCertificateData]; - [[MASAccessService sharedService] setAccessValueCertificate:nil withAccessValueType:MASAccessValueTypeSignedPublicCertificate]; - [[MASAccessService sharedService] setAccessValueNumber:[NSNumber numberWithInt:0] withAccessValueType:MASAccessValueTypeSignedPublicCertificateExpirationDate]; + [[MASAccessService sharedService] setAccessValueData:nil storageKey:MASKeychainStorageKeyPublicCertificateData]; + [[MASAccessService sharedService] setAccessValueCertificate:nil storageKey:MASKeychainStorageKeySignedPublicCertificate]; + [[MASAccessService sharedService] setAccessValueNumber:[NSNumber numberWithInt:0] storageKey:MASKeychainStorageKeyPublicCertificateExpirationDate]; // // Remove device's client MASFile for re-generation @@ -1406,7 +1425,7 @@ - (void)logOutDeviceAndClearLocalAccessToken:(BOOL)clearLocal completion:(MASCom // // Detect if device is already logged out (which is basically checking if id_token exists), if so stop here // - if(![accessService getAccessValueStringWithType:MASAccessValueTypeIdToken]) + if(![accessService getAccessValueStringWithStorageKey:MASKeychainStorageKeyIdToken]) { // // Notify @@ -1444,14 +1463,14 @@ - (void)logOutDeviceAndClearLocalAccessToken:(BOOL)clearLocal completion:(MASCom parameterInfo[MASDeviceLogoutAppRequestResponseKey] = [MASConfiguration currentConfiguration].ssoEnabled ? @"true" : @"false"; // IdToken - NSString *idToken = [[MASAccessService sharedService] getAccessValueStringWithType:MASAccessValueTypeIdToken]; + NSString *idToken = [[MASAccessService sharedService] getAccessValueStringWithStorageKey:MASKeychainStorageKeyIdToken]; if (idToken) { parameterInfo[MASIdTokenBodyRequestResponseKey] = idToken; } // IdTokenType - NSString *idTokenType = [[MASAccessService sharedService] getAccessValueStringWithType:MASAccessValueTypeIdTokenType]; + NSString *idTokenType = [[MASAccessService sharedService] getAccessValueStringWithStorageKey:MASKeychainStorageKeyIdTokenType]; if (idTokenType) { parameterInfo[MASIdTokenTypeBodyRequestResponseKey]= idTokenType; @@ -1508,8 +1527,8 @@ - (void)logOutDeviceAndClearLocalAccessToken:(BOOL)clearLocal completion:(MASCom // // Set id_token and id_token_type to nil // - [[MASAccessService sharedService] setAccessValueString:nil withAccessValueType:MASAccessValueTypeIdToken]; - [[MASAccessService sharedService] setAccessValueString:nil withAccessValueType:MASAccessValueTypeIdTokenType]; + [[MASAccessService sharedService] setAccessValueString:nil storageKey:MASKeychainStorageKeyIdToken]; + [[MASAccessService sharedService] setAccessValueString:nil storageKey:MASKeychainStorageKeyIdTokenType]; [[MASAccessService sharedService].currentAccessObj refresh]; // @@ -1712,6 +1731,11 @@ - (void)loginUsingUserCredentials:(MASCompletionErrorBlock)completion // If the UI handling framework is present and will handle this stop here // MASServiceRegistry *serviceRegistry = [MASServiceRegistry sharedRegistry]; + if([serviceRegistry browserBasedLoginWillHandleAuthentication:authCredentialsBlock]) + { + return; + } + if([serviceRegistry uiServiceWillHandleWithAuthCredentialsBlock:authCredentialsBlock]) { return; @@ -1946,7 +1970,7 @@ - (void)loginAsRefreshTokenWithCompletion:(MASCompletionErrorBlock)completion if(clientAuthorization) headerInfo[MASAuthorizationRequestResponseKey] = clientAuthorization; // MAG Identifier - NSString *magIdentifier = [[MASAccessService sharedService] getAccessValueStringWithType:MASAccessValueTypeMAGIdentifier]; + NSString *magIdentifier = [[MASAccessService sharedService] getAccessValueStringWithStorageKey:MASKeychainStorageKeyMAGIdentifier]; if(magIdentifier) headerInfo[MASMagIdentifierRequestResponseKey] = magIdentifier; // @@ -2015,7 +2039,7 @@ - (void)loginAsRefreshTokenWithCompletion:(MASCompletionErrorBlock)completion // // If authenticate user with refresh_token, we should invalidate local refresh_token, and re-validate the user's session with alternative method. // - [[MASAccessService sharedService] setAccessValueString:nil withAccessValueType:MASAccessValueTypeRefreshToken]; + [[MASAccessService sharedService] setAccessValueString:nil storageKey:MASKeychainStorageKeyRefreshToken]; [[MASAccessService sharedService].currentAccessObj refresh]; [blockSelf validateCurrentUserSession:completion]; @@ -2039,7 +2063,7 @@ - (void)loginAsRefreshTokenWithCompletion:(MASCompletionErrorBlock)completion { NSError *idTokenValidationError = nil; BOOL isIdTokenValid = [MASAccessService validateIdToken:[bodayInfo objectForKey:MASIdTokenBodyRequestResponseKey] - magIdentifier:[[MASAccessService sharedService] getAccessValueStringWithType:MASAccessValueTypeMAGIdentifier] + magIdentifier:[[MASAccessService sharedService] getAccessValueStringWithStorageKey:MASKeychainStorageKeyMAGIdentifier] error:&idTokenValidationError]; if (!isIdTokenValid && idTokenValidationError) diff --git a/MASFoundation/Classes/_private_/services/network/MASNetworkingService.h b/MASFoundation/Classes/_private_/services/network/MASNetworkingService.h index 6653a47c..69fc55c1 100644 --- a/MASFoundation/Classes/_private_/services/network/MASNetworkingService.h +++ b/MASFoundation/Classes/_private_/services/network/MASNetworkingService.h @@ -9,10 +9,11 @@ // #import "MASService.h" - #import "MASConstantsPrivate.h" + #import "MASAuthValidationOperation.h" +typedef NSURLRequest* (^MASSessionDataTaskHTTPRedirectBlock)(NSURLSession *_Nonnull session, NSURLSessionTask *_Nonnull task, NSURLResponse * _Nonnull response, NSURLRequest *_Nonnull request); @interface MASNetworkingService : MASService @@ -26,6 +27,12 @@ @property (nonatomic, assign, readonly) MASGatewayMonitoringStatus monitoringStatus; +/** + Http redirection block. Set this block only if you want to handle the redirection coming from the original NSURLRequest. + */ +@property (nonatomic) MASSessionDataTaskHTTPRedirectBlock httpRedirectionBlock; + + /** Constructs, if not exist, the shared operation that validates current session's registration and authentication status diff --git a/MASFoundation/Classes/_private_/services/network/MASNetworkingService.m b/MASFoundation/Classes/_private_/services/network/MASNetworkingService.m index 209a8a61..d016e392 100644 --- a/MASFoundation/Classes/_private_/services/network/MASNetworkingService.m +++ b/MASFoundation/Classes/_private_/services/network/MASNetworkingService.m @@ -11,7 +11,6 @@ #import "MASNetworkingService.h" #import "MASAccessService.h" -#import "MASConstantsPrivate.h" #import "MASConfigurationService.h" #import "MASLocationService.h" #import "MASModelService.h" @@ -603,9 +602,9 @@ - (MASSessionDataTaskCompletionBlock)sessionDataTaskCompletionBlockWithEndPoint: // // Remove slave client_id and client_secret from keychain // - [[MASAccessService sharedService] setAccessValueString:nil withAccessValueType:MASAccessValueTypeClientId]; - [[MASAccessService sharedService] setAccessValueString:nil withAccessValueType:MASAccessValueTypeClientSecret]; - [[MASAccessService sharedService] setAccessValueString:nil withAccessValueType:MASAccessValueTypeClientExpiration]; + [[MASAccessService sharedService] setAccessValueString:nil storageKey:MASKeychainStorageKeyClientId]; + [[MASAccessService sharedService] setAccessValueString:nil storageKey:MASKeychainStorageKeyClientSecret]; + [[MASAccessService sharedService] setAccessValueString:nil storageKey:MASKeychainStorageKeyClientExpiration]; // // Remove access_token from keychain @@ -657,6 +656,7 @@ - (MASSessionDataTaskCompletionBlock)sessionDataTaskCompletionBlockWithEndPoint: } + - (BOOL)isMAGEndpoint:(NSString *)endpoint { BOOL isMAGEndpoint = NO; @@ -1273,6 +1273,11 @@ - (void)httpRequest:(NSString *)httpMethod endPoint:(NSString *)endPoint paramet // // Construct MASSessionDataTaskOperation with request, and completion block to handle any responsive re-authentication or re-registration. // + if(self.httpRedirectionBlock) + { + [_sessionManager setSessionDidReceiveHTTPRedirectBlock:self.httpRedirectionBlock]; + } + MASSessionDataTaskOperation *operation = [_sessionManager dataOperationWithRequest:request completionHandler:[self sessionDataTaskCompletionBlockWithEndPoint:endPoint parameters:parameterInfo @@ -1283,6 +1288,7 @@ - (void)httpRequest:(NSString *)httpMethod endPoint:(NSString *)endPoint paramet isPublic:isPublic completionBlock:blockCompletion]]; + if (![self isMAGEndpoint:endPoint]) { // diff --git a/MASFoundation/Classes/_private_/services/network/internal/MASSessionDataTaskOperation.m b/MASFoundation/Classes/_private_/services/network/internal/MASSessionDataTaskOperation.m index 371b3e13..0329c917 100644 --- a/MASFoundation/Classes/_private_/services/network/internal/MASSessionDataTaskOperation.m +++ b/MASFoundation/Classes/_private_/services/network/internal/MASSessionDataTaskOperation.m @@ -75,9 +75,9 @@ - (void)start { NSMutableDictionary *mutableHeader = [self.request.headerInfo mutableCopy]; - if (![[self.request.headerInfo allKeys] containsObject:MASMagIdentifierRequestResponseKey] && [MASDevice currentDevice].isRegistered && [[MASAccessService sharedService] getAccessValueStringWithType:MASAccessValueTypeMAGIdentifier]) + if (![[self.request.headerInfo allKeys] containsObject:MASMagIdentifierRequestResponseKey] && [MASDevice currentDevice].isRegistered && [[MASAccessService sharedService] getAccessValueStringWithStorageKey:MASKeychainStorageKeyMAGIdentifier]) { - [mutableHeader setObject:[[MASAccessService sharedService] getAccessValueStringWithType:MASAccessValueTypeMAGIdentifier] forKey:MASMagIdentifierRequestResponseKey]; + [mutableHeader setObject:[[MASAccessService sharedService] getAccessValueStringWithStorageKey:MASKeychainStorageKeyMAGIdentifier] forKey:MASMagIdentifierRequestResponseKey]; } if (![[self.request.headerInfo allKeys] containsObject:MASAuthorizationRequestResponseKey] && [MASAccessService sharedService].currentAccessObj.accessToken) diff --git a/MASFoundation/Classes/_private_/services/network/internal/MASURLSessionManager.h b/MASFoundation/Classes/_private_/services/network/internal/MASURLSessionManager.h index ad42a64c..139d8155 100644 --- a/MASFoundation/Classes/_private_/services/network/internal/MASURLSessionManager.h +++ b/MASFoundation/Classes/_private_/services/network/internal/MASURLSessionManager.h @@ -150,4 +150,12 @@ typedef void (^MASNetworkSessionDidFinishEventsForBackgroundURLSessionBlock)(NSU - (void)setSessionDidReceiveAuthenticationChallengeBlock:(NSURLSessionAuthChallengeDisposition (^)(NSURLSession *session, NSURLAuthenticationChallenge *challenge, NSURLCredential **credential))block; + +/** + Set code block of session level redirection for the current NSURLRequest object. + + @param block http redirection code block. + */ +- (void)setSessionDidReceiveHTTPRedirectBlock:(NSURLRequest* (^)(NSURLSession *session,NSURLSessionTask *task, NSURLResponse* response,NSURLRequest *request))block; + @end diff --git a/MASFoundation/Classes/_private_/services/network/internal/MASURLSessionManager.m b/MASFoundation/Classes/_private_/services/network/internal/MASURLSessionManager.m index 52f37c81..f35e4139 100644 --- a/MASFoundation/Classes/_private_/services/network/internal/MASURLSessionManager.m +++ b/MASFoundation/Classes/_private_/services/network/internal/MASURLSessionManager.m @@ -17,6 +17,7 @@ @interface MASURLSessionManager () +#import "MASConstants.h" + +/** + MASBrowserBasedAuthentication class is a helper class to utilize SFSafariViewController to launch a customized login template. + * This class will get the redirection to receive the authorization code to perform login. + */ +@interface MASBrowserBasedAuthentication : NSObject + +# pragma mark - Browser Based Authentication + +/** + * Retrieve the shared MASBrowserBasedAuthentication singleton. + * + * @return Returns the shared MASBrowserBasedAuthentication singleton. + */ ++ (instancetype)sharedInstance; + + + +/** + * Method to load the browser with a URL that loads a templatized login page. + * + * @param webLoginBlock completion MASCompletionErrorBlock that receives the results. + */ +- (void)loadWebLoginTemplate:(MASAuthCredentialsBlock)webLoginBlock; + +@end diff --git a/MASFoundation/Classes/models/MASBrowserBasedAuthentication.m b/MASFoundation/Classes/models/MASBrowserBasedAuthentication.m new file mode 100644 index 00000000..8a9b792b --- /dev/null +++ b/MASFoundation/Classes/models/MASBrowserBasedAuthentication.m @@ -0,0 +1,302 @@ +// +// MASBrowserBasedAuthentication.m +// MASFoundation +// +// Copyright (c) 2017 CA. All rights reserved. +// +// This software may be modified and distributed under the terms +// of the MIT license. See the LICENSE file for details. +// + +#import "MASAccessService.h" +#import "MASAuthorizationResponse.h" +#import "MASBrowserBasedAuthentication.h" +#import "MASConfigurationService.h" +#import "MASGetURLRequest.h" +#import "MASModelService.h" +#import "UIAlertController+MAS.h" +#import + +@interface MASBrowserBasedAuthentication () +{ + +} + +@property (nonatomic) SFSafariViewController *safariViewController; +@property (nonatomic) MASAuthCredentialsBlock webLoginCallBack; + +@end + +@implementation MASBrowserBasedAuthentication + +# pragma mark - Shared Service + ++ (instancetype)sharedInstance +{ + static id sharedInstance = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^ + { + sharedInstance = [[MASBrowserBasedAuthentication alloc] init]; + }); + + return sharedInstance; +} + + +- (void)loadWebLoginTemplate:(MASAuthCredentialsBlock)webLoginBlock +{ + self.webLoginCallBack = webLoginBlock; + MASModelService* service = [MASModelService sharedService]; + [[MASAuthorizationResponse sharedInstance] setDelegate:self]; + __block MASBrowserBasedAuthentication *blockSelf = self; + + // + // Try to register so that all the essential things are set up in that API call and we get a valid URL. If Application is already registered the API returns without doing any work. + // + [service registerApplication:^(BOOL completed, NSError *error) { + [blockSelf getURLForWebLogin]; + }]; +} + + +- (void)getURLForWebLogin +{ + // + // Headers + // + MASIMutableOrderedDictionary *headerInfo = [MASIMutableOrderedDictionary new]; + + // + // Parameters + // + MASIMutableOrderedDictionary *parameterInfo = [MASIMutableOrderedDictionary new]; + + // ClientId + parameterInfo[MASClientKeyRequestResponseKey] = [[MASAccessService sharedService] getAccessValueStringWithStorageKey:MASKeychainStorageKeyClientId]; + + // RedirectUri + parameterInfo[MASRedirectUriRequestResponseKey] = [[MASApplication currentApplication].redirectUri absoluteString]; + + // Scope + NSString *scope = [MASApplication currentApplication].scopeAsString; + + // + // Workaround - msso_register scope should NOT be used to retrieve authenticationProviders when it is going to be used to "authenticate" + // msso_register scope should only contain for device registration with authorizationCode. + // When the authroizationCode was granted with msso_register scope and used to retrieve the tokens, it will FAIL with unknown error from the server. + // + if (scope && [[MASDevice currentDevice] isRegistered]) + { + scope = [scope replaceStringWithRegexPattern:@"\\bmsso_register\\b" withString:@""]; + } + + // + // If sso is disabled, manually remove msso scope, as it will create id_token with msso scope + // + if (scope && ![MASConfiguration currentConfiguration].ssoEnabled) + { + scope = [scope replaceStringWithRegexPattern:@"\\bmsso\\b" withString:@""]; + } + + parameterInfo[MASScopeRequestResponseKey] = scope; + + // ResponseType + parameterInfo[MASRequestResponseTypeRequestResponseKey] = @"code"; + + // Display + parameterInfo[MASDisplayRequestResponseKey] = @"template"; + + // PKCE Support - generate code verifier + [[MASAccessService sharedService].currentAccessObj generateCodeVerifier]; + + // PKCE Support - generate state + [[MASAccessService sharedService].currentAccessObj generatePKCEState]; + + // Retrieve code verifier + NSString *codeVerifier = [[MASAccessService sharedService].currentAccessObj retrieveCodeVerifier]; + + // Retrieve state + NSString *pkceState = [[MASAccessService sharedService].currentAccessObj retrievePKCEState]; + + if (codeVerifier) + { + // SHA256 the code verifier and encode it with base64url + NSString *codeChallenge = [NSString base64URLWithNSData:[codeVerifier sha256Data]]; + + if (codeChallenge) + { + parameterInfo[MASPKCECodeChallengeRequestResponseKey] = codeChallenge; + // + // code_challenge_method should be S256 if the code challenge is hashed; + // + // Otherwise, make code_challenge = code_verifier, and send code_challenge_method as plan, MASPKCECodeChallengeMethodPlainKey + // + parameterInfo[MASPKCECodeChallengeMethodRequestResponseKey] = MASPKCECodeChallengeMethodSHA256Key; + + parameterInfo[MASPKCEStateRequestResponseKey] = pkceState; + } + } + + //Put the mag-identifier in the url as query parameter for the device to be identified + NSString* magIdentifier = [[MASAccessService sharedService] getAccessValueStringWithStorageKey:MASKeychainStorageKeyMAGIdentifier]; + + if(magIdentifier && magIdentifier.length > 0) + { + parameterInfo[MASMagIdentifierRequestResponseKey] = magIdentifier; + } + + // + // Endpoint + // + NSString *endPoint = [MASConfiguration currentConfiguration].authorizationEndpointPath; + + // + // preserve the redirection block that was set earlier + // + MASSessionDataTaskHTTPRedirectBlock previousRedirectionBlock = [[MASNetworkingService sharedService] httpRedirectionBlock]; + [[MASNetworkingService sharedService] setHttpRedirectionBlock:[self getRedirectionBlock]]; + __block MASBrowserBasedAuthentication *blockSelf = self; + + // + // This get request would result in a redirection which contains the actual URL to be loaded into browser and hence this would be canceled after the redirection + // + [[MASNetworkingService sharedService] getFrom:endPoint withParameters:parameterInfo andHeaders:headerInfo requestType:MASRequestResponseTypeWwwFormUrlEncoded responseType:MASRequestResponseTypeWwwFormUrlEncoded completion:^(NSDictionary* response, NSError* error){ + + // + // We expect this API to be cancelled in the redirection and hence the only acceptable error here is cancel.Any other error could mean an error for authenticaion itself. Hence cancel authorization. + // + if(error.code != NSURLErrorCancelled) + { + DLog(@"error occured in BBA error info: %@",error); + blockSelf.webLoginCallBack(nil, YES, nil); + return; + } + + [[MASNetworkingService sharedService] setHttpRedirectionBlock:previousRedirectionBlock]; + }]; +} + +- (MASSessionDataTaskHTTPRedirectBlock)getRedirectionBlock +{ + __block MASBrowserBasedAuthentication *blockSelf = self; + MASSessionDataTaskHTTPRedirectBlock redirectionBlock = ^(NSURLSession *session, NSURLSessionTask *task, NSURLResponse * response, NSURLRequest *request){ + NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response; + if(httpResponse.statusCode == 302 && [self isBBARedirection:task.originalRequest]) + { + DLog(@"all headers %@",httpResponse.allHeaderFields); + NSString* locationURL = [httpResponse.allHeaderFields objectForKey:@"Location"]; + NSURL* redirectURL = [NSURL URLWithString:locationURL]; + [task cancel]; + + if(![blockSelf redirectURLHasErrors:redirectURL]) + { + [blockSelf launchBrowserWithURL:redirectURL]; + } + else{ + blockSelf.webLoginCallBack(nil, YES, nil); + } + } + return request; + }; + + return redirectionBlock; +} + +- (BOOL)isBBARedirection:(NSURLRequest*)request +{ + if([request.URL.absoluteString containsString:[MASConfiguration currentConfiguration].authorizationEndpointPath] && [request.URL.absoluteString containsString:@"display=template"]) + { + return YES; + } + + return NO; +} + + +- (BOOL)redirectURLHasErrors :(NSURL*)redirectURL +{ + NSString* redirectURLString = redirectURL.absoluteString; + if([redirectURLString containsString:@"x-ca-err"] && [redirectURLString containsString:@"error"] && [redirectURLString containsString:@"error_description"]) + { + return YES; + } + return NO; +} + + +- (void)launchBrowserWithURL:(NSURL*)templatizedURL +{ + __block MASBrowserBasedAuthentication *blockSelf = self; + __weak __typeof__(self) weakSelf = self; + blockSelf.safariViewController = [[SFSafariViewController alloc] initWithURL:templatizedURL]; + blockSelf.safariViewController.delegate = weakSelf; + + dispatch_async(dispatch_get_main_queue(), ^{ + [UIAlertController rootViewController].modalTransitionStyle = UIModalTransitionStyleCoverVertical; + + [[UIAlertController rootViewController] presentViewController:blockSelf.safariViewController animated:YES + completion:^{ + + DLog(@"Successfully displayed login template"); + }]; + + return; + }); +} + + +#pragma mark - SafariViewController Delegates + +- (void)safariViewControllerDidFinish:(SFSafariViewController *)controller +{ + self.webLoginCallBack(nil, YES, ^(BOOL completed, NSError* error){ + if(error) + { + DLog(@"Browser cancel clicked"); + } + }); +} + + +#pragma mark - Authorization Response delegate + +- (void)didReceiveAuthorizationCode:(NSString *)code +{ + MASAuthCredentialsAuthorizationCode *authCredentials = [MASAuthCredentialsAuthorizationCode initWithAuthorizationCode:code]; + [[MASNetworkingService sharedService] setHttpRedirectionBlock:nil]; + + self.webLoginCallBack(authCredentials, NO, ^(BOOL completed, NSError* error){ + // + // In either success or error case dismiss the browser and just log the status. The caller would pass the error state/success back to user. + // + if(error) + { + DLog(@"successfully logged in"); + } + DLog(@"successfully logged in"); + [self dismissBrowser]; + }); +} + + +- (void)didReceiveError:(NSError *)error +{ + self.webLoginCallBack(nil, YES, ^(BOOL completed, NSError* error){ + if(error) + { + DLog(@"Did not receive Authorization code"); + } + }); +} + +#pragma mark - UI + +- (void)dismissBrowser +{ + dispatch_async(dispatch_get_main_queue(), ^{ + [[UIAlertController rootViewController] dismissViewControllerAnimated:YES completion:nil]; + }); +} + +@end diff --git a/MASFoundation/Classes/models/MASClaims.m b/MASFoundation/Classes/models/MASClaims.m index 2b5d550b..54557475 100644 --- a/MASFoundation/Classes/models/MASClaims.m +++ b/MASFoundation/Classes/models/MASClaims.m @@ -68,8 +68,8 @@ - (id)initPrivate // // Prepare iss // - NSString *magIdentifier = [[MASAccessService sharedService] getAccessValueStringWithType:MASAccessValueTypeMAGIdentifier]; - NSString *clientId = [[MASAccessService sharedService] getAccessValueStringWithType:MASAccessValueTypeClientId]; + NSString *magIdentifier = [[MASAccessService sharedService] getAccessValueStringWithStorageKey:MASKeychainStorageKeyMAGIdentifier]; + NSString *clientId = [[MASAccessService sharedService] getAccessValueStringWithStorageKey:MASKeychainStorageKeyClientId]; if (magIdentifier && clientId) { diff --git a/MASFoundation/Classes/models/MASConfiguration.h b/MASFoundation/Classes/models/MASConfiguration.h index 51d544be..8d4eafd8 100644 --- a/MASFoundation/Classes/models/MASConfiguration.h +++ b/MASFoundation/Classes/models/MASConfiguration.h @@ -174,13 +174,17 @@ # pragma mark - Security Configuration /** - Sets security measure for SSL pinning, and SSL validation for specified host in MASSecurityConfiguration object + Sets security measure for SSL pinning, and SSL validation for specified host in MASSecurityConfiguration object. + + @remark MASSecurityConfiguration must have valid host in NSURL object with port number (port number is mandatory), at least one pinning information (either certificates, or public key hashes), or trust public PKI. If public PKI is not trusted, and no pinning information is provided, it will fail to store the security configuration object, and eventually fail on evaluating SSL for requests. @warning Upon SDK initialization, [MASConfiguration currentConfiguration].gatewayUrl's MASSecurityConfiguration object will be overwritten. If primary gateway's security configuration has to be modified, ensure to set security configuration after SDK initialization. - @param securityConfiguration MASSecurityConfiguration object with host, and security measure configuration values. - */ -+ (void)setSecurityConfiguration:(MASSecurityConfiguration *_Nonnull)securityConfiguration; + @param securityConfiguration MASSecurityConfiguration object with host, and security measure configuration values + @param error NSError object reference to notify any error occurred while validating MASSecurityConfiguration + @return YES if security configuration was successfully set + */ ++ (BOOL)setSecurityConfiguration:(MASSecurityConfiguration *_Nonnull)securityConfiguration error:(NSError *__nullable __autoreleasing *__nullable)error; @@ -352,4 +356,19 @@ + (NSError *_Nullable)validateJSONConfiguration:(NSDictionary *_Nonnull)configuration; + +///-------------------------------------- +/// @name Deprecated +///-------------------------------------- + +# pragma mark - Deprecated + +/** + Sets security measure for SSL pinning, and SSL validation for specified host in MASSecurityConfiguration object + + @warning Upon SDK initialization, [MASConfiguration currentConfiguration].gatewayUrl's MASSecurityConfiguration object will be overwritten. If primary gateway's security configuration has to be modified, ensure to set security configuration after SDK initialization. + @param securityConfiguration MASSecurityConfiguration object with host, and security measure configuration values. + */ ++ (void)setSecurityConfiguration:(MASSecurityConfiguration *_Nonnull)securityConfiguration DEPRECATED_MSG_ATTRIBUTE("[MASConfiguration setSecurityConfiguration:] is deprecated. Use [MASConfiguration setSecurityConfiguration:error:] instead for better handling of error cases."); + @end diff --git a/MASFoundation/Classes/models/MASConfiguration.m b/MASFoundation/Classes/models/MASConfiguration.m index 29cea4b4..d9705c15 100644 --- a/MASFoundation/Classes/models/MASConfiguration.m +++ b/MASFoundation/Classes/models/MASConfiguration.m @@ -201,7 +201,7 @@ - (id)init - (id)initPrivate { self = [super init]; - if(self) + if (self) { } @@ -212,7 +212,7 @@ - (id)initPrivate - (id)initWithConfigurationInfo:(NSDictionary *)info { - if(self = [super init]) + if (self = [super init]) { _configurationInfo_ = info; @@ -232,7 +232,10 @@ - (void)initializeEndpointsFromInfo:(NSDictionary *)info // // If the dictionary already exists ignore the call // - if(_endpointKeysToPaths) return; + if (_endpointKeysToPaths) + { + return; + } // // Create the dictionary @@ -243,15 +246,21 @@ - (void)initializeEndpointsFromInfo:(NSDictionary *)info // OAuth Endpoints // NSDictionary *oauthInfo = _configurationInfo_[MASOAuthConfigurationKey]; - if(oauthInfo) + if (oauthInfo) { // System Endpoints NSDictionary *endpointsInfo = oauthInfo[MASSystemEndpointsConfigurationKey]; - if(endpointsInfo) [_endpointKeysToPaths addEntriesFromDictionary:endpointsInfo]; + if (endpointsInfo) + { + [_endpointKeysToPaths addEntriesFromDictionary:endpointsInfo]; + } // Protected Endpoints endpointsInfo = oauthInfo[MASProtectedEndpointsConfigurationKey]; - if(endpointsInfo) [_endpointKeysToPaths addEntriesFromDictionary:endpointsInfo]; + if (endpointsInfo) + { + [_endpointKeysToPaths addEntriesFromDictionary:endpointsInfo]; + } } @@ -259,22 +268,28 @@ - (void)initializeEndpointsFromInfo:(NSDictionary *)info // MAG Endpoints // NSDictionary *magInfo = _configurationInfo_[MASMAGConfigurationKey]; - if(magInfo) + if (magInfo) { // System Endpoints NSDictionary *endpointsInfo = magInfo[MASSystemEndpointsConfigurationKey]; - if(endpointsInfo) [_endpointKeysToPaths addEntriesFromDictionary:endpointsInfo]; + if (endpointsInfo) + { + [_endpointKeysToPaths addEntriesFromDictionary:endpointsInfo]; + } // Protected Endpoints endpointsInfo = magInfo[MASProtectedEndpointsConfigurationKey]; - if(endpointsInfo) [_endpointKeysToPaths addEntriesFromDictionary:endpointsInfo]; + if (endpointsInfo) + { + [_endpointKeysToPaths addEntriesFromDictionary:endpointsInfo]; + } } // // MAS Endpoints // NSDictionary *masInfo = _configurationInfo_[MASConfigurationKey]; - if(masInfo) + if (masInfo) { // // currently scim-path is configured as String, maybe later when it comes as dictionary change it @@ -282,14 +297,14 @@ - (void)initializeEndpointsFromInfo:(NSDictionary *)info //scim-path NSString *scimPathInfo = masInfo[MASScimPathEndpoint]; - if(scimPathInfo) + if (scimPathInfo) { [_endpointKeysToPaths addEntriesFromDictionary:@{MASScimPathEndpoint : scimPathInfo}]; } //storage-path NSString *storagePathInfo = masInfo[MASStoragePathEndpoint]; - if(scimPathInfo) + if (scimPathInfo) { [_endpointKeysToPaths addEntriesFromDictionary:@{MASStoragePathEndpoint : storagePathInfo}]; } @@ -299,8 +314,10 @@ - (void)initializeEndpointsFromInfo:(NSDictionary *)info // Custom Endpoints // NSDictionary *customInfo = _configurationInfo_[MASCustomConfigurationKey]; - if(customInfo) [_endpointKeysToPaths addEntriesFromDictionary:customInfo]; - + if (customInfo) + { + [_endpointKeysToPaths addEntriesFromDictionary:customInfo]; + } // // Temporary Hardcoded Endpoints @@ -322,7 +339,7 @@ + (MASConfiguration *)instanceFromStorage // Attempt to retrieve from keychain // NSData *data = [[MASIKeyChainStore keyChainStoreWithService:[MASConfiguration currentConfiguration].gatewayUrl.absoluteString] dataForKey:[MASConfiguration.class description]]; - if(data) + if (data) { configuration = (MASConfiguration *)[NSKeyedUnarchiver unarchiveObjectWithData:data]; } @@ -337,11 +354,11 @@ - (void)saveToStorage // Save to the keychain // NSData *data = [NSKeyedArchiver archivedDataWithRootObject:self]; - if(data) + if (data) { NSError *error; [[MASIKeyChainStore keyChainStoreWithService:[MASConfiguration currentConfiguration].gatewayUrl.absoluteString] setData:data forKey:[MASConfiguration.class description] error:&error]; - if(error) + if (error) { DLog(@"Error attempting to save data: %@", [error localizedDescription]); } @@ -365,13 +382,16 @@ - (void)encodeWithCoder:(NSCoder *)aCoder MASKeyChainService *keyChainService = [MASKeyChainService keyChainService]; // Configuration - if(_configurationInfo_) [keyChainService setConfiguration:_configurationInfo_]; + if (_configurationInfo_) + { + [keyChainService setConfiguration:_configurationInfo_]; + } } - (id)initWithCoder:(NSCoder *)aDecoder { - if(self = [super init]) + if (self = [super init]) { MASKeyChainService *keyChainService = [MASKeyChainService keyChainService]; @@ -386,9 +406,38 @@ - (id)initWithCoder:(NSCoder *)aDecoder } -+ (void)setSecurityConfiguration:(MASSecurityConfiguration *)securityConfiguration ++ (BOOL)setSecurityConfiguration:(MASSecurityConfiguration *)securityConfiguration error:(NSError **)error { + // + // Validate the NSURL host for security configuration. + // + if (!securityConfiguration.host || !securityConfiguration.host.port) + { + if (error) + { + *error = [NSError errorForFoundationCode:MASFoundationErrorCodeConfigurationInvalidHostForSecurityConfiguration errorDomain:MASFoundationErrorDomainLocal]; + } + + return NO; + } + + // + // Validate pinning information for the security configuration. + // At least one pinning information (certificates or public key hashes) should be defined, or public PKI should be trusted. + // + if (!securityConfiguration.trustPublicPKI && (!securityConfiguration.certificates || [securityConfiguration.certificates count]== 0) && (!securityConfiguration.publicKeyHashes || [securityConfiguration.publicKeyHashes count] == 0)) + { + if (error) + { + *error = [NSError errorForFoundationCode:MASFoundationErrorCodeConfigurationInvalidPinningInfoForSecurityConfiguration errorDomain:MASFoundationErrorDomainLocal]; + } + + return NO; + } + [MASConfigurationService setSecurityConfiguration:securityConfiguration]; + + return YES; } @@ -553,7 +602,7 @@ - (NSString *)gatewayHostName error:nil]; NSUInteger numberOfMatches = [regexToValidateIP numberOfMatchesInString:gatewayInfo[MASGatewayHostNameKey] options:0 range:NSMakeRange(0, [gatewayInfo[MASGatewayHostNameKey] length])]; - if(_systemVersionNumber_ < 9.0 && numberOfMatches != 1) + if (_systemVersionNumber_ < 9.0 && numberOfMatches != 1) { if (![MASDevice currentDevice].isRegistered) { @@ -774,7 +823,7 @@ - (BOOL)enabledTrustedPublicPKI - (BOOL)ssoEnabled { MASAccessService *accessService = [MASAccessService sharedService]; - NSString *ssoEnabledString = [accessService getAccessValueStringWithType:MASAccessValueTypeMSSOEnabled]; + NSString *ssoEnabledString = [accessService getAccessValueStringWithStorageKey:MASKeychainStorageKeyMSSOEnabled]; if (ssoEnabledString) { @@ -793,7 +842,7 @@ - (void)setSsoEnabled:(BOOL)ssoEnabled { MASAccessService *accessService = [MASAccessService sharedService]; - [accessService setAccessValueString:(ssoEnabled ? @"true":@"false") withAccessValueType:MASAccessValueTypeMSSOEnabled]; + [accessService setAccessValueString:(ssoEnabled ? @"true":@"false") storageKey:MASKeychainStorageKeyMSSOEnabled]; } @@ -882,7 +931,7 @@ - (NSString *)debugDescription NSMutableString *endpoints = [[NSMutableString alloc] initWithString:@"\n\n {\n"]; NSString *keyToEndpoint; - for(NSString *endpointKey in _endpointKeysToPaths) + for (NSString *endpointKey in _endpointKeysToPaths) { keyToEndpoint = [NSString stringWithFormat:@" %@ = %@\n", endpointKey, _endpointKeysToPaths[endpointKey]]; [endpoints appendString:keyToEndpoint]; @@ -904,13 +953,13 @@ - (NSString *)debugDescription - (NSDictionary *)defaultApplicationClientInfo { NSMutableArray *applicationClientInfoFound = [NSMutableArray new]; - for(NSDictionary *info in self.applicationClients) + for (NSDictionary *info in self.applicationClients) { [applicationClientInfoFound addObject:info]; } // Should there be two or more allowed in the list that meet that criteria? Can it happen? - if(applicationClientInfoFound.count > 1) + if (applicationClientInfoFound.count > 1) { DLog(@"Warning: found %ld iOS clients that are enabled, just choosing first in the list", (long)applicationClientInfoFound.count); @@ -981,4 +1030,12 @@ - (NSArray *)generateCertificatesFromPEM:(NSArray *)certificatesAsPEM return certificatesAsDER; } + +# pragma mark - Deprecated + ++ (void)setSecurityConfiguration:(MASSecurityConfiguration *)securityConfiguration +{ + [self setSecurityConfiguration:securityConfiguration error:nil]; +} + @end diff --git a/MASFoundation/Classes/models/MASDevice.m b/MASFoundation/Classes/models/MASDevice.m index ab9e1aee..2c1c1414 100644 --- a/MASFoundation/Classes/models/MASDevice.m +++ b/MASFoundation/Classes/models/MASDevice.m @@ -57,16 +57,16 @@ - (BOOL)isRegistered // MASAccessService *accessService = [MASAccessService sharedService]; - NSString *vendorIdFromKeychain = [accessService getAccessValueStringWithType:MASAccessValueTypeDeviceVendorId]; + NSString *vendorIdFromKeychain = [accessService getAccessValueStringWithStorageKey:MASKeychainStorageKeyDeviceVendorId]; NSString *vendorIdCurrent = [MASDevice deviceVendorId]; // // Check if the vendorId in Keychain macth with current vendorId // - if([vendorIdCurrent isEqualToString:vendorIdFromKeychain]) + if ([vendorIdCurrent isEqualToString:vendorIdFromKeychain]) { - NSString *magIdentifier = [accessService getAccessValueStringWithType:MASAccessValueTypeMAGIdentifier]; - NSData *certificateData = [accessService getAccessValueCertificateWithType:MASAccessValueTypeSignedPublicCertificate]; + NSString *magIdentifier = [accessService getAccessValueStringWithStorageKey:MASKeychainStorageKeyMAGIdentifier]; + NSData *certificateData = [accessService getAccessValueCertificateWithStorageKey:MASKeychainStorageKeySignedPublicCertificate]; _isRegistered = (magIdentifier && certificateData); } @@ -215,7 +215,7 @@ - (void)encodeWithCoder:(NSCoder *)aCoder - (id)initWithCoder:(NSCoder *)aDecoder { - if(self = [super initWithCoder:aDecoder]) + if (self = [super initWithCoder:aDecoder]) { [self setValue:[aDecoder decodeObjectForKey:MASDeviceIdentifierPropertyKey] forKey:@"identifier"]; [self setValue:[aDecoder decodeObjectForKey:MASDeviceNamePropertyKey] forKey:@"name"]; diff --git a/MASFoundation/Classes/models/MASSharedStorage.h b/MASFoundation/Classes/models/MASSharedStorage.h new file mode 100644 index 00000000..7b68d72c --- /dev/null +++ b/MASFoundation/Classes/models/MASSharedStorage.h @@ -0,0 +1,87 @@ +// +// MASSharedStorage.h +// MASFoundation +// +// Copyright (c) 2017 CA. All rights reserved. +// +// This software may be modified and distributed under the terms +// of the MIT license. See the LICENSE file for details. +// + +#import + + +/** + MASSharedStorage class is designed for developers to write, read, and delete NSString or NSData data into shared keychain storage, + so that multiple applications with same keychain sharing group in the same device can share data between applications. + + @warning *Important:* MASSharedStorage will not be available if MASFoundation framework is not initialized; the framework should be initialized prior to write/read/delete any data into MASSharedStorage. + */ +@interface MASSharedStorage : MASObject + + + +///-------------------------------------- +/// @name Public +///-------------------------------------- + +# pragma mark - Public + + +/** + Finds NSString data stored with the key from shared keychain storage. + + @param key NSString of the key used to store the NSString data + @param error NSError object reference that would notify if there was any error while retrieving the data + @return NSString of data found with the key + */ ++ (NSString *_Nullable)findStringUsingKey:(NSString *_Nonnull)key error:(NSError * __nullable __autoreleasing * __nullable)error; + + + +/** + Finds NSData object stored with the key from shared keychain storage. + + @param key NSString of the key used to store the NSData object + @param error NSError object reference that would notify if there was any error while retrieving the data + @return NSData of data found with the key + */ ++ (NSData *_Nullable)findDataUsingKey:(NSString *_Nonnull)key error:(NSError * __nullable __autoreleasing * __nullable)error; + + + +/** + Saves NSString data with the specified key into shared keychain storage. + Save method can also be used to delete the data from the shared keychain storage by passing nil in string parameter with the key. + + @param string NSString data to be stored + @param key NSString of the key used to store the NSString data + @param error NSError object reference that would notify if there was any error while storing the data + @return BOOL result of saving operation + */ ++ (BOOL)saveString:(NSString *_Nonnull)string key:(NSString *_Nonnull)key error:(NSError * __nullable __autoreleasing * __nullable)error; + + + +/** + Saves NSData object with the specified key into shared keychain storage. + Save method can also be used to delete the data from the shared keychain storage by passing nil in data parameter with the key. + + @param data NSData object to be stored + @param key NSString of the key used to store the NSData object + @param error NSError object reference that would notify if there was any error while storing the data + @return BOOL result of saving operation + */ ++ (BOOL)saveData:(NSData *_Nonnull)data key:(NSString *_Nonnull)key error:(NSError * __nullable __autoreleasing * __nullable)error; + + + +/** + Deletes any data type with the specified key from shared keychain storage. + + @param key NSString of the key used to store the data + @param error NSError object reference that would notify if there was any error while deleting the data + */ ++ (void)deleteForKey:(NSString *_Nonnull)key error:(NSError * __nullable __autoreleasing * __nullable)error; + +@end diff --git a/MASFoundation/Classes/models/MASSharedStorage.m b/MASFoundation/Classes/models/MASSharedStorage.m new file mode 100644 index 00000000..84a652e8 --- /dev/null +++ b/MASFoundation/Classes/models/MASSharedStorage.m @@ -0,0 +1,264 @@ +// +// MASSharedStorage.m +// MASFoundation +// +// Copyright (c) 2017 CA. All rights reserved. +// +// This software may be modified and distributed under the terms +// of the MIT license. See the LICENSE file for details. +// + +#import "MASSharedStorage.h" + +#import "MASAccessService.h" +#import "MASConstantsPrivate.h" + +@implementation MASSharedStorage + ++ (NSString *)findStringUsingKey:(NSString *)key error:(NSError **)error +{ + // + // Check if SDK was initialized + // + if ([MAS MASState] != MASStateDidStart) + { + if (error) + { + *error = [NSError errorMASIsNotStarted]; + } + + return nil; + } + + // + // Check for data key + // + if (key == nil || [key length] <= 0) + { + if (error) + { + *error = [NSError errorForFoundationCode:MASFoundationErrorCodeSharedStorageNotNilKey errorDomain:MASFoundationErrorDomainLocal]; + } + + return nil; + } + + // + // Retrieve NSString from shared keychain storage + // + NSError *operationError = nil; + NSString *resultString = [[MASAccessService sharedService] getAccessValueStringWithStorageKey:[NSString stringWithFormat:@"%@.%@", MASSharedStorageCustomPrefix, key] error:&operationError]; + + // + // If an error occurred while keychain operation, convert it into MASFoundationErrorDomainLocal error object + // + if (operationError) + { + NSError *thisError = [NSError errorWithDomain:MASFoundationErrorDomainLocal code:operationError.code userInfo:@{NSLocalizedDescriptionKey : operationError.localizedDescription}]; + + if (error) + { + *error = thisError; + } + } + + return resultString; +} + + ++ (NSData *)findDataUsingKey:(NSString *)key error:(NSError **)error +{ + // + // Check if SDK was initialized + // + if ([MAS MASState] != MASStateDidStart) + { + if (error) + { + *error = [NSError errorMASIsNotStarted]; + } + + return nil; + } + + // + // Check for data key + // + if (key == nil || [key length] <= 0) + { + if (error) + { + *error = [NSError errorForFoundationCode:MASFoundationErrorCodeSharedStorageNotNilKey errorDomain:MASFoundationErrorDomainLocal]; + } + + return nil; + } + + // + // Retrieve NSData from shared keychain storage + // + NSError *operationError = nil; + NSData *resultData = [[MASAccessService sharedService] getAccessValueDataWithStorageKey:[NSString stringWithFormat:@"%@.%@", MASSharedStorageCustomPrefix, key] error:&operationError]; + + // + // If an error occurred while keychain operation, convert it into MASFoundationErrorDomainLocal error object + // + if (operationError) + { + NSError *thisError = [NSError errorWithDomain:MASFoundationErrorDomainLocal code:operationError.code userInfo:@{NSLocalizedDescriptionKey : operationError.localizedDescription}]; + + if (error) + { + *error = thisError; + } + } + + return resultData; +} + + ++ (BOOL)saveString:(NSString *)string key:(NSString *)key error:(NSError **)error +{ + // + // Check if SDK was initialized + // + if ([MAS MASState] != MASStateDidStart) + { + if (error) + { + *error = [NSError errorMASIsNotStarted]; + } + + return NO; + } + + // + // Check for data key + // + if (key == nil || [key length] <= 0) + { + if (error) + { + *error = [NSError errorForFoundationCode:MASFoundationErrorCodeSharedStorageNotNilKey errorDomain:MASFoundationErrorDomainLocal]; + } + + return NO; + } + + // + // Store NSString into shared keychain storage + // + NSError *operationError = nil; + BOOL result = [[MASAccessService sharedService] setAccessValueString:string storageKey:[NSString stringWithFormat:@"%@.%@", MASSharedStorageCustomPrefix, key] error:&operationError]; + + // + // If an error occurred while keychain operation, convert it into MASFoundationErrorDomainLocal error object + // + if (operationError) + { + NSError *thisError = [NSError errorWithDomain:MASFoundationErrorDomainLocal code:operationError.code userInfo:@{NSLocalizedDescriptionKey : operationError.localizedDescription}]; + + if (error) + { + *error = thisError; + } + } + + return result; +} + + ++ (BOOL)saveData:(NSData *)data key:(NSString *)key error:(NSError **)error +{ + // + // Check if SDK was initialized + // + if ([MAS MASState] != MASStateDidStart) + { + if (error) + { + *error = [NSError errorMASIsNotStarted]; + } + + return NO; + } + + // + // Check for data key + // + if (key == nil || [key length] <= 0) + { + if (error) + { + *error = [NSError errorForFoundationCode:MASFoundationErrorCodeSharedStorageNotNilKey errorDomain:MASFoundationErrorDomainLocal]; + } + + return NO; + } + + NSError *operationError = nil; + BOOL result = [[MASAccessService sharedService] setAccessValueData:data storageKey:[NSString stringWithFormat:@"%@.%@", MASSharedStorageCustomPrefix, key] error:&operationError]; + + // + // If an error occurred while keychain operation, convert it into MASFoundationErrorDomainLocal error object + // + if (operationError) + { + NSError *thisError = [NSError errorWithDomain:MASFoundationErrorDomainLocal code:operationError.code userInfo:@{NSLocalizedDescriptionKey : operationError.localizedDescription}]; + + if (error) + { + *error = thisError; + } + } + + return result; +} + + ++ (void)deleteForKey:(NSString *_Nonnull)key error:(NSError * __nullable __autoreleasing * __nullable)error +{ + // + // Check if SDK was initialized + // + if ([MAS MASState] != MASStateDidStart) + { + if (error) + { + *error = [NSError errorMASIsNotStarted]; + } + + return; + } + + // + // Check for data key + // + if (key == nil || [key length] <= 0) + { + if (error) + { + *error = [NSError errorForFoundationCode:MASFoundationErrorCodeSharedStorageNotNilKey errorDomain:MASFoundationErrorDomainLocal]; + } + + return; + } + + NSError *operationError = nil; + [[MASAccessService sharedService] deleteForStorageKey:[NSString stringWithFormat:@"%@.%@", MASSharedStorageCustomPrefix, key] error:&operationError]; + + // + // If an error occurred while keychain operation, convert it into MASFoundationErrorDomainLocal error object + // + if (operationError) + { + NSError *thisError = [NSError errorWithDomain:MASFoundationErrorDomainLocal code:operationError.code userInfo:@{NSLocalizedDescriptionKey : operationError.localizedDescription}]; + + if (error) + { + *error = thisError; + } + } +} + +@end diff --git a/MASFoundation/Classes/models/MASUser.h b/MASFoundation/Classes/models/MASUser.h index ff7c6507..78f5c497 100644 --- a/MASFoundation/Classes/models/MASUser.h +++ b/MASFoundation/Classes/models/MASUser.h @@ -261,6 +261,16 @@ +/** + Authenticate a user by launching a Browser which in turn loads a URL (templatized). + + @param completion The MASCompletionErrorBlock block that receives the results. On a successful completion, the user + available via [MASUser currentUser] has been updated with the new information. + */ ++(void)initializeBrowserBasedAuthenticationWithCompletion:(MASCompletionErrorBlock _Nullable)completion; + + + /** * Requesting userInfo for the MASUser object. * This method will retrieve additional information on the MASUser object. diff --git a/MASFoundation/Classes/models/MASUser.m b/MASFoundation/Classes/models/MASUser.m index da2b3d3b..34eaded7 100644 --- a/MASFoundation/Classes/models/MASUser.m +++ b/MASFoundation/Classes/models/MASUser.m @@ -42,7 +42,7 @@ + (MASUser *)currentUser + (NSString *_Nullable)authCredentialsType { - NSString *authCredentialsType = [[MASAccessService sharedService] getAccessValueStringWithType:MASAccessValueTypeCurrentAuthCredentialsGrantType]; + NSString *authCredentialsType = [[MASAccessService sharedService] getAccessValueStringWithStorageKey:MASKeychainStorageKeyCurrentAuthCredentialsGrantType]; return authCredentialsType; } @@ -142,7 +142,7 @@ - (BOOL)isCurrentUser // // Get currently authenticated user's object id to make sure that isCurrentUser flag can be determined properly for other users // - NSString *currentlyAuthenticatedUserObjectId = [[MASAccessService sharedService] getAccessValueStringWithType:MASAccessValueTypeAuthenticatedUserObjectId]; + NSString *currentlyAuthenticatedUserObjectId = [[MASAccessService sharedService] getAccessValueStringWithStorageKey:MASKeychainStorageKeyAuthenticatedUserObjectId]; return [self.objectId isEqualToString:currentlyAuthenticatedUserObjectId]; } @@ -154,7 +154,7 @@ - (BOOL)isAuthenticated // // Get currently authenticated user's object id to make sure that isAuthenticated flag can be determined properly for other users // - NSString *currentlyAuthenticatedUserObjectId = [[MASAccessService sharedService] getAccessValueStringWithType:MASAccessValueTypeAuthenticatedUserObjectId]; + NSString *currentlyAuthenticatedUserObjectId = [[MASAccessService sharedService] getAccessValueStringWithStorageKey:MASKeychainStorageKeyAuthenticatedUserObjectId]; // // if the user status is not MASUserStatusNotLoggedIn, @@ -169,7 +169,7 @@ - (BOOL)isSessionLocked // // Get currently authenticated user's object id to make sure that isAuthenticated flag can be determined properly for other users // - NSString *currentlyAuthenticatedUserObjectId = [[MASAccessService sharedService] getAccessValueStringWithType:MASAccessValueTypeAuthenticatedUserObjectId]; + NSString *currentlyAuthenticatedUserObjectId = [[MASAccessService sharedService] getAccessValueStringWithStorageKey:MASKeychainStorageKeyAuthenticatedUserObjectId]; if ([self.objectId isEqualToString:currentlyAuthenticatedUserObjectId]) { @@ -250,6 +250,24 @@ + (void)loginWithAuthCredentials:(MASAuthCredentials *_Nonnull)authCredentials c } ++(void)initializeBrowserBasedAuthenticationWithCompletion:(MASCompletionErrorBlock _Nullable)completion +{ + if(![MASModelService browserBasedAuthentication]) + { + if(completion) completion(NO, [NSError errorBrowserBasedAuthenticaionNotEnabled]); + return; + } + + if ([MASUser currentUser] && [MASUser currentUser].isAuthenticated) + { + if(completion) completion(NO, [NSError errorUserAlreadyAuthenticated]); + + return; + } + + [[MASModelService sharedService] validateCurrentUserSession:completion]; +} + - (void)requestUserInfoWithCompletion:(MASUserResponseErrorBlock)completion { [[MASModelService sharedService] requestUserInfoWithCompletion:completion]; @@ -287,7 +305,7 @@ - (void)logoutWithCompletion:(MASCompletionErrorBlock)completion // // Detect if there is id_token // - if([accessService getAccessValueStringWithType:MASAccessValueTypeIdToken]) + if ([accessService getAccessValueStringWithStorageKey:MASKeychainStorageKeyIdToken]) { [[MASModelService sharedService] logOutDeviceAndClearLocalAccessToken:YES completion:completion]; } diff --git a/MASFoundation/Info.plist b/MASFoundation/Info.plist index 033da143..6c0ca926 100644 --- a/MASFoundation/Info.plist +++ b/MASFoundation/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 1.5 + 1.6 CFBundleSignature ???? CFBundleVersion diff --git a/MASFoundation/MASFoundation.h b/MASFoundation/MASFoundation.h index 268dec54..10a69f8c 100644 --- a/MASFoundation/MASFoundation.h +++ b/MASFoundation/MASFoundation.h @@ -47,12 +47,13 @@ FOUNDATION_EXPORT const unsigned char MASFoundationVersionString[]; #import #import #import -#import -#import #import #import #import #import +#import +#import +#import // // AuthCredentials Models diff --git a/README.md b/README.md index abc786b3..81fc427a 100644 --- a/README.md +++ b/README.md @@ -72,9 +72,7 @@ For manual install, you add the Mobile SDK to your Xcode project. Note that you ## Set Up Project and Start the SDK -The following ***video*** describes how to set up the project and start the Mobile SDK. - -[![IMAGE ALT TEXT](http://img.youtube.com/vi/h95MF55Uuuw/0.jpg)](http://www.youtube.com/watch?v=h95MF55Uuuw "Starting the SDK") +To start your project, see [developer site](https://mas.ca.com/docs) After your project is properly configured, you must start the SDK to establish a secure connection with the backend services. The startup process includes: initialize necessary services for library (such as geo-location, BLE, and network services), and load configuration.