Skip to content

Commit

Permalink
fix: Return Swift optionals from Objective C methods that can return …
Browse files Browse the repository at this point in the history
…nil (aws-amplify#3912)

Co-authored-by: Brennan Stehling <[email protected]>
  • Loading branch information
ameter and brennanMKE authored Nov 29, 2021
1 parent af85337 commit 204a4d1
Show file tree
Hide file tree
Showing 16 changed files with 350 additions and 24 deletions.
2 changes: 1 addition & 1 deletion AWSCognitoAuth/AWSCognitoAuth.m
Original file line number Diff line number Diff line change
Expand Up @@ -1202,7 +1202,7 @@ -(instancetype) initWithToken:(NSString *)token {
}

-(NSDictionary *) claims {
NSDictionary * result = nil;
NSDictionary * result = @{};
NSArray *pieces = [self.tokenString componentsSeparatedByString:@"."];
if(pieces.count > 2){
NSString * claims = pieces[1];
Expand Down
11 changes: 10 additions & 1 deletion AWSCognitoIdentityProvider/AWSCognitoIdentityUser.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,17 @@ NS_ASSUME_NONNULL_BEGIN

/**
Get the device id
@warning This function is deprecated and will be removed in an upcoming minor
version of the SDK. You should use deviceIdentifier instead.
@deprecated Use deviceIdentifier instead.
*/
@property (nonatomic, readonly) NSString * deviceId;
@property (nonatomic, readonly) NSString * deviceId DEPRECATED_MSG_ATTRIBUTE("Use deviceIdentifier instead.");

/**
Get the device id
*/
@property (nonatomic, readonly, nullable) NSString * deviceIdentifier;

/**
Confirm a users' sign up with the confirmation code
Expand Down
9 changes: 7 additions & 2 deletions AWSCognitoIdentityProvider/AWSCognitoIdentityUser.m
Original file line number Diff line number Diff line change
Expand Up @@ -1701,7 +1701,12 @@ - (NSString*) strippedPoolName {

- (NSString*) deviceId {
AWSCognitoIdentityUserDeviceCredentials *deviceCredentials = [self getDeviceCredentials];
return deviceCredentials?deviceCredentials.deviceId:nil;
return deviceCredentials ? deviceCredentials.deviceId : nil;
}

- (NSString*) deviceIdentifier {
AWSCognitoIdentityUserDeviceCredentials *deviceCredentials = [self getDeviceCredentials];
return deviceCredentials ? deviceCredentials.deviceId : nil;
}

@end
Expand Down Expand Up @@ -1743,7 +1748,7 @@ -(instancetype) initWithToken:(NSString *)token {
}

-(NSDictionary<NSString *, id> *) tokenClaims {
NSDictionary * result = nil;
NSDictionary * result = @{};
NSArray *pieces = [self.tokenString componentsSeparatedByString:@"."];
if(pieces.count > 2){
NSString * claims = pieces[1];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,13 @@ NS_ASSUME_NONNULL_BEGIN
@interface NSData (NSDataBigInteger)
+ (NSData*) aws_dataWithBigInteger:(AWSJKBigInteger *)bigInteger;
+ (NSData*) aws_dataWithSignedBigInteger:(AWSJKBigInteger *)bigInteger;
+ (NSData*) aws_dataFromHexString:(NSString*)hexString;
/*!
@warning This function is deprecated and will be removed in an upcoming minor
version of the SDK. You should use aws_dataFromHexidecimalString instead.
@deprecated Use aws_dataFromHexidecimalString instead.
*/
+ (NSData*) aws_dataFromHexString:(NSString*)hexString DEPRECATED_MSG_ATTRIBUTE("Use aws_dataFromHexidecimalString instead.");
+ (nullable NSData*) aws_dataFromHexidecimalString:(NSString*)hexString;
- (AWSJKBigInteger *)aws_toBigInt;
void awsbigint_loadBigInt(void);
@end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,4 +160,33 @@ + (NSData*) aws_dataFromHexString:(NSString*)hexString {
return [NSData dataWithBytesNoCopy:output length:outputLen freeWhenDone:YES];
}

+ (NSData*) aws_dataFromHexidecimalString:(NSString*)hexString {
hexString = [[hexString lowercaseString] stringByReplacingOccurrencesOfString:@"0x" withString:@""];
NSData *hexStrData = [hexString dataUsingEncoding:NSASCIIStringEncoding];
NSUInteger len = [hexStrData length];
if (len % 2 != 0) {
return nil;
}

NSUInteger outputLen = len / 2;
if (outputLen == 0) {
return [NSData data];
}
uint8_t *output = malloc(sizeof(uint8_t) * outputLen);
if (output == NULL) {
// this situation is irrecoverable and we don't want to return something corrupted, so we raise an exception (avoiding NSAssert that may be disabled)
[NSException raise:@"NSInternalInconsistencyException" format:@"failed malloc" arguments:nil];
return nil;
}

const char *hexBytes = (const char*)[hexStrData bytes];
for (NSUInteger i = 0, j=0; i < len && j < outputLen; i += 2, j++) {
unsigned res;
sscanf(hexBytes+i, "%2x", &res);
output[j] = (uint8_t) (res & 0xff);
}

return [NSData dataWithBytesNoCopy:output length:outputLen freeWhenDone:YES];
}

@end
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ + (NSString *)userContextData: (NSString*) userPoolId username: (NSString * _Nul
#ifdef DEBUG
build = @"debug";
#endif
return [AWSCognitoIdentityASF userContextData: __IPHONE_OS_VERSION_MIN_REQUIRED
return [AWSCognitoIdentityASF userContextString: __IPHONE_OS_VERSION_MIN_REQUIRED
build:build userPoolId: userPoolId username:username deviceId:deviceId userPoolClientId:userPoolClientId];
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@
NS_ASSUME_NONNULL_BEGIN

@interface AWSCognitoIdentityASF : NSObject
+ (NSString *)userContextData: (int) minTarget build: (NSString *) build userPoolId: (NSString*) userPoolId username: (NSString *) username deviceId: ( NSString * _Nullable ) deviceId userPoolClientId: (NSString *) userPoolClientId;
/*!
@warning This function is deprecated and will be removed in an upcoming minor
version of the SDK. You should use userContextString instead.
@deprecated Use userContextString instead.
*/
+ (NSString *)userContextData: (int) minTarget build: (NSString *) build userPoolId: (NSString*) userPoolId username: (NSString *) username deviceId: ( NSString * _Nullable ) deviceId userPoolClientId: (NSString *) userPoolClientId DEPRECATED_MSG_ATTRIBUTE("Use userContextString instead.");

+ (nullable NSString *)userContextString: (int) minTarget build: (NSString *) build userPoolId: (NSString*) userPoolId username: (NSString *) username deviceId: ( NSString * _Nullable ) deviceId userPoolClientId: (NSString *) userPoolClientId;
@end
NS_ASSUME_NONNULL_END
107 changes: 103 additions & 4 deletions AWSCognitoIdentityProviderASF/Internal/AWSCognitoIdentityASF.m
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#import <CoreTelephony/CTCarrier.h>
#import <sys/utsname.h>
#import <CommonCrypto/CommonHMAC.h>
#import <AWSCore/AWSCocoaLumberjack.h>

@interface AWSCognitoIdentityASF()
+ (NSString *) dashIfNil: (NSString *) str;
Expand Down Expand Up @@ -74,8 +75,6 @@ + (NSString *) userContextData: (int) minTarget build: (NSString *) build userPo

NSString * minTargetString = [NSString stringWithFormat:@"%i", minTarget];



NSMutableDictionary * contextData= [NSMutableDictionary new];
[AWSCognitoIdentityASF addIfNotNil: contextData key:AWSCognitoIdentityAppName value:bundleIdentifier];
[AWSCognitoIdentityASF addIfNotNil: contextData key:AWSCognitoIdentityAppTargetSDK value: minTargetString];
Expand Down Expand Up @@ -108,7 +107,6 @@ + (NSString *) userContextData: (int) minTarget build: (NSString *) build userPo
@"timestamp" : [NSString stringWithFormat:@"%lli", [@(floor([[NSDate date] timeIntervalSince1970] * 1000)) longLongValue]]
};


NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
options:0
Expand Down Expand Up @@ -143,6 +141,107 @@ + (NSString *) userContextData: (int) minTarget build: (NSString *) build userPo
return base64Encoded;
}

+ (NSString *) userContextString: (int) minTarget build: (NSString *) build userPoolId: (NSString*) userPoolId username: (NSString *) username deviceId: (NSString * _Nullable) deviceId userPoolClientId: (NSString *) userPoolClientId {
UIDevice *device = [UIDevice currentDevice];
NSBundle *bundle = [NSBundle mainBundle];
NSString *bundleIdentifier = [bundle bundleIdentifier];
NSString *buildVersion = [bundle objectForInfoDictionaryKey:(NSString*)kCFBundleVersionKey];
NSString *bundleVersion = [bundle objectForInfoDictionaryKey:@"CFBundleShortVersionString"];
CGRect bounds = [[UIScreen mainScreen] nativeBounds];
CGFloat screenWidth = bounds.size.width;
CGFloat screenHeight = bounds.size.height;

NSDateFormatter *localTimeZoneFormatter = [NSDateFormatter new];
localTimeZoneFormatter.timeZone = [NSTimeZone localTimeZone];
localTimeZoneFormatter.dateFormat = @"Z";
NSString *localTimeZoneOffset = [localTimeZoneFormatter stringFromDate:[NSDate date]];

NSString *hourOffset = [localTimeZoneOffset substringToIndex:[localTimeZoneOffset length] - 2];
NSString *minuteOffset = [localTimeZoneOffset substringFromIndex:[localTimeZoneOffset length] - 2];
NSString *timezoneOffset = [NSString stringWithFormat:@"%@:%@",hourOffset,minuteOffset];
NSString * locale = [[NSLocale preferredLanguages] objectAtIndex:0];
CTTelephonyNetworkInfo *networkInfo = [[CTTelephonyNetworkInfo alloc] init];
NSString * networkType = [networkInfo currentRadioAccessTechnology];
CTCarrier *cellularProvider = [networkInfo subscriberCellularProvider];
NSString *countryCode = cellularProvider.isoCountryCode;
BOOL hasSimCard = countryCode != nil;
NSString *carrier = [cellularProvider carrierName];
NSString *fingerprint = [NSString stringWithFormat:@"Apple/%@/%@/-:%@/-/-:-/%@",
[AWSCognitoIdentityASF dashIfNil:[device model]],
[AWSCognitoIdentityASF dashIfNil:[AWSCognitoIdentityASF deviceName]],
[AWSCognitoIdentityASF dashIfNil:[device systemVersion]],
[AWSCognitoIdentityASF dashIfNil:build]];


NSString * minTargetString = [NSString stringWithFormat:@"%i", minTarget];

NSMutableDictionary * contextData= [NSMutableDictionary new];
[AWSCognitoIdentityASF addIfNotNil: contextData key:AWSCognitoIdentityAppName value:bundleIdentifier];
[AWSCognitoIdentityASF addIfNotNil: contextData key:AWSCognitoIdentityAppTargetSDK value: minTargetString];
[AWSCognitoIdentityASF addIfNotNil: contextData key:AWSCognitoIdentityAppVersion value:[NSString stringWithFormat:@"%@-%@",bundleVersion,buildVersion]];
[AWSCognitoIdentityASF addIfNotNil: contextData key:AWSCognitoIdentityDeviceName value:[device name]];
[AWSCognitoIdentityASF addIfNotNil: contextData key:AWSCognitoIdentityPhoneType value:[AWSCognitoIdentityASF deviceName]];
[AWSCognitoIdentityASF addIfNotNil: contextData key:AWSCognitoIdentityThirdPartyDeviceId value:[device identifierForVendor].UUIDString];
[AWSCognitoIdentityASF addIfNotNil: contextData key:AWSCognitoIdentityDeviceId value: ((deviceId == nil)? [device identifierForVendor].UUIDString : deviceId)]; //TODO
[AWSCognitoIdentityASF addIfNotNil: contextData key:AWSCognitoIdentityReleaseVersion value: [device systemVersion]];
[AWSCognitoIdentityASF addIfNotNil: contextData key:AWSCognitoIdentityPlatform value: [device systemName]];
[AWSCognitoIdentityASF addIfNotNil: contextData key:AWSCognitoIdentityBuildType value: build];
[AWSCognitoIdentityASF addIfNotNil: contextData key:AWSCognitoIdentityTimezone value: timezoneOffset];
[AWSCognitoIdentityASF addIfNotNil: contextData key:AWSCognitoIdentityDeviceHeight value: [NSString stringWithFormat:@"%.0f",screenHeight]];
[AWSCognitoIdentityASF addIfNotNil: contextData key:AWSCognitoIdentityDeviceWidth value: [NSString stringWithFormat:@"%.0f",screenWidth]];
[AWSCognitoIdentityASF addIfNotNil: contextData key:AWSCognitoIdentityDeviceLanguage value: locale];
[AWSCognitoIdentityASF addIfNotNil: contextData key:AWSCognitoIdentityCarrier value: carrier];
[AWSCognitoIdentityASF addIfNotNil: contextData key:AWSCognitoIdentityNetworkType value: networkType];
[AWSCognitoIdentityASF addIfNotNil: contextData key:AWSCognitoIdentityHasSimCard value:hasSimCard?@"true":@"false"];

[AWSCognitoIdentityASF addIfNotNil: contextData key:AWSCognitoIdentityDeviceFingerprint value:fingerprint];

if(username == nil){
username = @"unknown";
}

NSDictionary * payload = @{
@"contextData": contextData,
@"username":username,
@"userPoolId": userPoolId,
@"timestamp" : [NSString stringWithFormat:@"%lli", [@(floor([[NSDate date] timeIntervalSince1970] * 1000)) longLongValue]]
};

NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
options:0
error:&error];
if(error){
AWSDDLogError(@"Failed to parse JSON user context: %@", error);
return nil;
}

NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];

NSDictionary * result = @{
@"payload": jsonString,
@"version": AWSCognitoIdentityASFVersion,
@"signature": [AWSCognitoIdentityASF calculateSecretHash: jsonString clientId:userPoolClientId]
};

jsonData = [NSJSONSerialization dataWithJSONObject:result
options:0
error:&error];
jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];

if(error){
return nil;
}

NSData *data = [jsonString
dataUsingEncoding:NSUTF8StringEncoding];

// Get NSString from NSData object in Base64
NSString *base64Encoded = [data base64EncodedStringWithOptions:0];

return base64Encoded;
}


+ (NSString*) deviceName
{
Expand Down Expand Up @@ -178,4 +277,4 @@ + (void) addIfNotNil: (NSMutableDictionary *) dict key:(NSString *) key value:(N
}
}

@end
@end
8 changes: 7 additions & 1 deletion AWSCore/Authentication/AWSSignature.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,13 @@ FOUNDATION_EXPORT NSString * _Nonnull const AWSSignatureV4Terminator;

+ (NSData * _Nonnull)sha256HMacWithData:(NSData * _Nullable)data withKey:(NSData * _Nonnull)key;
+ (NSString * _Nonnull)hashString:(NSString * _Nullable)stringToHash;
+ (NSData * _Nonnull)hash:(NSData * _Nullable)dataToHash;
/*!
@warning This function is deprecated and will be removed in an upcoming minor
version of the SDK. You should use hashData instead.
@deprecated Use hashData instead.
*/
+ (NSData * _Nonnull)hash:(NSData * _Nullable)dataToHash DEPRECATED_MSG_ATTRIBUTE("Use hashData instead.");
+ (NSData * _Nullable)hashData:(NSData * _Nullable)dataToHash;
+ (NSString * _Nonnull)hexEncode:(NSString * _Nullable)string;
+ (NSString * _Nullable)HMACSign:(NSData * _Nullable)data withKey:(NSString * _Nonnull)key usingAlgorithm:(uint32_t)algorithm;

Expand Down
23 changes: 18 additions & 5 deletions AWSCore/Authentication/AWSSignature.m
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ + (NSData *)sha256HMacWithData:(NSData *)data withKey:(NSData *)key {
}

+ (NSString *)hashString:(NSString *)stringToHash {
return [[NSString alloc] initWithData:[self hash:[stringToHash dataUsingEncoding:NSUTF8StringEncoding]]
return [[NSString alloc] initWithData:[self hashData:[stringToHash dataUsingEncoding:NSUTF8StringEncoding]]
encoding:NSASCIIStringEncoding];
}

Expand All @@ -60,6 +60,19 @@ + (NSData *)hash:(NSData *)dataToHash {
return [[NSData alloc] initWithBytes:result length:CC_SHA256_DIGEST_LENGTH];
}

+ (NSData *)hashData:(NSData *)dataToHash {
if ([dataToHash length] > UINT32_MAX) {
return nil;
}

const void *cStr = [dataToHash bytes];
unsigned char result[CC_SHA256_DIGEST_LENGTH];

CC_SHA256(cStr, (uint32_t)[dataToHash length], result);

return [[NSData alloc] initWithBytes:result length:CC_SHA256_DIGEST_LENGTH];
}

+ (NSString *)hexEncode:(NSString *)string {
NSUInteger len = [string length];
if (len == 0) {
Expand Down Expand Up @@ -231,7 +244,7 @@ - (NSString *)signS3RequestV4:(NSMutableURLRequest *)urlRequest
[urlRequest addValue:@"aws-chunked" forHTTPHeaderField:@"Content-Encoding"]; //add aws-chunked keyword for s3 chunk upload
[urlRequest setValue:[NSString stringWithFormat:@"%lu", (unsigned long)contentLength] forHTTPHeaderField:@"x-amz-decoded-content-length"];
} else {
contentSha256 = [AWSSignatureSignerUtility hexEncode:[[NSString alloc] initWithData:[AWSSignatureSignerUtility hash:[urlRequest HTTPBody]] encoding:NSASCIIStringEncoding]];
contentSha256 = [AWSSignatureSignerUtility hexEncode:[[NSString alloc] initWithData:[AWSSignatureSignerUtility hashData:[urlRequest HTTPBody]] encoding:NSASCIIStringEncoding]];
//using Content-Length with value of '0' cause auth issue, remove it.
if (contentLength == 0) {
[urlRequest setValue:nil forHTTPHeaderField:@"Content-Length"];
Expand Down Expand Up @@ -324,7 +337,7 @@ - (NSString *)signRequestV4:(NSMutableURLRequest *)request
query = [NSString stringWithFormat:@""];
}

NSString *contentSha256 = [AWSSignatureSignerUtility hexEncode:[[NSString alloc] initWithData:[AWSSignatureSignerUtility hash:request.HTTPBody] encoding:NSASCIIStringEncoding]];
NSString *contentSha256 = [AWSSignatureSignerUtility hexEncode:[[NSString alloc] initWithData:[AWSSignatureSignerUtility hashData:request.HTTPBody] encoding:NSASCIIStringEncoding]];

NSString *canonicalRequest = [AWSSignatureV4Signer getCanonicalizedRequest:request.HTTPMethod
path:path
Expand Down Expand Up @@ -511,7 +524,7 @@ - (NSString *)signRequestV4:(NSMutableURLRequest *)request
if(signBody && [request.HTTPMethod isEqualToString:@"GET"]){
//in case of http get we sign the body as an empty string only if the sign body flag is set to true
NSData *emptyData = [@"" dataUsingEncoding:NSUTF8StringEncoding];
NSData *emptyDataHash = [AWSSignatureSignerUtility hash:emptyData];
NSData *emptyDataHash = [AWSSignatureSignerUtility hashData:emptyData];
NSString *emptyDataEncodedString = [[NSString alloc] initWithData:emptyDataHash
encoding:NSASCIIStringEncoding];
contentSha256 = [AWSSignatureSignerUtility hexEncode:emptyDataEncodedString];
Expand Down Expand Up @@ -932,7 +945,7 @@ - (BOOL)nextChunk {

// Signs data
- (NSData *)getSignedChunk:(NSData *)data {
NSString *chunkSha256 = [self dataToHexString:[AWSSignatureSignerUtility hash:data]];
NSString *chunkSha256 = [self dataToHexString:[AWSSignatureSignerUtility hashData:data]];
NSString *stringToSign = [NSString stringWithFormat:
@"%@\n%@\n%@\n%@\n%@\n%@",
@"AWS4-HMAC-SHA256-PAYLOAD",
Expand Down
1 change: 1 addition & 0 deletions AWSCore/Service/AWSClientContext.m
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ - (NSString *)JSONString {
error:&error];
if (!JSONData) {
AWSDDLogError(@"Failed to serialize JSON Data. [%@]", error);
return nil;
}

return [[NSString alloc] initWithData:JSONData
Expand Down
2 changes: 1 addition & 1 deletion AWSPinpoint/AWSPinpointService.m
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ - (AWSPinpoint *)initWithConfiguration:(AWSPinpointConfiguration *)configuration
}

if (configuration.enableAutoSessionRecording) {
[_pinpointContext.sessionClient startSession];
[_pinpointContext.sessionClient startPinpointSession];
}

AWSDDLogInfo(@"Pinpoint SDK Initialization successfully completed.");
Expand Down
Loading

0 comments on commit 204a4d1

Please sign in to comment.