From d3faaa2264172475358b18eee87f845373911a18 Mon Sep 17 00:00:00 2001 From: Rodrigo Reis Date: Tue, 5 Sep 2017 16:28:58 -0700 Subject: [PATCH 01/51] US374082 : [iOS] MAS network enhancement with tasks and RequestBuilder Interface to align with Android --- MASFoundation.xcodeproj/project.pbxproj | 34 +++- MASFoundation/Classes/MAS.h | 6 +- MASFoundation/Classes/MAS.m | 27 +++ .../models/Network/MASRequest+MASPrivate.h | 24 +++ .../models/Network/MASRequest+MASPrivate.m | 139 ++++++++++++++ .../Classes/models/Network/MASRequest.h | 145 +++++++++++++++ .../Classes/models/Network/MASRequest.m | 64 +++++++ .../models/Network/MASRequestBuilder.h | 172 ++++++++++++++++++ .../models/Network/MASRequestBuilder.m | 98 ++++++++++ MASFoundation/MASFoundation.h | 2 + 10 files changed, 709 insertions(+), 2 deletions(-) create mode 100644 MASFoundation/Classes/_private_/models/Network/MASRequest+MASPrivate.h create mode 100644 MASFoundation/Classes/_private_/models/Network/MASRequest+MASPrivate.m create mode 100644 MASFoundation/Classes/models/Network/MASRequest.h create mode 100644 MASFoundation/Classes/models/Network/MASRequest.m create mode 100644 MASFoundation/Classes/models/Network/MASRequestBuilder.h create mode 100644 MASFoundation/Classes/models/Network/MASRequestBuilder.m diff --git a/MASFoundation.xcodeproj/project.pbxproj b/MASFoundation.xcodeproj/project.pbxproj index 918ddd4e..0a039527 100644 --- a/MASFoundation.xcodeproj/project.pbxproj +++ b/MASFoundation.xcodeproj/project.pbxproj @@ -141,6 +141,12 @@ 10738A3E1C711C2F00B7E87E /* will_mosq.h in Headers */ = {isa = PBXBuildFile; fileRef = 10738A201C711C2F00B7E87E /* will_mosq.h */; }; 10D2D49E1C1686ED00DF8AC4 /* MASGroup+MASPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 10D2D49C1C1686ED00DF8AC4 /* MASGroup+MASPrivate.h */; }; 10D2D49F1C1686ED00DF8AC4 /* MASGroup+MASPrivate.m in Sources */ = {isa = PBXBuildFile; fileRef = 10D2D49D1C1686ED00DF8AC4 /* MASGroup+MASPrivate.m */; }; + 69BD8ABA1F55ED5B00045C3A /* MASRequestBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = 69BD8AB81F55ED5B00045C3A /* MASRequestBuilder.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 69BD8ABB1F55ED5B00045C3A /* MASRequestBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = 69BD8AB91F55ED5B00045C3A /* MASRequestBuilder.m */; }; + 69BD8ABE1F55ED8300045C3A /* MASRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 69BD8ABC1F55ED8300045C3A /* MASRequest.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 69BD8ABF1F55ED8300045C3A /* MASRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 69BD8ABD1F55ED8300045C3A /* MASRequest.m */; }; + 69BD8AC21F58C02900045C3A /* MASRequest+MASPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 69BD8AC01F58C02900045C3A /* MASRequest+MASPrivate.h */; }; + 69BD8AC31F58C02900045C3A /* MASRequest+MASPrivate.m in Sources */ = {isa = PBXBuildFile; fileRef = 69BD8AC11F58C02900045C3A /* 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 */; }; @@ -553,6 +559,12 @@ 10738A201C711C2F00B7E87E /* will_mosq.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = will_mosq.h; sourceTree = ""; }; 10D2D49C1C1686ED00DF8AC4 /* MASGroup+MASPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MASGroup+MASPrivate.h"; sourceTree = ""; }; 10D2D49D1C1686ED00DF8AC4 /* MASGroup+MASPrivate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MASGroup+MASPrivate.m"; sourceTree = ""; }; + 69BD8AB81F55ED5B00045C3A /* MASRequestBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MASRequestBuilder.h; sourceTree = ""; }; + 69BD8AB91F55ED5B00045C3A /* MASRequestBuilder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MASRequestBuilder.m; sourceTree = ""; }; + 69BD8ABC1F55ED8300045C3A /* MASRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MASRequest.h; sourceTree = ""; }; + 69BD8ABD1F55ED8300045C3A /* MASRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MASRequest.m; sourceTree = ""; }; + 69BD8AC01F58C02900045C3A /* MASRequest+MASPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "MASRequest+MASPrivate.h"; path = "Network/MASRequest+MASPrivate.h"; sourceTree = ""; }; + 69BD8AC11F58C02900045C3A /* MASRequest+MASPrivate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "MASRequest+MASPrivate.m"; path = "Network/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 +1055,15 @@ path = libmosquitto123; sourceTree = ""; }; + 69BD8AC41F58C04E00045C3A /* Network */ = { + isa = PBXGroup; + children = ( + 69BD8AC01F58C02900045C3A /* MASRequest+MASPrivate.h */, + 69BD8AC11F58C02900045C3A /* MASRequest+MASPrivate.m */, + ); + name = Network; + sourceTree = ""; + }; A4150EBD1BF16D9A00037E27 /* network */ = { isa = PBXGroup; children = ( @@ -1288,8 +1309,8 @@ A4831A9A1BD1A551007B4AE6 /* models */ = { isa = PBXGroup; children = ( - CB23578A1F0EE35A00D4C420 /* Network */, CB9975261EDCA718006CEBB1 /* AuthCredentials */, + CB23578A1F0EE35A00D4C420 /* Network */, A4831AA51BD1A551007B4AE6 /* MASObject.h */, A4831AA61BD1A551007B4AE6 /* MASObject.m */, A4831A9B1BD1A551007B4AE6 /* MASApplication.h */, @@ -1406,6 +1427,7 @@ isa = PBXGroup; children = ( CB99752B1EDCA749006CEBB1 /* AuthCredentials */, + 69BD8AC41F58C04E00045C3A /* Network */, CB1907F11C1794FC00A5EF16 /* MASAccess.h */, CB1907F21C1794FC00A5EF16 /* MASAccess.m */, A4831AE81BD1A87C007B4AE6 /* MASApplication+MASPrivate.h */, @@ -1455,6 +1477,10 @@ CB23578A1F0EE35A00D4C420 /* Network */ = { isa = PBXGroup; children = ( + 69BD8AB81F55ED5B00045C3A /* MASRequestBuilder.h */, + 69BD8AB91F55ED5B00045C3A /* MASRequestBuilder.m */, + 69BD8ABC1F55ED8300045C3A /* MASRequest.h */, + 69BD8ABD1F55ED8300045C3A /* MASRequest.m */, ); path = Network; sourceTree = ""; @@ -1678,6 +1704,8 @@ CBD25AEA1E78C47C00DFB47F /* JWTAlgorithmDataHolder.h in Headers */, 105B2F4D1CA6B3EA0005A2D0 /* safestack.h in Headers */, 10738A2E1C711C2F00B7E87E /* net_mosq.h in Headers */, + 69BD8ABA1F55ED5B00045C3A /* MASRequestBuilder.h in Headers */, + 69BD8ABE1F55ED8300045C3A /* MASRequest.h in Headers */, 105B2F311CA6B3EA0005A2D0 /* engine.h in Headers */, A858C6651D0978A6001FB9AD /* MASOTPService.h in Headers */, A4831AAB1BD1A551007B4AE6 /* MASAuthenticationProvider.h in Headers */, @@ -1881,6 +1909,7 @@ 105B2F2D1CA6B3EA0005A2D0 /* ebcdic.h in Headers */, A46F49ED1C2F5FC500A4C370 /* MASINTULocationManager.h in Headers */, A43BEBB21BE34D7700842522 /* CLLocationManager+MASPrivate.h in Headers */, + 69BD8AC21F58C02900045C3A /* MASRequest+MASPrivate.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2038,10 +2067,12 @@ A4150EFC1BF16EE200037E27 /* MASKeyChainService.m in Sources */, A47F12811C1D73530008E3F2 /* MASBluetoothPeripheral.m in Sources */, CBD25B061E78C47C00DFB47F /* JWTCoding+VersionThree.m in Sources */, + 69BD8ABB1F55ED5B00045C3A /* MASRequestBuilder.m in Sources */, A46F4A491C2F5FC500A4C370 /* RNCryptorEngine.m in Sources */, CBD25AED1E78C47C00DFB47F /* JWTAlgorithmDataHolderChain.m in Sources */, A46F49DA1C2F5FC500A4C370 /* MASINetworkActivityIndicatorManager.m in Sources */, A4831AAE1BD1A551007B4AE6 /* MASConfiguration.m in Sources */, + 69BD8ABF1F55ED8300045C3A /* MASRequest.m in Sources */, CBA3EB2F1E945F2400E64D9D /* MASClaims.m in Sources */, CBD25B151E7A0A9200DFB47F /* MF_Base64Additions.m in Sources */, 10738A3B1C711C2F00B7E87E /* util_mosq.c in Sources */, @@ -2097,6 +2128,7 @@ A46F49C51C2F5FC500A4C370 /* MASIHTTPRequestOperation.m in Sources */, A4150E701BF1643900037E27 /* MASIJSONResponseSerializer+MASPrivate.m in Sources */, A417BA521BF033C300EC9BCB /* CLLocation+MASPrivate.m in Sources */, + 69BD8AC31F58C02900045C3A /* MASRequest+MASPrivate.m in Sources */, A4831AB21BD1A551007B4AE6 /* MASFile.m in Sources */, CB0B585A1E258C2A00BC0163 /* MASAuthorizationResponse.m in Sources */, CB5E4C651C1D1B56001B3B8A /* MASGetURLRequest.m in Sources */, diff --git a/MASFoundation/Classes/MAS.h b/MASFoundation/Classes/MAS.h index c4431e1a..19d4ee02 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 @@ -929,6 +929,10 @@ withParameters:(NSDictionary *_Nullable)parameterInfo completion:(MASResponseInfoErrorBlock _Nullable)completion; + ++ (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..f78de16a 100644 --- a/MASFoundation/Classes/MAS.m +++ b/MASFoundation/Classes/MAS.m @@ -1464,6 +1464,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/_private_/models/Network/MASRequest+MASPrivate.h b/MASFoundation/Classes/_private_/models/Network/MASRequest+MASPrivate.h new file mode 100644 index 00000000..7c12b4a6 --- /dev/null +++ b/MASFoundation/Classes/_private_/models/Network/MASRequest+MASPrivate.h @@ -0,0 +1,24 @@ +// +// MASRequest+MASPrivate.h +// MASFoundation +// +// Created by Reis, Rodrigo on 2017-08-31. +// Copyright © 2017 CA Technologies. All rights reserved. +// + +#import + +#import "MASRequest.h" +#import "MASRequestBuilder.h" + +@interface MASRequest (MASPrivate) + +/** + Private initializer for MASRequest. + + @param url NSURL of the target domain + @return MASRequest object + */ +- (id)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..447e9e85 --- /dev/null +++ b/MASFoundation/Classes/_private_/models/Network/MASRequest+MASPrivate.m @@ -0,0 +1,139 @@ +// +// MASRequest+MASPrivate.m +// MASFoundation +// +// Created by Reis, Rodrigo on 2017-08-31. +// Copyright © 2017 CA Technologies. All rights reserved. +// + +#import + +#import "MASRequest+MASPrivate.h" + + +@interface MASRequest () + +@property (nonatomic, readwrite) NSString *endPoint; +@property (nonatomic, readwrite) NSString *httpMethod; +@property (nonatomic, readwrite) MASClaims *claims; +@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 + +- (id)initWithBuilder:(MASRequestBuilder *)builder +{ + self = [super init]; + if(self) + { + 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.claims = builder.claims; + self.privateKey = builder.privateKey; + self.header = builder.header; + self.body = builder.body; + self.query = builder.query; + + NSError *error; + + // + // determines whether or not digitally sign the request parameters with JWT signature + // + if(self.sign) + { + NSString *jwt; + + // + // check if MASClaims was provided, if not create a new and set the body content + // + if(!self.claims) + { + MASClaims *claims = [MASClaims claims]; + claims.content = self.body; + claims.contentType = @"application/json"; + self.claims = claims; + } + + // + // check if custom private key was provided + // + if(self.claims && self.privateKey) + { + jwt = [MAS signWithClaims:self.claims privateKey:self.privateKey error:&error]; + } + else { + jwt = [MAS signWithClaims:self.claims error:&error]; + } + + // + // injects JWT claims into the payload + // + if (!error) + { + [self setBody:@{@"jwt":jwt}]; + } + else { + // + // Notify block + // + if(builder.completionBlock) + { + builder.completionBlock(nil, error); + + return nil; + } + } + + } + + // + // 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]; + } + + + // + // Notify block + // + if(builder.completionBlock) + { + builder.completionBlock(nil, error); + } + } + + return self; +} + + +@end diff --git a/MASFoundation/Classes/models/Network/MASRequest.h b/MASFoundation/Classes/models/Network/MASRequest.h new file mode 100644 index 00000000..e116603f --- /dev/null +++ b/MASFoundation/Classes/models/Network/MASRequest.h @@ -0,0 +1,145 @@ +// +// MASRequest.h +// MASFoundation +// +// Created by Reis, Rodrigo on 2017-08-29. +// Copyright © 2017 CA Technologies. All rights reserved. +// + +#import + +#import "MASClaims.h" +#import "MASRequestBuilder.h" + +/** + MASRequest class is an object created by MASRequestBuilder. It's contains all parameters necessary to invoke an API. + The class cannot be constructed or changed directly, only through MASRequestBuilder. + */ +@interface MASRequest : NSObject + +NS_ASSUME_NONNULL_BEGIN + + +///-------------------------------------- +/// @name Properties +///-------------------------------------- + +# pragma mark - Properties + +/** + NSString value of the HTTP Method (GET, POST, PUT, DELETE). + */ +@property (nonatomic, strong, readonly) NSString *httpMethod; + +/** + BOOL value that determines whether or not the target host is a primary gateway or another gateway/public server. + */ +@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; + +/** + 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, 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 it's 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)delete:(void (^)(MASRequestBuilder *))block; + + +/** + Initialize MASRequest using MASRequestBuilder block and defining the request method as a HTTP GET call. This type of HTTP Method type + places it's 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)get:(void (^)(MASRequestBuilder *))block; + + +/** + Initialize MASRequest using MASRequestBuilder block and defining the request method as a HTTP PATCH call. This type of HTTP Method type + places it's 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)patch:(void (^)(MASRequestBuilder *))block; + + +/** + Initialize MASRequest using MASRequestBuilder block and defining the request method as a HTTP POST call. This type of HTTP Method type + places it's 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)post:(void (^)(MASRequestBuilder *))block; + + +/** + Initialize MASRequest using MASRequestBuilder block and defining the request method as a HTTP PUT call. This type of HTTP Method type + places it's 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)put:(void (^)(MASRequestBuilder *))block; + +NS_ASSUME_NONNULL_END + +@end diff --git a/MASFoundation/Classes/models/Network/MASRequest.m b/MASFoundation/Classes/models/Network/MASRequest.m new file mode 100644 index 00000000..0e5329af --- /dev/null +++ b/MASFoundation/Classes/models/Network/MASRequest.m @@ -0,0 +1,64 @@ +// +// MASRequest.m +// MASFoundation +// +// Created by Reis, Rodrigo on 2017-08-29. +// Copyright © 2017 CA Technologies. All rights reserved. +// + +#import "MASRequest.h" + +@interface MASRequest () + +@property (nonatomic, readwrite) NSString *endPoint; +@property (nonatomic, readwrite) NSString *httpMethod; +@property (nonatomic, readwrite) MASClaims *claims; +@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)delete:(void (^)(MASRequestBuilder *))block { + + MASRequestBuilder *builder = [[MASRequestBuilder alloc] initWithHTTPMethod:@"DELETE"]; + block(builder); + return [builder build]; +} + ++ (instancetype)get:(void (^)(MASRequestBuilder *))block { + + MASRequestBuilder *builder = [[MASRequestBuilder alloc] initWithHTTPMethod:@"GET"]; + block(builder); + return [builder build]; +} + ++ (instancetype)patch:(void (^)(MASRequestBuilder *))block { + + MASRequestBuilder *builder = [[MASRequestBuilder alloc] initWithHTTPMethod:@"PATCH"]; + block(builder); + return [builder build]; +} + ++ (instancetype)post:(void (^)(MASRequestBuilder *))block { + + MASRequestBuilder *builder = [[MASRequestBuilder alloc] initWithHTTPMethod:@"POST"]; + block(builder); + return [builder build]; +} + ++ (instancetype)put:(void (^)(MASRequestBuilder *))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..3d5d7195 --- /dev/null +++ b/MASFoundation/Classes/models/Network/MASRequestBuilder.h @@ -0,0 +1,172 @@ +// +// MASRequestBuilder.h +// MASFoundation +// +// Created by Reis, Rodrigo on 2017-08-29. +// Copyright © 2017 CA Technologies. All rights reserved. +// + +#import + +#import "MASClaims.h" + +/** + MASRequestBuilder class is an object that allows developers to progressively build a request as needed. + The class is mainly responsible for 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 : NSObject + +NS_ASSUME_NONNULL_BEGIN + +///-------------------------------------- +/// @name Properties +///-------------------------------------- + +# pragma mark - Properties + + +/** + NSString value of the HTTP Method (GET, POST, PUT, DELETE). + */ +@property (nonatomic, strong, readonly) NSString *httpMethod; + +/** + BOOL value that determines whether or not the target host is a primary gateway or another gateway/public server. + */ +@property (assign) BOOL isPublic; + +/** + BOOL value that determines whether or not digitally sign the request parameters with JWT signature. + */ +@property (assign) BOOL sign; + +/** + NSString value of the target endpoint. + */ +@property (nonatomic, strong, nullable) NSString *endPoint; + +/** + MASClaims object containing claims for JWT. + */ +@property (nonatomic, strong, nullable) MASClaims *claims; + +/** + NSData value of private key. + */ +@property (nonatomic, strong, nullable) 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; + +/** + MASResponseInfoErrorBlock (NSDictionary *responseInfo, NSError *error) property that will + receive the JSON response object or an NSError object if there is a failure. + */ +@property (nonatomic, strong, nullable) MASResponseInfoErrorBlock completionBlock; + + +///-------------------------------------- +/// @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)initWithHTTPMethod:(NSString *)method NS_DESIGNATED_INITIALIZER; + +///-------------------------------------- +/// @name Public +///-------------------------------------- + +# pragma mark - Public + + +/** + 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. + */ +- (id)build; + + +/** + 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 + */ +- (void)setSignWithClaims:(MASClaims *)claims; + + +/** + 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. + */ +- (void)setSignWithClaims:(MASClaims *)claims privateKey:(NSData *)privateKey; + + +/** + 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 *)key value:(NSString *)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 *)key value:(NSString *)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 *)key value:(NSString *)value; + + +NS_ASSUME_NONNULL_END + +@end diff --git a/MASFoundation/Classes/models/Network/MASRequestBuilder.m b/MASFoundation/Classes/models/Network/MASRequestBuilder.m new file mode 100644 index 00000000..94991acf --- /dev/null +++ b/MASFoundation/Classes/models/Network/MASRequestBuilder.m @@ -0,0 +1,98 @@ +// +// MASRequestBuilder.m +// MASFoundation +// +// Created by Reis, Rodrigo on 2017-08-29. +// Copyright © 2017 CA Technologies. All rights reserved. +// + +#import "MASRequestBuilder.h" + +#import "MASRequest+MASPrivate.h" + +@interface MASRequestBuilder () + +@property (nonatomic, strong, readwrite) NSString *httpMethod; + +@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 + +- (id)build +{ + return [[MASRequest alloc] initWithBuilder:self]; +} + + +- (void)setSignWithClaims:(MASClaims *)claims +{ + self.sign = TRUE; + self.claims = claims; +} + + +- (void)setSignWithClaims:(MASClaims *)claims privateKey:(NSData *)privateKey +{ + self.sign = TRUE; + self.claims = claims; + self.privateKey = privateKey; +} + + +- (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 From 9e165a2f9b82686c4b6f1b9981742a0e556ba080 Mon Sep 17 00:00:00 2001 From: Rodrigo Reis Date: Wed, 6 Sep 2017 15:31:43 -0700 Subject: [PATCH 02/51] Updated license information in the files. --- .../_private_/models/Network/MASRequest+MASPrivate.h | 6 ++++-- .../_private_/models/Network/MASRequest+MASPrivate.m | 6 ++++-- MASFoundation/Classes/models/Network/MASRequest.h | 6 ++++-- MASFoundation/Classes/models/Network/MASRequest.m | 6 ++++-- MASFoundation/Classes/models/Network/MASRequestBuilder.h | 6 ++++-- MASFoundation/Classes/models/Network/MASRequestBuilder.m | 6 ++++-- 6 files changed, 24 insertions(+), 12 deletions(-) diff --git a/MASFoundation/Classes/_private_/models/Network/MASRequest+MASPrivate.h b/MASFoundation/Classes/_private_/models/Network/MASRequest+MASPrivate.h index 7c12b4a6..97a57c86 100644 --- a/MASFoundation/Classes/_private_/models/Network/MASRequest+MASPrivate.h +++ b/MASFoundation/Classes/_private_/models/Network/MASRequest+MASPrivate.h @@ -2,8 +2,10 @@ // MASRequest+MASPrivate.h // MASFoundation // -// Created by Reis, Rodrigo on 2017-08-31. -// Copyright © 2017 CA Technologies. All rights reserved. +// 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 diff --git a/MASFoundation/Classes/_private_/models/Network/MASRequest+MASPrivate.m b/MASFoundation/Classes/_private_/models/Network/MASRequest+MASPrivate.m index 447e9e85..d2859df9 100644 --- a/MASFoundation/Classes/_private_/models/Network/MASRequest+MASPrivate.m +++ b/MASFoundation/Classes/_private_/models/Network/MASRequest+MASPrivate.m @@ -2,8 +2,10 @@ // MASRequest+MASPrivate.m // MASFoundation // -// Created by Reis, Rodrigo on 2017-08-31. -// Copyright © 2017 CA Technologies. All rights reserved. +// 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 diff --git a/MASFoundation/Classes/models/Network/MASRequest.h b/MASFoundation/Classes/models/Network/MASRequest.h index e116603f..624aafee 100644 --- a/MASFoundation/Classes/models/Network/MASRequest.h +++ b/MASFoundation/Classes/models/Network/MASRequest.h @@ -2,8 +2,10 @@ // MASRequest.h // MASFoundation // -// Created by Reis, Rodrigo on 2017-08-29. -// Copyright © 2017 CA Technologies. All rights reserved. +// 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 diff --git a/MASFoundation/Classes/models/Network/MASRequest.m b/MASFoundation/Classes/models/Network/MASRequest.m index 0e5329af..9d2736de 100644 --- a/MASFoundation/Classes/models/Network/MASRequest.m +++ b/MASFoundation/Classes/models/Network/MASRequest.m @@ -2,8 +2,10 @@ // MASRequest.m // MASFoundation // -// Created by Reis, Rodrigo on 2017-08-29. -// Copyright © 2017 CA Technologies. All rights reserved. +// 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" diff --git a/MASFoundation/Classes/models/Network/MASRequestBuilder.h b/MASFoundation/Classes/models/Network/MASRequestBuilder.h index 3d5d7195..d9ae920e 100644 --- a/MASFoundation/Classes/models/Network/MASRequestBuilder.h +++ b/MASFoundation/Classes/models/Network/MASRequestBuilder.h @@ -2,8 +2,10 @@ // MASRequestBuilder.h // MASFoundation // -// Created by Reis, Rodrigo on 2017-08-29. -// Copyright © 2017 CA Technologies. All rights reserved. +// 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 diff --git a/MASFoundation/Classes/models/Network/MASRequestBuilder.m b/MASFoundation/Classes/models/Network/MASRequestBuilder.m index 94991acf..555d5a4d 100644 --- a/MASFoundation/Classes/models/Network/MASRequestBuilder.m +++ b/MASFoundation/Classes/models/Network/MASRequestBuilder.m @@ -2,8 +2,10 @@ // MASRequestBuilder.m // MASFoundation // -// Created by Reis, Rodrigo on 2017-08-29. -// Copyright © 2017 CA Technologies. All rights reserved. +// 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" From 0acda1ff05f200695b808501a6d8ad229557d0d3 Mon Sep 17 00:00:00 2001 From: Rodrigo Reis Date: Thu, 7 Sep 2017 13:56:46 -0700 Subject: [PATCH 03/51] Updated with comments provided in the code review --- MASFoundation/Classes/MAS.h | 20 +++++- .../models/Network/MASRequest+MASPrivate.h | 7 +- .../models/Network/MASRequest+MASPrivate.m | 68 ++---------------- .../Classes/models/Network/MASRequest.h | 51 ++++++------- .../Classes/models/Network/MASRequest.m | 17 +++-- .../models/Network/MASRequestBuilder.h | 72 ++++++++++++------- .../models/Network/MASRequestBuilder.m | 57 +++++++++++++-- 7 files changed, 162 insertions(+), 130 deletions(-) diff --git a/MASFoundation/Classes/MAS.h b/MASFoundation/Classes/MAS.h index 19d4ee02..027a6e47 100644 --- a/MASFoundation/Classes/MAS.h +++ b/MASFoundation/Classes/MAS.h @@ -929,7 +929,25 @@ 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; diff --git a/MASFoundation/Classes/_private_/models/Network/MASRequest+MASPrivate.h b/MASFoundation/Classes/_private_/models/Network/MASRequest+MASPrivate.h index 97a57c86..a43d5946 100644 --- a/MASFoundation/Classes/_private_/models/Network/MASRequest+MASPrivate.h +++ b/MASFoundation/Classes/_private_/models/Network/MASRequest+MASPrivate.h @@ -8,10 +8,7 @@ // of the MIT license. See the LICENSE file for details. // -#import - -#import "MASRequest.h" -#import "MASRequestBuilder.h" +#import @interface MASRequest (MASPrivate) @@ -21,6 +18,6 @@ @param url NSURL of the target domain @return MASRequest object */ -- (id)initWithBuilder:(MASRequestBuilder *)builder; +- (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 index d2859df9..746cadce 100644 --- a/MASFoundation/Classes/_private_/models/Network/MASRequest+MASPrivate.m +++ b/MASFoundation/Classes/_private_/models/Network/MASRequest+MASPrivate.m @@ -8,8 +8,6 @@ // of the MIT license. See the LICENSE file for details. // -#import - #import "MASRequest+MASPrivate.h" @@ -17,7 +15,6 @@ @interface MASRequest () @property (nonatomic, readwrite) NSString *endPoint; @property (nonatomic, readwrite) NSString *httpMethod; -@property (nonatomic, readwrite) MASClaims *claims; @property (nonatomic, readwrite) NSData *privateKey; @property (nonatomic, readwrite) NSDictionary *header; @property (nonatomic, readwrite) NSDictionary *body; @@ -33,74 +30,25 @@ @implementation MASRequest (MASPrivate) # pragma mark - Lifecycle -- (id)initWithBuilder:(MASRequestBuilder *)builder +- (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.claims = builder.claims; self.privateKey = builder.privateKey; self.header = builder.header; self.body = builder.body; self.query = builder.query; - NSError *error; - - // - // determines whether or not digitally sign the request parameters with JWT signature - // - if(self.sign) - { - NSString *jwt; - - // - // check if MASClaims was provided, if not create a new and set the body content - // - if(!self.claims) - { - MASClaims *claims = [MASClaims claims]; - claims.content = self.body; - claims.contentType = @"application/json"; - self.claims = claims; - } - - // - // check if custom private key was provided - // - if(self.claims && self.privateKey) - { - jwt = [MAS signWithClaims:self.claims privateKey:self.privateKey error:&error]; - } - else { - jwt = [MAS signWithClaims:self.claims error:&error]; - } - - // - // injects JWT claims into the payload - // - if (!error) - { - [self setBody:@{@"jwt":jwt}]; - } - else { - // - // Notify block - // - if(builder.completionBlock) - { - builder.completionBlock(nil, error); - - return nil; - } - } - - } // // check if query parameters are provided @@ -124,14 +72,6 @@ - (id)initWithBuilder:(MASRequestBuilder *)builder self.endPoint = [components.URL absoluteString]; } - - // - // Notify block - // - if(builder.completionBlock) - { - builder.completionBlock(nil, error); - } } return self; diff --git a/MASFoundation/Classes/models/Network/MASRequest.h b/MASFoundation/Classes/models/Network/MASRequest.h index 624aafee..5b493627 100644 --- a/MASFoundation/Classes/models/Network/MASRequest.h +++ b/MASFoundation/Classes/models/Network/MASRequest.h @@ -8,18 +8,13 @@ // of the MIT license. See the LICENSE file for details. // -#import - -#import "MASClaims.h" #import "MASRequestBuilder.h" /** - MASRequest class is an object created by MASRequestBuilder. It's contains all parameters necessary to invoke an API. + 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 : NSObject - -NS_ASSUME_NONNULL_BEGIN +@interface MASRequest : MASObject ///-------------------------------------- @@ -31,54 +26,58 @@ NS_ASSUME_NONNULL_BEGIN /** NSString value of the HTTP Method (GET, POST, PUT, DELETE). */ -@property (nonatomic, strong, readonly) NSString *httpMethod; +@property (nonatomic, strong, readonly) NSString * _Nonnull httpMethod; + /** - BOOL value that determines whether or not the target host is a primary gateway or another gateway/public server. + 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; -/** - 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, 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. */ @@ -90,58 +89,62 @@ NS_ASSUME_NONNULL_BEGIN /** Initialize MASRequest using MASRequestBuilder block and defining the request method as a HTTP DELETE call. This type of HTTP Method type - places it's parameters within the NSURL itself as an HTTP query extension. + 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)delete:(void (^)(MASRequestBuilder *))block; ++ (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 it's parameters within the NSURL itself as an HTTP query extension. + 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)get:(void (^)(MASRequestBuilder *))block; ++ (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 it's parameters within the HTTP body in www-form-url-encoded format. + 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)patch:(void (^)(MASRequestBuilder *))block; ++ (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 it's parameters within the HTTP body in www-form-url-encoded format. + 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)post:(void (^)(MASRequestBuilder *))block; ++ (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 it's parameters within the HTTP body in www-form-url-encoded format. + 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)put:(void (^)(MASRequestBuilder *))block; ++ (instancetype _Nullable)putTo:(void (^_Nonnull)(MASRequestBuilder* _Nonnull builder))block; + -NS_ASSUME_NONNULL_END @end diff --git a/MASFoundation/Classes/models/Network/MASRequest.m b/MASFoundation/Classes/models/Network/MASRequest.m index 9d2736de..c63179d8 100644 --- a/MASFoundation/Classes/models/Network/MASRequest.m +++ b/MASFoundation/Classes/models/Network/MASRequest.m @@ -14,7 +14,6 @@ @interface MASRequest () @property (nonatomic, readwrite) NSString *endPoint; @property (nonatomic, readwrite) NSString *httpMethod; -@property (nonatomic, readwrite) MASClaims *claims; @property (nonatomic, readwrite) NSData *privateKey; @property (nonatomic, readwrite) NSDictionary *header; @property (nonatomic, readwrite) NSDictionary *body; @@ -28,39 +27,45 @@ @interface MASRequest () @implementation MASRequest -+ (instancetype)delete:(void (^)(MASRequestBuilder *))block { + ++ (instancetype)deleteFrom:(void (^)(MASRequestBuilder *builder))block { MASRequestBuilder *builder = [[MASRequestBuilder alloc] initWithHTTPMethod:@"DELETE"]; block(builder); return [builder build]; } -+ (instancetype)get:(void (^)(MASRequestBuilder *))block { + ++ (instancetype)getFrom:(void (^)(MASRequestBuilder *builder))block { MASRequestBuilder *builder = [[MASRequestBuilder alloc] initWithHTTPMethod:@"GET"]; block(builder); return [builder build]; } -+ (instancetype)patch:(void (^)(MASRequestBuilder *))block { + ++ (instancetype)patchTo:(void (^)(MASRequestBuilder *builder))block { MASRequestBuilder *builder = [[MASRequestBuilder alloc] initWithHTTPMethod:@"PATCH"]; block(builder); return [builder build]; } -+ (instancetype)post:(void (^)(MASRequestBuilder *))block { + ++ (instancetype)postTo:(void (^)(MASRequestBuilder *builder))block { MASRequestBuilder *builder = [[MASRequestBuilder alloc] initWithHTTPMethod:@"POST"]; block(builder); return [builder build]; } -+ (instancetype)put:(void (^)(MASRequestBuilder *))block { + ++ (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 index d9ae920e..11e8e698 100644 --- a/MASFoundation/Classes/models/Network/MASRequestBuilder.h +++ b/MASFoundation/Classes/models/Network/MASRequestBuilder.h @@ -8,13 +8,13 @@ // of the MIT license. See the LICENSE file for details. // -#import - #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 for receive parameters and create a MASRequest object. + 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, @@ -22,9 +22,8 @@ requestType:MASRequestResponseTypeJson, responseType:MASRequestResponseTypeJson. */ -@interface MASRequestBuilder : NSObject +@interface MASRequestBuilder : MASObject -NS_ASSUME_NONNULL_BEGIN ///-------------------------------------- /// @name Properties @@ -36,64 +35,68 @@ NS_ASSUME_NONNULL_BEGIN /** NSString value of the HTTP Method (GET, POST, PUT, DELETE). */ -@property (nonatomic, strong, readonly) NSString *httpMethod; +@property (nonatomic, strong, readonly) NSString * _Nonnull httpMethod; + /** - BOOL value that determines whether or not the target host is a primary gateway or another gateway/public server. + 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) BOOL sign; +@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) MASClaims *claims; +@property (nonatomic, strong, nullable, readonly) MASClaims *claims; + /** NSData value of private key. */ -@property (nonatomic, strong, nullable) NSData *privateKey; +@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; -/** - MASResponseInfoErrorBlock (NSDictionary *responseInfo, NSError *error) property that will - receive the JSON response object or an NSError object if there is a failure. - */ -@property (nonatomic, strong, nullable) MASResponseInfoErrorBlock completionBlock; - ///-------------------------------------- /// @name Lifecycle @@ -109,7 +112,9 @@ NS_ASSUME_NONNULL_BEGIN @param method NSString of the HTTP Method (GET, POST, PUT, DELETE) @return MASRequestBuilder object */ -- (instancetype)initWithHTTPMethod:(NSString *)method NS_DESIGNATED_INITIALIZER; +- (instancetype _Nonnull)initWithHTTPMethod:(NSString *_Nonnull)method NS_DESIGNATED_INITIALIZER; + + ///-------------------------------------- /// @name Public @@ -119,27 +124,41 @@ NS_ASSUME_NONNULL_BEGIN /** - Set to sign the request with a MASClaims object using custom private key in NSData format. + Create a MASRequest object using the parameters from MASRequestBuider - @param privateKey Custom private key in NSData format signed using RS256 algorithm. + @return MASRequest object */ -- (id)build; +- (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 *)claims; +- (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 *)claims privateKey:(NSData *)privateKey; +- (void)setSignWithClaims:(MASClaims *_Nonnull)claims privateKey:(NSData *_Nonnull)privateKey error:(NSError *__nullable __autoreleasing *__nullable)error; + /** @@ -148,7 +167,8 @@ NS_ASSUME_NONNULL_BEGIN @param key NSString containing name/type of the parameter. @param value NSString containing value of the parameter. */ -- (void)setHeaderParameter:(NSString *)key value:(NSString *)value; +- (void)setHeaderParameter:(NSString *_Nonnull)key value:(NSString *_Nonnull)value; + /** @@ -157,7 +177,8 @@ NS_ASSUME_NONNULL_BEGIN @param key NSString containing name/type of the parameter. @param value NSString containing value of the parameter. */ -- (void)setBodyParameter:(NSString *)key value:(NSString *)value; +- (void)setBodyParameter:(NSString *_Nonnull)key value:(NSString *_Nonnull)value; + /** @@ -166,9 +187,8 @@ NS_ASSUME_NONNULL_BEGIN @param key NSString containing name/type of the parameter. @param value NSString containing value of the parameter. */ -- (void)setQueryParameter:(NSString *)key value:(NSString *)value; +- (void)setQueryParameter:(NSString *_Nonnull)key value:(NSString *_Nonnull)value; -NS_ASSUME_NONNULL_END @end diff --git a/MASFoundation/Classes/models/Network/MASRequestBuilder.m b/MASFoundation/Classes/models/Network/MASRequestBuilder.m index 555d5a4d..49f88903 100644 --- a/MASFoundation/Classes/models/Network/MASRequestBuilder.m +++ b/MASFoundation/Classes/models/Network/MASRequestBuilder.m @@ -15,7 +15,9 @@ @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 @@ -42,24 +44,69 @@ - (instancetype)initWithHTTPMethod:(NSString *)method # pragma mark - Public -- (id)build + +- (MASRequest *)build { return [[MASRequest alloc] initWithBuilder:self]; } -- (void)setSignWithClaims:(MASClaims *)claims +- (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 +- (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}]; + } } @@ -74,6 +121,7 @@ - (void)setHeaderParameter:(NSString *)key value:(NSString *)value } } + - (void)setBodyParameter:(NSString *)key value:(NSString *)value { if(self.body) @@ -85,6 +133,7 @@ - (void)setBodyParameter:(NSString *)key value:(NSString *)value } } + - (void)setQueryParameter:(NSString *)key value:(NSString *)value { if(self.query) From 79dec946582565c051ded65d3eb410d4a32e5d9d Mon Sep 17 00:00:00 2001 From: Rodrigo Reis Date: Thu, 7 Sep 2017 15:41:48 -0700 Subject: [PATCH 04/51] Fixed some typo issues. --- MASFoundation/Classes/models/Network/MASRequestBuilder.h | 6 +++--- MASFoundation/Classes/models/Network/MASRequestBuilder.m | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/MASFoundation/Classes/models/Network/MASRequestBuilder.h b/MASFoundation/Classes/models/Network/MASRequestBuilder.h index 11e8e698..368ab55f 100644 --- a/MASFoundation/Classes/models/Network/MASRequestBuilder.h +++ b/MASFoundation/Classes/models/Network/MASRequestBuilder.h @@ -135,7 +135,7 @@ /** 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. + @param error NSError error reference object that returns any error occurred during JWT signature. */ - (void)setSignWithError:(NSError *__nullable __autoreleasing *__nullable)error; @@ -145,7 +145,7 @@ 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. + @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; @@ -155,7 +155,7 @@ 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. + @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; diff --git a/MASFoundation/Classes/models/Network/MASRequestBuilder.m b/MASFoundation/Classes/models/Network/MASRequestBuilder.m index 49f88903..d5531630 100644 --- a/MASFoundation/Classes/models/Network/MASRequestBuilder.m +++ b/MASFoundation/Classes/models/Network/MASRequestBuilder.m @@ -68,7 +68,7 @@ - (void)setSignWithError:(NSError *__nullable __autoreleasing *__nullable)error // // injects JWT claims into the payload // - if (!error) + if (!*error) { [self setBody:@{@"jwt":jwt}]; } @@ -85,7 +85,7 @@ - (void)setSignWithClaims:(MASClaims *)claims error:(NSError *__nullable __autor // // injects JWT claims into the payload // - if (!error) + if (!*error) { [self setBody:@{@"jwt":jwt}]; } @@ -103,7 +103,7 @@ - (void)setSignWithClaims:(MASClaims *)claims privateKey:(NSData *)privateKey er // // injects JWT claims into the payload // - if (!error) + if (!*error) { [self setBody:@{@"jwt":jwt}]; } From fd39a675cd0910815783429749ef9786a349765b Mon Sep 17 00:00:00 2001 From: James Go Date: Wed, 27 Sep 2017 16:48:23 -0700 Subject: [PATCH 05/51] DE311841 : [Cordova] [iOS] Closing the login screen and invoking the protected API, call get successful falling back to client credentials --- .../_deprecated_/L7SBrowserURLProtocol.m | 50 ++++--------------- 1 file changed, 10 insertions(+), 40 deletions(-) diff --git a/MASFoundation/Classes/_private_/_deprecated_/L7SBrowserURLProtocol.m b/MASFoundation/Classes/_private_/_deprecated_/L7SBrowserURLProtocol.m index 24f00524..5e0989d7 100644 --- a/MASFoundation/Classes/_private_/_deprecated_/L7SBrowserURLProtocol.m +++ b/MASFoundation/Classes/_private_/_deprecated_/L7SBrowserURLProtocol.m @@ -65,48 +65,18 @@ + (BOOL)requestIsCacheEquivalent:(NSURLRequest *)a toRequest:(NSURLRequest *)b { - (void)startLoading { NSMutableURLRequest *newRequest = [self.request mutableCopy]; - if ([MASApplication currentApplication].isAuthenticated) { - - if ([self.class isProtectedResource:self.request.URL]) - { - NSString *authorization = [MASUser authorizationBearerWithAccessToken]; - [newRequest setValue:authorization forHTTPHeaderField:@"Authorization"]; - [NSURLProtocol setProperty:@YES forKey:@"AuthorizationSet" inRequest:newRequest]; - } - else { - [NSURLProtocol setProperty:@NO forKey:@"AuthorizationSet" inRequest:newRequest]; - } - - self.connection = [NSURLConnection connectionWithRequest:newRequest delegate:self]; - } - else + + if ([MASApplication currentApplication].isAuthenticated && [self.class isProtectedResource:self.request.URL]) { - [self stopLoading]; - - [MAS setGrantFlow:MASGrantFlowClientCredentials]; - - [MAS start:^(BOOL completed, NSError *error) { - - if(error) - { - return; - } - else if (completed){ - - if ([self.class isProtectedResource:self.request.URL]) - { - NSString *authorization = [MASUser authorizationBearerWithAccessToken]; - [newRequest setValue:authorization forHTTPHeaderField:@"Authorization"]; - [NSURLProtocol setProperty:@YES forKey:@"AuthorizationSet" inRequest:newRequest]; - } - else { - [NSURLProtocol setProperty:@NO forKey:@"AuthorizationSet" inRequest:newRequest]; - } - - self.connection = [NSURLConnection connectionWithRequest:newRequest delegate:self]; - } - }]; + NSString *authorization = [MASUser authorizationBearerWithAccessToken]; + [newRequest setValue:authorization forHTTPHeaderField:@"Authorization"]; + [NSURLProtocol setProperty:@YES forKey:@"AuthorizationSet" inRequest:newRequest]; } + else { + [NSURLProtocol setProperty:@NO forKey:@"AuthorizationSet" inRequest:newRequest]; + } + + self.connection = [NSURLConnection connectionWithRequest:newRequest delegate:self]; } From 473cbed6dd62adacdeb7f5e8e6372163ca133814 Mon Sep 17 00:00:00 2001 From: James Go Date: Tue, 3 Oct 2017 17:31:43 -0700 Subject: [PATCH 06/51] US399506 : [iOS] MQTT Integration MAS Connecta CA public Cert --- MASFoundation/Classes/MQTT/MASMQTTClient.m | 4 +- .../_private_/services/file/MASFileService.m | 4 +- .../services/model/MASModelService.m | 6 +-- .../services/security/MASSecurityService.h | 12 +++--- .../services/security/MASSecurityService.m | 37 ++++++++++--------- 5 files changed, 32 insertions(+), 31 deletions(-) diff --git a/MASFoundation/Classes/MQTT/MASMQTTClient.m b/MASFoundation/Classes/MQTT/MASMQTTClient.m index 732fc50a..66a40447 100644 --- a/MASFoundation/Classes/MQTT/MASMQTTClient.m +++ b/MASFoundation/Classes/MQTT/MASMQTTClient.m @@ -844,13 +844,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_/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..c92d2796 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 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]]; } } From fba76db03863c30dfc65b9dd9f433080d7475abb Mon Sep 17 00:00:00 2001 From: Rodrigo Reis Date: Wed, 4 Oct 2017 15:53:22 -0700 Subject: [PATCH 07/51] [iOS] MAS credentials should be stored in the keychain as device only --- .../services/access/MASAccessService.m | 24 ++++++++----------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/MASFoundation/Classes/_private_/services/access/MASAccessService.m b/MASFoundation/Classes/_private_/services/access/MASAccessService.m index 441a2d23..6674cade 100644 --- a/MASFoundation/Classes/_private_/services/access/MASAccessService.m +++ b/MASFoundation/Classes/_private_/services/access/MASAccessService.m @@ -102,36 +102,32 @@ - (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 = FALSE; + localStorage.accessibility = MASIKeyChainStoreAccessibilityAfterFirstUnlockThisDeviceOnly; + 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 = FALSE; + sharedStorage.accessibility = MASIKeyChainStoreAccessibilityAfterFirstUnlockThisDeviceOnly; + // // storage dictionary property // _storages = [NSDictionary dictionaryWithObjectsAndKeys:localStorage, kMASAccessLocalStorageKey, sharedStorage, kMASAccessSharedStorageKey, nil]; } else { - - // - // Local storage - // - MASIKeyChainStore *localStorage = [MASIKeyChainStore keyChainStoreWithService:_localStorageServiceName]; - // // storage dictionary property // From b87f3ed586574c35d1d4c3cddd57ce9eb35adafd Mon Sep 17 00:00:00 2001 From: Rodrigo Reis Date: Thu, 5 Oct 2017 10:36:37 -0700 Subject: [PATCH 08/51] Performed changes requested by James on his review. --- .../Classes/_private_/services/access/MASAccessService.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MASFoundation/Classes/_private_/services/access/MASAccessService.m b/MASFoundation/Classes/_private_/services/access/MASAccessService.m index 6674cade..1ee01a8e 100644 --- a/MASFoundation/Classes/_private_/services/access/MASAccessService.m +++ b/MASFoundation/Classes/_private_/services/access/MASAccessService.m @@ -110,7 +110,7 @@ - (void)serviceWillStart // Local storage // MASIKeyChainStore *localStorage = [MASIKeyChainStore keyChainStoreWithService:_localStorageServiceName]; - localStorage.synchronizable = FALSE; + localStorage.synchronizable = NO; localStorage.accessibility = MASIKeyChainStoreAccessibilityAfterFirstUnlockThisDeviceOnly; if ([MASConfiguration currentConfiguration].ssoEnabled && [self isAccessGroupAccessible]) @@ -119,7 +119,7 @@ - (void)serviceWillStart // Shared storage // MASIKeyChainStore *sharedStorage = [MASIKeyChainStore keyChainStoreWithService:_sharedStorageServiceName accessGroup:self.accessGroup]; - sharedStorage.synchronizable = FALSE; + sharedStorage.synchronizable = NO; sharedStorage.accessibility = MASIKeyChainStoreAccessibilityAfterFirstUnlockThisDeviceOnly; // From b0b92c46b821629dc6b6da7f0fef1991a4cf4318 Mon Sep 17 00:00:00 2001 From: Rodrigo Reis Date: Fri, 6 Oct 2017 09:09:34 -0700 Subject: [PATCH 09/51] Exposed methods to allow developer set Keychain Synchronizable property, by default, the Keychain will not be synchronized through iCloud. --- MASFoundation/Classes/MAS.h | 20 +++++++++++++++++++ MASFoundation/Classes/MAS.m | 12 +++++++++++ .../services/access/MASAccessService.h | 18 +++++++++++++++++ .../services/access/MASAccessService.m | 19 ++++++++++++++---- 4 files changed, 65 insertions(+), 4 deletions(-) diff --git a/MASFoundation/Classes/MAS.h b/MASFoundation/Classes/MAS.h index c4431e1a..84741825 100644 --- a/MASFoundation/Classes/MAS.h +++ b/MASFoundation/Classes/MAS.h @@ -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 ///-------------------------------------- diff --git a/MASFoundation/Classes/MAS.m b/MASFoundation/Classes/MAS.m index d1981d96..a633832a 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 { // 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 1ee01a8e..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 @@ -110,8 +123,7 @@ - (void)serviceWillStart // Local storage // MASIKeyChainStore *localStorage = [MASIKeyChainStore keyChainStoreWithService:_localStorageServiceName]; - localStorage.synchronizable = NO; - localStorage.accessibility = MASIKeyChainStoreAccessibilityAfterFirstUnlockThisDeviceOnly; + localStorage.synchronizable = _isKeychainSynchronizable_; if ([MASConfiguration currentConfiguration].ssoEnabled && [self isAccessGroupAccessible]) { @@ -119,8 +131,7 @@ - (void)serviceWillStart // Shared storage // MASIKeyChainStore *sharedStorage = [MASIKeyChainStore keyChainStoreWithService:_sharedStorageServiceName accessGroup:self.accessGroup]; - sharedStorage.synchronizable = NO; - sharedStorage.accessibility = MASIKeyChainStoreAccessibilityAfterFirstUnlockThisDeviceOnly; + sharedStorage.synchronizable = _isKeychainSynchronizable_; // // storage dictionary property From 098d786d37d86cd91f12539f69f2fb1be1f06846 Mon Sep 17 00:00:00 2001 From: Rodrigo Reis Date: Wed, 11 Oct 2017 13:23:25 -0700 Subject: [PATCH 10/51] ARCHIVE_OUTPUTFOLDER update. --- MASFoundation.xcodeproj/project.pbxproj | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/MASFoundation.xcodeproj/project.pbxproj b/MASFoundation.xcodeproj/project.pbxproj index e3351493..72546735 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 = ( ); @@ -1984,18 +1985,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 */ From 088f8c38d26cfddf6c40c55187f8e03fb6df2960 Mon Sep 17 00:00:00 2001 From: James Go Date: Thu, 12 Oct 2017 15:39:51 -0700 Subject: [PATCH 11/51] US408725 : MQTT fails to re-establish connection when user logs-out, and re-logs-in with different user. --- MASFoundation/Classes/MASConstants.h | 7 +++ MASFoundation/Classes/MQTT/MASMQTTClient.m | 43 ++++++++++++++++--- .../services/model/MASModelService.m | 7 ++- MASFoundation/Classes/models/MASDevice.m | 5 +++ 4 files changed, 54 insertions(+), 8 deletions(-) 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..fdeb3739 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(self) + { + _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]; diff --git a/MASFoundation/Classes/_private_/services/model/MASModelService.m b/MASFoundation/Classes/_private_/services/model/MASModelService.m index 92284303..c0225d2e 100644 --- a/MASFoundation/Classes/_private_/services/model/MASModelService.m +++ b/MASFoundation/Classes/_private_/services/model/MASModelService.m @@ -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/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]; } From c41194e40f03d5643c8ff11f0d8fa47363e4ffb2 Mon Sep 17 00:00:00 2001 From: James Go Date: Thu, 12 Oct 2017 15:45:57 -0700 Subject: [PATCH 12/51] US408725 : MQTT fails to re-establish connection when user logs-out, and re-logs-in with different user. --- MASFoundation/Classes/MQTT/MASMQTTClient.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MASFoundation/Classes/MQTT/MASMQTTClient.m b/MASFoundation/Classes/MQTT/MASMQTTClient.m index fdeb3739..deec5139 100644 --- a/MASFoundation/Classes/MQTT/MASMQTTClient.m +++ b/MASFoundation/Classes/MQTT/MASMQTTClient.m @@ -110,7 +110,7 @@ - (void)clearConnection if ([blockSelf isEqual:_sharedClient]) { - @synchronized(self) + @synchronized(blockSelf) { _sharedClient = nil; } From e1bbb875504ad66a71e922b304131c57591f6e66 Mon Sep 17 00:00:00 2001 From: James Go Date: Fri, 13 Oct 2017 12:54:09 -0700 Subject: [PATCH 13/51] DE321921 : [iOS][MASFoundation] Remove hard coded endpoint value in MASConfiguration --- MASFoundation/Classes/models/MASConfiguration.m | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) 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"; From 141bdd61926e976c7404285d11d345a2e2fb2537 Mon Sep 17 00:00:00 2001 From: Rodrigo Reis Date: Mon, 16 Oct 2017 09:51:12 -0700 Subject: [PATCH 14/51] [iOS] Validate if VendorID exists in the sharedKeychain before sending to server --- .../_private_/models/MASDevice+MASPrivate.h | 9 +++++++++ .../_private_/models/MASDevice+MASPrivate.m | 18 +++++++++++++++++- .../services/access/MASAccessService.h | 1 + .../services/access/MASAccessService.m | 14 +++++++++++++- MASFoundation/Classes/models/MASDevice.m | 11 +++++++++++ 5 files changed, 51 insertions(+), 2 deletions(-) diff --git a/MASFoundation/Classes/_private_/models/MASDevice+MASPrivate.h b/MASFoundation/Classes/_private_/models/MASDevice+MASPrivate.h index 0b5c0fa9..ecbb5815 100644 --- a/MASFoundation/Classes/_private_/models/MASDevice+MASPrivate.h +++ b/MASFoundation/Classes/_private_/models/MASDevice+MASPrivate.h @@ -81,4 +81,13 @@ */ + (NSString *)deviceNameBase64Encoded; + +/** + * Retrieves the device vendor identifier that is uniquely generated for the + * specific device the framework is running upon. + * + * @return Returns the unique NSString device vendor identifier. + */ ++ (NSString *)deviceVendorId; + @end diff --git a/MASFoundation/Classes/_private_/models/MASDevice+MASPrivate.m b/MASFoundation/Classes/_private_/models/MASDevice+MASPrivate.m index 3ca228cf..48dab8cf 100644 --- a/MASFoundation/Classes/_private_/models/MASDevice+MASPrivate.m +++ b/MASFoundation/Classes/_private_/models/MASDevice+MASPrivate.m @@ -145,6 +145,15 @@ - (void)saveWithUpdatedInfo:(NSDictionary *)info [accessService setAccessValueNumber:[NSNumber numberWithDouble:[expirationDate timeIntervalSince1970]] withAccessValueType:MASAccessValueTypeSignedPublicCertificateExpirationDate]; } + // + // Device Vendor Id + // + NSString *deviceVendorId = [MASDevice deviceVendorId]; + if (deviceVendorId) + { + [accessService setAccessValueString:deviceVendorId withAccessValueType:MASAccessValueTypeDeviceVendorId]; + } + // // Reload MASAccess object after storing id-token and type // @@ -183,7 +192,7 @@ - (BOOL)isClientCertificateExpired + (NSString *)deviceIdBase64Encoded { - NSString *deviceId = [[[UIDevice currentDevice] identifierForVendor] UUIDString]; + NSString *deviceId = [MASDevice deviceVendorId]; // // If the sso is disabled, generate unique device id to differentiate the application's registration record from others. @@ -215,4 +224,11 @@ + (NSString *)deviceNameBase64Encoded; return [deviceNameData base64EncodedStringWithOptions:0]; } + ++ (NSString *)deviceVendorId +{ + return [[[UIDevice currentDevice] identifierForVendor] UUIDString]; +} + + @end diff --git a/MASFoundation/Classes/_private_/services/access/MASAccessService.h b/MASFoundation/Classes/_private_/services/access/MASAccessService.h index 7ab122e0..077e6038 100644 --- a/MASFoundation/Classes/_private_/services/access/MASAccessService.h +++ b/MASFoundation/Classes/_private_/services/access/MASAccessService.h @@ -51,6 +51,7 @@ typedef NS_ENUM(NSInteger, MASAccessValueType) MASAccessValueTypeTrustedServerCertificate, MASAccessValueTypeCurrentAuthCredentialsGrantType, MASAccessValueTypeMASUserObjectData, + MASAccessValueTypeDeviceVendorId, }; diff --git a/MASFoundation/Classes/_private_/services/access/MASAccessService.m b/MASFoundation/Classes/_private_/services/access/MASAccessService.m index efdb6e80..a03e0d4b 100644 --- a/MASFoundation/Classes/_private_/services/access/MASAccessService.m +++ b/MASFoundation/Classes/_private_/services/access/MASAccessService.m @@ -745,6 +745,9 @@ - (NSString *)getStorageKeyWithAccessValueType:(MASAccessValueType)type case MASAccessValueTypeMASUserObjectData: storageKey = kMASAccessSharedStorageKey; break; + case MASAccessValueTypeDeviceVendorId: + storageKey = kMASAccessSharedStorageKey; + break; default: // // MASAccessValueTypeUknonw @@ -857,24 +860,33 @@ - (NSString *)convertAccessTypeToString:(MASAccessValueType)type 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 (![self isAccessGroupAccessible]) { accessTypeToString = [NSString stringWithFormat:@"_%@", accessTypeToString]; diff --git a/MASFoundation/Classes/models/MASDevice.m b/MASFoundation/Classes/models/MASDevice.m index 645399ce..5d384a7f 100644 --- a/MASFoundation/Classes/models/MASDevice.m +++ b/MASFoundation/Classes/models/MASDevice.m @@ -55,6 +55,17 @@ - (BOOL)isRegistered // MASAccessService *accessService = [MASAccessService sharedService]; + NSString *vendorIdFromKeychain = [accessService getAccessValueStringWithType:MASAccessValueTypeDeviceVendorId]; + NSString *vendorIdCurrent = [MASDevice deviceVendorId]; + + if([vendorIdCurrent isEqualToString:vendorIdFromKeychain]) + { + NSLog(@"YES, SAME VENDOR ID ;-)"); + } + else { + NSLog(@"NOOOOO, DIFFERENT VENDOR ID :-("); + } + NSString *magIdentifier = [accessService getAccessValueStringWithType:MASAccessValueTypeMAGIdentifier]; NSData *certificateData = [accessService getAccessValueCertificateWithType:MASAccessValueTypeSignedPublicCertificate]; From 5c78b86b37cd2f02ae70e69d8a722ba919f4054f Mon Sep 17 00:00:00 2001 From: James Go Date: Mon, 16 Oct 2017 16:24:41 -0700 Subject: [PATCH 15/51] DE321925 : [iOS][MASFoundation] Configuration is not being read properly after the app update --- .../Classes/models/MASConfiguration.m | 74 ++++++++++--------- 1 file changed, 40 insertions(+), 34 deletions(-) diff --git a/MASFoundation/Classes/models/MASConfiguration.m b/MASFoundation/Classes/models/MASConfiguration.m index edd665b7..84b29b8b 100644 --- a/MASFoundation/Classes/models/MASConfiguration.m +++ b/MASFoundation/Classes/models/MASConfiguration.m @@ -166,10 +166,16 @@ -(id)valueForKeyPathWithIndexes:(NSString*)fullPath @end +@interface MASConfiguration () + +@property (strong, nonatomic) NSMutableDictionary *endpointKeysToPaths; + +@end + + @implementation MASConfiguration static NSDictionary *_configurationInfo_; -static NSMutableDictionary *_endpointKeysToPaths_; static float _systemVersionNumber_; @@ -226,12 +232,12 @@ - (void)initializeEndpointsFromInfo:(NSDictionary *)info // // If the dictionary already exists ignore the call // - if(_endpointKeysToPaths_) return; + if(_endpointKeysToPaths) return; // // Create the dictionary // - _endpointKeysToPaths_ = [NSMutableDictionary new]; + _endpointKeysToPaths = [NSMutableDictionary new]; // // OAuth Endpoints @@ -241,11 +247,11 @@ - (void)initializeEndpointsFromInfo:(NSDictionary *)info { // 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]; } @@ -257,11 +263,11 @@ - (void)initializeEndpointsFromInfo:(NSDictionary *)info { // 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]; } // @@ -278,14 +284,14 @@ - (void)initializeEndpointsFromInfo:(NSDictionary *)info NSString *scimPathInfo = masInfo[MASScimPathEndpoint]; if(scimPathInfo) { - [_endpointKeysToPaths_ addEntriesFromDictionary:@{MASScimPathEndpoint : scimPathInfo}]; + [_endpointKeysToPaths addEntriesFromDictionary:@{MASScimPathEndpoint : scimPathInfo}]; } //storage-path NSString *storagePathInfo = masInfo[MASStoragePathEndpoint]; if(scimPathInfo) { - [_endpointKeysToPaths_ addEntriesFromDictionary:@{MASStoragePathEndpoint : storagePathInfo}]; + [_endpointKeysToPaths addEntriesFromDictionary:@{MASStoragePathEndpoint : storagePathInfo}]; } } @@ -293,18 +299,18 @@ - (void)initializeEndpointsFromInfo:(NSDictionary *)info // Custom Endpoints // NSDictionary *customInfo = _configurationInfo_[MASCustomConfigurationKey]; - if(customInfo) [_endpointKeysToPaths_ addEntriesFromDictionary:customInfo]; + if(customInfo) [_endpointKeysToPaths addEntriesFromDictionary:customInfo]; // // Temporary Hardcoded Endpoints // - _endpointKeysToPaths_[MASDeviceRegisterClientEndpoint] = @"/connect/device/register/client"; + _endpointKeysToPaths[MASDeviceRegisterClientEndpoint] = @"/connect/device/register/client"; - _endpointKeysToPaths_[MASUsersLDAPEndpoint] = @"/scim/ldap/v2/users"; - _endpointKeysToPaths_[MASUserGroupsLDAPEndpoint] = @"/scim/ldap/v2/groups"; - _endpointKeysToPaths_[MASUsersMSADEndpoint] = @"/scim/msad/v2/users"; - _endpointKeysToPaths_[MASUserGroupsMSADEndpoint] = @"/scim/msad/v2/groups"; + _endpointKeysToPaths[MASUsersLDAPEndpoint] = @"/scim/ldap/v2/users"; + _endpointKeysToPaths[MASUserGroupsLDAPEndpoint] = @"/scim/ldap/v2/groups"; + _endpointKeysToPaths[MASUsersMSADEndpoint] = @"/scim/msad/v2/users"; + _endpointKeysToPaths[MASUserGroupsMSADEndpoint] = @"/scim/msad/v2/groups"; } @@ -600,7 +606,7 @@ - (NSURL *)gatewayUrl - (NSString *)endpointPathForKey:(NSString *)endpointKey { - NSString *endpointPath = _endpointKeysToPaths_[endpointKey]; + NSString *endpointPath = _endpointKeysToPaths[endpointKey]; return endpointPath; } @@ -610,97 +616,97 @@ - (NSString *)endpointPathForKey:(NSString *)endpointKey - (NSString *)scimPathEndpointPath { - return _endpointKeysToPaths_[MASScimPathEndpoint]; + return _endpointKeysToPaths[MASScimPathEndpoint]; } - (NSString *)storagePathEndpointPath { - return _endpointKeysToPaths_[MASStoragePathEndpoint]; + return _endpointKeysToPaths[MASStoragePathEndpoint]; } - (NSString *)authorizationEndpointPath { - return _endpointKeysToPaths_[MASAuthorizationEndpoint]; + return _endpointKeysToPaths[MASAuthorizationEndpoint]; } - (NSString *)clientInitializeEndpointPath { - return _endpointKeysToPaths_[MASClientInitializeEndpoint]; + return _endpointKeysToPaths[MASClientInitializeEndpoint]; } - (NSString *)authenticateOTPEndpointPath { - return _endpointKeysToPaths_[MASAuthenticateOTPEndpoint]; + return _endpointKeysToPaths[MASAuthenticateOTPEndpoint]; } - (NSString *)deviceListAllEndpointPath { - return _endpointKeysToPaths_[MASDeviceListEndpoint]; + return _endpointKeysToPaths[MASDeviceListEndpoint]; } - (NSString *)deviceRegisterEndpointPath { - return _endpointKeysToPaths_[MASDeviceRegisterEndpoint]; + return _endpointKeysToPaths[MASDeviceRegisterEndpoint]; } - (NSString *)deviceRegisterClientEndpointPath { - return _endpointKeysToPaths_[MASDeviceRegisterClientEndpoint]; + return _endpointKeysToPaths[MASDeviceRegisterClientEndpoint]; } - (NSString *)deviceRenewEndpointPath { - return _endpointKeysToPaths_[MASDeviceRenewEndpoint]; + return _endpointKeysToPaths[MASDeviceRenewEndpoint]; } - (NSString *)deviceRemoveEndpointPath { - return _endpointKeysToPaths_[MASDeviceRemoveEndpoint]; + return _endpointKeysToPaths[MASDeviceRemoveEndpoint]; } - (NSString *)enterpriseBrowserEndpointPath { - return _endpointKeysToPaths_[MASEnterpriseBrowserEndpoint]; + return _endpointKeysToPaths[MASEnterpriseBrowserEndpoint]; } - (NSString *)tokenEndpointPath { - return _endpointKeysToPaths_[MASTokenEndpoint]; + return _endpointKeysToPaths[MASTokenEndpoint]; } - (NSString *)tokenRevokeEndpointPath { - return _endpointKeysToPaths_[MASTokenRevokeEndpoint]; + return _endpointKeysToPaths[MASTokenRevokeEndpoint]; } - (NSString *)userInfoEndpointPath { - return _endpointKeysToPaths_[MASUserInfoEndpoint]; + return _endpointKeysToPaths[MASUserInfoEndpoint]; } - (NSString *)userSessionLogoutEndpointPath { - return _endpointKeysToPaths_[MASUserSessionLogoutEndpoint]; + return _endpointKeysToPaths[MASUserSessionLogoutEndpoint]; } - (NSString *)userSessionStatusEndpointPath { - return _endpointKeysToPaths_[MASUserSessionStatusEndpoint]; + return _endpointKeysToPaths[MASUserSessionStatusEndpoint]; } @@ -876,9 +882,9 @@ - (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]]; + keyToEndpoint = [NSString stringWithFormat:@" %@ = %@\n", endpointKey, _endpointKeysToPaths[endpointKey]]; [endpoints appendString:keyToEndpoint]; } [endpoints appendString:@" }"]; From c1e691b47856b45a70f3f4b426050883173971cf Mon Sep 17 00:00:00 2001 From: Rodrigo Reis Date: Mon, 16 Oct 2017 17:34:24 -0700 Subject: [PATCH 16/51] Resolved merge conflicts in project file --- MASFoundation.xcodeproj/project.pbxproj | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/MASFoundation.xcodeproj/project.pbxproj b/MASFoundation.xcodeproj/project.pbxproj index 72546735..e087a7a7 100644 --- a/MASFoundation.xcodeproj/project.pbxproj +++ b/MASFoundation.xcodeproj/project.pbxproj @@ -564,6 +564,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 = ""; }; @@ -1044,6 +1050,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 = ( @@ -1407,6 +1422,7 @@ isa = PBXGroup; children = ( CB99752B1EDCA749006CEBB1 /* AuthCredentials */, + 699C17941F958660008C1B11 /* Network */, CB1907F11C1794FC00A5EF16 /* MASAccess.h */, CB1907F21C1794FC00A5EF16 /* MASAccess.m */, A4831AE81BD1A87C007B4AE6 /* MASApplication+MASPrivate.h */, @@ -1456,6 +1472,10 @@ CB23578A1F0EE35A00D4C420 /* Network */ = { isa = PBXGroup; children = ( + 699C17911F9585BC008C1B11 /* MASRequest.h */, + 699C17901F9585BC008C1B11 /* MASRequest.m */, + 699C17921F9585BC008C1B11 /* MASRequestBuilder.h */, + 699C17931F9585BD008C1B11 /* MASRequestBuilder.m */, ); path = Network; sourceTree = ""; From a628cf8098bbd8fc7c6fdafa7256a8388e931f0e Mon Sep 17 00:00:00 2001 From: Rodrigo Reis Date: Tue, 17 Oct 2017 11:17:15 -0700 Subject: [PATCH 17/51] Fixed missing headers issue. --- MASFoundation.xcodeproj/project.pbxproj | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/MASFoundation.xcodeproj/project.pbxproj b/MASFoundation.xcodeproj/project.pbxproj index e087a7a7..aab8da93 100644 --- a/MASFoundation.xcodeproj/project.pbxproj +++ b/MASFoundation.xcodeproj/project.pbxproj @@ -152,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 */; }; @@ -1671,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 */, @@ -1894,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 */, @@ -2135,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 */, @@ -2157,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 */, @@ -2166,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 */, From e3437bc151d51990bc5817e5c965cb69ae00957c Mon Sep 17 00:00:00 2001 From: Rodrigo Reis Date: Wed, 18 Oct 2017 12:05:56 -0700 Subject: [PATCH 18/51] [iOS] Validate if VendorID exists in the sharedKeychain before sending to server --- MASFoundation/Classes/models/MASDevice.m | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/MASFoundation/Classes/models/MASDevice.m b/MASFoundation/Classes/models/MASDevice.m index 5d384a7f..0cfbfd28 100644 --- a/MASFoundation/Classes/models/MASDevice.m +++ b/MASFoundation/Classes/models/MASDevice.m @@ -50,6 +50,8 @@ + (void)setProximityLoginDelegate:(id)delegate - (BOOL)isRegistered { + _isRegistered = NO; + // // Obtain key chain items to determine registration status // @@ -57,20 +59,18 @@ - (BOOL)isRegistered NSString *vendorIdFromKeychain = [accessService getAccessValueStringWithType:MASAccessValueTypeDeviceVendorId]; NSString *vendorIdCurrent = [MASDevice deviceVendorId]; - + + // + // Check if the vendorId in Keychain macth with current vendorId + // if([vendorIdCurrent isEqualToString:vendorIdFromKeychain]) { - NSLog(@"YES, SAME VENDOR ID ;-)"); - } - else { - NSLog(@"NOOOOO, DIFFERENT VENDOR ID :-("); + NSString *magIdentifier = [accessService getAccessValueStringWithType:MASAccessValueTypeMAGIdentifier]; + NSData *certificateData = [accessService getAccessValueCertificateWithType:MASAccessValueTypeSignedPublicCertificate]; + + _isRegistered = (magIdentifier && certificateData); } - NSString *magIdentifier = [accessService getAccessValueStringWithType:MASAccessValueTypeMAGIdentifier]; - NSData *certificateData = [accessService getAccessValueCertificateWithType:MASAccessValueTypeSignedPublicCertificate]; - - _isRegistered = (magIdentifier && certificateData); - return _isRegistered; } @@ -133,7 +133,6 @@ - (void)resetLocally } - # pragma mark - Lifecycle - (id)init From 7c92035e148e37b135f74ed4f8c482d106c3411d Mon Sep 17 00:00:00 2001 From: McKercher Date: Mon, 23 Oct 2017 11:20:43 -0700 Subject: [PATCH 19/51] Product name changes --- CONTRIBUTING.md | 22 ++++----- GUIDELINES.md | 20 ++++---- README.md | 129 +++++------------------------------------------- 3 files changed, 33 insertions(+), 138 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 38d86533..3b8d6f13 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,11 +1,11 @@ -# Contribute to CA Mobile App Services SDK +# Contribute to iOS Mobile SDK Contributions are welcome and much appreciated. Just follow these easy steps to contribute. ## Code Standard and Guideline -For consistency, we ask that you adhere to some basic code guidelines when contributing to the MAS SDK. See the [Code Standard and Guideline][guidelines] for details. +For consistency, we ask that you adhere to some basic code guidelines when contributing to the iOS Mobile SDK. See the [Code Standard and Guideline][guidelines] for details. ## Our Development Process -To continue improving the SDK, the MAS development team will work on the same GitHub repos as you. The `develop branch` is used for development, and the `master branch` is used only for stable releases. +To continue improving the SDK, our development team will work on the same GitHub repos as you. The `develop branch` is used for development, and the `master branch` is used only for stable releases. **Note:** For production environments, please use releases only from the master branch. ### Pull Requests @@ -14,7 +14,7 @@ We welcome and encourage pull requests. When we get a pull request, it is peer r Follow these steps for pull requests: 1. Fork the repo and create your branch from `master`. -4. For any new code, add unit tests. +2. For any new code, add unit tests. 3. If you've changed APIs, update code comments for AppleDocs. 4. Verify that the test suite passes. 5. Verify that your code follows the [Code Standard Guideline][guidelines] @@ -44,12 +44,12 @@ Before filing a new issue, check Known Issues to see if your problem already exi * Anything else that seems relevant. ## License -By contributing to CA Mobile App Services SDK, you agree that your contributions will be licensed under its [license][license-link]. +By contributing to iOS Mobile SDK, you agree that your contributions will be licensed under its [license][license-link]. - [guidelines]: /GUIDELINES.md - [community]: https://communities.ca.com/community/ca-api-management-community/content?filterID=contentstatus%5Bpublished%5D~category%5Bca-mobile-api-gateway%5D - [license-link]: /LICENSE - [cla]: https://www.clahub.com/agreements/CAAPIM/iOS-MAS-Foundation - [casupport]: https://support.ca.com/irj/portal/implsvcnewcase - +[guidelines]: /GUIDELINES.md +[community]: https://communities.ca.com/community/ca-api-management-community/content?filterID=contentstatus%5Bpublished%5D~category%5Bca-mobile-api-gateway%5D +[license-link]: /LICENSE +[cla]: https://www.clahub.com/agreements/CAAPIM/iOS-MAS-Foundation +[casupport]: https://support.ca.com/irj/portal/implsvcnewcase + diff --git a/GUIDELINES.md b/GUIDELINES.md index 125ee546..28972890 100644 --- a/GUIDELINES.md +++ b/GUIDELINES.md @@ -1,21 +1,19 @@ -# CA Technologies Mobile App Services Objective-C Style Guide +# CA Technologies Objective-C Style Guide -This document describes the Objective-C coding style of iOS team for CA Technologies Mobile App Services. This guideline is recommended to comply with all Objective-C implementations of our products. +This document describes the Objective-C coding style of the iOS Mobile SDK team. This guideline is recommended to comply with all Objective-C implementations of our products. -## Review Apple's Official Coding Guideline +## Review Apple Official Coding Guideline -Beyond the guidelines defined in this document, we also recommend reviewing Apple's official coding guidelines. +Beyond the guidelines defined in this document, we also recommend reviewing the Apple official coding guidelines. * [Programming with Objective-C](http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Introduction/introObjectiveC.html) * [Cocoa Fundamentals Guide](https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CocoaFundamentals/Introduction/Introduction.html) * [Coding Guidelines for Cocoa](https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CodingGuidelines/CodingGuidelines.html) * [App Programming Guide for iOS](http://developer.apple.com/library/ios/#documentation/iphone/conceptual/iphoneosprogrammingguide/Introduction/Introduction.html) -### MAS Products +### iOS Mobile SDK -For more information about MAS, see [Mobile App Service developer](http://mas.ca.com). - -Mobile App Services consists of multiple functional products separated into individual frameworks. +The iOS Mobile SDK consists these frameworks. * MASFoundation * MASUI @@ -23,7 +21,7 @@ Mobile App Services consists of multiple functional products separated into indi * MASIdentityManagement * MASStorage -All of frameworks are recommended to comply with the coding guideline. +All of frameworks are recommended to comply with the coding guideline. For more information about the iOS Mobile SDK, see [developer website](http://mas.ca.com). ## Table of Contents @@ -346,7 +344,7 @@ typedef NS_ENUM(NSInteger, MASRequestResponseType) + (MASObject *)currentObject; - (void)setObject:(id)object forKeyedSubscript:(id )key; -``` +``` **Not:** @@ -356,7 +354,7 @@ typedef NS_ENUM(NSInteger, MASRequestResponseType) +(MASObject*)currentObject; -(void)setObject:(id)object forKeyedSubscript:(id)key; -``` +``` #### Newline diff --git a/README.md b/README.md index 635b7ca0..ba39f5ff 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -MASFoundation is the core iOS framework of the Mobile SDK, which is part of [CA Mobile App Services][mas.ca.com]. MASFoundation handles the communication and authentication layer of the Mobile SDK, making it easy for developers to establish a secure connection (TLS, Mutual SSL) to any CA Mobile API Gateway (MAG). +MASFoundation is the core iOS framework of the iOS Mobile SDK, which is part of CA Mobile API Gateway. MASFoundation handles the communication and authentication layer of the iOS Mobile SDK, making it easy for developers to establish a secure connection (TLS, Mutual SSL) to any CA Mobile API Gateway (MAG). ## Features @@ -15,15 +15,15 @@ The MASFoundation framework has the following features: + OTP - One Time Password + PKCE - Proof Key for Code Exchange + SSL Pinning with certificate, public key, or public key hash + + Fingerprint Sessions Lock - Support phone unlocking using fingerprint recognition - Dynamic SDK Configuration - Enterprise Browser - Geo Location ## Get Started +- Check out our [documentation][docs] for sample code, video tutorials, and more. - [Download MASFoundation][download] -- Read the ["Getting Started" guide][get-started] or watch some [video tutorials][videos] -- Check out our [documentation][docs] for more details and sample codes ## Communication @@ -36,109 +36,6 @@ The MASFoundation framework has the following features: Contributions are welcome and much appreciated. To learn more, see the [Contribution Guidelines][contributing]. -## Installation - -MASFoundation supports multiple methods for installing the library in a project. - -### Cocoapods (Podfile) Install - -To integrate MASFoundation into your Xcode project using CocoaPods, specify it in your **Podfile:** - -``` -source 'https://github.com/CocoaPods/Specs.git' -platform :ios, '9.0' - -pod 'MASFoundation' -``` -Then, run the following command using the command prompt from the folder of your project: - -``` -$ pod install -``` - -### Manual Install - -For manual install, you add the Mobile SDK to your Xcode project. Note that you must add the MASFoundation library. For complete MAS functionality, install all of the MAS libraries as shown. - -1. Open your project in Xcode. -2. Drag the SDK library files, and drop them into your project in the left navigator panel in Xcode. Select the option, `Copy items if needed`. -3. Select `File->Add files to 'project name'` and add the msso_config.json file from your project folder. -4. In Xcode "Build Setting” of your Project Target, add `-ObjC` for `Other Linker Flags`. -5. Import the following Mobile SDK library header file to the classes or to the .pch file if your project has one. - -``` -#import -``` - -## 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") - -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. - -Ideally, SDK startup should be processed before app startup (during the splash/loading screen of your app). We recommended that you process any communication with the backend services upon successful completion of the startup method. Otherwise, the secure communication is not guaranteed and may fail. - -MASFoundation includes the following methods to start the SDK. - -##### Start with standard method -```objectivec - //Initializing the SDK. - [MAS start:^(BOOL completion, NSError *error) { - //Your code here! - }]; -``` -This method starts the SDK with the currently-active configuration. A currently-active configuration is: 1) the last successfully used configuration, 2) the default JSON configuration file (i.e. msso_config.json in your app bundle) or 3) the custom JSON configuration file defined in `[MAS setConfigurationFileName:]`. - -**Recommended for**: Most environments, including production. - -##### Start with default configuration -```objectivec - //Initializing the SDK. - [MAS startWithDefaultConfiguration:YES completion:^(BOOL completed, NSError *error) - //Your code here! - }]; -``` -This method starts the SDK with the currently-active configuration, or the default configuration (depending on the parameter). If you specify the `YES` parameter, this overwrites the currently-active configuration with the default configuration (if two configurations are different.). If you pass the `NO` parameter, this behaves the same as `[MAS start:];`. If the SDK is already started, this method: stops the SDK, then restarts it with the custom JSON object. - -**Recommended for**: Development environments where configurations change often. - -##### Start using custom JSON -```objectivec - //Your custom JSON object. - NSDictionary *jsonObject = @{....}; - - //Initializing the SDK with custom JSON object. - [MAS startWithJSON: jsonObject completion:^(BOOL completed, NSError *error) { - //Your code here! - }]; -``` -This method starts the SDK using the custom JSON object in, NSDictionary. This method overwrites the currently-active configuration with the custom JSON object, and stores it as the active configuration. If the SDK is already started, this method: stops SDK, then it restarts it with the custom JSON object. - -**Recommended for**: Using multiple MAG servers so you can dynamically change the configuration during runtime. Note: The backend servers must have a version of the product that supports dynamic configuration. - -##### Start using file URL -```objectivec - NSString *jsonPath = [[NSBundle mainBundle] pathForResource:@"your_file_name" - ofType:@"json"]; - NSURL *thisURL = [NSURL fileURLWithPath:jsonPath]; - - //Initializing the SDK with file URL of JSON configuration. - [MAS startWithURL:thisURL completion:^(BOOL completed, NSError *error) { - //Your code here! - }]; -``` -This method starts the SDK using the custom JSON configuration file. The custom file can be defined in NSURL format, which indicates the path of the custom file. This method overwrites the currently-active configuration with the custom JSON file, and stores it as the active configuration. If the SDK is already started, this method: stops the SDK, then restarts it with the custom JSON file. - -The SDK accepts the NSURL only with __local file path__. If the Web URL is provided, the startup method fails. - -**Recommended for**: Using multiple MAG servers so you can dynamically change the configuration during runtime. Note: The backend servers must have a version of the product that supports dynamic configuration. - -## Documentation - -For more documentation and API references, go to our [main website][docs] - ## License Copyright (c) 2016 CA. All rights reserved. @@ -146,13 +43,13 @@ Copyright (c) 2016 CA. All rights reserved. This software may be modified and distributed under the terms of the MIT license. See the [LICENSE][license-link] file for details. - [mag]: https://docops.ca.com/mag - [mas.ca.com]: http://mas.ca.com/ - [get-started]: http://mas.ca.com/get-started/ - [docs]: http://mas.ca.com/docs/ - [blog]: http://mas.ca.com/blog/ - [videos]: https://www.ca.com/us/developers/mas/videos.html - [StackOverflow]: http://stackoverflow.com/questions/tagged/massdk - [download]: https://github.com/CAAPIM/iOS-MAS-Foundation/archive/master.zip - [contributing]: https://github.com/CAAPIM/iOS-MAS-Foundation/blob/develop/CONTRIBUTING.md - [license-link]: /LICENSE +[mag]: https://docops.ca.com/mag +[mas.ca.com]: http://mas.ca.com/ +[get-started]: http://mas.ca.com/get-started/ +[docs]: http://mas.ca.com/docs/ +[blog]: http://mas.ca.com/blog/ +[videos]: https://www.ca.com/us/developers/mas/videos.html +[StackOverflow]: http://stackoverflow.com/questions/tagged/massdk +[download]: https://github.com/CAAPIM/iOS-MAS-Foundation/archive/master.zip +[contributing]: https://github.com/CAAPIM/iOS-MAS-Foundation/blob/develop/CONTRIBUTING.md +[license-link]: /LICENSE From 36888b73cad4a4f5c0b1590e74fc3485c5127fa9 Mon Sep 17 00:00:00 2001 From: James Go Date: Tue, 24 Oct 2017 11:46:17 -0700 Subject: [PATCH 20/51] DE324142 : [iOS][MASFoundation] Device de-registration should adhere server response for clearing local credentials --- .../services/model/MASModelService.m | 40 ++++++++++--------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/MASFoundation/Classes/_private_/services/model/MASModelService.m b/MASFoundation/Classes/_private_/services/model/MASModelService.m index 26f50a98..0aa71154 100644 --- a/MASFoundation/Classes/_private_/services/model/MASModelService.m +++ b/MASFoundation/Classes/_private_/services/model/MASModelService.m @@ -684,6 +684,11 @@ - (void)deregisterCurrentDeviceWithCompletion:(MASCompletionErrorBlock)completio // MASIMutableOrderedDictionary *mutableHeaderInfo = [MASIMutableOrderedDictionary new]; + // + // Post the Mobile SDK will attempt to deregister device + // + [[NSNotificationCenter defaultCenter] postNotificationName:MASDeviceWillDeregisterNotification object:self]; + __block MASModelService *blockSelf = self; // @@ -694,6 +699,23 @@ - (void)deregisterCurrentDeviceWithCompletion:(MASCompletionErrorBlock)completio andHeaders:mutableHeaderInfo completion:^(NSDictionary *responseInfo, NSError *error) { + // + // Detect if error, if so stop here + // + if(error) + { + // + // Post the did fail to deregister in cloud notification + // + [[NSNotificationCenter defaultCenter] postNotificationName:MASDeviceDidFailToDeregisterNotification object:self]; + + // + // Notify + // + if(completion) completion(NO, [NSError errorFromApiResponseInfo:responseInfo andError:error]); + + return; + } // // Clear currentUser object upon log-out @@ -727,24 +749,6 @@ - (void)deregisterCurrentDeviceWithCompletion:(MASCompletionErrorBlock)completio // [[NSNotificationCenter defaultCenter] postNotificationName:MASDeviceDidDeregisterOnDeviceNotification object:self]; - // - // Detect if error, if so stop here - // - if(error) - { - // - // Post the did fail to deregister in cloud notification - // - [[NSNotificationCenter defaultCenter] postNotificationName:MASDeviceDidFailToDeregisterNotification object:self]; - - // - // Notify - // - if(completion) completion(NO, [NSError errorFromApiResponseInfo:responseInfo andError:error]); - - return; - } - // // Post the did deregister in cloud notification // From 2652e336ca5980b5a4b10875dd6d7135499df67d Mon Sep 17 00:00:00 2001 From: McKercher Date: Tue, 24 Oct 2017 12:29:14 -0700 Subject: [PATCH 21/51] Added back installation for Cocoapods. --- README.md | 123 +++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 113 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index ba39f5ff..abc786b3 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,109 @@ The MASFoundation framework has the following features: Contributions are welcome and much appreciated. To learn more, see the [Contribution Guidelines][contributing]. +## Installation + +MASFoundation supports multiple methods for installing the library in a project. + +### Cocoapods (Podfile) Install + +To integrate MASFoundation into your Xcode project using CocoaPods, specify it in your **Podfile:** + +``` +source 'https://github.com/CocoaPods/Specs.git' +platform :ios, '9.0' + +pod 'MASFoundation' +``` +Then, run the following command using the command prompt from the folder of your project: + +``` +$ pod install +``` + +### Manual Install + +For manual install, you add the Mobile SDK to your Xcode project. Note that you must add the MASFoundation library. For complete MAS functionality, install all of the MAS libraries as shown. + +1. Open your project in Xcode. +2. Drag the SDK library files, and drop them into your project in the left navigator panel in Xcode. Select the option, `Copy items if needed`. +3. Select `File->Add files to 'project name'` and add the msso_config.json file from your project folder. +4. In Xcode "Build Setting” of your Project Target, add `-ObjC` for `Other Linker Flags`. +5. Import the following Mobile SDK library header file to the classes or to the .pch file if your project has one. + +``` +#import +``` + +## 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") + +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. + +Ideally, SDK startup should be processed before app startup (during the splash/loading screen of your app). We recommended that you process any communication with the backend services upon successful completion of the startup method. Otherwise, the secure communication is not guaranteed and may fail. + +MASFoundation includes the following methods to start the SDK. + +##### Start with standard method +```objectivec + //Initializing the SDK. + [MAS start:^(BOOL completion, NSError *error) { + //Your code here! + }]; +``` +This method starts the SDK with the currently-active configuration. A currently-active configuration is: 1) the last successfully used configuration, 2) the default JSON configuration file (i.e. msso_config.json in your app bundle) or 3) the custom JSON configuration file defined in `[MAS setConfigurationFileName:]`. + +**Recommended for**: Most environments, including production. + +##### Start with default configuration +```objectivec + //Initializing the SDK. + [MAS startWithDefaultConfiguration:YES completion:^(BOOL completed, NSError *error) + //Your code here! + }]; +``` +This method starts the SDK with the currently-active configuration, or the default configuration (depending on the parameter). If you specify the `YES` parameter, this overwrites the currently-active configuration with the default configuration (if two configurations are different.). If you pass the `NO` parameter, this behaves the same as `[MAS start:];`. If the SDK is already started, this method: stops the SDK, then restarts it with the custom JSON object. + +**Recommended for**: Development environments where configurations change often. + +##### Start using custom JSON +```objectivec + //Your custom JSON object. + NSDictionary *jsonObject = @{....}; + + //Initializing the SDK with custom JSON object. + [MAS startWithJSON: jsonObject completion:^(BOOL completed, NSError *error) { + //Your code here! + }]; +``` +This method starts the SDK using the custom JSON object in, NSDictionary. This method overwrites the currently-active configuration with the custom JSON object, and stores it as the active configuration. If the SDK is already started, this method: stops SDK, then it restarts it with the custom JSON object. + +**Recommended for**: Using multiple MAG servers so you can dynamically change the configuration during runtime. Note: The backend servers must have a version of the product that supports dynamic configuration. + +##### Start using file URL +```objectivec + NSString *jsonPath = [[NSBundle mainBundle] pathForResource:@"your_file_name" + ofType:@"json"]; + NSURL *thisURL = [NSURL fileURLWithPath:jsonPath]; + + //Initializing the SDK with file URL of JSON configuration. + [MAS startWithURL:thisURL completion:^(BOOL completed, NSError *error) { + //Your code here! + }]; +``` +This method starts the SDK using the custom JSON configuration file. The custom file can be defined in NSURL format, which indicates the path of the custom file. This method overwrites the currently-active configuration with the custom JSON file, and stores it as the active configuration. If the SDK is already started, this method: stops the SDK, then restarts it with the custom JSON file. + +The SDK accepts the NSURL only with __local file path__. If the Web URL is provided, the startup method fails. + +**Recommended for**: Using multiple MAG servers so you can dynamically change the configuration during runtime. Note: The backend servers must have a version of the product that supports dynamic configuration. + +## Documentation + +For more documentation and API references, go to our [main website][docs] + ## License Copyright (c) 2016 CA. All rights reserved. @@ -43,13 +146,13 @@ Copyright (c) 2016 CA. All rights reserved. This software may be modified and distributed under the terms of the MIT license. See the [LICENSE][license-link] file for details. -[mag]: https://docops.ca.com/mag -[mas.ca.com]: http://mas.ca.com/ -[get-started]: http://mas.ca.com/get-started/ -[docs]: http://mas.ca.com/docs/ -[blog]: http://mas.ca.com/blog/ -[videos]: https://www.ca.com/us/developers/mas/videos.html -[StackOverflow]: http://stackoverflow.com/questions/tagged/massdk -[download]: https://github.com/CAAPIM/iOS-MAS-Foundation/archive/master.zip -[contributing]: https://github.com/CAAPIM/iOS-MAS-Foundation/blob/develop/CONTRIBUTING.md -[license-link]: /LICENSE + [mag]: https://docops.ca.com/mag + [mas.ca.com]: http://mas.ca.com/ + [get-started]: http://mas.ca.com/get-started/ + [docs]: http://mas.ca.com/docs/ + [blog]: http://mas.ca.com/blog/ + [videos]: https://www.ca.com/us/developers/mas/videos.html + [StackOverflow]: http://stackoverflow.com/questions/tagged/massdk + [download]: https://github.com/CAAPIM/iOS-MAS-Foundation/archive/master.zip + [contributing]: https://github.com/CAAPIM/iOS-MAS-Foundation/blob/develop/CONTRIBUTING.md + [license-link]: /LICENSE From 3804aa2933b898fbbbb8397a3c63ccb546992d40 Mon Sep 17 00:00:00 2001 From: James Go Date: Thu, 26 Oct 2017 10:12:02 -0700 Subject: [PATCH 22/51] DE324462 : [iOS][MASFoundation] MASAuthCredentialsJWT should not be re-used for registration and authentication --- .../Classes/models/AuthCredentials/MASAuthCredentialsJWT.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MASFoundation/Classes/models/AuthCredentials/MASAuthCredentialsJWT.m b/MASFoundation/Classes/models/AuthCredentials/MASAuthCredentialsJWT.m index 54d45503..5c07a31b 100644 --- a/MASFoundation/Classes/models/AuthCredentials/MASAuthCredentialsJWT.m +++ b/MASFoundation/Classes/models/AuthCredentials/MASAuthCredentialsJWT.m @@ -49,7 +49,7 @@ - (instancetype)initPrivateWithJWT:(NSString *)jwt tokenType:(NSString *)tokenTy } _canRegisterDevice = YES; - _isReuseable = YES; + _isReuseable = NO; } return self; From 4d7d72f14154836703054f49007b731ecbfde4ed Mon Sep 17 00:00:00 2001 From: James Go Date: Mon, 6 Nov 2017 16:42:52 -0800 Subject: [PATCH 23/51] US416558 : [iOS] SharedStorage API --- MASFoundation/Classes/MAS.m | 4 +- MASFoundation/Classes/MQTT/MASMQTTHelper.m | 2 +- .../MASAuthCredentials+MASPrivate.m | 6 +- .../MASAuthCredentialsClientCredentials.m | 4 +- .../Classes/_private_/models/MASAccess.m | 108 ++-- .../models/MASApplication+MASPrivate.m | 29 +- .../_private_/models/MASClaims+MASPrivate.m | 4 +- .../_private_/models/MASDevice+MASPrivate.m | 18 +- .../_private_/models/MASUser+MASPrivate.m | 10 +- .../services/access/MASAccessService.h | 128 ++-- .../services/access/MASAccessService.m | 545 +++++++----------- .../services/model/MASModelService.m | 30 +- .../services/network/MASNetworkingService.m | 6 +- .../internal/MASSessionDataTaskOperation.m | 4 +- .../services/security/MASSecurityService.m | 12 +- .../MASAuthCredentialsAuthorizationCode.m | 4 +- .../AuthCredentials/MASAuthCredentialsJWT.m | 4 +- MASFoundation/Classes/models/MASApplication.m | 6 +- MASFoundation/Classes/models/MASClaims.m | 4 +- .../Classes/models/MASConfiguration.m | 4 +- MASFoundation/Classes/models/MASDevice.m | 6 +- MASFoundation/Classes/models/MASUser.m | 10 +- 22 files changed, 412 insertions(+), 536 deletions(-) diff --git a/MASFoundation/Classes/MAS.m b/MASFoundation/Classes/MAS.m index db17fbab..6f470ced 100644 --- a/MASFoundation/Classes/MAS.m +++ b/MASFoundation/Classes/MAS.m @@ -206,7 +206,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 +1641,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/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_/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..d112574e 100644 --- a/MASFoundation/Classes/_private_/models/MASApplication+MASPrivate.m +++ b/MASFoundation/Classes/_private_/models/MASApplication+MASPrivate.m @@ -56,8 +56,7 @@ - (id)initWithConfiguration nil) forKey:@"redirectUri"]; MASAccessService *accessService = [MASAccessService sharedService]; - - NSData *trustedServerCertificate = [accessService getAccessValueDataWithType:MASAccessValueTypeTrustedServerCertificate]; + NSData *trustedServerCertificate = [accessService getAccessValueDataWithStorageKey:MASKeychainStorageKeyTrustedServerCertificate]; if(!trustedServerCertificate) { // @@ -67,7 +66,7 @@ - (id)initWithConfiguration if(certificates && certificates.count > 0) { trustedServerCertificate = certificates[0]; - [accessService setAccessValueData:trustedServerCertificate withAccessValueType:MASAccessValueTypeTrustedServerCertificate]; + [accessService setAccessValueData:trustedServerCertificate storageKey:MASKeychainStorageKeyTrustedServerCertificate]; } } @@ -200,7 +199,7 @@ - (void)saveWithUpdatedInfo:(NSDictionary *)info NSNumber *clientExpiration = bodyInfo[MASClientExpirationRequestResponseKey]; if(clientExpiration) { - [accessService setAccessValueNumber:clientExpiration withAccessValueType:MASAccessValueTypeClientExpiration]; + [accessService setAccessValueNumber:clientExpiration storageKey:MASKeychainStorageKeyClientExpiration]; } // @@ -209,7 +208,7 @@ - (void)saveWithUpdatedInfo:(NSDictionary *)info NSString *clientId = bodyInfo[MASClientKeyRequestResponseKey]; if(clientId) { - [accessService setAccessValueString:clientId withAccessValueType:MASAccessValueTypeClientId]; + [accessService setAccessValueString:clientId storageKey:MASKeychainStorageKeyClientId]; } // @@ -218,7 +217,7 @@ - (void)saveWithUpdatedInfo:(NSDictionary *)info NSString *clientSecret = bodyInfo[MASClientSecretRequestResponseKey]; 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]]; } @@ -268,7 +267,7 @@ + (NSDate *)expirationAsDate // MASAccessService *accessService = [MASAccessService sharedService]; - NSNumber *clientExpiration = [accessService getAccessValueNumberWithType:MASAccessValueTypeClientExpiration]; + 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,9 +309,9 @@ - (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 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..131b9a33 100644 --- a/MASFoundation/Classes/_private_/models/MASUser+MASPrivate.m +++ b/MASFoundation/Classes/_private_/models/MASUser+MASPrivate.m @@ -46,7 +46,7 @@ + (MASUser *)instanceFromStorage // Attempt to retrieve from keychain // - NSData *data = [[MASAccessService sharedService] getAccessValueDataWithType:MASAccessValueTypeMASUserObjectData]; + NSData *data = [[MASAccessService sharedService] getAccessValueDataWithStorageKey:MASKeychainStorageKeyMASUserObjectData]; if(data) { @@ -65,7 +65,7 @@ - (void)saveToStorage NSData *data = [NSKeyedArchiver archivedDataWithRootObject:self]; if(data) { - [[MASAccessService sharedService] setAccessValueData:data withAccessValueType:MASAccessValueTypeMASUserObjectData]; + [[MASAccessService sharedService] setAccessValueData:data storageKey:MASKeychainStorageKeyMASUserObjectData]; } } @@ -172,12 +172,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 +203,7 @@ - (void)reset { [self resetPartial]; - [[MASAccessService sharedService] setAccessValueData:nil withAccessValueType:MASAccessValueTypeMASUserObjectData]; + [[MASAccessService sharedService] setAccessValueData:nil storageKey:MASKeychainStorageKeyMASUserObjectData]; } - (void)resetPartial diff --git a/MASFoundation/Classes/_private_/services/access/MASAccessService.h b/MASFoundation/Classes/_private_/services/access/MASAccessService.h index 077e6038..cfa4abc5 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 @@ -164,7 +165,7 @@ typedef NS_ENUM(NSInteger, MASAccessValueType) * @param certificate NSData form of certificate * @param type MASAccessValueType enum specifying the value key */ -- (void)setAccessValueCertificate:(NSData *)certificate withAccessValueType:(MASAccessValueType)type; +- (void)setAccessValueCertificate:(NSData *)certificate storageKey:(NSString *)storageKey; @@ -175,7 +176,7 @@ typedef NS_ENUM(NSInteger, MASAccessValueType) * * @return Certificate value by the specified value key */ -- (id)getAccessValueCertificateWithType:(MASAccessValueType)type; +- (id)getAccessValueCertificateWithStorageKey:(NSString *)storageKey; @@ -185,7 +186,7 @@ typedef NS_ENUM(NSInteger, MASAccessValueType) * @param data NSData to store into keychain * @param type MASAccessValueType enum value for the value key */ -- (void)setAccessValueData:(NSData *)data withAccessValueType:(MASAccessValueType)type; +- (void)setAccessValueData:(NSData *)data storageKey:(NSString *)storageKey; @@ -196,7 +197,7 @@ typedef NS_ENUM(NSInteger, MASAccessValueType) * * @return NSData of the access data by the specified value key */ -- (NSData *)getAccessValueDataWithType:(MASAccessValueType)type; +- (NSData *)getAccessValueDataWithStorageKey:(NSString *)storageKey; @@ -206,7 +207,7 @@ typedef NS_ENUM(NSInteger, MASAccessValueType) * @param string NSString to store into keychain * @param type MASAccessValueType enum value for the value key */ -- (void)setAccessValueString:(NSString *)string withAccessValueType:(MASAccessValueType)type; +- (void)setAccessValueString:(NSString *)string storageKey:(NSString *)storageKey; @@ -217,7 +218,7 @@ typedef NS_ENUM(NSInteger, MASAccessValueType) * * @return NSString of the access data by the specified value key */ -- (NSString *)getAccessValueStringWithType:(MASAccessValueType)type; +- (NSString *)getAccessValueStringWithStorageKey:(NSString *)storageKey; @@ -227,7 +228,7 @@ typedef NS_ENUM(NSInteger, MASAccessValueType) * @param dictionary NSDictionary to store into keychain * @param type MASAccessValueType enum value for the value key */ -- (void)setAccessValueDictionary:(NSDictionary *)dictionary withAccessValueType:(MASAccessValueType)type; +- (void)setAccessValueDictionary:(NSDictionary *)dictionary storageKey:(NSString *)storageKey; @@ -238,7 +239,7 @@ typedef NS_ENUM(NSInteger, MASAccessValueType) * * @return NSDictionary of the access data by the specified value key */ -- (NSDictionary *)getAccessValueDictionaryWithType:(MASAccessValueType)type; +- (NSDictionary *)getAccessValueDictionaryWithStorageKey:(NSString *)storageKey; @@ -248,7 +249,7 @@ typedef NS_ENUM(NSInteger, MASAccessValueType) * @param number NSNumber to store into keychain * @param type MASAccessValueType enum value for the value key */ -- (void)setAccessValueNumber:(NSNumber *)number withAccessValueType:(MASAccessValueType)type; +- (void)setAccessValueNumber:(NSNumber *)number storageKey:(NSString *)storageKey; @@ -259,7 +260,7 @@ typedef NS_ENUM(NSInteger, MASAccessValueType) * * @return NSNumber of the access data by the specified value key */ -- (NSNumber *)getAccessValueNumberWithType:(MASAccessValueType)type; +- (NSNumber *)getAccessValueNumberWithStorageKey:(NSString *)storageKey; @@ -273,7 +274,7 @@ typedef NS_ENUM(NSInteger, MASAccessValueType) * @param cryptoKey SecKeyRef to store into keychain * @param type MASAccessValueType enum value for the value key */ -- (void)setAccessValueCryptoKey:(SecKeyRef)cryptoKey withAccessValueType:(MASAccessValueType)type; +- (void)setAccessValueCryptoKey:(SecKeyRef)cryptoKey storageKey:(NSString *)storageKey; @@ -288,8 +289,13 @@ typedef NS_ENUM(NSInteger, MASAccessValueType) * * @return SecKeyRef of the access data by the specified value key */ -- (SecKeyRef)getAccessValueCryptoKeyWithType:(MASAccessValueType)type; +- (SecKeyRef)getAccessValueCryptoKeyWithStorageKey:(NSString *)storageKey; + + +///-------------------------------------- +/// @name Public +///-------------------------------------- # pragma mark - Public @@ -303,6 +309,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 +321,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 +343,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 +362,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..468ae48a 100644 --- a/MASFoundation/Classes/_private_/services/access/MASAccessService.m +++ b/MASFoundation/Classes/_private_/services/access/MASAccessService.m @@ -28,6 +28,39 @@ 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 @@ -42,6 +75,10 @@ @interface MASAccessService () @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 +139,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. @@ -240,11 +318,22 @@ - (void)saveAccessValuesWithDictionary:(NSDictionary *)dictionary forceToOverwri # pragma mark - Storage methods -- (void)setAccessValueCertificate:(NSData *)certificate withAccessValueType:(MASAccessValueType)type +- (id)getAccessValueIdentities { - NSString *storageKey = [self getStorageKeyWithAccessValueType:type]; - NSString *accessValueAsString = [self convertAccessTypeToString:type]; - MASIKeyChainStore *destinationStorage = _storages[storageKey]; + //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 *storageType = [self getStorageTypeWithKey:storageKey]; + NSString *accessValueAsString = [self convertKeyString:storageKey]; + MASIKeyChainStore *destinationStorage = _storages[storageType]; NSData * certData = nil; @@ -269,35 +358,24 @@ - (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 +- (void)setAccessValueData:(NSData *)data storageKey:(NSString *)storageKey { - //DLog(@"\n\ncalled\n\n"); - MASIKeyChainStore *keychainStore = [MASIKeyChainStore keyChainStore]; - NSArray *identities = [keychainStore identitiesWithCertificateLabel:[self convertAccessTypeToString:MASAccessValueTypeSignedPublicCertificate]]; + NSString *storageType = [self getStorageTypeWithKey:storageKey]; + NSString *accessValueAsString = [self convertKeyString:storageKey]; + MASIKeyChainStore *destinationStorage = _storages[storageType]; - return identities; -} - - -- (void)setAccessValueData:(NSData *)data withAccessValueType:(MASAccessValueType)type -{ - - NSString *storageKey = [self getStorageKeyWithAccessValueType:type]; - NSString *accessValueAsString = [self convertAccessTypeToString:type]; - MASIKeyChainStore *destinationStorage = _storages[storageKey]; - - BOOL isSecuredData = [self isSecuredData:type]; + BOOL isSecuredData = [self isSecureData:storageKey]; if (isSecuredData) { @@ -326,12 +404,12 @@ - (void)setAccessValueData:(NSData *)data withAccessValueType:(MASAccessValueTyp } -- (NSData *)getAccessValueDataWithType:(MASAccessValueType)type +- (NSData *)getAccessValueDataWithStorageKey:(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 *keychainData = [destinationStorage dataForKey:accessValueAsString]; @@ -339,20 +417,20 @@ - (NSData *)getAccessValueDataWithType:(MASAccessValueType)type } -- (void)setAccessValueString:(NSString *)string withAccessValueType:(MASAccessValueType)type +- (void)setAccessValueString:(NSString *)string storageKey:(NSString *)storageKey { - [self setAccessValueString:string withAccessValueType:type error:nil]; + [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 * __nullable __autoreleasing * __nullable)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]; - BOOL isSecuredData = [self isSecuredData:type]; + BOOL isSecuredData = [self isSecureData:storageKey]; if (isSecuredData) { @@ -389,18 +467,18 @@ - (BOOL)setAccessValueString:(NSString *)string withAccessValueType:(MASAccessVa } -- (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 * __nullable __autoreleasing * __nullable)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]; NSString *securedString = [destinationStorage stringForKey:accessValueAsString userOperationPrompt:userOperationPrompt error:error]; @@ -408,12 +486,12 @@ - (NSString *)getAccessValueStringWithType:(MASAccessValueType)type userOperatio } -- (NSString *)getAccessValueStringWithType:(MASAccessValueType)type error:(NSError * __nullable __autoreleasing * __nullable)error +- (NSString *)getAccessValueStringWithStorageKey:(NSString *)storageKey error:(NSError * __nullable __autoreleasing * __nullable)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]; NSString *securedString = [destinationStorage stringForKey:accessValueAsString error:error]; @@ -421,7 +499,7 @@ - (NSString *)getAccessValueStringWithType:(MASAccessValueType)type error:(NSErr } -- (void)setAccessValueDictionary:(NSDictionary *)dictionary withAccessValueType:(MASAccessValueType)type +- (void)setAccessValueDictionary:(NSDictionary *)dictionary storageKey:(NSString *)storageKey { // @@ -434,17 +512,17 @@ - (void)setAccessValueDictionary:(NSDictionary *)dictionary withAccessValueType: // if(thisData) { - [self setAccessValueData:thisData withAccessValueType:type]; + [self setAccessValueData:thisData storageKey:storageKey]; } } -- (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,7 +531,7 @@ - (NSDictionary *)getAccessValueDictionaryWithType:(MASAccessValueType)type } -- (void)setAccessValueNumber:(NSNumber *)number withAccessValueType:(MASAccessValueType)type +- (void)setAccessValueNumber:(NSNumber *)number storageKey:(NSString *)storageKey { // convert dictionary to data // @@ -464,17 +542,17 @@ - (void)setAccessValueNumber:(NSNumber *)number withAccessValueType:(MASAccessVa // if(thisData) { - [self setAccessValueData:thisData withAccessValueType:type]; + [self setAccessValueData:thisData storageKey:storageKey]; } } -- (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 +561,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 ([storageType isEqualToString:MASKeychainStorageKeyPublicKey]) { keyIdentifierStr = [NSString stringWithFormat:@"%@.%@", [MASConfiguration currentConfiguration].gatewayUrl.absoluteString, @"publicKey"]; } - else if (type == MASAccessValueTypePrivateKey) + else if ([storageType isEqualToString:MASKeychainStorageKeyPrivateKey]) { keyIdentifierStr = [NSString stringWithFormat:@"%@.%@", [MASConfiguration currentConfiguration].gatewayUrl.absoluteString, @"privateKey"]; } @@ -510,20 +589,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 ([storageType isEqualToString:MASKeychainStorageKeyPublicKey]) { keyIdentifierStr = [NSString stringWithFormat:@"%@.%@", [MASConfiguration currentConfiguration].gatewayUrl.absoluteString, @"publicKey"]; } - else if (type == MASAccessValueTypePrivateKey) + else if ([storageType isEqualToString:MASKeychainStorageKeyPrivateKey]) { keyIdentifierStr = [NSString stringWithFormat:@"%@.%@", [MASConfiguration currentConfiguration].gatewayUrl.absoluteString, @"privateKey"]; } @@ -544,7 +623,7 @@ - (SecKeyRef)getAccessValueCryptoKeyWithType:(MASAccessValueType)type #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 +641,7 @@ + (NSString *)padding: (NSString *) encodedString{ return encodedString; } + + (NSDictionary *)getIdTokenSegments:(NSString *)idToken error:(NSError *__autoreleasing *)error { NSDictionary *segmentsDict = nil; @@ -598,6 +678,7 @@ + (NSDictionary *)getIdTokenSegments:(NSString *)idToken error:(NSError *__autor return segmentsDict; } + + (NSDictionary *)unwrap:(NSString *)data { NSDictionary *dictionary = nil; @@ -615,284 +696,45 @@ + (NSDictionary *)unwrap:(NSString *)data return dictionary; } -- (BOOL)isSecuredData:(MASAccessValueType)type + +- (NSString *)convertKeyString:(NSString *)key { - BOOL isSecuredData = NO; + NSString *accessTypeToString = [NSString stringWithFormat:@"%@.%@", _gatewayIdentifier, key]; - switch (type) { - case MASAccessValueTypeSecuredIdToken: - isSecuredData = YES; - break; - - 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]; } - 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 kMASAccessSharedStorageKey; } - - return accessTypeToString; } @@ -1034,7 +876,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 +890,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 +903,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 +962,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 +971,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 +993,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 +1017,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 @@ -1223,7 +1065,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]; @@ -1261,7 +1103,7 @@ + (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) { @@ -1393,6 +1235,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 +1260,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]; // diff --git a/MASFoundation/Classes/_private_/services/model/MASModelService.m b/MASFoundation/Classes/_private_/services/model/MASModelService.m index 0aa71154..e89189f2 100644 --- a/MASFoundation/Classes/_private_/services/model/MASModelService.m +++ b/MASFoundation/Classes/_private_/services/model/MASModelService.m @@ -155,9 +155,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]; } @@ -396,7 +396,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]; @@ -1308,9 +1308,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 +1406,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 +1444,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 +1508,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]; // @@ -1946,7 +1946,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 +2015,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 +2039,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.m b/MASFoundation/Classes/_private_/services/network/MASNetworkingService.m index 209a8a61..c4415cac 100644 --- a/MASFoundation/Classes/_private_/services/network/MASNetworkingService.m +++ b/MASFoundation/Classes/_private_/services/network/MASNetworkingService.m @@ -603,9 +603,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 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/security/MASSecurityService.m b/MASFoundation/Classes/_private_/services/security/MASSecurityService.m index c3d46a1d..56239924 100644 --- a/MASFoundation/Classes/_private_/services/security/MASSecurityService.m +++ b/MASFoundation/Classes/_private_/services/security/MASSecurityService.m @@ -102,7 +102,7 @@ - (void)serviceDidReset - (NSURLCredential *)createUrlCredential { NSArray *identities = [[MASAccessService sharedService] getAccessValueIdentities]; - NSArray *certificates = [[MASAccessService sharedService] getAccessValueCertificateWithType:MASAccessValueTypeSignedPublicCertificate]; + NSArray *certificates = [[MASAccessService sharedService] getAccessValueCertificateWithStorageKey:MASKeychainStorageKeySignedPublicCertificate]; //DLog(@"\n\ncalled and identities is: %@ and certificates is: %@", identities, certificates); @@ -235,7 +235,7 @@ - (NSString *)generateCSRWithUsername:(NSString *)userName // // Store private key bits into keychain // - [[MASAccessService sharedService] setAccessValueString:keyContents withAccessValueType:MASAccessValueTypePrivateKeyBits]; + [[MASAccessService sharedService] setAccessValueString:keyContents storageKey:MASKeychainStorageKeyPrivateKeyBits]; } if (!X509_REQ_sign(req, privatekey, EVP_sha1())) @@ -337,12 +337,12 @@ - (void)generateKeypair // if(privateKeyRef) { - [[MASAccessService sharedService] setAccessValueCryptoKey:privateKeyRef withAccessValueType:MASAccessValueTypePrivateKey]; + [[MASAccessService sharedService] setAccessValueCryptoKey:privateKeyRef storageKey:MASKeychainStorageKeyPrivateKey]; } if(publicKeyRef) { - [[MASAccessService sharedService] setAccessValueCryptoKey:publicKeyRef withAccessValueType:MASAccessValueTypePublicKey]; + [[MASAccessService sharedService] setAccessValueCryptoKey:publicKeyRef storageKey:MASKeychainStorageKeyPublicKey]; } privateKeyRef = NULL; @@ -422,7 +422,7 @@ - (MASFile *)getDeviceClientCertificate if (!signedCert) { - NSData *signedCertificateData = [[MASAccessService sharedService] getAccessValueDataWithType:MASAccessValueTypeSignedPublicCertificateData]; + NSData *signedCertificateData = [[MASAccessService sharedService] getAccessValueDataWithStorageKey:MASKeychainStorageKeyPublicCertificateData]; if (signedCertificateData) { @@ -478,7 +478,7 @@ - (MASFile *)getPrivateKey // // Retrieve privateKeyBits from keychain. // - NSString *privateKeyBits = [[MASAccessService sharedService] getAccessValueStringWithType:MASAccessValueTypePrivateKeyBits]; + NSString *privateKeyBits = [[MASAccessService sharedService] getAccessValueStringWithStorageKey:MASKeychainStorageKeyPrivateKeyBits]; if (privateKeyBits) { diff --git a/MASFoundation/Classes/models/AuthCredentials/MASAuthCredentialsAuthorizationCode.m b/MASFoundation/Classes/models/AuthCredentials/MASAuthCredentialsAuthorizationCode.m index bc75b7f9..277d3cf1 100644 --- a/MASFoundation/Classes/models/AuthCredentials/MASAuthCredentialsAuthorizationCode.m +++ b/MASFoundation/Classes/models/AuthCredentials/MASAuthCredentialsAuthorizationCode.m @@ -142,13 +142,13 @@ - (NSDictionary *)getParameters MASAccessService *accessService = [MASAccessService sharedService]; // ClientId - NSString *clientId = [accessService getAccessValueStringWithType:MASAccessValueTypeClientId]; + NSString *clientId = [accessService getAccessValueStringWithStorageKey:MASKeychainStorageKeyClientId]; if (clientId) { parameterInfo[MASClientIdentifierRequestResponseKey] = clientId; } - NSString *clientSecret = [accessService getAccessValueStringWithType:MASAccessValueTypeClientSecret]; + NSString *clientSecret = [accessService getAccessValueStringWithStorageKey:MASKeychainStorageKeyClientSecret]; if (clientSecret) { parameterInfo[MASClientSecretRequestResponseKey] = clientSecret; diff --git a/MASFoundation/Classes/models/AuthCredentials/MASAuthCredentialsJWT.m b/MASFoundation/Classes/models/AuthCredentials/MASAuthCredentialsJWT.m index 5c07a31b..93777227 100644 --- a/MASFoundation/Classes/models/AuthCredentials/MASAuthCredentialsJWT.m +++ b/MASFoundation/Classes/models/AuthCredentials/MASAuthCredentialsJWT.m @@ -79,8 +79,8 @@ - (void)loginWithCredential:(MASCompletionErrorBlock)completion // If there is an error from the server complaining about invalid token, // invalidate local id_token and id_token_type and revalidate the user's session. // - [[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]; } diff --git a/MASFoundation/Classes/models/MASApplication.m b/MASFoundation/Classes/models/MASApplication.m index 15d7d480..43923b77 100644 --- a/MASFoundation/Classes/models/MASApplication.m +++ b/MASFoundation/Classes/models/MASApplication.m @@ -108,9 +108,9 @@ - (BOOL)isRegistered // 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]; _isRegistered = (clientExpiration && clientId && clientSecret && !self.isExpired); return _isRegistered; 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.m b/MASFoundation/Classes/models/MASConfiguration.m index 29cea4b4..268b55d7 100644 --- a/MASFoundation/Classes/models/MASConfiguration.m +++ b/MASFoundation/Classes/models/MASConfiguration.m @@ -774,7 +774,7 @@ - (BOOL)enabledTrustedPublicPKI - (BOOL)ssoEnabled { MASAccessService *accessService = [MASAccessService sharedService]; - NSString *ssoEnabledString = [accessService getAccessValueStringWithType:MASAccessValueTypeMSSOEnabled]; + NSString *ssoEnabledString = [accessService getAccessValueStringWithStorageKey:MASKeychainStorageKeyMSSOEnabled]; if (ssoEnabledString) { @@ -793,7 +793,7 @@ - (void)setSsoEnabled:(BOOL)ssoEnabled { MASAccessService *accessService = [MASAccessService sharedService]; - [accessService setAccessValueString:(ssoEnabled ? @"true":@"false") withAccessValueType:MASAccessValueTypeMSSOEnabled]; + [accessService setAccessValueString:(ssoEnabled ? @"true":@"false") storageKey:MASKeychainStorageKeyMSSOEnabled]; } diff --git a/MASFoundation/Classes/models/MASDevice.m b/MASFoundation/Classes/models/MASDevice.m index ab9e1aee..76cfbb19 100644 --- a/MASFoundation/Classes/models/MASDevice.m +++ b/MASFoundation/Classes/models/MASDevice.m @@ -57,7 +57,7 @@ - (BOOL)isRegistered // MASAccessService *accessService = [MASAccessService sharedService]; - NSString *vendorIdFromKeychain = [accessService getAccessValueStringWithType:MASAccessValueTypeDeviceVendorId]; + NSString *vendorIdFromKeychain = [accessService getAccessValueStringWithStorageKey:MASKeychainStorageKeyDeviceVendorId]; NSString *vendorIdCurrent = [MASDevice deviceVendorId]; // @@ -65,8 +65,8 @@ - (BOOL)isRegistered // 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); } diff --git a/MASFoundation/Classes/models/MASUser.m b/MASFoundation/Classes/models/MASUser.m index da2b3d3b..f0645db8 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]) { @@ -287,7 +287,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]; } From 940df22db465eeddb99476edf786f439a44200a6 Mon Sep 17 00:00:00 2001 From: James Go Date: Tue, 7 Nov 2017 15:49:27 -0800 Subject: [PATCH 24/51] US416558 : [iOS] SharedStorage API --- MASFoundation.xcodeproj/project.pbxproj | 8 + MASFoundation/Classes/MASConstants.h | 5 + .../_private_/categories/NSError+MASPrivate.m | 5 + .../services/access/MASAccessService.h | 86 +++++-- .../services/access/MASAccessService.m | 132 ++++++++--- .../Classes/models/MASSharedStorage.h | 76 ++++++ .../Classes/models/MASSharedStorage.m | 217 ++++++++++++++++++ MASFoundation/MASFoundation.h | 5 +- 8 files changed, 479 insertions(+), 55 deletions(-) create mode 100644 MASFoundation/Classes/models/MASSharedStorage.h create mode 100644 MASFoundation/Classes/models/MASSharedStorage.m diff --git a/MASFoundation.xcodeproj/project.pbxproj b/MASFoundation.xcodeproj/project.pbxproj index aab8da93..cac3bf9e 100644 --- a/MASFoundation.xcodeproj/project.pbxproj +++ b/MASFoundation.xcodeproj/project.pbxproj @@ -310,6 +310,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 */; }; @@ -735,6 +737,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 +1346,8 @@ CB14D2181D02266D004F772E /* MASProximityLoginQRCode.m */, CBA3EB2C1E945F2400E64D9D /* MASClaims.h */, CBA3EB2D1E945F2400E64D9D /* MASClaims.m */, + CB1FD1491FB23701000AFA25 /* MASSharedStorage.h */, + CB1FD14A1FB23701000AFA25 /* MASSharedStorage.m */, ); path = models; sourceTree = ""; @@ -1677,6 +1683,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 */, @@ -2091,6 +2098,7 @@ 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 */, diff --git a/MASFoundation/Classes/MASConstants.h b/MASFoundation/Classes/MASConstants.h index 003e0284..963db9f9 100644 --- a/MASFoundation/Classes/MASConstants.h +++ b/MASFoundation/Classes/MASConstants.h @@ -459,6 +459,11 @@ typedef NS_ENUM(NSInteger, MASFoundationErrorCode) MASFoundationErrorCodeJWTUnexpectedClassType = 170002, MASFoundationErrorCodeJWTSerializationError = 170003, + // + // Shared Keychain Storage + // + MASFoundationErrorCodeSharedStorageNotAllowedDataKey = 180001, + MASFoundationErrorCodeCount = -999999 }; diff --git a/MASFoundation/Classes/_private_/categories/NSError+MASPrivate.m b/MASFoundation/Classes/_private_/categories/NSError+MASPrivate.m index cfd4c0e4..75fc749a 100644 --- a/MASFoundation/Classes/_private_/categories/NSError+MASPrivate.m +++ b/MASFoundation/Classes/_private_/categories/NSError+MASPrivate.m @@ -1103,6 +1103,11 @@ + (NSString *)descriptionForFoundationErrorCode:(MASFoundationErrorCode)errorCod case MASFoundationErrorCodeJWTUnexpectedClassType: return @"Mis-match of reserved JWT claim value's type (%@)"; case MASFoundationErrorCodeJWTSerializationError: return @"Claim value (%@) cannot be serialized"; + // + // Custom shared keychain storage + // + case MASFoundationErrorCodeSharedStorageNotAllowedDataKey: return @"Data key is reserved, and not allowed to read and/or modify."; + // // Default // diff --git a/MASFoundation/Classes/_private_/services/access/MASAccessService.h b/MASFoundation/Classes/_private_/services/access/MASAccessService.h index cfa4abc5..a498a5e2 100644 --- a/MASFoundation/Classes/_private_/services/access/MASAccessService.h +++ b/MASFoundation/Classes/_private_/services/access/MASAccessService.h @@ -163,7 +163,7 @@ extern NSString * const MASKeychainStorageKeyDeviceVendorId; * 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 storageKey:(NSString *)storageKey; @@ -172,7 +172,7 @@ extern NSString * const MASKeychainStorageKeyDeviceVendorId; /** * 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 */ @@ -181,19 +181,32 @@ extern NSString * const MASKeychainStorageKeyDeviceVendorId; /** - * 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 storageKey:(NSString *)storageKey; +- (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 */ @@ -201,20 +214,44 @@ extern NSString * const MASKeychainStorageKeyDeviceVendorId; +/** + 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; + + + /** * 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 + */ +- (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 */ -- (void)setAccessValueString:(NSString *)string storageKey:(NSString *)storageKey; +- (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 */ @@ -222,20 +259,31 @@ extern NSString * const MASKeychainStorageKeyDeviceVendorId; +/** + 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; + + + /** * 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 storageKey:(NSString *)storageKey; +- (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 */ @@ -247,16 +295,16 @@ extern NSString * const MASKeychainStorageKeyDeviceVendorId; * 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 storageKey:(NSString *)storageKey; +- (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 */ @@ -272,7 +320,7 @@ extern NSString * const MASKeychainStorageKeyDeviceVendorId; * 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 storageKey:(NSString *)storageKey; @@ -285,7 +333,7 @@ extern NSString * const MASKeychainStorageKeyDeviceVendorId; * 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 */ diff --git a/MASFoundation/Classes/_private_/services/access/MASAccessService.m b/MASFoundation/Classes/_private_/services/access/MASAccessService.m index 468ae48a..184c560d 100644 --- a/MASFoundation/Classes/_private_/services/access/MASAccessService.m +++ b/MASFoundation/Classes/_private_/services/access/MASAccessService.m @@ -25,6 +25,7 @@ static NSString *const kMASAccessSharedStorageKey = @"sharedStorage"; static NSString *const kMASAccessLocalStorageKey = @"localStorage"; +static NSString *const kMASAccessCustomSharedStorageKey = @"customSharedStorage"; static NSString *const kMASAccessIsNotFreshInstallFlag = @"isNotFreshInstall"; @@ -69,6 +70,7 @@ @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; @@ -194,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]; + customSharedStorage.synchronizable = _isKeychainSynchronizable_; // // Local storage @@ -214,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]; } @@ -368,14 +376,21 @@ - (id)getAccessValueCertificateWithStorageKey:(NSString *)storageKey } -- (void)setAccessValueData:(NSData *)data storageKey:(NSString *)storageKey +- (BOOL)setAccessValueData:(NSData *)data storageKey:(NSString *)storageKey +{ + return [self setAccessValueData:data storageKey:storageKey error:nil]; +} + + +- (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; BOOL isSecuredData = [self isSecureData:storageKey]; + BOOL result = NO; if (isSecuredData) { @@ -387,49 +402,69 @@ - (void)setAccessValueData:(NSData *)data storageKey:(NSString *)storageKey // 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 *)getAccessValueDataWithStorageKey:(NSString *)storageKey error:(NSError **)error +{ NSString *storageType = [self getStorageTypeWithKey:storageKey]; NSString *accessValueAsString = [self convertKeyString:storageKey]; MASIKeyChainStore *destinationStorage = _storages[storageType]; + NSError *operationError = nil; + + NSData *keychainData = [destinationStorage dataForKey:accessValueAsString error:&operationError]; + + if (error) + { + *error = operationError; + } - NSData *keychainData = [destinationStorage dataForKey:accessValueAsString]; - return keychainData; } -- (void)setAccessValueString:(NSString *)string storageKey:(NSString *)storageKey +- (BOOL)setAccessValueString:(NSString *)string storageKey:(NSString *)storageKey { - [self setAccessValueString:string storageKey:storageKey error:nil]; + return [self setAccessValueString:string storageKey:storageKey error:nil]; } -- (BOOL)setAccessValueString:(NSString *)string storageKey:(NSString *)storageKey error:(NSError * __nullable __autoreleasing * __nullable)error +- (BOOL)setAccessValueString:(NSString *)string storageKey:(NSString *)storageKey error:(NSError **)error { NSString *storageType = [self getStorageTypeWithKey:storageKey]; NSString *accessValueAsString = [self convertKeyString:storageKey]; MASIKeyChainStore *destinationStorage = _storages[storageType]; + NSError *operationError = nil; + BOOL result = NO; BOOL isSecuredData = [self isSecureData:storageKey]; if (isSecuredData) @@ -442,14 +477,14 @@ - (BOOL)setAccessValueString:(NSString *)string storageKey:(NSString *)storageKe // 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) @@ -459,61 +494,73 @@ - (BOOL)setAccessValueString:(NSString *)string storageKey:(NSString *)storageKe if (error) { - return NO; - } - else { - return YES; + *error = operationError; } + + return result; } - (NSString *)getAccessValueStringWithStorageKey:(NSString *)storageKey { - return [self getAccessValueStringWithStorageKey:storageKey error:nil]; } -- (NSString *)getAccessValueStringWithStorageKey:(NSString *)storageKey userOperationPrompt:(NSString *)userOperationPrompt error:(NSError * __nullable __autoreleasing * __nullable)error +- (NSString *)getAccessValueStringWithStorageKey:(NSString *)storageKey userOperationPrompt:(NSString *)userOperationPrompt error:(NSError **)error { 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 *)getAccessValueStringWithStorageKey:(NSString *)storageKey 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 *securedString = [destinationStorage stringForKey:accessValueAsString error:error]; + NSString *securedString = [destinationStorage stringForKey:accessValueAsString error:&operationError]; + + if (error) + { + *error = operationError; + } return securedString; } -- (void)setAccessValueDictionary:(NSDictionary *)dictionary storageKey:(NSString *)storageKey +- (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) { - [self setAccessValueData:thisData storageKey:storageKey]; + result = [self setAccessValueData:thisData storageKey:storageKey]; } + + return result; } @@ -531,19 +578,22 @@ - (NSDictionary *)getAccessValueDictionaryWithStorageKey:(NSString *)storageKey } -- (void)setAccessValueNumber:(NSNumber *)number storageKey:(NSString *)storageKey +- (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) { - [self setAccessValueData:thisData storageKey:storageKey]; + result = [self setAccessValueData:thisData storageKey:storageKey]; } + + return result; } @@ -699,14 +749,28 @@ + (NSDictionary *)unwrap:(NSString *)data - (NSString *)convertKeyString:(NSString *)key { - NSString *accessTypeToString = [NSString stringWithFormat:@"%@.%@", _gatewayIdentifier, key]; + NSString *accessTypeToString = nil; // - // When access gruop is not accessiable, differentiate the key to make sure there is no conflict of device registration record in the future + // Internal system data // - if (![self isAccessGroupAccessible]) + if ([_sharedStorageKeys containsObject:key] || [_localStorageKeys containsObject:key]) { - accessTypeToString = [NSString stringWithFormat:@"_%@", accessTypeToString]; + accessTypeToString = [NSString stringWithFormat:@"%@.%@", _gatewayIdentifier, key]; + + // + // 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 = [NSString stringWithFormat:@"%@.%@", kMASAccessCustomSharedStorageKey, key]; } return accessTypeToString; @@ -733,7 +797,7 @@ - (NSString *)getStorageTypeWithKey:(NSString *)key // 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 kMASAccessSharedStorageKey; + return kMASAccessCustomSharedStorageKey; } } diff --git a/MASFoundation/Classes/models/MASSharedStorage.h b/MASFoundation/Classes/models/MASSharedStorage.h new file mode 100644 index 00000000..dccf4fe1 --- /dev/null +++ b/MASFoundation/Classes/models/MASSharedStorage.h @@ -0,0 +1,76 @@ +// +// 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 store, and retrieve 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:* there are some of the keys that are reserved by MASFoundation framework which will not store, or retrieve value with the same key. + Key should be generic to its use-case, and any internal system data reserved by MASFoundation framework will not be readable through this class. + */ +@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. + + @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. + + @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; + +@end diff --git a/MASFoundation/Classes/models/MASSharedStorage.m b/MASFoundation/Classes/models/MASSharedStorage.m new file mode 100644 index 00000000..d73bfe83 --- /dev/null +++ b/MASFoundation/Classes/models/MASSharedStorage.m @@ -0,0 +1,217 @@ +// +// 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" + +@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 if key is reserved for internal system data or not + // + if ([[MASAccessService sharedService] isInternalDataForStorageKey:key]) + { + if (error) + { + *error = [NSError errorForFoundationCode:MASFoundationErrorCodeSharedStorageNotAllowedDataKey errorDomain:MASFoundationErrorDomainLocal]; + } + + return nil; + } + + // + // Retrieve NSString from shared keychain storage + // + NSError *operationError = nil; + NSString *resultString = [[MASAccessService sharedService] getAccessValueStringWithStorageKey: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 if key is reserved for internal system data or not + // + if ([[MASAccessService sharedService] isInternalDataForStorageKey:key]) + { + if (error) + { + *error = [NSError errorForFoundationCode:MASFoundationErrorCodeSharedStorageNotAllowedDataKey errorDomain:MASFoundationErrorDomainLocal]; + } + + return nil; + } + + // + // Retrieve NSData from shared keychain storage + // + NSError *operationError = nil; + NSData *resultData = [[MASAccessService sharedService] getAccessValueDataWithStorageKey: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 if key is reserved for internal system data or not + // + if ([[MASAccessService sharedService] isInternalDataForStorageKey:key]) + { + if (error) + { + *error = [NSError errorForFoundationCode:MASFoundationErrorCodeSharedStorageNotAllowedDataKey errorDomain:MASFoundationErrorDomainLocal]; + } + + return NO; + } + + // + // Store NSString into shared keychain storage + // + NSError *operationError = nil; + BOOL result = [[MASAccessService sharedService] setAccessValueString:string storageKey: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 if key is reserved for internal system data or not + // + if ([[MASAccessService sharedService] isInternalDataForStorageKey:key]) + { + if (error) + { + *error = [NSError errorForFoundationCode:MASFoundationErrorCodeSharedStorageNotAllowedDataKey errorDomain:MASFoundationErrorDomainLocal]; + } + + return NO; + } + + NSError *operationError = nil; + BOOL result = [[MASAccessService sharedService] setAccessValueData:data storageKey: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; +} + +@end 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 From 891ab3d476304e4ead919e301d06332b7929235e Mon Sep 17 00:00:00 2001 From: James Go Date: Tue, 7 Nov 2017 16:07:02 -0800 Subject: [PATCH 25/51] US416558 : [iOS] SharedStorage API --- MASFoundation/Classes/MASConstants.h | 5 -- .../_private_/categories/NSError+MASPrivate.m | 5 -- .../Classes/models/MASSharedStorage.h | 7 +-- .../Classes/models/MASSharedStorage.m | 52 ------------------- 4 files changed, 4 insertions(+), 65 deletions(-) diff --git a/MASFoundation/Classes/MASConstants.h b/MASFoundation/Classes/MASConstants.h index 963db9f9..003e0284 100644 --- a/MASFoundation/Classes/MASConstants.h +++ b/MASFoundation/Classes/MASConstants.h @@ -459,11 +459,6 @@ typedef NS_ENUM(NSInteger, MASFoundationErrorCode) MASFoundationErrorCodeJWTUnexpectedClassType = 170002, MASFoundationErrorCodeJWTSerializationError = 170003, - // - // Shared Keychain Storage - // - MASFoundationErrorCodeSharedStorageNotAllowedDataKey = 180001, - MASFoundationErrorCodeCount = -999999 }; diff --git a/MASFoundation/Classes/_private_/categories/NSError+MASPrivate.m b/MASFoundation/Classes/_private_/categories/NSError+MASPrivate.m index 75fc749a..cfd4c0e4 100644 --- a/MASFoundation/Classes/_private_/categories/NSError+MASPrivate.m +++ b/MASFoundation/Classes/_private_/categories/NSError+MASPrivate.m @@ -1103,11 +1103,6 @@ + (NSString *)descriptionForFoundationErrorCode:(MASFoundationErrorCode)errorCod case MASFoundationErrorCodeJWTUnexpectedClassType: return @"Mis-match of reserved JWT claim value's type (%@)"; case MASFoundationErrorCodeJWTSerializationError: return @"Claim value (%@) cannot be serialized"; - // - // Custom shared keychain storage - // - case MASFoundationErrorCodeSharedStorageNotAllowedDataKey: return @"Data key is reserved, and not allowed to read and/or modify."; - // // Default // diff --git a/MASFoundation/Classes/models/MASSharedStorage.h b/MASFoundation/Classes/models/MASSharedStorage.h index dccf4fe1..69867a73 100644 --- a/MASFoundation/Classes/models/MASSharedStorage.h +++ b/MASFoundation/Classes/models/MASSharedStorage.h @@ -12,11 +12,10 @@ /** - MASSharedStorage class is designed for developers to store, and retrieve NSString or NSData data into shared keychain storage, + 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:* there are some of the keys that are reserved by MASFoundation framework which will not store, or retrieve value with the same key. - Key should be generic to its use-case, and any internal system data reserved by MASFoundation framework will not be readable through this class. + @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 @@ -53,6 +52,7 @@ /** 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 @@ -65,6 +65,7 @@ /** 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 diff --git a/MASFoundation/Classes/models/MASSharedStorage.m b/MASFoundation/Classes/models/MASSharedStorage.m index d73bfe83..4f3bdce3 100644 --- a/MASFoundation/Classes/models/MASSharedStorage.m +++ b/MASFoundation/Classes/models/MASSharedStorage.m @@ -29,19 +29,6 @@ + (NSString *)findStringUsingKey:(NSString *)key error:(NSError **)error return nil; } - // - // Check if key is reserved for internal system data or not - // - if ([[MASAccessService sharedService] isInternalDataForStorageKey:key]) - { - if (error) - { - *error = [NSError errorForFoundationCode:MASFoundationErrorCodeSharedStorageNotAllowedDataKey errorDomain:MASFoundationErrorDomainLocal]; - } - - return nil; - } - // // Retrieve NSString from shared keychain storage // @@ -80,19 +67,6 @@ + (NSData *)findDataUsingKey:(NSString *)key error:(NSError **)error return nil; } - // - // Check if key is reserved for internal system data or not - // - if ([[MASAccessService sharedService] isInternalDataForStorageKey:key]) - { - if (error) - { - *error = [NSError errorForFoundationCode:MASFoundationErrorCodeSharedStorageNotAllowedDataKey errorDomain:MASFoundationErrorDomainLocal]; - } - - return nil; - } - // // Retrieve NSData from shared keychain storage // @@ -131,19 +105,6 @@ + (BOOL)saveString:(NSString *)string key:(NSString *)key error:(NSError **)erro return NO; } - // - // Check if key is reserved for internal system data or not - // - if ([[MASAccessService sharedService] isInternalDataForStorageKey:key]) - { - if (error) - { - *error = [NSError errorForFoundationCode:MASFoundationErrorCodeSharedStorageNotAllowedDataKey errorDomain:MASFoundationErrorDomainLocal]; - } - - return NO; - } - // // Store NSString into shared keychain storage // @@ -182,19 +143,6 @@ + (BOOL)saveData:(NSData *)data key:(NSString *)key error:(NSError **)error return NO; } - // - // Check if key is reserved for internal system data or not - // - if ([[MASAccessService sharedService] isInternalDataForStorageKey:key]) - { - if (error) - { - *error = [NSError errorForFoundationCode:MASFoundationErrorCodeSharedStorageNotAllowedDataKey errorDomain:MASFoundationErrorDomainLocal]; - } - - return NO; - } - NSError *operationError = nil; BOOL result = [[MASAccessService sharedService] setAccessValueData:data storageKey:key error:&operationError]; From e09cee9683fcfeb4e3d5717c8c2a6f9cd9158183 Mon Sep 17 00:00:00 2001 From: James Go Date: Thu, 9 Nov 2017 10:40:40 -0800 Subject: [PATCH 26/51] US416558 : [iOS] SharedStorage API --- .../Classes/_private_/services/access/MASAccessService.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MASFoundation/Classes/_private_/services/access/MASAccessService.m b/MASFoundation/Classes/_private_/services/access/MASAccessService.m index 184c560d..343a4c12 100644 --- a/MASFoundation/Classes/_private_/services/access/MASAccessService.m +++ b/MASFoundation/Classes/_private_/services/access/MASAccessService.m @@ -620,11 +620,11 @@ - (void)setAccessValueCryptoKey:(SecKeyRef)cryptoKey storageKey:(NSString *)stor NSString *keyIdentifierStr = nil; - if ([storageType isEqualToString:MASKeychainStorageKeyPublicKey]) + if ([storageKey isEqualToString:MASKeychainStorageKeyPublicKey]) { keyIdentifierStr = [NSString stringWithFormat:@"%@.%@", [MASConfiguration currentConfiguration].gatewayUrl.absoluteString, @"publicKey"]; } - else if ([storageType isEqualToString:MASKeychainStorageKeyPrivateKey]) + else if ([storageKey isEqualToString:MASKeychainStorageKeyPrivateKey]) { keyIdentifierStr = [NSString stringWithFormat:@"%@.%@", [MASConfiguration currentConfiguration].gatewayUrl.absoluteString, @"privateKey"]; } From d932fc96245d55cc825c4d163d22acb7c8c2687f Mon Sep 17 00:00:00 2001 From: James Go Date: Thu, 9 Nov 2017 10:55:48 -0800 Subject: [PATCH 27/51] US416558 : [iOS] SharedStorage API --- MASFoundation/Classes/MASConstants.h | 5 ++ .../_private_/categories/NSError+MASPrivate.m | 5 ++ .../Classes/models/MASSharedStorage.m | 52 +++++++++++++++++++ 3 files changed, 62 insertions(+) diff --git a/MASFoundation/Classes/MASConstants.h b/MASFoundation/Classes/MASConstants.h index 003e0284..2505b83e 100644 --- a/MASFoundation/Classes/MASConstants.h +++ b/MASFoundation/Classes/MASConstants.h @@ -459,6 +459,11 @@ typedef NS_ENUM(NSInteger, MASFoundationErrorCode) MASFoundationErrorCodeJWTUnexpectedClassType = 170002, MASFoundationErrorCodeJWTSerializationError = 170003, + // + // SharedStorage + // + MASFoundationErrorCodeSharedStorageNotNilKey = 180001, + MASFoundationErrorCodeCount = -999999 }; diff --git a/MASFoundation/Classes/_private_/categories/NSError+MASPrivate.m b/MASFoundation/Classes/_private_/categories/NSError+MASPrivate.m index cfd4c0e4..51ecb6bc 100644 --- a/MASFoundation/Classes/_private_/categories/NSError+MASPrivate.m +++ b/MASFoundation/Classes/_private_/categories/NSError+MASPrivate.m @@ -1102,6 +1102,11 @@ + (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."; // // Default diff --git a/MASFoundation/Classes/models/MASSharedStorage.m b/MASFoundation/Classes/models/MASSharedStorage.m index 4f3bdce3..3f1dda9f 100644 --- a/MASFoundation/Classes/models/MASSharedStorage.m +++ b/MASFoundation/Classes/models/MASSharedStorage.m @@ -29,6 +29,19 @@ + (NSString *)findStringUsingKey:(NSString *)key error:(NSError **)error 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 // @@ -67,6 +80,19 @@ + (NSData *)findDataUsingKey:(NSString *)key error:(NSError **)error 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 // @@ -105,6 +131,19 @@ + (BOOL)saveString:(NSString *)string key:(NSString *)key error:(NSError **)erro 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 // @@ -143,6 +182,19 @@ + (BOOL)saveData:(NSData *)data key:(NSString *)key error:(NSError **)error 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:key error:&operationError]; From 7f653ddd3e1da0ae8a358b81114fb01846960ede Mon Sep 17 00:00:00 2001 From: James Go Date: Thu, 9 Nov 2017 13:57:10 -0800 Subject: [PATCH 28/51] US416558 : [iOS] SharedStorage API --- .../_private_/services/access/MASAccessService.m | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/MASFoundation/Classes/_private_/services/access/MASAccessService.m b/MASFoundation/Classes/_private_/services/access/MASAccessService.m index 343a4c12..d7baf115 100644 --- a/MASFoundation/Classes/_private_/services/access/MASAccessService.m +++ b/MASFoundation/Classes/_private_/services/access/MASAccessService.m @@ -202,7 +202,7 @@ - (void)serviceWillStart // // Custom shared storage // - MASIKeyChainStore *customSharedStorage = [MASIKeyChainStore keyChainStoreWithService:_customSharedStorageServiceName]; + MASIKeyChainStore *customSharedStorage = [MASIKeyChainStore keyChainStoreWithService:_customSharedStorageServiceName accessGroup:self.accessGroup]; customSharedStorage.synchronizable = _isKeychainSynchronizable_; // @@ -1366,6 +1366,17 @@ - (NSString *)debugSecuredDescription [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]]; + } + [keychainDescription appendString:@"\n\n*********************\n\n"]; return keychainDescription; From ac61efffa059701c83cff588784e8b28a77a1b4c Mon Sep 17 00:00:00 2001 From: James Go Date: Thu, 9 Nov 2017 14:13:28 -0800 Subject: [PATCH 29/51] US416558 : [iOS] SharedStorage API --- .../Classes/_private_/services/access/MASAccessService.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MASFoundation/Classes/_private_/services/access/MASAccessService.m b/MASFoundation/Classes/_private_/services/access/MASAccessService.m index d7baf115..1d83c3a4 100644 --- a/MASFoundation/Classes/_private_/services/access/MASAccessService.m +++ b/MASFoundation/Classes/_private_/services/access/MASAccessService.m @@ -648,11 +648,11 @@ - (SecKeyRef)getAccessValueCryptoKeyWithStorageKey:(NSString *)storageKey NSString *keyIdentifierStr = nil; - if ([storageType isEqualToString:MASKeychainStorageKeyPublicKey]) + if ([storageKey isEqualToString:MASKeychainStorageKeyPublicKey]) { keyIdentifierStr = [NSString stringWithFormat:@"%@.%@", [MASConfiguration currentConfiguration].gatewayUrl.absoluteString, @"publicKey"]; } - else if ([storageType isEqualToString:MASKeychainStorageKeyPrivateKey]) + else if ([storageKey isEqualToString:MASKeychainStorageKeyPrivateKey]) { keyIdentifierStr = [NSString stringWithFormat:@"%@.%@", [MASConfiguration currentConfiguration].gatewayUrl.absoluteString, @"privateKey"]; } From 545d1b729aa37971a8859fb65cb86b8eea8d1c21 Mon Sep 17 00:00:00 2001 From: James Go Date: Fri, 10 Nov 2017 13:41:41 -0800 Subject: [PATCH 30/51] US416558 : [iOS] SharedStorage API --- MASFoundation/Classes/_private_/MASConstantsPrivate.h | 5 +++++ .../Classes/_private_/services/access/MASAccessService.m | 2 +- MASFoundation/Classes/models/MASSharedStorage.m | 9 +++++---- 3 files changed, 11 insertions(+), 5 deletions(-) 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_/services/access/MASAccessService.m b/MASFoundation/Classes/_private_/services/access/MASAccessService.m index 1d83c3a4..26e6d290 100644 --- a/MASFoundation/Classes/_private_/services/access/MASAccessService.m +++ b/MASFoundation/Classes/_private_/services/access/MASAccessService.m @@ -770,7 +770,7 @@ - (NSString *)convertKeyString:(NSString *)key // External custom data in shared keychain storage // else { - accessTypeToString = [NSString stringWithFormat:@"%@.%@", kMASAccessCustomSharedStorageKey, key]; + accessTypeToString = key; } return accessTypeToString; diff --git a/MASFoundation/Classes/models/MASSharedStorage.m b/MASFoundation/Classes/models/MASSharedStorage.m index 3f1dda9f..c7d0916d 100644 --- a/MASFoundation/Classes/models/MASSharedStorage.m +++ b/MASFoundation/Classes/models/MASSharedStorage.m @@ -11,6 +11,7 @@ #import "MASSharedStorage.h" #import "MASAccessService.h" +#import "MASConstantsPrivate.h" @implementation MASSharedStorage @@ -46,7 +47,7 @@ + (NSString *)findStringUsingKey:(NSString *)key error:(NSError **)error // Retrieve NSString from shared keychain storage // NSError *operationError = nil; - NSString *resultString = [[MASAccessService sharedService] getAccessValueStringWithStorageKey:key error:&operationError]; + NSString *resultString = [[MASAccessService sharedService] getAccessValueStringWithStorageKey:[NSString stringWithFormat:@"%@.%@", MASSharedStorageCustomPrefix, key] error:&operationError]; // // If an error occurred while keychain operation, convert it into MASFoundationErrorDomainLocal error object @@ -97,7 +98,7 @@ + (NSData *)findDataUsingKey:(NSString *)key error:(NSError **)error // Retrieve NSData from shared keychain storage // NSError *operationError = nil; - NSData *resultData = [[MASAccessService sharedService] getAccessValueDataWithStorageKey:key error:&operationError]; + NSData *resultData = [[MASAccessService sharedService] getAccessValueDataWithStorageKey:[NSString stringWithFormat:@"%@.%@", MASSharedStorageCustomPrefix, key] error:&operationError]; // // If an error occurred while keychain operation, convert it into MASFoundationErrorDomainLocal error object @@ -148,7 +149,7 @@ + (BOOL)saveString:(NSString *)string key:(NSString *)key error:(NSError **)erro // Store NSString into shared keychain storage // NSError *operationError = nil; - BOOL result = [[MASAccessService sharedService] setAccessValueString:string storageKey:key error:&operationError]; + 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 @@ -196,7 +197,7 @@ + (BOOL)saveData:(NSData *)data key:(NSString *)key error:(NSError **)error } NSError *operationError = nil; - BOOL result = [[MASAccessService sharedService] setAccessValueData:data storageKey:key error:&operationError]; + 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 From a0d4bd6fb8a1c7a51bc3c1efc06301a6fd6bc5a3 Mon Sep 17 00:00:00 2001 From: Kaylie Son Date: Tue, 14 Nov 2017 12:56:31 -0800 Subject: [PATCH 31/51] US416558 : [iOS] SharedStorage API --- .../models/MASApplication+MASPrivate.m | 32 ++++++------- .../_private_/models/MASUser+MASPrivate.m | 46 +++++++++++++------ .../services/access/MASAccessService.m | 37 +++++++++------ .../services/security/MASSecurityService.m | 12 ++--- MASFoundation/Classes/models/MASDevice.m | 4 +- MASFoundation/Classes/models/MASUser.m | 2 +- 6 files changed, 79 insertions(+), 54 deletions(-) diff --git a/MASFoundation/Classes/_private_/models/MASApplication+MASPrivate.m b/MASFoundation/Classes/_private_/models/MASApplication+MASPrivate.m index d112574e..8c4a9d2f 100644 --- a/MASFoundation/Classes/_private_/models/MASApplication+MASPrivate.m +++ b/MASFoundation/Classes/_private_/models/MASApplication+MASPrivate.m @@ -57,13 +57,13 @@ - (id)initWithConfiguration MASAccessService *accessService = [MASAccessService sharedService]; NSData *trustedServerCertificate = [accessService getAccessValueDataWithStorageKey:MASKeychainStorageKeyTrustedServerCertificate]; - if(!trustedServerCertificate) + 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 storageKey:MASKeychainStorageKeyTrustedServerCertificate]; @@ -73,7 +73,7 @@ - (id)initWithConfiguration // // If the credentials are NOT dynamic set them here // - if(!configuration.applicationCredentialsAreDynamic) + if (!configuration.applicationCredentialsAreDynamic) { NSDictionary *credentialsFromConfiguration = @ { @@ -107,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]; } @@ -159,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; @@ -197,7 +197,7 @@ - (void)saveWithUpdatedInfo:(NSDictionary *)info // Client Expiration // NSNumber *clientExpiration = bodyInfo[MASClientExpirationRequestResponseKey]; - if(clientExpiration) + if (clientExpiration) { [accessService setAccessValueNumber:clientExpiration storageKey:MASKeychainStorageKeyClientExpiration]; } @@ -206,7 +206,7 @@ - (void)saveWithUpdatedInfo:(NSDictionary *)info // Client Key // NSString *clientId = bodyInfo[MASClientKeyRequestResponseKey]; - if(clientId) + if (clientId) { [accessService setAccessValueString:clientId storageKey:MASKeychainStorageKeyClientId]; } @@ -215,7 +215,7 @@ - (void)saveWithUpdatedInfo:(NSDictionary *)info // Client Secret // NSString *clientSecret = bodyInfo[MASClientSecretRequestResponseKey]; - if(clientSecret) + if (clientSecret) { [accessService setAccessValueString:clientSecret storageKey:MASKeychainStorageKeyClientSecret]; } @@ -244,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,7 +268,7 @@ + (NSDate *)expirationAsDate MASAccessService *accessService = [MASAccessService sharedService]; NSNumber *clientExpiration = [accessService getAccessValueNumberWithStorageKey:MASKeychainStorageKeyClientExpiration]; - if(!clientExpiration) + if (!clientExpiration) { return nil; } @@ -316,7 +316,7 @@ - (BOOL)isExpired // // Expiration is nil, then it is considered expired // - if(!clientExpiration) + if (!clientExpiration) { isExpired = YES; } @@ -325,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; } @@ -333,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; } @@ -348,7 +348,7 @@ - (NSString *)authenticationStatusAsString // // Detect status and respond appropriately // - switch([self authenticationStatus]) + switch ([self authenticationStatus]) { // // Not Logged In @@ -381,7 +381,7 @@ - (NSString *)scopeTypeToString:(MASScopeType)scopeType // // Detect type and respond appropriately // - switch(scopeType) + switch (scopeType) { // // OpenId diff --git a/MASFoundation/Classes/_private_/models/MASUser+MASPrivate.m b/MASFoundation/Classes/_private_/models/MASUser+MASPrivate.m index 131b9a33..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]; } @@ -48,7 +48,7 @@ + (MASUser *)instanceFromStorage NSData *data = [[MASAccessService sharedService] getAccessValueDataWithStorageKey:MASKeychainStorageKeyMASUserObjectData]; - if(data) + if (data) { user = (MASUser *)[NSKeyedUnarchiver unarchiveObjectWithData:data]; } @@ -63,7 +63,7 @@ - (void)saveToStorage // Save to the keychain // NSData *data = [NSKeyedArchiver archivedDataWithRootObject:self]; - if(data) + if (data) { [[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]; @@ -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/access/MASAccessService.m b/MASFoundation/Classes/_private_/services/access/MASAccessService.m index 26e6d290..503b067b 100644 --- a/MASFoundation/Classes/_private_/services/access/MASAccessService.m +++ b/MASFoundation/Classes/_private_/services/access/MASAccessService.m @@ -301,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; @@ -555,7 +555,7 @@ - (BOOL)setAccessValueDictionary:(NSDictionary *)dictionary storageKey:(NSString // // make sure the data exists // - if(thisData) + if (thisData) { result = [self setAccessValueData:thisData storageKey:storageKey]; } @@ -588,7 +588,7 @@ - (BOOL)setAccessValueNumber:(NSNumber *)number storageKey:(NSString *)storageKe // // make sure the data exists // - if(thisData) + if (thisData) { result = [self setAccessValueData:thisData storageKey:storageKey]; } @@ -789,7 +789,7 @@ - (NSString *)getStorageTypeWithKey:(NSString *)key { return kMASAccessSharedStorageKey; } - else if([_localStorageKeys containsObject:key]) + else if ([_localStorageKeys containsObject:key]) { return kMASAccessLocalStorageKey; } @@ -837,7 +837,7 @@ - (NSString *)accessGroup // // if accessGroup is not defined // - if(!_accessGroup) + if (!_accessGroup) { NSString *groupSuffix = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"MSSOSDKKeychainGroup"]; @@ -1119,7 +1119,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 @@ -1155,7 +1156,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) { @@ -1167,7 +1169,8 @@ + (BOOL)validateIdToken:(NSString *)idToken magIdentifier:(NSString *)magIdentif // // case 2: aud doesn't match with clientId // - if (![aud isEqualToString:[[MASAccessService sharedService] getAccessValueStringWithStorageKey:MASKeychainStorageKeyClientId]]){ + if (![aud isEqualToString:[[MASAccessService sharedService] getAccessValueStringWithStorageKey:MASKeychainStorageKeyClientId]]) + { if (error) { @@ -1179,7 +1182,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) { @@ -1191,7 +1195,8 @@ + (BOOL)validateIdToken:(NSString *)idToken magIdentifier:(NSString *)magIdentif // // case 4: JWT expired // - if ([exp timeIntervalSinceNow] < 0){ + if ([exp timeIntervalSinceNow] < 0) + { if (error) { @@ -1264,9 +1269,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" @@ -1350,7 +1357,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]]; } @@ -1361,7 +1368,7 @@ - (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]]; } @@ -1372,7 +1379,7 @@ - (NSString *)debugSecuredDescription value = [NSString stringWithFormat:@"\n\n Custom (%@):\n", kMASAccessCustomSharedStorageKey]; [keychainDescription appendString:value]; - for(NSString *key in [_storages[kMASAccessCustomSharedStorageKey] allKeys]) + for (NSString *key in [_storages[kMASAccessCustomSharedStorageKey] allKeys]) { [keychainDescription appendString:[NSString stringWithFormat:@"\n key: %@", key]]; } diff --git a/MASFoundation/Classes/_private_/services/security/MASSecurityService.m b/MASFoundation/Classes/_private_/services/security/MASSecurityService.m index 56239924..465c5404 100644 --- a/MASFoundation/Classes/_private_/services/security/MASSecurityService.m +++ b/MASFoundation/Classes/_private_/services/security/MASSecurityService.m @@ -140,7 +140,7 @@ - (void)deleteAsymmetricKeys // Delete the private key // sanityCheck = SecItemDelete((__bridge CFDictionaryRef)queryPrivateKey); - if(!(sanityCheck == noErr || sanityCheck == errSecItemNotFound)) + if (!(sanityCheck == noErr || sanityCheck == errSecItemNotFound)) { DLog(@"Error removing private key, OSStatus == %d.", (int)sanityCheck ); } @@ -149,7 +149,7 @@ - (void)deleteAsymmetricKeys // Delete the public key // sanityCheck = SecItemDelete((__bridge CFDictionaryRef)queryPublicKey); - if(!(sanityCheck == noErr || sanityCheck == errSecItemNotFound)) + if (!(sanityCheck == noErr || sanityCheck == errSecItemNotFound)) { DLog(@"Error removing public key, OSStatus == %d.", (int)sanityCheck ); } @@ -226,7 +226,7 @@ - (NSString *)generateCSRWithUsername:(NSString *)userName // // Store new value in keychain // - if(privateKeyBits) + if (privateKeyBits) { NSString *keyContents = [self evpKeyToString:privatekey]; @@ -327,7 +327,7 @@ - (void)generateKeypair [keyPairAttr setObject:publicKeyAttr forKey:(__bridge id)kSecPublicKeyAttrs]; sanityCheck = SecKeyGeneratePair((__bridge CFDictionaryRef)keyPairAttr, &publicKeyRef, &privateKeyRef); - if(!( sanityCheck == noErr && publicKeyRef != NULL && privateKeyRef != NULL)) + if (!( sanityCheck == noErr && publicKeyRef != NULL && privateKeyRef != NULL)) { DLog(@"Error with something really bad went wrong with generating the key pair"); } @@ -335,12 +335,12 @@ - (void)generateKeypair // // Storing privateKey and publicKey into keychain // - if(privateKeyRef) + if (privateKeyRef) { [[MASAccessService sharedService] setAccessValueCryptoKey:privateKeyRef storageKey:MASKeychainStorageKeyPrivateKey]; } - if(publicKeyRef) + if (publicKeyRef) { [[MASAccessService sharedService] setAccessValueCryptoKey:publicKeyRef storageKey:MASKeychainStorageKeyPublicKey]; } diff --git a/MASFoundation/Classes/models/MASDevice.m b/MASFoundation/Classes/models/MASDevice.m index 76cfbb19..2c1c1414 100644 --- a/MASFoundation/Classes/models/MASDevice.m +++ b/MASFoundation/Classes/models/MASDevice.m @@ -63,7 +63,7 @@ - (BOOL)isRegistered // // Check if the vendorId in Keychain macth with current vendorId // - if([vendorIdCurrent isEqualToString:vendorIdFromKeychain]) + if ([vendorIdCurrent isEqualToString:vendorIdFromKeychain]) { NSString *magIdentifier = [accessService getAccessValueStringWithStorageKey:MASKeychainStorageKeyMAGIdentifier]; NSData *certificateData = [accessService getAccessValueCertificateWithStorageKey:MASKeychainStorageKeySignedPublicCertificate]; @@ -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/MASUser.m b/MASFoundation/Classes/models/MASUser.m index f0645db8..9cc8fc67 100644 --- a/MASFoundation/Classes/models/MASUser.m +++ b/MASFoundation/Classes/models/MASUser.m @@ -287,7 +287,7 @@ - (void)logoutWithCompletion:(MASCompletionErrorBlock)completion // // Detect if there is id_token // - if([accessService getAccessValueStringWithStorageKey:MASKeychainStorageKeyIdToken]) + if ([accessService getAccessValueStringWithStorageKey:MASKeychainStorageKeyIdToken]) { [[MASModelService sharedService] logOutDeviceAndClearLocalAccessToken:YES completion:completion]; } From 572f9623d1577baf22cd4a31b2c1ba8dd1bce774 Mon Sep 17 00:00:00 2001 From: Mahendra Nimishakavi Date: Mon, 20 Nov 2017 18:14:03 +0530 Subject: [PATCH 32/51] initial code related to browser based authentication --- MASFoundation.xcodeproj/project.pbxproj | 16 ++ MASFoundation/Classes/MAS.h | 9 + MASFoundation/Classes/MAS.m | 6 + .../categories/UIAlertController+MAS.h | 69 ++++++ .../categories/UIAlertController+MAS.m | 172 ++++++++++++++ .../_private_/services/MASServiceRegistry.h | 11 + .../_private_/services/MASServiceRegistry.m | 15 ++ .../services/model/MASModelService.h | 17 ++ .../services/model/MASModelService.m | 30 ++- .../models/MASBrowserBasedAuthentication.h | 34 +++ .../models/MASBrowserBasedAuthentication.m | 218 ++++++++++++++++++ 11 files changed, 594 insertions(+), 3 deletions(-) create mode 100644 MASFoundation/Classes/_private_/categories/UIAlertController+MAS.h create mode 100644 MASFoundation/Classes/_private_/categories/UIAlertController+MAS.m create mode 100644 MASFoundation/Classes/models/MASBrowserBasedAuthentication.h create mode 100644 MASFoundation/Classes/models/MASBrowserBasedAuthentication.m diff --git a/MASFoundation.xcodeproj/project.pbxproj b/MASFoundation.xcodeproj/project.pbxproj index cac3bf9e..237e62ba 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, ); }; }; @@ -720,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 = ""; }; @@ -1348,6 +1356,8 @@ CBA3EB2D1E945F2400E64D9D /* MASClaims.m */, CB1FD1491FB23701000AFA25 /* MASSharedStorage.h */, CB1FD14A1FB23701000AFA25 /* MASSharedStorage.m */, + C81CC3CA1FC2EA190058718E /* MASBrowserBasedAuthentication.h */, + C81CC3CB1FC2EA190058718E /* MASBrowserBasedAuthentication.m */, ); path = models; sourceTree = ""; @@ -1402,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 */, @@ -1724,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 */, @@ -2092,6 +2106,7 @@ 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 */, @@ -2152,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 */, diff --git a/MASFoundation/Classes/MAS.h b/MASFoundation/Classes/MAS.h index 8d290576..1e10044a 100644 --- a/MASFoundation/Classes/MAS.h +++ b/MASFoundation/Classes/MAS.h @@ -110,6 +110,15 @@ + (void)setOTPCredentialsBlock:(MASOTPCredentialsBlock _Nullable)oneTimePassword; +/** + * 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. diff --git a/MASFoundation/Classes/MAS.m b/MASFoundation/Classes/MAS.m index 6f470ced..98787fd9 100644 --- a/MASFoundation/Classes/MAS.m +++ b/MASFoundation/Classes/MAS.m @@ -92,6 +92,12 @@ + (void)setOTPCredentialsBlock:(MASOTPCredentialsBlock)oneTimePassword } ++(void)enableBrowserBasedAuthentication:(BOOL)enable +{ + [[MASModelService sharedService] setBrowserBasedLogin:enable]; +} + + + (void)setGatewayMonitor:(MASGatewayMonitorStatusBlock)monitor { [MASNetworkingService setGatewayMonitor:monitor]; diff --git a/MASFoundation/Classes/_private_/categories/UIAlertController+MAS.h b/MASFoundation/Classes/_private_/categories/UIAlertController+MAS.h new file mode 100644 index 00000000..7b158d89 --- /dev/null +++ b/MASFoundation/Classes/_private_/categories/UIAlertController+MAS.h @@ -0,0 +1,69 @@ +// +// UIAlertController+MAS.h +// MASFoundation +// +// Created by nimma01 on 11/10/17. +// Copyright © 2017 CA Technologies. All rights reserved. +// + +#import + +@interface UIAlertController (MAS) +///-------------------------------------- +/// @name Authentication Alerts +///------------------------------------- + +# pragma mark - Authentication Alerts + +/** + * Displays on screen an authentication UIAlertController modally in the currently + * visible UIViewController. + */ ++ (void)popupAuthenticationAlert; + + +/** + * Displays on screen an authentication UIAlertController modally in the selected + * UIViewController modally. + * + * @param viewController The UIViewController in which to present the modal UIAlertController. + */ ++ (void)popupAuthenticationAlertInViewController:(UIViewController *)viewController; + + + +///-------------------------------------- +/// @name Error Alerts +///------------------------------------- + +# pragma mark - Error Alerts + +/** + * Displays on screen an error UIAlertController modally in the currently + * visible UIViewController. + */ ++ (void)popupErrorAlert:(NSError *)error; + + +/** + * Displays on screen an error UIAlertController modally in the selected + * UIViewController modally. + * + * @param error The NSError contents to show in the UIAlertController. + * @param viewController The UIViewController in which to present the modal UIAlertController. + */ ++ (void)popupErrorAlert:(NSError *)error inViewController:(UIViewController *)viewController; + + + +///-------------------------------------- +/// @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..a34df9a5 --- /dev/null +++ b/MASFoundation/Classes/_private_/categories/UIAlertController+MAS.m @@ -0,0 +1,172 @@ +// +// 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 - Authentication Alerts + ++ (void)popupAuthenticationAlert +{ + [self popupAuthenticationAlertInViewController:[self rootViewController]]; +} + + ++ (void)popupAuthenticationAlertInViewController:(UIViewController *)viewController +{ + // + // Ensure this is done in the main UI thread. We don't know where the call is coming from + // + dispatch_async(dispatch_get_main_queue(), ^ + { + // + // Create alert controller + // + UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Sign In (MASUI)" + message:@"You need to sign in with your user credentials" + preferredStyle:UIAlertControllerStyleAlert]; + + // + // Username text field + // + [alertController addTextFieldWithConfigurationHandler:^(UITextField *textField) + { + textField.placeholder = NSLocalizedString(@"username", nil); + }]; + + // + // Password text field + // + [alertController addTextFieldWithConfigurationHandler:^(UITextField *textField) + { + textField.placeholder = NSLocalizedString(@"password", nil); + textField.secureTextEntry = YES; + }]; + + // + // OK Action + // + UIAlertAction *okAction = [UIAlertAction + actionWithTitle:NSLocalizedString(@"OK", @"OK action") + style:UIAlertActionStyleDefault + handler:^(UIAlertAction *action) + { + UITextField *usernameTextField = alertController.textFields.firstObject; + UITextField *passwordTextField = alertController.textFields.lastObject; + + // + // Attempt to authenticate + // + [MASUser loginWithUserName:usernameTextField.text password:passwordTextField.text completion:^(BOOL completed, NSError *error) { + + DLog(@"viewController received authentication response completed: %@ or error: %@", + (completed ? @"Yes" : @"No"), [error debugDescription]); + + if(error) + { + [UIAlertController popupErrorAlert:error]; + return; + } + }]; + }]; + + [alertController addAction:okAction]; + + // + // Cancel Action + // + UIAlertAction *cancelAction = [UIAlertAction + actionWithTitle:NSLocalizedString(@"Cancel", @"Cancel action") + style:UIAlertActionStyleDefault + handler:nil]; + + [alertController addAction:cancelAction]; + + [viewController presentViewController:alertController animated:YES completion:nil]; + }); +} + + +# pragma mark - Error Alert + ++ (void)popupErrorAlert:(NSError *)error +{ + [self popupErrorAlert:error inViewController:[self rootViewController]]; +} + + ++ (void)popupErrorAlert:(NSError *)error inViewController:(UIViewController *)viewController +{ + // + // Ensure this is done in the main UI thread. We don't know where the call is coming from + // + dispatch_async(dispatch_get_main_queue(), ^ + { + UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Error" + message:[error localizedDescription] + preferredStyle:UIAlertControllerStyleAlert]; + + UIAlertAction *ok = [UIAlertAction actionWithTitle:@"OK" + style:UIAlertActionStyleDefault + handler:^(UIAlertAction * action) + { + [alertController dismissViewControllerAnimated:YES completion:nil]; + }]; + + [alertController addAction:ok]; + + [viewController presentViewController:alertController animated:NO completion:nil]; + }); +} + + ++ (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_/services/MASServiceRegistry.h b/MASFoundation/Classes/_private_/services/MASServiceRegistry.h index 694f9508..34b5ec54 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 MASCompletionErrorBlock to receive login result. + * @return Return YES if handled, NO if not. + */ +-(BOOL)browserBasedLoginWillHandleAuthentication : (MASCompletionErrorBlock)bbaLoginBlock; + @end diff --git a/MASFoundation/Classes/_private_/services/MASServiceRegistry.m b/MASFoundation/Classes/_private_/services/MASServiceRegistry.m index 9c375214..b0788eeb 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 : (MASCompletionErrorBlock)bbaLoginBlock +{ + if(![[MASModelService sharedService] browserBasedLogin]) + { + return NO; + } + + [[MASBrowserBasedAuthentication sharedInstance] loadWebLoginTemplate:bbaLoginBlock]; + return YES; + +} + @end diff --git a/MASFoundation/Classes/_private_/services/model/MASModelService.h b/MASFoundation/Classes/_private_/services/model/MASModelService.h index 50b63377..4155579d 100644 --- a/MASFoundation/Classes/_private_/services/model/MASModelService.h +++ b/MASFoundation/Classes/_private_/services/model/MASModelService.h @@ -82,6 +82,23 @@ - (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)setBrowserBasedLogin : (BOOL)browserBasedLogin; + + +/** + * The current state of browser based login. + * + * @return BOOL value is returned. + */ +-(BOOL)browserBasedLogin; + + ///-------------------------------------- /// @name Application ///-------------------------------------- diff --git a/MASFoundation/Classes/_private_/services/model/MASModelService.m b/MASFoundation/Classes/_private_/services/model/MASModelService.m index e89189f2..ce60366d 100644 --- a/MASFoundation/Classes/_private_/services/model/MASModelService.m +++ b/MASFoundation/Classes/_private_/services/model/MASModelService.m @@ -29,6 +29,7 @@ @interface MASModelService () @property (nonatomic, strong, readwrite) MASAuthenticationProviders *currentProviders; +@property (nonatomic) BOOL isBrowserBasedLogin; @end @@ -39,7 +40,6 @@ @implementation MASModelService static MASUserLoginWithUserCredentialsBlock _userLoginBlock_ = nil; static MASUserAuthCredentialsBlock _userAuthCredentialsBlock_ = nil; - # pragma mark - Properties @@ -71,6 +71,19 @@ - (void)setUserObject:(MASUser *)user _currentUser = user; } + +-(void)setBrowserBasedLogin : (BOOL)browserBasedLogin +{ + self.isBrowserBasedLogin = browserBasedLogin; +} + + +-(BOOL)browserBasedLogin +{ + return self.isBrowserBasedLogin; +} + + # pragma mark - Shared Service + (instancetype)sharedService @@ -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 || self.isBrowserBasedLogin) { // @@ -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:completion]) + { + return; + } + if([serviceRegistry uiServiceWillHandleWithAuthCredentialsBlock:authCredentialsBlock]) { return; @@ -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:completion]) + { + return; + } + if([serviceRegistry uiServiceWillHandleWithAuthCredentialsBlock:authCredentialsBlock]) { return; diff --git a/MASFoundation/Classes/models/MASBrowserBasedAuthentication.h b/MASFoundation/Classes/models/MASBrowserBasedAuthentication.h new file mode 100644 index 00000000..e0b79d3c --- /dev/null +++ b/MASFoundation/Classes/models/MASBrowserBasedAuthentication.h @@ -0,0 +1,34 @@ +// +// MASBrowserBasedAuthentication.h +// MASFoundation +// +// Created by nimma01 on 20/11/17. +// Copyright © 2017 CA Technologies. All rights reserved. +// + +#import +#import "MASConstants.h" + +@interface MASBrowserBasedAuthentication : NSObject +{ + +} + + +/** + * 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 : (MASCompletionErrorBlock)webLoginBlock; + +@end diff --git a/MASFoundation/Classes/models/MASBrowserBasedAuthentication.m b/MASFoundation/Classes/models/MASBrowserBasedAuthentication.m new file mode 100644 index 00000000..a303bf7b --- /dev/null +++ b/MASFoundation/Classes/models/MASBrowserBasedAuthentication.m @@ -0,0 +1,218 @@ +// +// MASBrowserBasedAuthentication.m +// MASFoundation +// +// Created by nimma01 on 20/11/17. +// Copyright © 2017 CA Technologies. All rights reserved. +// + +#import "MASBrowserBasedAuthentication.h" +#import +#import "MASAuthorizationResponse.h" +#import "UIAlertController+MAS.h" +#import "MASConfigurationService.h" +#import "MASAccessService.h" +#import "MASGetURLRequest.h" +#import "MASModelService.h" + +@interface MASBrowserBasedAuthentication () +{ + +} + +@property (nonatomic) SFSafariViewController* safariViewController; +@property (nonatomic) MASCompletionErrorBlock 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 : (MASCompletionErrorBlock)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) { + + NSURL* url = [blockSelf getURLForWebLogin]; + DLog(@"url used for browser based authentication is %@",url.absoluteString); + blockSelf.safariViewController = [[SFSafariViewController alloc] initWithURL:url]; + __block UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:blockSelf.safariViewController]; + + dispatch_async(dispatch_get_main_queue(), ^ + { + [UIAlertController rootViewController].modalTransitionStyle = UIModalTransitionStyleCoverVertical; + + [[UIAlertController rootViewController] presentViewController:navigationController animated:YES + completion:^{ + + navigationController = nil; + }]; + + return; + }); + }]; +} + + +- (NSURL*)getURLForWebLogin +{ + // + // Endpoint + // + NSString *endPoint = [MASConfiguration currentConfiguration].authorizationEndpointPath; + + // + // 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; + + //Remove register scopes if device is already registered (required for BBA to work) + /* if([[MASDevice currentDevice] isRegistered]) + { + scope = [scope stringByReplacingOccurrencesOfString:@"msso_client_register" withString:@""]; + scope = [scope stringByReplacingOccurrencesOfString:@"msso_register" withString:@""]; + + }*/ + + // + // 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]; + //DLog(@"mag-identifier is %@",magIdentifier); + if(magIdentifier && magIdentifier.length > 0) + { + parameterInfo[MASMagIdentifierRequestResponseKey] = magIdentifier; + } + + return [MASGetURLRequest requestForEndpoint:endPoint withParameters:parameterInfo andHeaders:headerInfo requestType:MASRequestResponseTypeUnknown responseType:MASRequestResponseTypeUnknown isPublic:YES].URL; +} + + +#pragma mark - Authorization Response delegate + +-(void)didReceiveAuthorizationCode:(NSString *)code +{ + __block MASBrowserBasedAuthentication *blockSelf = self; + [MASUser loginWithAuthorizationCode:code completion:^(BOOL completed,NSError* error){ + [blockSelf dismissBrowser]; + if(error) + { + DLog(@"error occured %@",error.localizedDescription); + blockSelf.webLoginCallBack(completed, error); + return; + } + + DLog(@"Browser Based Login Successful"); + blockSelf.webLoginCallBack(completed, error); + + + }]; +} + + +-(void)didReceiveError:(NSError *)error +{ + self.webLoginCallBack(NO, error); +} + +#pragma mark - UI + +-(void)dismissBrowser +{ + dispatch_async(dispatch_get_main_queue(), ^{ + [[UIAlertController rootViewController] dismissViewControllerAnimated:YES completion:nil]; + }); +} + +@end From db7ccbb8193c94dac532750d6bacc05d39b62b83 Mon Sep 17 00:00:00 2001 From: Mahendra Nimishakavi Date: Tue, 21 Nov 2017 14:16:40 +0530 Subject: [PATCH 33/51] added code for explicit login in MASUser class --- .../Classes/models/MASBrowserBasedAuthentication.m | 13 +++++++++++-- MASFoundation/Classes/models/MASUser.h | 10 ++++++++++ MASFoundation/Classes/models/MASUser.m | 12 ++++++++++++ 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/MASFoundation/Classes/models/MASBrowserBasedAuthentication.m b/MASFoundation/Classes/models/MASBrowserBasedAuthentication.m index a303bf7b..e1826078 100644 --- a/MASFoundation/Classes/models/MASBrowserBasedAuthentication.m +++ b/MASFoundation/Classes/models/MASBrowserBasedAuthentication.m @@ -15,7 +15,7 @@ #import "MASGetURLRequest.h" #import "MASModelService.h" -@interface MASBrowserBasedAuthentication () +@interface MASBrowserBasedAuthentication () { } @@ -49,7 +49,7 @@ -(void)loadWebLoginTemplate : (MASCompletionErrorBlock)webLoginBlock MASModelService* service = [MASModelService sharedService]; [[MASAuthorizationResponse sharedInstance] setDelegate:self]; __block MASBrowserBasedAuthentication *blockSelf = self; - + __weak __typeof__(self) weakSelf = 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. // @@ -58,6 +58,7 @@ -(void)loadWebLoginTemplate : (MASCompletionErrorBlock)webLoginBlock NSURL* url = [blockSelf getURLForWebLogin]; DLog(@"url used for browser based authentication is %@",url.absoluteString); blockSelf.safariViewController = [[SFSafariViewController alloc] initWithURL:url]; + blockSelf.safariViewController.delegate = weakSelf; __block UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:blockSelf.safariViewController]; dispatch_async(dispatch_get_main_queue(), ^ @@ -179,6 +180,14 @@ - (NSURL*)getURLForWebLogin } +#pragma mark - SafariViewController Delegates + +-(void)safariViewControllerDidFinish:(SFSafariViewController *)controller +{ + self.webLoginCallBack(NO, nil); +} + + #pragma mark - Authorization Response delegate -(void)didReceiveAuthorizationCode:(NSString *)code diff --git a/MASFoundation/Classes/models/MASUser.h b/MASFoundation/Classes/models/MASUser.h index ff7c6507..d79c09a6 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)initializeBrowserBasedLoginWithCompletion : (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 9cc8fc67..9c751916 100644 --- a/MASFoundation/Classes/models/MASUser.m +++ b/MASFoundation/Classes/models/MASUser.m @@ -250,6 +250,18 @@ + (void)loginWithAuthCredentials:(MASAuthCredentials *_Nonnull)authCredentials c } ++(void)initializeBrowserBasedLoginWithCompletion : (MASCompletionErrorBlock _Nullable)completion +{ + 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]; From a06367b2f8c946892b9406ebafaba1ffd3992fb9 Mon Sep 17 00:00:00 2001 From: Kaylie Son Date: Tue, 21 Nov 2017 11:22:24 -0800 Subject: [PATCH 34/51] DE328373 : [iOS][Multi-Server] MAS Set Security Configuration call gets success though setting Public Server and Trust Public PKI value set as 'False' --- MASFoundation/Classes/MASConstants.h | 6 + .../_private_/categories/NSError+MASPrivate.m | 6 + .../Classes/models/MASConfiguration.h | 27 ++++- .../Classes/models/MASConfiguration.m | 105 ++++++++++++++---- 4 files changed, 116 insertions(+), 28 deletions(-) diff --git a/MASFoundation/Classes/MASConstants.h b/MASFoundation/Classes/MASConstants.h index 2505b83e..2a4a86c6 100644 --- a/MASFoundation/Classes/MASConstants.h +++ b/MASFoundation/Classes/MASConstants.h @@ -329,6 +329,12 @@ typedef NS_ENUM(NSInteger, MASFoundationErrorCode) MASFoundationErrorCodeConfigurationLoadingFailedJsonValidation = 100203, MASFoundationErrorCodeConfigurationInvalidEndpoint = 100204, + // + // Security Configuration + // + MASFoundationErrorCodeConfigurationInvalidHostForSecurityConfiguration = 100211, + MASFoundationErrorCodeConfigurationInvalidPinningInfoForSecurityConfiguration = 100212, + // // Geolocation // diff --git a/MASFoundation/Classes/_private_/categories/NSError+MASPrivate.m b/MASFoundation/Classes/_private_/categories/NSError+MASPrivate.m index 51ecb6bc..1a3c0c90 100644 --- a/MASFoundation/Classes/_private_/categories/NSError+MASPrivate.m +++ b/MASFoundation/Classes/_private_/categories/NSError+MASPrivate.m @@ -984,6 +984,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 // 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 268b55d7..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) { @@ -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 From 7bc04ed6ba10dbd21c0a82feaacb166028f3dcf1 Mon Sep 17 00:00:00 2001 From: Kaylie Son Date: Tue, 21 Nov 2017 12:38:38 -0800 Subject: [PATCH 35/51] US416558 : [iOS] SharedStorage API --- .../services/access/MASAccessService.h | 10 ++++ .../services/access/MASAccessService.m | 17 +++++++ .../Classes/models/MASSharedStorage.h | 10 ++++ .../Classes/models/MASSharedStorage.m | 46 +++++++++++++++++++ 4 files changed, 83 insertions(+) diff --git a/MASFoundation/Classes/_private_/services/access/MASAccessService.h b/MASFoundation/Classes/_private_/services/access/MASAccessService.h index a498a5e2..dfb9c3f0 100644 --- a/MASFoundation/Classes/_private_/services/access/MASAccessService.h +++ b/MASFoundation/Classes/_private_/services/access/MASAccessService.h @@ -341,6 +341,16 @@ extern NSString * const MASKeychainStorageKeyDeviceVendorId; +/** + 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 ///-------------------------------------- diff --git a/MASFoundation/Classes/_private_/services/access/MASAccessService.m b/MASFoundation/Classes/_private_/services/access/MASAccessService.m index 503b067b..38c86a4f 100644 --- a/MASFoundation/Classes/_private_/services/access/MASAccessService.m +++ b/MASFoundation/Classes/_private_/services/access/MASAccessService.m @@ -671,6 +671,23 @@ - (SecKeyRef)getAccessValueCryptoKeyWithStorageKey:(NSString *)storageKey } +- (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:storageKey error:&operationError]; + + if (operationError && error) + { + *error = operationError; + } +} + + #pragma mark - Private + (NSString *)padding:(NSString *)encodedString{ diff --git a/MASFoundation/Classes/models/MASSharedStorage.h b/MASFoundation/Classes/models/MASSharedStorage.h index 69867a73..7b68d72c 100644 --- a/MASFoundation/Classes/models/MASSharedStorage.h +++ b/MASFoundation/Classes/models/MASSharedStorage.h @@ -74,4 +74,14 @@ */ + (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 index c7d0916d..84a652e8 100644 --- a/MASFoundation/Classes/models/MASSharedStorage.m +++ b/MASFoundation/Classes/models/MASSharedStorage.m @@ -215,4 +215,50 @@ + (BOOL)saveData:(NSData *)data key:(NSString *)key error:(NSError **)error 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 From e5a886063b91a268fd468b56f47438de62a64df2 Mon Sep 17 00:00:00 2001 From: Kaylie Son Date: Tue, 21 Nov 2017 12:40:33 -0800 Subject: [PATCH 36/51] US416558 : [iOS] SharedStorage API --- .../Classes/_private_/services/access/MASAccessService.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MASFoundation/Classes/_private_/services/access/MASAccessService.m b/MASFoundation/Classes/_private_/services/access/MASAccessService.m index 38c86a4f..cedf6246 100644 --- a/MASFoundation/Classes/_private_/services/access/MASAccessService.m +++ b/MASFoundation/Classes/_private_/services/access/MASAccessService.m @@ -679,7 +679,7 @@ - (void)deleteForStorageKey:(NSString *)storageKey error:(NSError **)error NSError *operationError = nil; - [destinationStorage removeItemForKey:storageKey error:&operationError]; + [destinationStorage removeItemForKey:accessValueAsString error:&operationError]; if (operationError && error) { From bb0a2a5c0136a4f9abbdb901c604b6b6d1caa6a1 Mon Sep 17 00:00:00 2001 From: Mahendra Nimishakavi Date: Wed, 22 Nov 2017 19:08:28 +0530 Subject: [PATCH 37/51] added some code to handle the redirection and load the template --- .../_private_/services/MASServiceRegistry.h | 4 +- .../_private_/services/MASServiceRegistry.m | 2 +- .../services/model/MASModelService.m | 4 +- .../services/network/MASNetworkingService.h | 7 +- .../services/network/MASNetworkingService.m | 8 +- .../network/internal/MASURLSessionManager.h | 1 + .../network/internal/MASURLSessionManager.m | 8 ++ .../models/MASBrowserBasedAuthentication.h | 2 +- .../models/MASBrowserBasedAuthentication.m | 88 +++++++++++++++---- 9 files changed, 97 insertions(+), 27 deletions(-) diff --git a/MASFoundation/Classes/_private_/services/MASServiceRegistry.h b/MASFoundation/Classes/_private_/services/MASServiceRegistry.h index 34b5ec54..781e5f37 100644 --- a/MASFoundation/Classes/_private_/services/MASServiceRegistry.h +++ b/MASFoundation/Classes/_private_/services/MASServiceRegistry.h @@ -193,9 +193,9 @@ typedef NS_ENUM(NSInteger, MASRegistryState) * For this method to handle authentication it requires browser based login to be enabled. * @see enableBrowserBasedAuthentication * - * @param bbaLoginBlock The MASCompletionErrorBlock to receive login result. + * @param bbaLoginBlock The MASAuthCredentialsBlock to receive login result. * @return Return YES if handled, NO if not. */ --(BOOL)browserBasedLoginWillHandleAuthentication : (MASCompletionErrorBlock)bbaLoginBlock; +-(BOOL)browserBasedLoginWillHandleAuthentication : (MASAuthCredentialsBlock)bbaLoginBlock; @end diff --git a/MASFoundation/Classes/_private_/services/MASServiceRegistry.m b/MASFoundation/Classes/_private_/services/MASServiceRegistry.m index b0788eeb..5f759f10 100644 --- a/MASFoundation/Classes/_private_/services/MASServiceRegistry.m +++ b/MASFoundation/Classes/_private_/services/MASServiceRegistry.m @@ -935,7 +935,7 @@ - (BOOL)uiServiceWillHandleOTPChannelSelection:(NSArray *)supportedChannels } --(BOOL)browserBasedLoginWillHandleAuthentication : (MASCompletionErrorBlock)bbaLoginBlock +-(BOOL)browserBasedLoginWillHandleAuthentication : (MASAuthCredentialsBlock)bbaLoginBlock { if(![[MASModelService sharedService] browserBasedLogin]) { diff --git a/MASFoundation/Classes/_private_/services/model/MASModelService.m b/MASFoundation/Classes/_private_/services/model/MASModelService.m index ce60366d..c4b2ad8e 100644 --- a/MASFoundation/Classes/_private_/services/model/MASModelService.m +++ b/MASFoundation/Classes/_private_/services/model/MASModelService.m @@ -923,7 +923,7 @@ - (void)registerDeviceWithCompletion:(MASCompletionErrorBlock)completion // MASServiceRegistry *serviceRegistry = [MASServiceRegistry sharedRegistry]; - if([serviceRegistry browserBasedLoginWillHandleAuthentication:completion]) + if([serviceRegistry browserBasedLoginWillHandleAuthentication:authCredentialsBlock]) { return; } @@ -1731,7 +1731,7 @@ - (void)loginUsingUserCredentials:(MASCompletionErrorBlock)completion // If the UI handling framework is present and will handle this stop here // MASServiceRegistry *serviceRegistry = [MASServiceRegistry sharedRegistry]; - if([serviceRegistry browserBasedLoginWillHandleAuthentication:completion]) + if([serviceRegistry browserBasedLoginWillHandleAuthentication:authCredentialsBlock]) { return; } diff --git a/MASFoundation/Classes/_private_/services/network/MASNetworkingService.h b/MASFoundation/Classes/_private_/services/network/MASNetworkingService.h index 6653a47c..ca85efab 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,10 @@ @property (nonatomic, assign, readonly) MASGatewayMonitoringStatus monitoringStatus; +@property (nonatomic) MASSessionDataTaskHTTPRedirectBlock httpRedirectionBlock; + +//@property (nonatomic, copy) MASSessionDataTask1CompletionBlock httpBlock; + /** 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 c4415cac..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" @@ -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/MASURLSessionManager.h b/MASFoundation/Classes/_private_/services/network/internal/MASURLSessionManager.h index ad42a64c..a2c67eb5 100644 --- a/MASFoundation/Classes/_private_/services/network/internal/MASURLSessionManager.h +++ b/MASFoundation/Classes/_private_/services/network/internal/MASURLSessionManager.h @@ -149,5 +149,6 @@ typedef void (^MASNetworkSessionDidFinishEventsForBackgroundURLSessionBlock)(NSU */ - (void)setSessionDidReceiveAuthenticationChallengeBlock:(NSURLSessionAuthChallengeDisposition (^)(NSURLSession *session, NSURLAuthenticationChallenge *challenge, NSURLCredential **credential))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 () Date: Thu, 23 Nov 2017 13:04:45 +0530 Subject: [PATCH 38/51] [ADD] Adding new blocks for handling Biometric Registration and Deregistration UI --- MASFoundation/Classes/MASConstants.h | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/MASFoundation/Classes/MASConstants.h b/MASFoundation/Classes/MASConstants.h index 2a4a86c6..1a9de06a 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 ///-------------------------------------- From 9e1cd5730c328614a4968ea47b545584359e2740 Mon Sep 17 00:00:00 2001 From: Mahendra Nimishakavi Date: Thu, 23 Nov 2017 18:35:06 +0530 Subject: [PATCH 39/51] included review comments - filter the redirection only to BBA , made Static properties on MASModelService and fixed other comments. --- MASFoundation/Classes/MAS.m | 2 +- MASFoundation/Classes/MASConstants.h | 4 + .../_private_/categories/NSError+MASPrivate.h | 10 +- .../_private_/categories/NSError+MASPrivate.m | 11 +- .../categories/UIAlertController+MAS.h | 46 ------- .../categories/UIAlertController+MAS.m | 113 ------------------ .../_private_/services/MASServiceRegistry.m | 2 +- .../services/model/MASModelService.h | 4 +- .../services/model/MASModelService.m | 14 +-- .../network/requests/MASGetURLRequest.m | 2 +- .../models/MASBrowserBasedAuthentication.h | 8 +- .../models/MASBrowserBasedAuthentication.m | 74 ++++++------ MASFoundation/Classes/models/MASUser.h | 2 +- MASFoundation/Classes/models/MASUser.m | 8 +- 14 files changed, 82 insertions(+), 218 deletions(-) diff --git a/MASFoundation/Classes/MAS.m b/MASFoundation/Classes/MAS.m index 98787fd9..ef590fcd 100644 --- a/MASFoundation/Classes/MAS.m +++ b/MASFoundation/Classes/MAS.m @@ -94,7 +94,7 @@ + (void)setOTPCredentialsBlock:(MASOTPCredentialsBlock)oneTimePassword +(void)enableBrowserBasedAuthentication:(BOOL)enable { - [[MASModelService sharedService] setBrowserBasedLogin:enable]; + [MASModelService setBrowserBasedAuthentication:enable]; } diff --git a/MASFoundation/Classes/MASConstants.h b/MASFoundation/Classes/MASConstants.h index 2505b83e..bfaa6848 100644 --- a/MASFoundation/Classes/MASConstants.h +++ b/MASFoundation/Classes/MASConstants.h @@ -459,6 +459,10 @@ typedef NS_ENUM(NSInteger, MASFoundationErrorCode) MASFoundationErrorCodeJWTUnexpectedClassType = 170002, MASFoundationErrorCodeJWTSerializationError = 170003, + // + // Browser Based Login + // + MASFoundationErrorCodeBBANotEnabled = 180000, // // SharedStorage // 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 51ecb6bc..43e31a42 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 @@ -1107,7 +1112,11 @@ + (NSString *)descriptionForFoundationErrorCode:(MASFoundationErrorCode)errorCod // 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 index 7b158d89..ec8de498 100644 --- a/MASFoundation/Classes/_private_/categories/UIAlertController+MAS.h +++ b/MASFoundation/Classes/_private_/categories/UIAlertController+MAS.h @@ -9,52 +9,6 @@ #import @interface UIAlertController (MAS) -///-------------------------------------- -/// @name Authentication Alerts -///------------------------------------- - -# pragma mark - Authentication Alerts - -/** - * Displays on screen an authentication UIAlertController modally in the currently - * visible UIViewController. - */ -+ (void)popupAuthenticationAlert; - - -/** - * Displays on screen an authentication UIAlertController modally in the selected - * UIViewController modally. - * - * @param viewController The UIViewController in which to present the modal UIAlertController. - */ -+ (void)popupAuthenticationAlertInViewController:(UIViewController *)viewController; - - - -///-------------------------------------- -/// @name Error Alerts -///------------------------------------- - -# pragma mark - Error Alerts - -/** - * Displays on screen an error UIAlertController modally in the currently - * visible UIViewController. - */ -+ (void)popupErrorAlert:(NSError *)error; - - -/** - * Displays on screen an error UIAlertController modally in the selected - * UIViewController modally. - * - * @param error The NSError contents to show in the UIAlertController. - * @param viewController The UIViewController in which to present the modal UIAlertController. - */ -+ (void)popupErrorAlert:(NSError *)error inViewController:(UIViewController *)viewController; - - ///-------------------------------------- /// @name Public diff --git a/MASFoundation/Classes/_private_/categories/UIAlertController+MAS.m b/MASFoundation/Classes/_private_/categories/UIAlertController+MAS.m index a34df9a5..cbd86f3e 100644 --- a/MASFoundation/Classes/_private_/categories/UIAlertController+MAS.m +++ b/MASFoundation/Classes/_private_/categories/UIAlertController+MAS.m @@ -9,122 +9,9 @@ #import "UIAlertController+MAS.h" #import "MASUser.h" @implementation UIAlertController (MAS) -# pragma mark - Authentication Alerts - -+ (void)popupAuthenticationAlert -{ - [self popupAuthenticationAlertInViewController:[self rootViewController]]; -} - - -+ (void)popupAuthenticationAlertInViewController:(UIViewController *)viewController -{ - // - // Ensure this is done in the main UI thread. We don't know where the call is coming from - // - dispatch_async(dispatch_get_main_queue(), ^ - { - // - // Create alert controller - // - UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Sign In (MASUI)" - message:@"You need to sign in with your user credentials" - preferredStyle:UIAlertControllerStyleAlert]; - - // - // Username text field - // - [alertController addTextFieldWithConfigurationHandler:^(UITextField *textField) - { - textField.placeholder = NSLocalizedString(@"username", nil); - }]; - - // - // Password text field - // - [alertController addTextFieldWithConfigurationHandler:^(UITextField *textField) - { - textField.placeholder = NSLocalizedString(@"password", nil); - textField.secureTextEntry = YES; - }]; - - // - // OK Action - // - UIAlertAction *okAction = [UIAlertAction - actionWithTitle:NSLocalizedString(@"OK", @"OK action") - style:UIAlertActionStyleDefault - handler:^(UIAlertAction *action) - { - UITextField *usernameTextField = alertController.textFields.firstObject; - UITextField *passwordTextField = alertController.textFields.lastObject; - - // - // Attempt to authenticate - // - [MASUser loginWithUserName:usernameTextField.text password:passwordTextField.text completion:^(BOOL completed, NSError *error) { - - DLog(@"viewController received authentication response completed: %@ or error: %@", - (completed ? @"Yes" : @"No"), [error debugDescription]); - - if(error) - { - [UIAlertController popupErrorAlert:error]; - return; - } - }]; - }]; - - [alertController addAction:okAction]; - - // - // Cancel Action - // - UIAlertAction *cancelAction = [UIAlertAction - actionWithTitle:NSLocalizedString(@"Cancel", @"Cancel action") - style:UIAlertActionStyleDefault - handler:nil]; - - [alertController addAction:cancelAction]; - - [viewController presentViewController:alertController animated:YES completion:nil]; - }); -} - # pragma mark - Error Alert -+ (void)popupErrorAlert:(NSError *)error -{ - [self popupErrorAlert:error inViewController:[self rootViewController]]; -} - - -+ (void)popupErrorAlert:(NSError *)error inViewController:(UIViewController *)viewController -{ - // - // Ensure this is done in the main UI thread. We don't know where the call is coming from - // - dispatch_async(dispatch_get_main_queue(), ^ - { - UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Error" - message:[error localizedDescription] - preferredStyle:UIAlertControllerStyleAlert]; - - UIAlertAction *ok = [UIAlertAction actionWithTitle:@"OK" - style:UIAlertActionStyleDefault - handler:^(UIAlertAction * action) - { - [alertController dismissViewControllerAnimated:YES completion:nil]; - }]; - - [alertController addAction:ok]; - - [viewController presentViewController:alertController animated:NO completion:nil]; - }); -} - - + (UIViewController *) presentedViewController:(id)viewController { if ([viewController isKindOfClass:[UINavigationController class]]) diff --git a/MASFoundation/Classes/_private_/services/MASServiceRegistry.m b/MASFoundation/Classes/_private_/services/MASServiceRegistry.m index 5f759f10..d7148fc4 100644 --- a/MASFoundation/Classes/_private_/services/MASServiceRegistry.m +++ b/MASFoundation/Classes/_private_/services/MASServiceRegistry.m @@ -937,7 +937,7 @@ - (BOOL)uiServiceWillHandleOTPChannelSelection:(NSArray *)supportedChannels -(BOOL)browserBasedLoginWillHandleAuthentication : (MASAuthCredentialsBlock)bbaLoginBlock { - if(![[MASModelService sharedService] browserBasedLogin]) + if(![MASModelService browserBasedAuthentication]) { return NO; } diff --git a/MASFoundation/Classes/_private_/services/model/MASModelService.h b/MASFoundation/Classes/_private_/services/model/MASModelService.h index 4155579d..f7b6b2bc 100644 --- a/MASFoundation/Classes/_private_/services/model/MASModelService.h +++ b/MASFoundation/Classes/_private_/services/model/MASModelService.h @@ -88,7 +88,7 @@ * @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)setBrowserBasedLogin : (BOOL)browserBasedLogin; ++(void)setBrowserBasedAuthentication : (BOOL)browserBasedAuthentication; /** @@ -96,7 +96,7 @@ * * @return BOOL value is returned. */ --(BOOL)browserBasedLogin; ++(BOOL)browserBasedAuthentication; ///-------------------------------------- diff --git a/MASFoundation/Classes/_private_/services/model/MASModelService.m b/MASFoundation/Classes/_private_/services/model/MASModelService.m index c4b2ad8e..6026fde9 100644 --- a/MASFoundation/Classes/_private_/services/model/MASModelService.m +++ b/MASFoundation/Classes/_private_/services/model/MASModelService.m @@ -29,7 +29,7 @@ @interface MASModelService () @property (nonatomic, strong, readwrite) MASAuthenticationProviders *currentProviders; -@property (nonatomic) BOOL isBrowserBasedLogin; + @end @@ -39,7 +39,7 @@ @implementation MASModelService static MASGrantFlow _grantFlow_ = MASGrantFlowClientCredentials; static MASUserLoginWithUserCredentialsBlock _userLoginBlock_ = nil; static MASUserAuthCredentialsBlock _userAuthCredentialsBlock_ = nil; - +static BOOL _isBrowserBasedAuthentication_; # pragma mark - Properties @@ -72,15 +72,15 @@ - (void)setUserObject:(MASUser *)user } --(void)setBrowserBasedLogin : (BOOL)browserBasedLogin ++(void)setBrowserBasedAuthentication : (BOOL)browserBasedAuthentication { - self.isBrowserBasedLogin = browserBasedLogin; + _isBrowserBasedAuthentication_ = browserBasedAuthentication; } --(BOOL)browserBasedLogin ++(BOOL)browserBasedAuthentication { - return self.isBrowserBasedLogin; + return _isBrowserBasedAuthentication_; } @@ -380,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 || self.isBrowserBasedLogin) + if (([MASApplication currentApplication].isAuthenticated && [MASApplication currentApplication].authenticationStatus == MASAuthenticationStatusLoginWithUser) || [MASAccess currentAccess].isSessionLocked || _isBrowserBasedAuthentication_) { // diff --git a/MASFoundation/Classes/_private_/services/network/requests/MASGetURLRequest.m b/MASFoundation/Classes/_private_/services/network/requests/MASGetURLRequest.m index 74b1d3fb..f17f61d8 100644 --- a/MASFoundation/Classes/_private_/services/network/requests/MASGetURLRequest.m +++ b/MASFoundation/Classes/_private_/services/network/requests/MASGetURLRequest.m @@ -46,7 +46,7 @@ + (MASGetURLRequest *)requestForEndpoint:(NSString *)endPoint NSURL *url = [NSURL URLWithString:endPointWithQueryParameters relativeToURL:[MASConfiguration currentConfiguration].gatewayUrl]; NSAssert(url, @"URL cannot be nil"); - + NSLog(@"url in sdk is %@",url.absoluteString); // // Create the request // diff --git a/MASFoundation/Classes/models/MASBrowserBasedAuthentication.h b/MASFoundation/Classes/models/MASBrowserBasedAuthentication.h index 2cafa95f..0994c69b 100644 --- a/MASFoundation/Classes/models/MASBrowserBasedAuthentication.h +++ b/MASFoundation/Classes/models/MASBrowserBasedAuthentication.h @@ -2,8 +2,10 @@ // MASBrowserBasedAuthentication.h // MASFoundation // -// Created by nimma01 on 20/11/17. -// Copyright © 2017 CA Technologies. All rights reserved. +// 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 @@ -29,6 +31,6 @@ * * @param webLoginBlock completion MASCompletionErrorBlock that receives the results. */ --(void)loadWebLoginTemplate : (MASAuthCredentialsBlock)webLoginBlock; +-(void)loadWebLoginTemplate:(MASAuthCredentialsBlock)webLoginBlock; @end diff --git a/MASFoundation/Classes/models/MASBrowserBasedAuthentication.m b/MASFoundation/Classes/models/MASBrowserBasedAuthentication.m index 891bb8bc..1eca7f30 100644 --- a/MASFoundation/Classes/models/MASBrowserBasedAuthentication.m +++ b/MASFoundation/Classes/models/MASBrowserBasedAuthentication.m @@ -2,8 +2,10 @@ // MASBrowserBasedAuthentication.m // MASFoundation // -// Created by nimma01 on 20/11/17. -// Copyright © 2017 CA Technologies. All rights reserved. +// 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 "MASBrowserBasedAuthentication.h" @@ -43,7 +45,7 @@ + (instancetype)sharedInstance } --(void)loadWebLoginTemplate : (MASAuthCredentialsBlock)webLoginBlock +-(void)loadWebLoginTemplate:(MASAuthCredentialsBlock)webLoginBlock { self.webLoginCallBack = webLoginBlock; MASModelService* service = [MASModelService sharedService]; @@ -54,36 +56,14 @@ -(void)loadWebLoginTemplate : (MASAuthCredentialsBlock)webLoginBlock // 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) { - - NSURL* url = [blockSelf getURLForWebLogin]; + [blockSelf getURLForWebLogin]; DLog(@"url used for browser based authentication is %@",url.absoluteString); - /* blockSelf.safariViewController = [[SFSafariViewController alloc] initWithURL:url]; - blockSelf.safariViewController.delegate = weakSelf; - __block UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:blockSelf.safariViewController]; - - dispatch_async(dispatch_get_main_queue(), ^ - { - [UIAlertController rootViewController].modalTransitionStyle = UIModalTransitionStyleCoverVertical; - - [[UIAlertController rootViewController] presentViewController:navigationController animated:YES - completion:^{ - - navigationController = nil; - }]; - - return; - });*/ - }]; + }]; } -- (NSURL*)getURLForWebLogin +- (void)getURLForWebLogin { - // - // Endpoint - // - NSString *endPoint = [MASConfiguration currentConfiguration].authorizationEndpointPath; - // // Headers // @@ -176,42 +156,51 @@ - (NSURL*)getURLForWebLogin parameterInfo[MASMagIdentifierRequestResponseKey] = magIdentifier; } + // + // Endpoint + // + NSString *endPoint = [MASConfiguration currentConfiguration].authorizationEndpointPath; + [[MASNetworkingService sharedService] setHttpRedirectionBlock:[self getRedirectionBlock]]; - [[MASNetworkingService sharedService] getFrom:@"/auth/oauth/v2/authorize" withParameters:parameterInfo andHeaders:headerInfo requestType:MASRequestResponseTypeWwwFormUrlEncoded responseType:MASRequestResponseTypeWwwFormUrlEncoded isPublic:YES completion:^(NSDictionary* response, NSError* error){ + [[MASNetworkingService sharedService] getFrom:endPoint withParameters:parameterInfo andHeaders:headerInfo requestType:MASRequestResponseTypeWwwFormUrlEncoded responseType:MASRequestResponseTypeWwwFormUrlEncoded completion:^(NSDictionary* response, NSError* error){ if(error) { - NSLog(@"error is %@",error.localizedDescription); + DLog(@"error is %@",error.localizedDescription); } - NSLog(@"response is %@",response); + DLog(@"response is %@",response); }]; - - - - return [MASGetURLRequest requestForEndpoint:endPoint withParameters:parameterInfo andHeaders:headerInfo requestType:MASRequestResponseTypeUnknown responseType:MASRequestResponseTypeUnknown isPublic:YES].URL; } -(MASSessionDataTaskHTTPRedirectBlock)getRedirectionBlock { MASSessionDataTaskHTTPRedirectBlock redirectionBlock = ^(NSURLSession *session, NSURLSessionTask *task, NSURLResponse * response, NSURLRequest *request){ NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response; - if(httpResponse.statusCode == 302) + if(httpResponse.statusCode == 302 && [self isBBARedirection:task.originalRequest]) { - NSLog(@"all headers %@",httpResponse.allHeaderFields); + DLog(@"all headers %@",httpResponse.allHeaderFields); NSString* locationURL = [httpResponse.allHeaderFields objectForKey:@"Location"]; NSURL* redirectURL = [NSURL URLWithString:locationURL]; [task cancel]; [self launchBrowserWithURL:redirectURL]; } - 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; +} + -(void)launchBrowserWithURL : (NSURL*)templatizedURL { __block MASBrowserBasedAuthentication *blockSelf = self; @@ -239,7 +228,12 @@ -(void)launchBrowserWithURL : (NSURL*)templatizedURL -(void)safariViewControllerDidFinish:(SFSafariViewController *)controller { - //self.webLoginCallBack(NO, nil); + self.webLoginCallBack(nil, YES, ^(BOOL completed, NSError* error){ + if(error) + { + DLog(@"Browser dismissed"); + } + }); } @@ -254,7 +248,7 @@ -(void)didReceiveAuthorizationCode:(NSString *)code { //error } - NSLog(@"successfully logged in"); + DLog(@"successfully logged in"); [self dismissBrowser]; }); } diff --git a/MASFoundation/Classes/models/MASUser.h b/MASFoundation/Classes/models/MASUser.h index d79c09a6..78f5c497 100644 --- a/MASFoundation/Classes/models/MASUser.h +++ b/MASFoundation/Classes/models/MASUser.h @@ -267,7 +267,7 @@ @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)initializeBrowserBasedLoginWithCompletion : (MASCompletionErrorBlock _Nullable)completion; ++(void)initializeBrowserBasedAuthenticationWithCompletion:(MASCompletionErrorBlock _Nullable)completion; diff --git a/MASFoundation/Classes/models/MASUser.m b/MASFoundation/Classes/models/MASUser.m index 9c751916..34eaded7 100644 --- a/MASFoundation/Classes/models/MASUser.m +++ b/MASFoundation/Classes/models/MASUser.m @@ -250,8 +250,14 @@ + (void)loginWithAuthCredentials:(MASAuthCredentials *_Nonnull)authCredentials c } -+(void)initializeBrowserBasedLoginWithCompletion : (MASCompletionErrorBlock _Nullable)completion ++(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]); From 4e7e1850d0d95c7ea2a6d6e3714d51fbc89a62b8 Mon Sep 17 00:00:00 2001 From: Mahendra Nimishakavi Date: Fri, 24 Nov 2017 14:31:55 +0530 Subject: [PATCH 40/51] saved older redirection block if any and set it back after BBA --- .../Classes/models/MASBrowserBasedAuthentication.m | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/MASFoundation/Classes/models/MASBrowserBasedAuthentication.m b/MASFoundation/Classes/models/MASBrowserBasedAuthentication.m index 1eca7f30..7a9479af 100644 --- a/MASFoundation/Classes/models/MASBrowserBasedAuthentication.m +++ b/MASFoundation/Classes/models/MASBrowserBasedAuthentication.m @@ -57,7 +57,7 @@ -(void)loadWebLoginTemplate:(MASAuthCredentialsBlock)webLoginBlock // [service registerApplication:^(BOOL completed, NSError *error) { [blockSelf getURLForWebLogin]; - DLog(@"url used for browser based authentication is %@",url.absoluteString); + //DLog(@"url used for browser based authentication is %@",url.absoluteString); }]; } @@ -161,16 +161,16 @@ - (void)getURLForWebLogin // NSString *endPoint = [MASConfiguration currentConfiguration].authorizationEndpointPath; + MASSessionDataTaskHTTPRedirectBlock oldRedirectionBlock = [[MASNetworkingService sharedService] httpRedirectionBlock]; [[MASNetworkingService sharedService] setHttpRedirectionBlock:[self getRedirectionBlock]]; [[MASNetworkingService sharedService] getFrom:endPoint withParameters:parameterInfo andHeaders:headerInfo requestType:MASRequestResponseTypeWwwFormUrlEncoded responseType:MASRequestResponseTypeWwwFormUrlEncoded completion:^(NSDictionary* response, NSError* error){ if(error) { - DLog(@"error is %@",error.localizedDescription); - + DLog(@"original request to get the url cancelled"); } - - DLog(@"response is %@",response); + [[MASNetworkingService sharedService] setHttpRedirectionBlock:oldRedirectionBlock]; + //DLog(@"response is %@",response); }]; } From 92a60c9d8a7fdcf53b2f3c587619e9794525bd7c Mon Sep 17 00:00:00 2001 From: Mahendra Nimishakavi Date: Fri, 24 Nov 2017 14:39:07 +0530 Subject: [PATCH 41/51] handled error case when authorization code is not received --- .../Classes/models/MASBrowserBasedAuthentication.m | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/MASFoundation/Classes/models/MASBrowserBasedAuthentication.m b/MASFoundation/Classes/models/MASBrowserBasedAuthentication.m index 7a9479af..e4dcb265 100644 --- a/MASFoundation/Classes/models/MASBrowserBasedAuthentication.m +++ b/MASFoundation/Classes/models/MASBrowserBasedAuthentication.m @@ -256,7 +256,12 @@ -(void)didReceiveAuthorizationCode:(NSString *)code -(void)didReceiveError:(NSError *)error { - //self.webLoginCallBack(NO, error); + self.webLoginCallBack(nil, YES, ^(BOOL completed, NSError* error){ + if(error) + { + DLog(@"Did not receive Authorization code"); + } + }); } #pragma mark - UI From c48f6c4f1b166739c38bd635127046025b4ec303 Mon Sep 17 00:00:00 2001 From: Mahendra Nimishakavi Date: Fri, 24 Nov 2017 20:20:07 +0530 Subject: [PATCH 42/51] improvements and error handling across --- .../services/model/MASModelService.m | 2 +- .../models/MASBrowserBasedAuthentication.h | 5 ++ .../models/MASBrowserBasedAuthentication.m | 63 +++++++++++-------- 3 files changed, 42 insertions(+), 28 deletions(-) diff --git a/MASFoundation/Classes/_private_/services/model/MASModelService.m b/MASFoundation/Classes/_private_/services/model/MASModelService.m index 6026fde9..71b6213c 100644 --- a/MASFoundation/Classes/_private_/services/model/MASModelService.m +++ b/MASFoundation/Classes/_private_/services/model/MASModelService.m @@ -39,7 +39,7 @@ @implementation MASModelService static MASGrantFlow _grantFlow_ = MASGrantFlowClientCredentials; static MASUserLoginWithUserCredentialsBlock _userLoginBlock_ = nil; static MASUserAuthCredentialsBlock _userAuthCredentialsBlock_ = nil; -static BOOL _isBrowserBasedAuthentication_; +static BOOL _isBrowserBasedAuthentication_ = NO; # pragma mark - Properties diff --git a/MASFoundation/Classes/models/MASBrowserBasedAuthentication.h b/MASFoundation/Classes/models/MASBrowserBasedAuthentication.h index 0994c69b..12d7f7ae 100644 --- a/MASFoundation/Classes/models/MASBrowserBasedAuthentication.h +++ b/MASFoundation/Classes/models/MASBrowserBasedAuthentication.h @@ -16,6 +16,11 @@ } +///-------------------------------------- +/// @name Public +///-------------------------------------- + +# pragma mark - Browser Based Authentication /** * Retrieve the shared MASBrowserBasedAuthentication singleton. diff --git a/MASFoundation/Classes/models/MASBrowserBasedAuthentication.m b/MASFoundation/Classes/models/MASBrowserBasedAuthentication.m index e4dcb265..99d9f23b 100644 --- a/MASFoundation/Classes/models/MASBrowserBasedAuthentication.m +++ b/MASFoundation/Classes/models/MASBrowserBasedAuthentication.m @@ -51,13 +51,12 @@ -(void)loadWebLoginTemplate:(MASAuthCredentialsBlock)webLoginBlock MASModelService* service = [MASModelService sharedService]; [[MASAuthorizationResponse sharedInstance] setDelegate:self]; __block MASBrowserBasedAuthentication *blockSelf = self; - __weak __typeof__(self) weakSelf = 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]; - //DLog(@"url used for browser based authentication is %@",url.absoluteString); }]; } @@ -83,14 +82,6 @@ - (void)getURLForWebLogin // Scope NSString *scope = [MASApplication currentApplication].scopeAsString; - //Remove register scopes if device is already registered (required for BBA to work) - /* if([[MASDevice currentDevice] isRegistered]) - { - scope = [scope stringByReplacingOccurrencesOfString:@"msso_client_register" withString:@""]; - scope = [scope stringByReplacingOccurrencesOfString:@"msso_register" withString:@""]; - - }*/ - // // 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. @@ -161,15 +152,24 @@ - (void)getURLForWebLogin // NSString *endPoint = [MASConfiguration currentConfiguration].authorizationEndpointPath; - MASSessionDataTaskHTTPRedirectBlock oldRedirectionBlock = [[MASNetworkingService sharedService] httpRedirectionBlock]; + // + // preserve the redirection block that was set earlier + // + MASSessionDataTaskHTTPRedirectBlock previousRedirectionBlock = [[MASNetworkingService sharedService] httpRedirectionBlock]; [[MASNetworkingService sharedService] setHttpRedirectionBlock:[self getRedirectionBlock]]; + // + // 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){ if(error) { + // + // This error is expected as we cancel the Get request after the redirection + // DLog(@"original request to get the url cancelled"); } - [[MASNetworkingService sharedService] setHttpRedirectionBlock:oldRedirectionBlock]; + [[MASNetworkingService sharedService] setHttpRedirectionBlock:previousRedirectionBlock]; //DLog(@"response is %@",response); }]; } @@ -192,7 +192,7 @@ -(MASSessionDataTaskHTTPRedirectBlock)getRedirectionBlock return redirectionBlock; } --(BOOL)isBBARedirection : (NSURLRequest*)request +-(BOOL)isBBARedirection:(NSURLRequest*)request { if([request.URL.absoluteString containsString:[MASConfiguration currentConfiguration].authorizationEndpointPath] && [request.URL.absoluteString containsString:@"display=template"]) { @@ -201,25 +201,31 @@ -(BOOL)isBBARedirection : (NSURLRequest*)request return NO; } --(void)launchBrowserWithURL : (NSURL*)templatizedURL +-(void)launchBrowserWithURL:(NSURL*)templatizedURL { __block MASBrowserBasedAuthentication *blockSelf = self; __weak __typeof__(self) weakSelf = self; blockSelf.safariViewController = [[SFSafariViewController alloc] initWithURL:templatizedURL]; + + if (@available(iOS 11.0, *)) { + blockSelf.safariViewController.dismissButtonStyle = SFSafariViewControllerDismissButtonStyleCancel; + } else { + // Fallback on earlier versions + } blockSelf.safariViewController.delegate = weakSelf; + __block UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:blockSelf.safariViewController]; - dispatch_async(dispatch_get_main_queue(), ^ - { - [UIAlertController rootViewController].modalTransitionStyle = UIModalTransitionStyleCoverVertical; - - [[UIAlertController rootViewController] presentViewController:navigationController animated:YES - completion:^{ - - navigationController = nil; - }]; - - return; + dispatch_async(dispatch_get_main_queue(), ^{ + [UIAlertController rootViewController].modalTransitionStyle = UIModalTransitionStyleCoverVertical; + + [[UIAlertController rootViewController] presentViewController:navigationController animated:YES + completion:^{ + + navigationController = nil; + }]; + + return; }); } @@ -231,7 +237,7 @@ -(void)safariViewControllerDidFinish:(SFSafariViewController *)controller self.webLoginCallBack(nil, YES, ^(BOOL completed, NSError* error){ if(error) { - DLog(@"Browser dismissed"); + DLog(@"Browser cancel clicked"); } }); } @@ -244,9 +250,12 @@ -(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) { - //error + DLog(@"successfully logged in"); } DLog(@"successfully logged in"); [self dismissBrowser]; From 6a086c5c23b4bfdc32ddf15b92c037f02b8036ab Mon Sep 17 00:00:00 2001 From: Mahendra Nimishakavi Date: Mon, 27 Nov 2017 12:58:14 +0530 Subject: [PATCH 43/51] Taken care of all the indentation and spacing and complied to code guidelines of MAS --- MASFoundation/Classes/MAS.h | 3 +- MASFoundation/Classes/MAS.m | 2 +- .../services/model/MASModelService.h | 6 +- .../services/model/MASModelService.m | 4 +- .../services/network/MASNetworkingService.h | 4 +- .../network/internal/MASURLSessionManager.h | 9 ++- .../models/MASBrowserBasedAuthentication.h | 13 ++-- .../models/MASBrowserBasedAuthentication.m | 59 ++++++++++--------- 8 files changed, 56 insertions(+), 44 deletions(-) diff --git a/MASFoundation/Classes/MAS.h b/MASFoundation/Classes/MAS.h index 1e10044a..65d8de1c 100644 --- a/MASFoundation/Classes/MAS.h +++ b/MASFoundation/Classes/MAS.h @@ -110,13 +110,14 @@ + (void)setOTPCredentialsBlock:(MASOTPCredentialsBlock _Nullable)oneTimePassword; + /** * 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; ++ (void)enableBrowserBasedAuthentication:(BOOL)enable; diff --git a/MASFoundation/Classes/MAS.m b/MASFoundation/Classes/MAS.m index ef590fcd..ddda9014 100644 --- a/MASFoundation/Classes/MAS.m +++ b/MASFoundation/Classes/MAS.m @@ -92,7 +92,7 @@ + (void)setOTPCredentialsBlock:(MASOTPCredentialsBlock)oneTimePassword } -+(void)enableBrowserBasedAuthentication:(BOOL)enable ++ (void)enableBrowserBasedAuthentication:(BOOL)enable { [MASModelService setBrowserBasedAuthentication:enable]; } diff --git a/MASFoundation/Classes/_private_/services/model/MASModelService.h b/MASFoundation/Classes/_private_/services/model/MASModelService.h index f7b6b2bc..d2c356cd 100644 --- a/MASFoundation/Classes/_private_/services/model/MASModelService.h +++ b/MASFoundation/Classes/_private_/services/model/MASModelService.h @@ -82,13 +82,15 @@ - (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; ++ (void)setBrowserBasedAuthentication:(BOOL)browserBasedAuthentication; + /** @@ -96,7 +98,7 @@ * * @return BOOL value is returned. */ -+(BOOL)browserBasedAuthentication; ++ (BOOL)browserBasedAuthentication; ///-------------------------------------- diff --git a/MASFoundation/Classes/_private_/services/model/MASModelService.m b/MASFoundation/Classes/_private_/services/model/MASModelService.m index 71b6213c..205ce5e3 100644 --- a/MASFoundation/Classes/_private_/services/model/MASModelService.m +++ b/MASFoundation/Classes/_private_/services/model/MASModelService.m @@ -72,13 +72,13 @@ - (void)setUserObject:(MASUser *)user } -+(void)setBrowserBasedAuthentication : (BOOL)browserBasedAuthentication ++ (void)setBrowserBasedAuthentication : (BOOL)browserBasedAuthentication { _isBrowserBasedAuthentication_ = browserBasedAuthentication; } -+(BOOL)browserBasedAuthentication ++ (BOOL)browserBasedAuthentication { return _isBrowserBasedAuthentication_; } diff --git a/MASFoundation/Classes/_private_/services/network/MASNetworkingService.h b/MASFoundation/Classes/_private_/services/network/MASNetworkingService.h index ca85efab..69fc55c1 100644 --- a/MASFoundation/Classes/_private_/services/network/MASNetworkingService.h +++ b/MASFoundation/Classes/_private_/services/network/MASNetworkingService.h @@ -27,9 +27,11 @@ typedef NSURLRequest* (^MASSessionDataTaskHTTPRedirectBlock)(NSURLSession *_Nonn @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; -//@property (nonatomic, copy) MASSessionDataTask1CompletionBlock httpBlock; /** diff --git a/MASFoundation/Classes/_private_/services/network/internal/MASURLSessionManager.h b/MASFoundation/Classes/_private_/services/network/internal/MASURLSessionManager.h index a2c67eb5..139d8155 100644 --- a/MASFoundation/Classes/_private_/services/network/internal/MASURLSessionManager.h +++ b/MASFoundation/Classes/_private_/services/network/internal/MASURLSessionManager.h @@ -149,6 +149,13 @@ typedef void (^MASNetworkSessionDidFinishEventsForBackgroundURLSessionBlock)(NSU */ - (void)setSessionDidReceiveAuthenticationChallengeBlock:(NSURLSessionAuthChallengeDisposition (^)(NSURLSession *session, NSURLAuthenticationChallenge *challenge, NSURLCredential **credential))block; --(void)setSessionDidReceiveHTTPRedirectBlock : (NSURLRequest* (^)(NSURLSession *session,NSURLSessionTask *task, NSURLResponse* response,NSURLRequest *request))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/models/MASBrowserBasedAuthentication.h b/MASFoundation/Classes/models/MASBrowserBasedAuthentication.h index 12d7f7ae..235634cf 100644 --- a/MASFoundation/Classes/models/MASBrowserBasedAuthentication.h +++ b/MASFoundation/Classes/models/MASBrowserBasedAuthentication.h @@ -11,14 +11,11 @@ #import #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 -{ - -} - -///-------------------------------------- -/// @name Public -///-------------------------------------- # pragma mark - Browser Based Authentication @@ -36,6 +33,6 @@ * * @param webLoginBlock completion MASCompletionErrorBlock that receives the results. */ --(void)loadWebLoginTemplate:(MASAuthCredentialsBlock)webLoginBlock; +- (void)loadWebLoginTemplate:(MASAuthCredentialsBlock)webLoginBlock; @end diff --git a/MASFoundation/Classes/models/MASBrowserBasedAuthentication.m b/MASFoundation/Classes/models/MASBrowserBasedAuthentication.m index 99d9f23b..56efa02a 100644 --- a/MASFoundation/Classes/models/MASBrowserBasedAuthentication.m +++ b/MASFoundation/Classes/models/MASBrowserBasedAuthentication.m @@ -8,28 +8,27 @@ // of the MIT license. See the LICENSE file for details. // -#import "MASBrowserBasedAuthentication.h" -#import +#import "MASAccessService.h" #import "MASAuthorizationResponse.h" -#import "UIAlertController+MAS.h" +#import "MASBrowserBasedAuthentication.h" #import "MASConfigurationService.h" -#import "MASAccessService.h" #import "MASGetURLRequest.h" #import "MASModelService.h" +#import "UIAlertController+MAS.h" +#import @interface MASBrowserBasedAuthentication () { } -@property (nonatomic) SFSafariViewController* safariViewController; +@property (nonatomic) SFSafariViewController *safariViewController; @property (nonatomic) MASAuthCredentialsBlock webLoginCallBack; @end @implementation MASBrowserBasedAuthentication - # pragma mark - Shared Service + (instancetype)sharedInstance @@ -141,7 +140,7 @@ - (void)getURLForWebLogin //Put the mag-identifier in the url as query parameter for the device to be identified NSString* magIdentifier = [[MASAccessService sharedService] getAccessValueStringWithStorageKey:MASKeychainStorageKeyMAGIdentifier]; - //DLog(@"mag-identifier is %@",magIdentifier); + if(magIdentifier && magIdentifier.length > 0) { parameterInfo[MASMagIdentifierRequestResponseKey] = magIdentifier; @@ -157,36 +156,37 @@ - (void)getURLForWebLogin // MASSessionDataTaskHTTPRedirectBlock previousRedirectionBlock = [[MASNetworkingService sharedService] httpRedirectionBlock]; [[MASNetworkingService sharedService] setHttpRedirectionBlock:[self getRedirectionBlock]]; + // // 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){ - if(error) - { - // - // This error is expected as we cancel the Get request after the redirection - // - DLog(@"original request to get the url cancelled"); - } - [[MASNetworkingService sharedService] setHttpRedirectionBlock:previousRedirectionBlock]; - //DLog(@"response is %@",response); + if(error) + { + // + // This error is expected as we cancel the Get request after the redirection + // + DLog(@"original request to get the url cancelled"); + } + + [[MASNetworkingService sharedService] setHttpRedirectionBlock:previousRedirectionBlock]; }]; } -(MASSessionDataTaskHTTPRedirectBlock)getRedirectionBlock { 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]; - [self launchBrowserWithURL:redirectURL]; - } - return 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]; + [self launchBrowserWithURL:redirectURL]; + } + return request; }; return redirectionBlock; @@ -198,6 +198,7 @@ -(BOOL)isBBARedirection:(NSURLRequest*)request { return YES; } + return NO; } @@ -209,7 +210,8 @@ -(void)launchBrowserWithURL:(NSURL*)templatizedURL if (@available(iOS 11.0, *)) { blockSelf.safariViewController.dismissButtonStyle = SFSafariViewControllerDismissButtonStyleCancel; - } else { + } + else { // Fallback on earlier versions } blockSelf.safariViewController.delegate = weakSelf; @@ -222,7 +224,7 @@ -(void)launchBrowserWithURL:(NSURL*)templatizedURL [[UIAlertController rootViewController] presentViewController:navigationController animated:YES completion:^{ - navigationController = nil; + navigationController = nil; }]; return; @@ -249,6 +251,7 @@ -(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. From a1a55ab47d1830574470f073fb7374c9b0d8f3c5 Mon Sep 17 00:00:00 2001 From: James Go Date: Mon, 27 Nov 2017 13:02:08 -0800 Subject: [PATCH 44/51] US427126 : [iOS] Update SDK Version, and ChangeLog --- CHANGELOG.md | 24 ++++++++++++++++++++++-- MASFoundation.xcodeproj/project.pbxproj | 4 ++-- MASFoundation/Info.plist | 2 +- 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5508e73e..18e1cf7f 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 that Mobile SDK tried to consume same credentials for a certian period of time. It is fixed that JWT credentials can only be consumed one time, and not re-usable. [DE324462] +- Device de-registration was removing all credentials from Mobile SDK regardless of the result of de-registration request. It is fixed that Mobile SDK will only remove credentials when de-registration request succeeds. +- Mobile SDK was changing `MASGrantFlow` to client credentials in certain scenario with Cordova SDK. It is fixed that Mobile SDK will not switch the `MASGrantFlow` by itself. +- Mobile SDK enhances device registration flow, so that it can handle the device registration record more smoothly. This will remove hassle for developers seeing "This device has already been registered and has not been configured to accept updates" error message while development phase. [US406920] +- `MASConfiguration` was not properly updating the updated endpoint values when switching to a different configuration. It is now fixed. [DE321925] +- `MASConfiguration` had some hard-coded values for client credentials device registration endpoint. `MASConfiguration` will now always read the value from the configuration. [DE321921] +- `MASMQTTClient` was not able to re-establish MQTT connection when the user session is logged-out, and logs-in with different account. Mobile SDK will now properly handle session change for MQTT connection. [US408725] +- Mobile SDK now only stores all credentials to the device only. All data will not be backed-up or transferred with iCloud unless otherwise `[MAS setKeychainSynchroizable:]` is explicitly set to `YES`. [US388853] +- Mobile SDK's MQTT connection was not able to establish mutual SSL connection with public CA certificate. It is fixed now that Mobile SDK can establish 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 deperecated. Please use `[MASSecurityConfiguration setSecurityConfiguration:error:]` for better handling of error cases while setting 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 cac3bf9e..7589be77 100644 --- a/MASFoundation.xcodeproj/project.pbxproj +++ b/MASFoundation.xcodeproj/project.pbxproj @@ -2318,7 +2318,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 = ""; @@ -2363,7 +2363,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/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 From 56f4ea532fcc41bf30f259046fa029af76d72b73 Mon Sep 17 00:00:00 2001 From: bmckercher Date: Mon, 27 Nov 2017 14:19:08 -0800 Subject: [PATCH 45/51] Minor edits --- CHANGELOG.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 18e1cf7f..d396e8db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,22 +1,22 @@ # Version 1.6.00 ### Bug fixes -- `MASAuthCredentialsJWT` credentials was marked as re-usable, so that Mobile SDK tried to consume same credentials for a certian period of time. It is fixed that JWT credentials can only be consumed one time, and not re-usable. [DE324462] -- Device de-registration was removing all credentials from Mobile SDK regardless of the result of de-registration request. It is fixed that Mobile SDK will only remove credentials when de-registration request succeeds. -- Mobile SDK was changing `MASGrantFlow` to client credentials in certain scenario with Cordova SDK. It is fixed that Mobile SDK will not switch the `MASGrantFlow` by itself. -- Mobile SDK enhances device registration flow, so that it can handle the device registration record more smoothly. This will remove hassle for developers seeing "This device has already been registered and has not been configured to accept updates" error message while development phase. [US406920] -- `MASConfiguration` was not properly updating the updated endpoint values when switching to a different configuration. It is now fixed. [DE321925] -- `MASConfiguration` had some hard-coded values for client credentials device registration endpoint. `MASConfiguration` will now always read the value from the configuration. [DE321921] -- `MASMQTTClient` was not able to re-establish MQTT connection when the user session is logged-out, and logs-in with different account. Mobile SDK will now properly handle session change for MQTT connection. [US408725] -- Mobile SDK now only stores all credentials to the device only. All data will not be backed-up or transferred with iCloud unless otherwise `[MAS setKeychainSynchroizable:]` is explicitly set to `YES`. [US388853] -- Mobile SDK's MQTT connection was not able to establish mutual SSL connection with public CA certificate. It is fixed now that Mobile SDK can establish mutual SSL with public CA certificate when **entire certificate chain** is exported in JSON configuration. [US399506] +- `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. +- 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. +- 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 deperecated. Please use `[MASSecurityConfiguration setSecurityConfiguration:error:]` for better handling of error cases while setting security configuration object. [DE328373] +- `[MASConfiguration setSecurityConfiguration:]` is deperecated. Please use `[MASSecurityConfiguration setSecurityConfiguration:error:]` for better handling of error cases when setting the security configuration object. [DE328373] # Version 1.5.00 From d2e6374d9c6d627b7db2a2fcbfad016cfa8bc980 Mon Sep 17 00:00:00 2001 From: bmckercher Date: Mon, 27 Nov 2017 15:44:14 -0800 Subject: [PATCH 46/51] Updated link Link to delete Start the SDK video. --- README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) 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. From d7e950a3d16ce86da9cb499092056fc4343b098a Mon Sep 17 00:00:00 2001 From: Mahendra Nimishakavi Date: Wed, 29 Nov 2017 12:55:43 +0530 Subject: [PATCH 47/51] remove code related to iOS 11 and changed navigation for Safariviewcontroller to show done button for all versions of iOS --- .../models/MASBrowserBasedAuthentication.m | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/MASFoundation/Classes/models/MASBrowserBasedAuthentication.m b/MASFoundation/Classes/models/MASBrowserBasedAuthentication.m index 56efa02a..1b759628 100644 --- a/MASFoundation/Classes/models/MASBrowserBasedAuthentication.m +++ b/MASFoundation/Classes/models/MASBrowserBasedAuthentication.m @@ -207,24 +207,15 @@ -(void)launchBrowserWithURL:(NSURL*)templatizedURL __block MASBrowserBasedAuthentication *blockSelf = self; __weak __typeof__(self) weakSelf = self; blockSelf.safariViewController = [[SFSafariViewController alloc] initWithURL:templatizedURL]; - - if (@available(iOS 11.0, *)) { - blockSelf.safariViewController.dismissButtonStyle = SFSafariViewControllerDismissButtonStyleCancel; - } - else { - // Fallback on earlier versions - } - blockSelf.safariViewController.delegate = weakSelf; - - __block UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:blockSelf.safariViewController]; + blockSelf.safariViewController.delegate = weakSelf; dispatch_async(dispatch_get_main_queue(), ^{ [UIAlertController rootViewController].modalTransitionStyle = UIModalTransitionStyleCoverVertical; - [[UIAlertController rootViewController] presentViewController:navigationController animated:YES + [[UIAlertController rootViewController] presentViewController:blockSelf.safariViewController animated:YES completion:^{ - navigationController = nil; + DLog(@"Successfully displayed login template"); }]; return; From 75f7746e6050216e56e381532e95a6ac45151ccf Mon Sep 17 00:00:00 2001 From: Mahendra Nimishakavi Date: Fri, 1 Dec 2017 17:20:02 +0530 Subject: [PATCH 48/51] checking if the redirect url is good and taking necessary action --- .../_private_/services/MASServiceRegistry.h | 2 +- .../_private_/services/MASServiceRegistry.m | 2 +- .../models/MASBrowserBasedAuthentication.m | 38 ++++++++++++++----- 3 files changed, 31 insertions(+), 11 deletions(-) diff --git a/MASFoundation/Classes/_private_/services/MASServiceRegistry.h b/MASFoundation/Classes/_private_/services/MASServiceRegistry.h index 781e5f37..d2c18078 100644 --- a/MASFoundation/Classes/_private_/services/MASServiceRegistry.h +++ b/MASFoundation/Classes/_private_/services/MASServiceRegistry.h @@ -196,6 +196,6 @@ typedef NS_ENUM(NSInteger, MASRegistryState) * @param bbaLoginBlock The MASAuthCredentialsBlock to receive login result. * @return Return YES if handled, NO if not. */ --(BOOL)browserBasedLoginWillHandleAuthentication : (MASAuthCredentialsBlock)bbaLoginBlock; +- (BOOL)browserBasedLoginWillHandleAuthentication : (MASAuthCredentialsBlock)bbaLoginBlock; @end diff --git a/MASFoundation/Classes/_private_/services/MASServiceRegistry.m b/MASFoundation/Classes/_private_/services/MASServiceRegistry.m index d7148fc4..f0b11b73 100644 --- a/MASFoundation/Classes/_private_/services/MASServiceRegistry.m +++ b/MASFoundation/Classes/_private_/services/MASServiceRegistry.m @@ -935,7 +935,7 @@ - (BOOL)uiServiceWillHandleOTPChannelSelection:(NSArray *)supportedChannels } --(BOOL)browserBasedLoginWillHandleAuthentication : (MASAuthCredentialsBlock)bbaLoginBlock +- (BOOL)browserBasedLoginWillHandleAuthentication : (MASAuthCredentialsBlock)bbaLoginBlock { if(![MASModelService browserBasedAuthentication]) { diff --git a/MASFoundation/Classes/models/MASBrowserBasedAuthentication.m b/MASFoundation/Classes/models/MASBrowserBasedAuthentication.m index 1b759628..a605b165 100644 --- a/MASFoundation/Classes/models/MASBrowserBasedAuthentication.m +++ b/MASFoundation/Classes/models/MASBrowserBasedAuthentication.m @@ -44,7 +44,7 @@ + (instancetype)sharedInstance } --(void)loadWebLoginTemplate:(MASAuthCredentialsBlock)webLoginBlock +- (void)loadWebLoginTemplate:(MASAuthCredentialsBlock)webLoginBlock { self.webLoginCallBack = webLoginBlock; MASModelService* service = [MASModelService sharedService]; @@ -174,8 +174,9 @@ - (void)getURLForWebLogin }]; } --(MASSessionDataTaskHTTPRedirectBlock)getRedirectionBlock +- (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]) @@ -184,7 +185,14 @@ -(MASSessionDataTaskHTTPRedirectBlock)getRedirectionBlock NSString* locationURL = [httpResponse.allHeaderFields objectForKey:@"Location"]; NSURL* redirectURL = [NSURL URLWithString:locationURL]; [task cancel]; - [self launchBrowserWithURL:redirectURL]; + + if(![blockSelf redirectURLHasErrors:redirectURL]) + { + [blockSelf launchBrowserWithURL:redirectURL]; + } + else{ + blockSelf.webLoginCallBack(nil, YES, nil); + } } return request; }; @@ -192,7 +200,7 @@ -(MASSessionDataTaskHTTPRedirectBlock)getRedirectionBlock return redirectionBlock; } --(BOOL)isBBARedirection:(NSURLRequest*)request +- (BOOL)isBBARedirection:(NSURLRequest*)request { if([request.URL.absoluteString containsString:[MASConfiguration currentConfiguration].authorizationEndpointPath] && [request.URL.absoluteString containsString:@"display=template"]) { @@ -202,7 +210,19 @@ -(BOOL)isBBARedirection:(NSURLRequest*)request return NO; } --(void)launchBrowserWithURL:(NSURL*)templatizedURL + +- (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; @@ -225,7 +245,7 @@ -(void)launchBrowserWithURL:(NSURL*)templatizedURL #pragma mark - SafariViewController Delegates --(void)safariViewControllerDidFinish:(SFSafariViewController *)controller +- (void)safariViewControllerDidFinish:(SFSafariViewController *)controller { self.webLoginCallBack(nil, YES, ^(BOOL completed, NSError* error){ if(error) @@ -238,7 +258,7 @@ -(void)safariViewControllerDidFinish:(SFSafariViewController *)controller #pragma mark - Authorization Response delegate --(void)didReceiveAuthorizationCode:(NSString *)code +- (void)didReceiveAuthorizationCode:(NSString *)code { MASAuthCredentialsAuthorizationCode *authCredentials = [MASAuthCredentialsAuthorizationCode initWithAuthorizationCode:code]; [[MASNetworkingService sharedService] setHttpRedirectionBlock:nil]; @@ -257,7 +277,7 @@ -(void)didReceiveAuthorizationCode:(NSString *)code } --(void)didReceiveError:(NSError *)error +- (void)didReceiveError:(NSError *)error { self.webLoginCallBack(nil, YES, ^(BOOL completed, NSError* error){ if(error) @@ -269,7 +289,7 @@ -(void)didReceiveError:(NSError *)error #pragma mark - UI --(void)dismissBrowser +- (void)dismissBrowser { dispatch_async(dispatch_get_main_queue(), ^{ [[UIAlertController rootViewController] dismissViewControllerAnimated:YES completion:nil]; From eab6edb24f0e9748de24e93b83515008b90cdab7 Mon Sep 17 00:00:00 2001 From: Mahendra Nimishakavi Date: Wed, 6 Dec 2017 14:46:02 +0530 Subject: [PATCH 49/51] resolving defect where a server does not respond to the authorize call or there is a invalid redirect URI --- .../Classes/models/MASBrowserBasedAuthentication.m | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/MASFoundation/Classes/models/MASBrowserBasedAuthentication.m b/MASFoundation/Classes/models/MASBrowserBasedAuthentication.m index a605b165..8a9b792b 100644 --- a/MASFoundation/Classes/models/MASBrowserBasedAuthentication.m +++ b/MASFoundation/Classes/models/MASBrowserBasedAuthentication.m @@ -156,18 +156,21 @@ - (void)getURLForWebLogin // 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){ - if(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) { - // - // This error is expected as we cancel the Get request after the redirection - // - DLog(@"original request to get the url cancelled"); + DLog(@"error occured in BBA error info: %@",error); + blockSelf.webLoginCallBack(nil, YES, nil); + return; } [[MASNetworkingService sharedService] setHttpRedirectionBlock:previousRedirectionBlock]; From c26af70abf44af063e9bfe0628459b44f06987ae Mon Sep 17 00:00:00 2001 From: James Go Date: Tue, 12 Dec 2017 09:26:26 -0800 Subject: [PATCH 50/51] US427126 : Updating ChangeLog.md with reference --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d396e8db..75b2c53e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,8 +2,8 @@ ### 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. -- 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. +- 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] From e13a83a4046ef98d7977393ab9fdca1bc1c22df4 Mon Sep 17 00:00:00 2001 From: James Go Date: Tue, 12 Dec 2017 09:47:12 -0800 Subject: [PATCH 51/51] US427126 : Updating ChangeLog.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 75b2c53e..e68e92fd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,7 +16,7 @@ - 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 deperecated. Please use `[MASSecurityConfiguration setSecurityConfiguration:error:]` for better handling of error cases when setting the security configuration object. [DE328373] +- `[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