diff --git a/MASFoundation.xcodeproj/project.pbxproj b/MASFoundation.xcodeproj/project.pbxproj index e3351493..aab8da93 100644 --- a/MASFoundation.xcodeproj/project.pbxproj +++ b/MASFoundation.xcodeproj/project.pbxproj @@ -11,7 +11,8 @@ isa = PBXAggregateTarget; buildConfigurationList = 1059D3BC1B61C00500223267 /* Build configuration list for PBXAggregateTarget "UniversalFrameworkMASFoundation" */; buildPhases = ( - 1059D3BD1B61C00D00223267 /* ShellScript */, + 69DE19DB1F8E8A2300F4C7FE /* Log Build Settings */, + 1059D3BD1B61C00D00223267 /* Run Script */, ); dependencies = ( ); @@ -151,6 +152,12 @@ 10E027A51F72B10100EAB103 /* RNDecryptor.m in Sources */ = {isa = PBXBuildFile; fileRef = 10E0279B1F72B10100EAB103 /* RNDecryptor.m */; }; 10E027A61F72B10100EAB103 /* RNEncryptor.h in Headers */ = {isa = PBXBuildFile; fileRef = 10E0279C1F72B10100EAB103 /* RNEncryptor.h */; }; 10E027A71F72B10100EAB103 /* RNEncryptor.m in Sources */ = {isa = PBXBuildFile; fileRef = 10E0279D1F72B10100EAB103 /* RNEncryptor.m */; }; + 69B7DF681F9675600056DD3A /* MASRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 699C17911F9585BC008C1B11 /* MASRequest.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 69B7DF691F9675600056DD3A /* MASRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 699C17901F9585BC008C1B11 /* MASRequest.m */; }; + 69B7DF6A1F9675600056DD3A /* MASRequestBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = 699C17921F9585BC008C1B11 /* MASRequestBuilder.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 69B7DF6B1F9675600056DD3A /* MASRequestBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = 699C17931F9585BD008C1B11 /* MASRequestBuilder.m */; }; + 69B7DF6C1F96756B0056DD3A /* MASRequest+MASPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 699C17951F958660008C1B11 /* MASRequest+MASPrivate.h */; }; + 69B7DF6D1F96756B0056DD3A /* MASRequest+MASPrivate.m in Sources */ = {isa = PBXBuildFile; fileRef = 699C17961F958660008C1B11 /* MASRequest+MASPrivate.m */; }; A4150E6F1BF1643900037E27 /* MASIJSONResponseSerializer+MASPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = A4150E691BF1643900037E27 /* MASIJSONResponseSerializer+MASPrivate.h */; }; A4150E701BF1643900037E27 /* MASIJSONResponseSerializer+MASPrivate.m in Sources */ = {isa = PBXBuildFile; fileRef = A4150E6A1BF1643900037E27 /* MASIJSONResponseSerializer+MASPrivate.m */; }; A4150E711BF1643900037E27 /* NSMutableURLRequest+MASPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = A4150E6B1BF1643900037E27 /* NSMutableURLRequest+MASPrivate.h */; }; @@ -563,6 +570,12 @@ 10E0279B1F72B10100EAB103 /* RNDecryptor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNDecryptor.m; sourceTree = ""; }; 10E0279C1F72B10100EAB103 /* RNEncryptor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNEncryptor.h; sourceTree = ""; }; 10E0279D1F72B10100EAB103 /* RNEncryptor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNEncryptor.m; sourceTree = ""; }; + 699C17901F9585BC008C1B11 /* MASRequest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MASRequest.m; sourceTree = ""; }; + 699C17911F9585BC008C1B11 /* MASRequest.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MASRequest.h; sourceTree = ""; }; + 699C17921F9585BC008C1B11 /* MASRequestBuilder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MASRequestBuilder.h; sourceTree = ""; }; + 699C17931F9585BD008C1B11 /* MASRequestBuilder.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MASRequestBuilder.m; sourceTree = ""; }; + 699C17951F958660008C1B11 /* MASRequest+MASPrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "MASRequest+MASPrivate.h"; sourceTree = ""; }; + 699C17961F958660008C1B11 /* MASRequest+MASPrivate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "MASRequest+MASPrivate.m"; sourceTree = ""; }; A4150E691BF1643900037E27 /* MASIJSONResponseSerializer+MASPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MASIJSONResponseSerializer+MASPrivate.h"; sourceTree = ""; }; A4150E6A1BF1643900037E27 /* MASIJSONResponseSerializer+MASPrivate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MASIJSONResponseSerializer+MASPrivate.m"; sourceTree = ""; }; A4150E6B1BF1643900037E27 /* NSMutableURLRequest+MASPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSMutableURLRequest+MASPrivate.h"; sourceTree = ""; }; @@ -1043,6 +1056,15 @@ path = libmosquitto123; sourceTree = ""; }; + 699C17941F958660008C1B11 /* Network */ = { + isa = PBXGroup; + children = ( + 699C17951F958660008C1B11 /* MASRequest+MASPrivate.h */, + 699C17961F958660008C1B11 /* MASRequest+MASPrivate.m */, + ); + path = Network; + sourceTree = ""; + }; A4150EBD1BF16D9A00037E27 /* network */ = { isa = PBXGroup; children = ( @@ -1406,6 +1428,7 @@ isa = PBXGroup; children = ( CB99752B1EDCA749006CEBB1 /* AuthCredentials */, + 699C17941F958660008C1B11 /* Network */, CB1907F11C1794FC00A5EF16 /* MASAccess.h */, CB1907F21C1794FC00A5EF16 /* MASAccess.m */, A4831AE81BD1A87C007B4AE6 /* MASApplication+MASPrivate.h */, @@ -1455,6 +1478,10 @@ CB23578A1F0EE35A00D4C420 /* Network */ = { isa = PBXGroup; children = ( + 699C17911F9585BC008C1B11 /* MASRequest.h */, + 699C17901F9585BC008C1B11 /* MASRequest.m */, + 699C17921F9585BC008C1B11 /* MASRequestBuilder.h */, + 699C17931F9585BD008C1B11 /* MASRequestBuilder.m */, ); path = Network; sourceTree = ""; @@ -1650,6 +1677,8 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( + 69B7DF6A1F9675600056DD3A /* MASRequestBuilder.h in Headers */, + 69B7DF681F9675600056DD3A /* MASRequest.h in Headers */, CBAFD24C1F2BD46C0034DF02 /* MASSecurityConfiguration.h in Headers */, CB9975421EDF5761006CEBB1 /* MASAuthCredentials.h in Headers */, CB99754A1EDF57D6006CEBB1 /* MASAuthCredentialsPassword.h in Headers */, @@ -1873,6 +1902,7 @@ CBD25AFB1E78C47C00DFB47F /* JWTClaimsSet.h in Headers */, 105B2F461CA6B3EA0005A2D0 /* pkcs7.h in Headers */, 105B2F441CA6B3EA0005A2D0 /* pem2.h in Headers */, + 69B7DF6C1F96756B0056DD3A /* MASRequest+MASPrivate.h in Headers */, A417BA511BF033C300EC9BCB /* CLLocation+MASPrivate.h in Headers */, CBD25B011E78C47C00DFB47F /* JWTCoding+ResultTypes.h in Headers */, A4831AF61BD1A8CA007B4AE6 /* MASDevice+MASPrivate.h in Headers */, @@ -1984,18 +2014,33 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - 1059D3BD1B61C00D00223267 /* ShellScript */ = { + 1059D3BD1B61C00D00223267 /* Run Script */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); + name = "Run Script"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "set -e\n\n#---------------\n#Framework Name\n#---------------\n\nFRAMEWORK_NAME=MASFoundation\n\n\n#---------------\n#SDK Directory\n#---------------\n\nSDK_DIR=../iOS_SDK\n\n\n#-----------------------\n#CleanUp Build Cache\n#-----------------------\n\nxcodebuild -project $PROJECT_NAME.xcodeproj -configuration Debug -alltargets clean\nxcodebuild -project $PROJECT_NAME.xcodeproj -configuration Release -alltargets clean\n\n\n#-----------------------\n#CleanUp Previous Builds\n#-----------------------\n\n# Remove the framework from the Project Folder\nrm -Rf \"${PROJECT_DIR}/${FRAMEWORK_NAME}.framework\"\n\n# Remove Build folder from DerivedData\nrm -Rf \"${BUILD_DIR}\"\n\n\n#-----------------------\n#Creating New Builds\n#-----------------------\n\n# define output folder environment variable\nUNIVERSAL_OUTPUTFOLDER=${BUILD_DIR}/${CONFIGURATION}-universal\nARCHIVE_OUTPUTFOLDER=${BUILD_DIR}/../Intermediates/ArchiveIntermediates/$PROJECT_NAME/IntermediateBuildFilesPath/UninstalledProducts/iphoneos\n\n# Archive framework for iPhoneOS with BitCode enabled\n#xcodebuild -scheme $PROJECT_NAME -configuration Release archive\n\nxcodebuild OTHER_CFLAGS=\"-fembed-bitcode\" -scheme $PROJECT_NAME -configuration Release archive CODE_SIGN_IDENTITY=\"iPhone Distribution: CA, Inc (RAKRWMN9VH)\" -archivePath \"${BUILD_DIR}\"\n\n# Build framework for iPhoneOS\n#xcodebuild -target ${FRAMEWORK_NAME} ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphoneos BUILD_DIR=\"${BUILD_DIR}\" BUILD_ROOT=\"${BUILD_ROOT}\" CODE_SIGN_IDENTITY=\"iPhone Distribution: CA, Inc (RAKRWMN9VH)\"\n\n# Build framework for iPhoneSimulator\nxcodebuild -target ${FRAMEWORK_NAME} -configuration ${CONFIGURATION} -sdk iphonesimulator BUILD_DIR=\"${BUILD_DIR}\" BUILD_ROOT=\"${BUILD_ROOT}\" CODE_SIGN_IDENTITY=\"iPhone Distribution: CA, Inc (RAKRWMN9VH)\"\n\n\n#-----------------------\n#Creating Universal Framework\n#-----------------------\n\nmkdir -p \"${UNIVERSAL_OUTPUTFOLDER}\"\nmkdir -p \"${SDK_DIR}\"\n\n\n# Build the universal library\nlipo -create -output \"${UNIVERSAL_OUTPUTFOLDER}/${FRAMEWORK_NAME}\" \"${ARCHIVE_OUTPUTFOLDER}/${FRAMEWORK_NAME}.framework/${FRAMEWORK_NAME}\" \"${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${FRAMEWORK_NAME}.framework/${FRAMEWORK_NAME}\"\n\n# Copy the .framework folder of iphoneos\ncp -R \"${ARCHIVE_OUTPUTFOLDER}/${FRAMEWORK_NAME}.framework\" \"${UNIVERSAL_OUTPUTFOLDER}/\"\n\n# Delete the library for iphoneos\nrm \"${UNIVERSAL_OUTPUTFOLDER}/${FRAMEWORK_NAME}.framework/${FRAMEWORK_NAME}\"\n\n# Move the Universal Library into our framework\nmv \"${UNIVERSAL_OUTPUTFOLDER}/${FRAMEWORK_NAME}\" \"${UNIVERSAL_OUTPUTFOLDER}/${FRAMEWORK_NAME}.framework/\"\n\n# Remove the _CodeSignature from the UniversalFramework\nrm -Rf \"${UNIVERSAL_OUTPUTFOLDER}/${FRAMEWORK_NAME}.framework/_CodeSignature\"\n\n# Copy the framework\ncp -R \"${UNIVERSAL_OUTPUTFOLDER}/${FRAMEWORK_NAME}.framework\" \"${SDK_DIR}\"\n\n#-----------------------\n#Deleting Build Folder\n#-----------------------\n\n# Remove build folder from the Project Folder\nrm -Rf \"${PROJECT_DIR}/build\"\n\n"; + shellScript = "set -e\n\n#---------------\n#Framework Name\n#---------------\n\nFRAMEWORK_NAME=MASFoundation\n\n\n#---------------\n#SDK Directory\n#---------------\n\nSDK_DIR=../iOS_SDK\n\n\n#-----------------------\n#CleanUp Build Cache\n#-----------------------\n\nxcodebuild -project $PROJECT_NAME.xcodeproj -configuration Debug -alltargets clean\nxcodebuild -project $PROJECT_NAME.xcodeproj -configuration Release -alltargets clean\n\n\n#-----------------------\n#CleanUp Previous Builds\n#-----------------------\n\n# Remove the framework from the Project Folder\nrm -Rf \"${PROJECT_DIR}/${FRAMEWORK_NAME}.framework\"\n\n# Remove Build folder from DerivedData\nrm -Rf \"${BUILD_DIR}\"\n\n\n#-----------------------\n#Creating New Builds\n#-----------------------\n\n# define output folder environment variable\nUNIVERSAL_OUTPUTFOLDER=${BUILD_DIR}/${CONFIGURATION}-universal\nARCHIVE_OUTPUTFOLDER=${OBJROOT}/ArchiveIntermediates/$PROJECT_NAME/IntermediateBuildFilesPath/UninstalledProducts/iphoneos\n\n# Archive framework for iPhoneOS with BitCode enabled\n#xcodebuild -scheme $PROJECT_NAME -configuration Release archive\n\nxcodebuild OTHER_CFLAGS=\"-fembed-bitcode\" -scheme $PROJECT_NAME -configuration Release archive CODE_SIGN_IDENTITY=\"iPhone Distribution: CA, Inc (RAKRWMN9VH)\" -archivePath \"${BUILD_DIR}\"\n\n# Build framework for iPhoneOS\n#xcodebuild -target ${FRAMEWORK_NAME} ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphoneos BUILD_DIR=\"${BUILD_DIR}\" BUILD_ROOT=\"${BUILD_ROOT}\" CODE_SIGN_IDENTITY=\"iPhone Distribution: CA, Inc (RAKRWMN9VH)\"\n\n# Build framework for iPhoneSimulator\nxcodebuild -target ${FRAMEWORK_NAME} -configuration ${CONFIGURATION} -sdk iphonesimulator BUILD_DIR=\"${BUILD_DIR}\" BUILD_ROOT=\"${BUILD_ROOT}\" CODE_SIGN_IDENTITY=\"iPhone Distribution: CA, Inc (RAKRWMN9VH)\"\n\n\n#-----------------------\n#Creating Universal Framework\n#-----------------------\n\nmkdir -p \"${UNIVERSAL_OUTPUTFOLDER}\"\nmkdir -p \"${SDK_DIR}\"\n\n\n# Build the universal library\nlipo -create -output \"${UNIVERSAL_OUTPUTFOLDER}/${FRAMEWORK_NAME}\" \"${ARCHIVE_OUTPUTFOLDER}/${FRAMEWORK_NAME}.framework/${FRAMEWORK_NAME}\" \"${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${FRAMEWORK_NAME}.framework/${FRAMEWORK_NAME}\"\n\n# Copy the .framework folder of iphoneos\ncp -R \"${ARCHIVE_OUTPUTFOLDER}/${FRAMEWORK_NAME}.framework\" \"${UNIVERSAL_OUTPUTFOLDER}/\"\n\n# Delete the library for iphoneos\nrm \"${UNIVERSAL_OUTPUTFOLDER}/${FRAMEWORK_NAME}.framework/${FRAMEWORK_NAME}\"\n\n# Move the Universal Library into our framework\nmv \"${UNIVERSAL_OUTPUTFOLDER}/${FRAMEWORK_NAME}\" \"${UNIVERSAL_OUTPUTFOLDER}/${FRAMEWORK_NAME}.framework/\"\n\n# Remove the _CodeSignature from the UniversalFramework\nrm -Rf \"${UNIVERSAL_OUTPUTFOLDER}/${FRAMEWORK_NAME}.framework/_CodeSignature\"\n\n# Copy the framework\ncp -R \"${UNIVERSAL_OUTPUTFOLDER}/${FRAMEWORK_NAME}.framework\" \"${SDK_DIR}\"\n\n#-----------------------\n#Deleting Build Folder\n#-----------------------\n\n# Remove build folder from the Project Folder\nrm -Rf \"${PROJECT_DIR}/build\"\n\n"; + }; + 69DE19DB1F8E8A2300F4C7FE /* Log Build Settings */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Log Build Settings"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/bash; + shellScript = export; }; /* End PBXShellScriptBuildPhase section */ @@ -2099,6 +2144,7 @@ A46F49C51C2F5FC500A4C370 /* MASIHTTPRequestOperation.m in Sources */, A4150E701BF1643900037E27 /* MASIJSONResponseSerializer+MASPrivate.m in Sources */, A417BA521BF033C300EC9BCB /* CLLocation+MASPrivate.m in Sources */, + 69B7DF6D1F96756B0056DD3A /* MASRequest+MASPrivate.m in Sources */, A4831AB21BD1A551007B4AE6 /* MASFile.m in Sources */, CB0B585A1E258C2A00BC0163 /* MASAuthorizationResponse.m in Sources */, CB5E4C651C1D1B56001B3B8A /* MASGetURLRequest.m in Sources */, @@ -2121,6 +2167,7 @@ CB2357931F0EF53600D4C420 /* MASURLSessionManager.m in Sources */, 10738A291C711C2F00B7E87E /* mosquitto.c in Sources */, A4150EE81BF16E5B00037E27 /* MASFileService.m in Sources */, + 69B7DF691F9675600056DD3A /* MASRequest.m in Sources */, CBD25B081E78C47C00DFB47F /* JWTCoding+VersionTwo.m in Sources */, A483C2021BE6D0C5007572CE /* CBCentralManager+MASPrivate.m in Sources */, CBD25AFA1E78C47C00DFB47F /* JWTClaim.m in Sources */, @@ -2130,6 +2177,7 @@ CB5E4C751C1D26BA001B3B8A /* MASPatchURLRequest.m in Sources */, A46F49CB1C2F5FC500A4C370 /* MASINetworkActivityLogger.m in Sources */, A46F49BB1C2F5FC500A4C370 /* fmemopen.c in Sources */, + 69B7DF6B1F9675600056DD3A /* MASRequestBuilder.m in Sources */, A4150EFE1BF16EE200037E27 /* MASSecurityService.m in Sources */, 10738A371C711C2F00B7E87E /* time_mosq.c in Sources */, A46F49C21C2F5FC500A4C370 /* MASIKeyChainStore.m in Sources */, diff --git a/MASFoundation/Classes/MAS.h b/MASFoundation/Classes/MAS.h index c4431e1a..8d290576 100644 --- a/MASFoundation/Classes/MAS.h +++ b/MASFoundation/Classes/MAS.h @@ -12,7 +12,7 @@ #import "MASConstants.h" #import "MASClaims.h" - +#import "MASRequest.h" /** * The top level MAS object represents the Mobile App Services SDK in it's entirety. It @@ -148,6 +148,26 @@ +/** + * Sets BOOL indicator whether the Keychain is synchronized through iCloud. + * By default, the Keychain is not synchronized through iCloud. + * + * @param enabled BOOL YES to enable synchroniztion, NO to disable it. + */ ++ (void)setKeychainSynchronizable:(BOOL)enabled; + + + +/** + * Gets BOOL indicator of Keychain sincronization enabled or not. + * By default, the Keychain is not synchronized through iCloud. + * + * @return return BOOL value indicating Keychain sincronization is enabled or not + */ ++ (BOOL)isKeychainSynchronizable; + + + ///-------------------------------------- /// @name Start & Stop ///-------------------------------------- @@ -929,6 +949,28 @@ withParameters:(NSDictionary *_Nullable)parameterInfo completion:(MASResponseInfoErrorBlock _Nullable)completion; +/** + * Invoke the endpoint with the parameters defined in the MASRequest object + * + * If endPointPath is full URL format (including port number and http protocol), SDK will validate the server from the client side through SSL pinning (authentication challenge) with + * provided subjectKeyHash (also known as public key hash) in configuration in mag.mobile_sdk.trusted_cert_pinned_public_key_hashes and mag.mobile_sdk.enable_public_key_pinning. + * ALL of servers' public key hashes in certificate chain must be defined in the list. This means when it is configured to use public key hash pinning for SSL pinning, + * subjectKeyHash (public key hash) of the gateway must be also present within the list. The list can contain multiple hash values in array for multiple servers. + * + * When SDK fails to validate SSL with certificate or subjectKeyHash pinning for communication to HTTPs, SDK will cancel the request. + * + * If endPointPath is full URL format, upon successful SSL pinning validation, SDK will also validate the user session against primary gateway regardless the request is being made + * to the primary gateway or not. To ensure bypass the user session validation for public API, use [MAS deleteFrom:withParameters:requestType:responseType:isPublic:completion:] method + * with isPublic being YES. + * + * @param request MASRequest An object containing all parameters to call the endpoint + * When the value is set to true, all automatically injected credentials in SDK will be excluded in the request. + * @param completion An MASResponseInfoErrorBlock (NSDictionary *responseInfo, NSError *error) that will + * receive the JSON response object or an NSError object if there is a failure. + */ ++ (void)invoke:(nonnull MASRequest *)request completion:(nullable MASResponseInfoErrorBlock)completion; + + ///-------------------------------------- /// @name JWT Signing ///-------------------------------------- diff --git a/MASFoundation/Classes/MAS.m b/MASFoundation/Classes/MAS.m index d1981d96..db17fbab 100644 --- a/MASFoundation/Classes/MAS.m +++ b/MASFoundation/Classes/MAS.m @@ -98,6 +98,18 @@ + (void)setGatewayMonitor:(MASGatewayMonitorStatusBlock)monitor } ++ (void)setKeychainSynchronizable:(BOOL)enabled +{ + [MASAccessService setKeychainSynchronizable:enabled]; +} + + ++ (BOOL)isKeychainSynchronizable +{ + return [MASAccessService isKeychainSynchronizable]; +} + + + (MASState)MASState { // @@ -1464,6 +1476,33 @@ + (void)putTo:(nonnull NSString *)endPoint } ++ (void)invoke:(nonnull MASRequest *)request completion:(nullable MASResponseInfoErrorBlock)completion +{ + // + // Process the request + // + if ([request.httpMethod isEqualToString:@"DELETE"]) + { + [self deleteFrom:request.endPoint withParameters:request.body andHeaders:request.header requestType:request.requestType responseType:request.responseType isPublic:request.isPublic completion:completion]; + } + else if ([request.httpMethod isEqualToString:@"GET"]) + { + [self getFrom:request.endPoint withParameters:request.body andHeaders:request.header requestType:request.requestType responseType:request.responseType isPublic:request.isPublic completion:completion]; + } + else if ([request.httpMethod isEqualToString:@"PATCH"]) + { + [self patchTo:request.endPoint withParameters:request.body andHeaders:request.header requestType:request.requestType responseType:request.responseType isPublic:request.isPublic completion:completion]; + } + else if ([request.httpMethod isEqualToString:@"POST"]) + { + [self postTo:request.endPoint withParameters:request.body andHeaders:request.header requestType:request.requestType responseType:request.responseType isPublic:request.isPublic completion:completion]; + } + else if ([request.httpMethod isEqualToString:@"PUT"]) + { + [self putTo:request.endPoint withParameters:request.body andHeaders:request.header requestType:request.requestType responseType:request.responseType isPublic:request.isPublic completion:completion]; + } +} + # pragma mark - Private diff --git a/MASFoundation/Classes/MASConstants.h b/MASFoundation/Classes/MASConstants.h index f6d668c3..003e0284 100644 --- a/MASFoundation/Classes/MASConstants.h +++ b/MASFoundation/Classes/MASConstants.h @@ -556,6 +556,13 @@ static NSString *const _Nonnull MASDeviceDidFailToDeregisterNotification = @"MAS static NSString *const _Nonnull MASDeviceDidDeregisterNotification = @"MASDeviceDidDeregisterNotification"; +/** + * The NSString constant for the device notification indicating that the MASDevice + * has reset locally. + */ +static NSString *const _Nonnull MASDeviceDidResetLocallyNotification = @"MASDeviceDidResetLocallyNotification"; + + ///-------------------------------------- /// @name User Notifications diff --git a/MASFoundation/Classes/MQTT/MASMQTTClient.m b/MASFoundation/Classes/MQTT/MASMQTTClient.m index 732fc50a..2221aefc 100644 --- a/MASFoundation/Classes/MQTT/MASMQTTClient.m +++ b/MASFoundation/Classes/MQTT/MASMQTTClient.m @@ -80,31 +80,45 @@ @implementation MASMQTTClient + (instancetype)sharedClient { - static dispatch_once_t onceToken; - if (!_sharedClient) { - dispatch_once(&onceToken, ^{ - + @synchronized(self) + { if ([MASUser currentUser].isAuthenticated && [MASDevice currentDevice].isRegistered) { - + // // Init MQTT client for current gateway // _sharedClient = [[MASMQTTClient alloc] initWithClientId:[MASMQTTHelper mqttClientId] cleanSession:NO]; } else { - + //Return nil in case Authentication or Registration is not done yet. _sharedClient = nil; } - }); + } } return _sharedClient; } +- (void)clearConnection +{ + __block MASMQTTClient *blockSelf = self; + [self disconnectWithCompletionHandler:^(NSUInteger code) { + + if ([blockSelf isEqual:_sharedClient]) + { + @synchronized(blockSelf) + { + _sharedClient = nil; + } + } + }]; +} + + // Initialize is called just before the first object is allocated - (void)initialize { @@ -151,6 +165,19 @@ - (MASMQTTClient *)initWithClientId:(NSString *)clientId cleanSession:(BOOL)clea // } self.queue = dispatch_queue_create(cstrClientId, NULL); + + // + // Subscribe following information to reset the current MQTT session due to the change in SDK's authenticated session + // + // - user logout + // - device de-registration + // - device reset locally + // - gateway switch + // + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(clearConnection) name:MASUserDidLogoutNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(clearConnection) name:MASDeviceDidDeregisterNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(clearConnection) name:MASDeviceDidResetLocallyNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(clearConnection) name:MASWillSwitchGatewayServerNotification object:nil]; } _sharedClient = self; @@ -158,6 +185,7 @@ - (MASMQTTClient *)initWithClientId:(NSString *)clientId cleanSession:(BOOL)clea return self; } + #pragma mark - Setup methods -(void)setUsername:(NSString *)username Password:(NSString *)password @@ -590,6 +618,7 @@ - (void)disconnectWithCompletionHandler:(MQTTDisconnectionHandler)completionHand mosquitto_disconnect(mosq); } + - (void)reconnect:(NSNotification *)notification { [self reconnect]; @@ -844,13 +873,13 @@ - (void)setupTLSWithServerCert:(NSString *)certPath withClientCert:(NSString *)c // if (!certPath) { - thisFile = [[MASSecurityService sharedService] getClientCertificate]; + thisFile = [[MASSecurityService sharedService] getServerCertificate]; certPath = [thisFile filePath]; //[[MASFile findFileWithName:@"MAS.crt"] filePath]; } if (!clientCertPath) { - thisFile = [[MASSecurityService sharedService] getSignedCertificate]; + thisFile = [[MASSecurityService sharedService] getDeviceClientCertificate]; clientCertPath = [thisFile filePath]; //[[MASFile findFileWithName:@"MASSigned.crt"] filePath]; } diff --git a/MASFoundation/Classes/_private_/models/Network/MASRequest+MASPrivate.h b/MASFoundation/Classes/_private_/models/Network/MASRequest+MASPrivate.h new file mode 100644 index 00000000..a43d5946 --- /dev/null +++ b/MASFoundation/Classes/_private_/models/Network/MASRequest+MASPrivate.h @@ -0,0 +1,23 @@ +// +// MASRequest+MASPrivate.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 + +@interface MASRequest (MASPrivate) + +/** + Private initializer for MASRequest. + + @param url NSURL of the target domain + @return MASRequest object + */ +- (instancetype)initWithBuilder:(MASRequestBuilder *)builder; + +@end diff --git a/MASFoundation/Classes/_private_/models/Network/MASRequest+MASPrivate.m b/MASFoundation/Classes/_private_/models/Network/MASRequest+MASPrivate.m new file mode 100644 index 00000000..746cadce --- /dev/null +++ b/MASFoundation/Classes/_private_/models/Network/MASRequest+MASPrivate.m @@ -0,0 +1,81 @@ +// +// MASRequest+MASPrivate.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 "MASRequest+MASPrivate.h" + + +@interface MASRequest () + +@property (nonatomic, readwrite) NSString *endPoint; +@property (nonatomic, readwrite) NSString *httpMethod; +@property (nonatomic, readwrite) NSData *privateKey; +@property (nonatomic, readwrite) NSDictionary *header; +@property (nonatomic, readwrite) NSDictionary *body; +@property (nonatomic, readwrite) NSDictionary *query; +@property (assign, readwrite) BOOL isPublic; +@property (assign, readwrite) BOOL sign; +@property (assign, readwrite) MASRequestResponseType requestType; +@property (assign, readwrite) MASRequestResponseType responseType; + +@end + +@implementation MASRequest (MASPrivate) + +# pragma mark - Lifecycle + +- (instancetype)initWithBuilder:(MASRequestBuilder *)builder +{ + self = [super init]; + if(self) + { + // + // copy parameters from builder + // + self.endPoint = builder.endPoint; + self.isPublic = builder.isPublic; + self.sign = builder.sign; + self.requestType = builder.requestType; + self.responseType = builder.responseType; + self.httpMethod = builder.httpMethod; + self.privateKey = builder.privateKey; + self.header = builder.header; + self.body = builder.body; + self.query = builder.query; + + + // + // check if query parameters are provided + // + if(self.query) + { + // + // add query parameters into URL + // + NSURL *url = [NSURL URLWithString:self.endPoint]; + + NSMutableArray *queryItems = [NSMutableArray array]; + for (NSString *key in self.query) { + NSURLQueryItem *queryItem = [NSURLQueryItem queryItemWithName:key value:self.query[key]]; + [queryItems addObject:queryItem]; + } + + NSURLComponents *components = [NSURLComponents componentsWithURL:url resolvingAgainstBaseURL:NO]; + components.queryItems = [queryItems copy]; + + self.endPoint = [components.URL absoluteString]; + } + + } + + return self; +} + + +@end diff --git a/MASFoundation/Classes/_private_/services/access/MASAccessService.h b/MASFoundation/Classes/_private_/services/access/MASAccessService.h index 64dc044b..7ab122e0 100644 --- a/MASFoundation/Classes/_private_/services/access/MASAccessService.h +++ b/MASFoundation/Classes/_private_/services/access/MASAccessService.h @@ -99,6 +99,24 @@ typedef NS_ENUM(NSInteger, MASAccessValueType) +/** + * Static boolean property indicating Keychain sincronization is enabled or not. + * + * @return return BOOL value indicating Keychain sincronization is enabled or not + */ ++ (BOOL)isKeychainSynchronizable; + + + +/** + * Setter of static boolean property indicating Keychain sincronization is enabled or not. + * + * @param enable BOOL value indicating Keychain sincronization is enabled or not + */ ++ (void)setKeychainSynchronizable:(BOOL)enable; + + + ///-------------------------------------- /// @name Shared Service ///-------------------------------------- diff --git a/MASFoundation/Classes/_private_/services/access/MASAccessService.m b/MASFoundation/Classes/_private_/services/access/MASAccessService.m index 441a2d23..efdb6e80 100644 --- a/MASFoundation/Classes/_private_/services/access/MASAccessService.m +++ b/MASFoundation/Classes/_private_/services/access/MASAccessService.m @@ -49,6 +49,7 @@ @implementation MASAccessService static BOOL _isPKCEEnabled_ = YES; +static BOOL _isKeychainSynchronizable_ = NO; # pragma mark - Properties @@ -64,6 +65,18 @@ + (void)enablePKCE:(BOOL)enable } ++ (BOOL)isKeychainSynchronizable +{ + return _isKeychainSynchronizable_; +} + + ++ (void)setKeychainSynchronizable:(BOOL)enable +{ + _isKeychainSynchronizable_ = enable; +} + + # pragma mark - Shared Service + (instancetype)sharedService @@ -102,36 +115,30 @@ - (void)serviceWillStart // _gatewayIdentifier = [MASConfiguration currentConfiguration].gatewayUrl.absoluteString; - _localStorageServiceName = [NSString stringWithFormat:@"%@.%@", _gatewayIdentifier, kMASAccessLocalStorageServiceName]; _sharedStorageServiceName = [NSString stringWithFormat:@"%@.%@", _gatewayIdentifier, kMASAccessSharedStorageServiceName]; + // + // Local storage + // + MASIKeyChainStore *localStorage = [MASIKeyChainStore keyChainStoreWithService:_localStorageServiceName]; + localStorage.synchronizable = _isKeychainSynchronizable_; + if ([MASConfiguration currentConfiguration].ssoEnabled && [self isAccessGroupAccessible]) { - - // - // Local storage - // - MASIKeyChainStore *localStorage = [MASIKeyChainStore keyChainStoreWithService:_localStorageServiceName]; - // // Shared storage // MASIKeyChainStore *sharedStorage = [MASIKeyChainStore keyChainStoreWithService:_sharedStorageServiceName accessGroup:self.accessGroup]; - + sharedStorage.synchronizable = _isKeychainSynchronizable_; + // // storage dictionary property // _storages = [NSDictionary dictionaryWithObjectsAndKeys:localStorage, kMASAccessLocalStorageKey, sharedStorage, kMASAccessSharedStorageKey, nil]; } else { - - // - // Local storage - // - MASIKeyChainStore *localStorage = [MASIKeyChainStore keyChainStoreWithService:_localStorageServiceName]; - // // storage dictionary property // diff --git a/MASFoundation/Classes/_private_/services/file/MASFileService.m b/MASFoundation/Classes/_private_/services/file/MASFileService.m index e10ef761..8e0abe97 100644 --- a/MASFoundation/Classes/_private_/services/file/MASFileService.m +++ b/MASFoundation/Classes/_private_/services/file/MASFileService.m @@ -57,7 +57,7 @@ - (NSString *)debugDescription // // ServerCertificate // - MASFile *file = [[MASSecurityService sharedService] getClientCertificate]; //[self findFileWithName:MASCertificate]; + MASFile *file = [[MASSecurityService sharedService] getServerCertificate]; //[self findFileWithName:MASCertificate]; if(file) { filesFound = YES; @@ -68,7 +68,7 @@ - (NSString *)debugDescription // // SignedCertificate // - file = [[MASSecurityService sharedService] getSignedCertificate]; //[self findFileWithName:MASSignedCertificate]; + file = [[MASSecurityService sharedService] getDeviceClientCertificate]; //[self findFileWithName:MASSignedCertificate]; if(file) { filesFound = YES; diff --git a/MASFoundation/Classes/_private_/services/model/MASModelService.m b/MASFoundation/Classes/_private_/services/model/MASModelService.m index 92284303..26f50a98 100644 --- a/MASFoundation/Classes/_private_/services/model/MASModelService.m +++ b/MASFoundation/Classes/_private_/services/model/MASModelService.m @@ -1309,10 +1309,10 @@ - (void)renewClientCertificateWithCompletion:(MASCompletionErrorBlock)completion [[MASAccessService sharedService] setAccessValueNumber:[NSNumber numberWithInt:0] withAccessValueType:MASAccessValueTypeSignedPublicCertificateExpirationDate]; // - // Remove signedCertificate MASFile for re-generation + // Remove device's client MASFile for re-generation // - MASFile *signedCertificate = [[MASSecurityService sharedService] getSignedCertificate]; - [MASFile removeItemAtFilePath:[signedCertificate filePath]]; + MASFile *deviceClientCert = [[MASSecurityService sharedService] getDeviceClientCertificate]; + [MASFile removeItemAtFilePath:[deviceClientCert filePath]]; // // Updated with latest info @@ -1480,7 +1480,7 @@ - (void)logOutDeviceAndClearLocalAccessToken:(BOOL)clearLocal completion:(MASCom // // Post the notification // - [[NSNotificationCenter defaultCenter] postNotificationName:MASDeviceDidFailToRegisterNotification object:blockSelf]; + [[NSNotificationCenter defaultCenter] postNotificationName:MASUserDidFailToLogoutNotification object:blockSelf]; return; } @@ -1496,6 +1496,11 @@ - (void)logOutDeviceAndClearLocalAccessToken:(BOOL)clearLocal completion:(MASCom [blockSelf clearCurrentUserForLogout]; } + // + // Post the notification + // + [[NSNotificationCenter defaultCenter] postNotificationName:MASUserDidLogoutNotification object:blockSelf]; + // // Set id_token and id_token_type to nil // diff --git a/MASFoundation/Classes/_private_/services/security/MASSecurityService.h b/MASFoundation/Classes/_private_/services/security/MASSecurityService.h index c252cfd1..a6f6d291 100644 --- a/MASFoundation/Classes/_private_/services/security/MASSecurityService.h +++ b/MASFoundation/Classes/_private_/services/security/MASSecurityService.h @@ -83,20 +83,20 @@ # pragma mark - MASFile Security /** - * Generate MASFile object for current gateway's signed certificate. + * Generate MASFile object for current device's client certificate. * - * @return Returns MASFile object of signed certificate for current configuration's gateway. + * @return Returns MASFile object of device's client for current configuration's gateway. */ -- (MASFile *)getSignedCertificate; +- (MASFile *)getDeviceClientCertificate; /** - * Generate MASFile object for current gateway's client certificate. + * Generate MASFile object for current gateway's server certificate. * - * @return Returns MASFile object of client certificate for current configuration's gateway. + * @return Returns MASFile object of server certificate for current configuration's gateway. */ -- (MASFile *)getClientCertificate; +- (MASFile *)getServerCertificate; diff --git a/MASFoundation/Classes/_private_/services/security/MASSecurityService.m b/MASFoundation/Classes/_private_/services/security/MASSecurityService.m index 594573c5..c3d46a1d 100644 --- a/MASFoundation/Classes/_private_/services/security/MASSecurityService.m +++ b/MASFoundation/Classes/_private_/services/security/MASSecurityService.m @@ -415,7 +415,7 @@ - (NSData *)publicKeyBits # pragma mark - MASFile Security -- (MASFile *)getSignedCertificate +- (MASFile *)getDeviceClientCertificate { NSString *gatewayIdentifier = [[[MASConfiguration currentConfiguration].gatewayUrl.absoluteString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding] stringByReplacingOccurrencesOfString:@"https://" withString:@""]; MASFile *signedCert = [MASFile findFileWithName:[NSString stringWithFormat:@"%@.%@", gatewayIdentifier, MASSignedCertificate]]; @@ -435,7 +435,7 @@ - (MASFile *)getSignedCertificate } -- (MASFile *)getClientCertificate +- (MASFile *)getServerCertificate { NSString *gatewayIdentifier = [[[MASConfiguration currentConfiguration].gatewayUrl.absoluteString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding] stringByReplacingOccurrencesOfString:@"https://" withString:@""]; MASFile *clientCert = [MASFile findFileWithName:[NSString stringWithFormat:@"%@.%@", gatewayIdentifier, MASCertificate]]; @@ -446,17 +446,18 @@ - (MASFile *)getClientCertificate // Create the public server certificate file // NSArray *certs = [[MASConfiguration currentConfiguration] gatewayCertificatesAsPEMData]; - if(certs.count > 0) + NSMutableData *certificateData = [NSMutableData data]; + + for (NSData *cert in certs) + { + [certificateData appendData:cert]; + [certificateData appendData:[@"\n" dataUsingEncoding:NSUTF8StringEncoding]]; + } + + if (certificateData) { - NSData *certificateData = certs[0]; - - //DLog(@"\n\nServer Certificate class is: %@\n\n and value: %@\n\n", [[certificateData class] debugDescription], certificateData); - - if(certificateData) - { - clientCert = [MASFile fileWithName:[NSString stringWithFormat:@"%@.%@", gatewayIdentifier, MASCertificate] contents:certificateData]; - [clientCert save]; - } + clientCert = [MASFile fileWithName:[NSString stringWithFormat:@"%@.%@", gatewayIdentifier, MASCertificate] contents:certificateData]; + [clientCert save]; } } @@ -496,22 +497,22 @@ - (MASFile *)getPrivateKey - (void)removeAllFiles { MASFile *privateKey = [self getPrivateKey]; - MASFile *clientCert = [self getClientCertificate]; - MASFile *signedCert = [self getSignedCertificate]; + MASFile *serverCert = [self getServerCertificate]; + MASFile *deviceClientCert = [self getDeviceClientCertificate]; if ([privateKey filePath]) { [MASFile removeItemAtFilePath:[privateKey filePath]]; } - if ([clientCert filePath]) + if ([serverCert filePath]) { - [MASFile removeItemAtFilePath:[clientCert filePath]]; + [MASFile removeItemAtFilePath:[serverCert filePath]]; } - if ([signedCert filePath]) + if ([deviceClientCert filePath]) { - [MASFile removeItemAtFilePath:[signedCert filePath]]; + [MASFile removeItemAtFilePath:[deviceClientCert filePath]]; } } diff --git a/MASFoundation/Classes/models/MASConfiguration.m b/MASFoundation/Classes/models/MASConfiguration.m index edd665b7..3d2cba88 100644 --- a/MASFoundation/Classes/models/MASConfiguration.m +++ b/MASFoundation/Classes/models/MASConfiguration.m @@ -100,7 +100,7 @@ static NSString *const MASClientInitializeEndpoint = @"client_credential_init_endpoint_path"; // string static NSString *const MASDeviceListEndpoint = @"device_list_endpoint_path"; // string static NSString *const MASDeviceRegisterEndpoint = @"device_register_endpoint_path"; // string -static NSString *const MASDeviceRegisterClientEndpoint = @"device_register_client_endpoint_path"; // string +static NSString *const MASDeviceRegisterClientEndpoint = @"device_client_register_endpoint_path"; // string static NSString *const MASDeviceRenewEndpoint = @"device_renew_endpoint_path"; // string static NSString *const MASDeviceRemoveEndpoint = @"device_remove_endpoint_path"; // string static NSString *const MASEnterpriseBrowserEndpoint = @"enterprise_browser_endpoint_path"; // string @@ -299,8 +299,6 @@ - (void)initializeEndpointsFromInfo:(NSDictionary *)info // // Temporary Hardcoded Endpoints // - _endpointKeysToPaths_[MASDeviceRegisterClientEndpoint] = @"/connect/device/register/client"; - _endpointKeysToPaths_[MASUsersLDAPEndpoint] = @"/scim/ldap/v2/users"; _endpointKeysToPaths_[MASUserGroupsLDAPEndpoint] = @"/scim/ldap/v2/groups"; _endpointKeysToPaths_[MASUsersMSADEndpoint] = @"/scim/msad/v2/users"; diff --git a/MASFoundation/Classes/models/MASDevice.m b/MASFoundation/Classes/models/MASDevice.m index 645399ce..2f1e952e 100644 --- a/MASFoundation/Classes/models/MASDevice.m +++ b/MASFoundation/Classes/models/MASDevice.m @@ -119,6 +119,11 @@ - (void)resetLocally // re-establish URL session // [[MASNetworkingService sharedService] establishURLSession]; + + // + // Post the did reset locally notification + // + [[NSNotificationCenter defaultCenter] postNotificationName:MASDeviceDidResetLocallyNotification object:self]; } diff --git a/MASFoundation/Classes/models/Network/MASRequest.h b/MASFoundation/Classes/models/Network/MASRequest.h new file mode 100644 index 00000000..5b493627 --- /dev/null +++ b/MASFoundation/Classes/models/Network/MASRequest.h @@ -0,0 +1,150 @@ +// +// MASRequest.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 "MASRequestBuilder.h" + +/** + MASRequest class is an object created by MASRequestBuilder. It contains all necessary information to invoke an API. + The class cannot be constructed or changed directly, only through MASRequestBuilder. + */ +@interface MASRequest : MASObject + + +///-------------------------------------- +/// @name Properties +///-------------------------------------- + +# pragma mark - Properties + +/** + NSString value of the HTTP Method (GET, POST, PUT, DELETE). + */ +@property (nonatomic, strong, readonly) NSString * _Nonnull httpMethod; + + +/** + BOOL value that determines whether or not to include credentials of primary gateway in the request. + */ +@property (assign, readonly) BOOL isPublic; + + +/** + BOOL value that determines whether or not digitally sign the request parameters with JWT signature. + */ +@property (assign, readonly) BOOL sign; + + +/** + NSString value of the specific end point path fragment to append to the base Gateway URL. endPoint value can also be defined as full URL format; in this case, + SDK must be configured to add add the external host as a trusted source using MASSecurityConfiguration object. + */ +@property (nonatomic, strong, nullable, readonly) NSString *endPoint; + + +/** + NSData value of private key. + */ +@property (nonatomic, strong, nullable, readonly) NSData *privateKey; + + +/** + NSDictionary of type/value parameters to put into the header of a request. + */ +@property (nonatomic, strong, nullable, readonly) NSDictionary *header; + + +/** + NSDictionary of type/value parameters to put into the body of a request. + */ +@property (nonatomic, strong, nullable, readonly) NSDictionary *body; + + +/** + NSDictionary of type/value parameters to put into the URL of a request. + */ +@property (nonatomic, strong, nullable, readonly) NSDictionary *query; + + +/** + MASRequestResponseType value that specifies what type formatting is required for request body. + */ +@property (assign, readonly) MASRequestResponseType requestType; + + +/** + MASRequestResponseType value that specifies what type formatting is required for response body. + */ +@property (assign, readonly) MASRequestResponseType responseType; + + +# pragma mark - Public + + +/** + Initialize MASRequest using MASRequestBuilder block and defining the request method as a HTTP DELETE call. This type of HTTP Method type + places its parameters within the NSURL itself as an HTTP query extension. + + @discussion default values for designated initializer are: isPublic: NO, sign: NO, requestType:MASRequestResponseTypeJson, responseType:MASRequestResponseTypeJson. + @param block MASRequestBuilder block containing all paramters to build the request. + @return MASRequestBuilder object + */ ++ (instancetype _Nullable)deleteFrom:(void (^_Nonnull)(MASRequestBuilder* _Nonnull builder))block; + + + +/** + Initialize MASRequest using MASRequestBuilder block and defining the request method as a HTTP GET call. This type of HTTP Method type + places its parameters within the NSURL itself as an HTTP query extension. + + @discussion default values for designated initializer are: isPublic: NO, sign: NO, requestType:MASRequestResponseTypeJson, responseType:MASRequestResponseTypeJson. + @param block MASRequestBuilder block containing all paramters to build the request. + @return MASRequestBuilder object + */ ++ (instancetype _Nullable)getFrom:(void (^_Nonnull)(MASRequestBuilder* _Nonnull builder))block; + + + +/** + Initialize MASRequest using MASRequestBuilder block and defining the request method as a HTTP PATCH call. This type of HTTP Method type + places its parameters within the HTTP body in www-form-url-encoded format. + + @discussion default values for designated initializer are: isPublic: NO, sign: NO, requestType:MASRequestResponseTypeJson, responseType:MASRequestResponseTypeJson. + @param block MASRequestBuilder block containing all paramters to build the request. + @return MASRequestBuilder object + */ ++ (instancetype _Nullable)patchTo:(void (^_Nonnull)(MASRequestBuilder* _Nonnull builder))block; + + + +/** + Initialize MASRequest using MASRequestBuilder block and defining the request method as a HTTP POST call. This type of HTTP Method type + places its parameters within the HTTP body in www-form-url-encoded format. + + @discussion default values for designated initializer are: isPublic: NO, sign: NO, requestType:MASRequestResponseTypeJson, responseType:MASRequestResponseTypeJson. + @param block MASRequestBuilder block containing all paramters to build the request. + @return MASRequestBuilder object + */ ++ (instancetype _Nullable)postTo:(void (^_Nonnull)(MASRequestBuilder* _Nonnull builder))block; + + + +/** + Initialize MASRequest using MASRequestBuilder block and defining the request method as a HTTP PUT call. This type of HTTP Method type + places its parameters within the HTTP body in www-form-url-encoded format. + + @discussion default values for designated initializer are: isPublic: NO, sign: NO, requestType:MASRequestResponseTypeJson, responseType:MASRequestResponseTypeJson. + @param block MASRequestBuilder block containing all paramters to build the request. + @return MASRequestBuilder object + */ ++ (instancetype _Nullable)putTo:(void (^_Nonnull)(MASRequestBuilder* _Nonnull builder))block; + + + +@end diff --git a/MASFoundation/Classes/models/Network/MASRequest.m b/MASFoundation/Classes/models/Network/MASRequest.m new file mode 100644 index 00000000..c63179d8 --- /dev/null +++ b/MASFoundation/Classes/models/Network/MASRequest.m @@ -0,0 +1,71 @@ +// +// MASRequest.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 "MASRequest.h" + +@interface MASRequest () + +@property (nonatomic, readwrite) NSString *endPoint; +@property (nonatomic, readwrite) NSString *httpMethod; +@property (nonatomic, readwrite) NSData *privateKey; +@property (nonatomic, readwrite) NSDictionary *header; +@property (nonatomic, readwrite) NSDictionary *body; +@property (nonatomic, readwrite) NSDictionary *query; +@property (assign, readwrite) BOOL isPublic; +@property (assign, readwrite) BOOL sign; +@property (assign, readwrite) MASRequestResponseType requestType; +@property (assign, readwrite) MASRequestResponseType responseType; + +@end + +@implementation MASRequest + + ++ (instancetype)deleteFrom:(void (^)(MASRequestBuilder *builder))block { + + MASRequestBuilder *builder = [[MASRequestBuilder alloc] initWithHTTPMethod:@"DELETE"]; + block(builder); + return [builder build]; +} + + ++ (instancetype)getFrom:(void (^)(MASRequestBuilder *builder))block { + + MASRequestBuilder *builder = [[MASRequestBuilder alloc] initWithHTTPMethod:@"GET"]; + block(builder); + return [builder build]; +} + + ++ (instancetype)patchTo:(void (^)(MASRequestBuilder *builder))block { + + MASRequestBuilder *builder = [[MASRequestBuilder alloc] initWithHTTPMethod:@"PATCH"]; + block(builder); + return [builder build]; +} + + ++ (instancetype)postTo:(void (^)(MASRequestBuilder *builder))block { + + MASRequestBuilder *builder = [[MASRequestBuilder alloc] initWithHTTPMethod:@"POST"]; + block(builder); + return [builder build]; +} + + ++ (instancetype)putTo:(void (^)(MASRequestBuilder *builder))block { + + MASRequestBuilder *builder = [[MASRequestBuilder alloc] initWithHTTPMethod:@"PUT"]; + block(builder); + return [builder build]; +} + + +@end diff --git a/MASFoundation/Classes/models/Network/MASRequestBuilder.h b/MASFoundation/Classes/models/Network/MASRequestBuilder.h new file mode 100644 index 00000000..368ab55f --- /dev/null +++ b/MASFoundation/Classes/models/Network/MASRequestBuilder.h @@ -0,0 +1,194 @@ +// +// MASRequestBuilder.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 "MASClaims.h" + +@class MASRequest; + +/** + MASRequestBuilder class is an object that allows developers to progressively build a request as needed. + The class is mainly responsible to receive parameters and create a MASRequest object. + + Default configuration value for designated initializer, [[MASRequestBuilder alloc] initWithHTTPMethod:], would be: + isPublic: NO, + sign: NO, + requestType:MASRequestResponseTypeJson, + responseType:MASRequestResponseTypeJson. + */ +@interface MASRequestBuilder : MASObject + + +///-------------------------------------- +/// @name Properties +///-------------------------------------- + +# pragma mark - Properties + + +/** + NSString value of the HTTP Method (GET, POST, PUT, DELETE). + */ +@property (nonatomic, strong, readonly) NSString * _Nonnull httpMethod; + + +/** + BOOL value that determines whether or not to include credentials of primary gateway in the request. + */ +@property (assign) BOOL isPublic; + + +/** + BOOL value that determines whether or not digitally sign the request parameters with JWT signature. + */ +@property (assign, readonly) BOOL sign; + + +/** + NSString value of the target endpoint. + */ +@property (nonatomic, strong, nullable) NSString *endPoint; + + +/** + MASClaims object containing claims for JWT. + */ +@property (nonatomic, strong, nullable, readonly) MASClaims *claims; + + +/** + NSData value of private key. + */ +@property (nonatomic, strong, nullable, readonly) NSData *privateKey; + + +/** + NSDictionary of type/value parameters to put into the header of a request. + */ +@property (nonatomic, strong, nullable) NSDictionary *header; + + +/** + NSDictionary of type/value parameters to put into the body of a request. + */ +@property (nonatomic, strong, nullable) NSDictionary *body; + + +/** + NSDictionary of type/value parameters to put into the URL of a request. + */ +@property (nonatomic, strong, nullable) NSDictionary *query; + + +/** + MASRequestResponseType value that specifies what type formatting is required for request body. + */ +@property (assign) MASRequestResponseType requestType; + + +/** + MASRequestResponseType value that specifies what type formatting is required for response body. + */ +@property (assign) MASRequestResponseType responseType; + + +///-------------------------------------- +/// @name Lifecycle +///-------------------------------------- + +# pragma mark - Lifecycle + + +/** + Designated initializer for MASRequestBuilder. + + @discussion default values for designated initializer are: isPublic: NO, sign: NO, requestType:MASRequestResponseTypeJson, responseType:MASRequestResponseTypeJson. + @param method NSString of the HTTP Method (GET, POST, PUT, DELETE) + @return MASRequestBuilder object + */ +- (instancetype _Nonnull)initWithHTTPMethod:(NSString *_Nonnull)method NS_DESIGNATED_INITIALIZER; + + + +///-------------------------------------- +/// @name Public +///-------------------------------------- + +# pragma mark - Public + + +/** + Create a MASRequest object using the parameters from MASRequestBuider + + @return MASRequest object + */ +- (MASRequest *_Nullable)build; + + + +/** + Set to sign the body of request using default private key from device registration against primary gateway. + + @param error NSError error reference object that returns any error occurred during JWT signature. + */ +- (void)setSignWithError:(NSError *__nullable __autoreleasing *__nullable)error; + + + +/** + Set to sign the request with a MASClaims object using default private key from device registration against primary gateway. + + @param claims MASClaims object containing claims for JWT + @param error NSError error reference object that returns any error occurred during JWT signature. + */ +- (void)setSignWithClaims:(MASClaims *_Nonnull)claims error:(NSError *__nullable __autoreleasing *__nullable)error; + + + +/** + Set to sign the request with a MASClaims object using custom private key in NSData format. + + @param privateKey Custom private key in NSData format signed using RS256 algorithm. + @param error NSError error reference object that returns any error occurred during JWT signature. + */ +- (void)setSignWithClaims:(MASClaims *_Nonnull)claims privateKey:(NSData *_Nonnull)privateKey error:(NSError *__nullable __autoreleasing *__nullable)error; + + + +/** + Append parameter into the header of a request. + + @param key NSString containing name/type of the parameter. + @param value NSString containing value of the parameter. + */ +- (void)setHeaderParameter:(NSString *_Nonnull)key value:(NSString *_Nonnull)value; + + + +/** + Append parameter into the body of a request. + + @param key NSString containing name/type of the parameter. + @param value NSString containing value of the parameter. + */ +- (void)setBodyParameter:(NSString *_Nonnull)key value:(NSString *_Nonnull)value; + + + +/** + Append parameter into the URL of a request. + + @param key NSString containing name/type of the parameter. + @param value NSString containing value of the parameter. + */ +- (void)setQueryParameter:(NSString *_Nonnull)key value:(NSString *_Nonnull)value; + + + +@end diff --git a/MASFoundation/Classes/models/Network/MASRequestBuilder.m b/MASFoundation/Classes/models/Network/MASRequestBuilder.m new file mode 100644 index 00000000..d5531630 --- /dev/null +++ b/MASFoundation/Classes/models/Network/MASRequestBuilder.m @@ -0,0 +1,149 @@ +// +// MASRequestBuilder.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 "MASRequestBuilder.h" + +#import "MASRequest+MASPrivate.h" + +@interface MASRequestBuilder () + +@property (nonatomic, strong, readwrite) NSString *httpMethod; +@property (assign, readwrite) BOOL sign; +@property (nonatomic, strong, readwrite) MASClaims *claims; +@property (nonatomic, strong, readwrite) NSData *privateKey; +@end + +@implementation MASRequestBuilder + + +# pragma mark - Lifecycle + + +- (instancetype)initWithHTTPMethod:(NSString *)method +{ + self = [super init]; + + if (self) { + self.httpMethod = method; + self.isPublic = NO; + self.sign = NO; + self.requestType = MASRequestResponseTypeJson; + self.responseType = MASRequestResponseTypeJson; + } + + return self; +} + + +# pragma mark - Public + + +- (MASRequest *)build +{ + return [[MASRequest alloc] initWithBuilder:self]; +} + + +- (void)setSignWithError:(NSError *__nullable __autoreleasing *__nullable)error +{ + self.sign = TRUE; + + // + // create a new MASClaims and set the body content + // + MASClaims *claims = [MASClaims claims]; + claims.content = self.body; + claims.contentType = @"application/json"; + self.claims = claims; + + NSString *jwt = [MAS signWithClaims:claims error:error]; + + // + // injects JWT claims into the payload + // + if (!*error) + { + [self setBody:@{@"jwt":jwt}]; + } + +} + +- (void)setSignWithClaims:(MASClaims *)claims error:(NSError *__nullable __autoreleasing *__nullable)error +{ + self.sign = TRUE; + self.claims = claims; + + NSString *jwt = [MAS signWithClaims:claims error:error]; + + // + // injects JWT claims into the payload + // + if (!*error) + { + [self setBody:@{@"jwt":jwt}]; + } +} + + +- (void)setSignWithClaims:(MASClaims *)claims privateKey:(NSData *)privateKey error:(NSError *__nullable __autoreleasing *__nullable)error +{ + self.sign = TRUE; + self.claims = claims; + self.privateKey = privateKey; + + NSString *jwt = [MAS signWithClaims:claims privateKey:self.privateKey error:error]; + + // + // injects JWT claims into the payload + // + if (!*error) + { + [self setBody:@{@"jwt":jwt}]; + } +} + + +- (void)setHeaderParameter:(NSString *)key value:(NSString *)value +{ + if(self.header) + { + [self.header setValue:value forKey:key]; + } + else { + self.header = [[NSDictionary alloc] initWithObjectsAndKeys:value,key, nil]; + } +} + + +- (void)setBodyParameter:(NSString *)key value:(NSString *)value +{ + if(self.body) + { + [self.body setValue:value forKey:key]; + } + else { + self.body = [[NSDictionary alloc] initWithObjectsAndKeys:value,key, nil]; + } +} + + +- (void)setQueryParameter:(NSString *)key value:(NSString *)value +{ + if(self.query) + { + [self.query setValue:value forKey:key]; + } + else { + self.query = [[NSDictionary alloc] initWithObjectsAndKeys:value,key, nil]; + } +} + + +@end diff --git a/MASFoundation/MASFoundation.h b/MASFoundation/MASFoundation.h index 15882b5e..268dec54 100644 --- a/MASFoundation/MASFoundation.h +++ b/MASFoundation/MASFoundation.h @@ -51,6 +51,8 @@ FOUNDATION_EXPORT const unsigned char MASFoundationVersionString[]; #import #import #import +#import +#import // // AuthCredentials Models