// // Copyright 2014-2017 Amazon.com, // Inc. or its affiliates. All Rights Reserved. // // SPDX-License-Identifier: Apache-2.0 // #import "AWSCognitoIdentityProvider.h" #import "AWSCognitoIdentityUser_Internal.h" #import "AWSCognitoIdentityUserPool_Internal.h" #import <AWSCore/AWSUICKeyChainStore.h> #import <CommonCrypto/CommonHMAC.h> #import "NSData+AWSCognitoIdentityProvider.h" #import "AWSCognitoIdentityProviderModel.h" #import <AWSCognitoIdentityProviderASF/AWSCognitoIdentityProviderASF.h> static const NSString * AWSCognitoIdentityUserPoolCurrentUser = @"currentUser"; @interface AWSCognitoIdentityUserPool() @property (nonatomic, strong) AWSCognitoIdentityProvider *client; @property (nonatomic, strong) AWSServiceConfiguration *configuration; @property (nonatomic, strong) AWSCognitoIdentityUserPoolConfiguration *userPoolConfiguration; @property (nonatomic, strong) NSString * pinpointEndpointId; @property (nonatomic, assign) BOOL isCustomAuth; @end @interface AWSCognitoIdentityProvider() - (instancetype)initWithConfiguration:(AWSServiceConfiguration *)configuration; @end @implementation AWSCognitoIdentityUserPool static AWSSynchronizedMutableDictionary *_serviceClients = nil; static NSString *const AWSInfoCognitoUserPool = @"CognitoUserPool"; static NSString *const AWSCognitoUserPoolIdLegacy = @"CognitoUserPoolId"; static NSString *const AWSCognitoUserPoolAppClientIdLegacy = @"CognitoUserPoolAppClientId"; static NSString *const AWSCognitoUserPoolAppClientSecretLegacy = @"CognitoUserPoolAppClientSecret"; static NSString *const AWSCognitoUserPoolId = @"PoolId"; static NSString *const AWSCognitoUserPoolAppClientId = @"AppClientId"; static NSString *const AWSCognitoUserPoolAppClientSecret = @"AppClientSecret"; static NSString *const AWSCognitoUserPoolPinpointAppId = @"PinpointAppId"; static NSString *const AWSCognitoUserPoolMigrationEnabled = @"MigrationEnabled"; static NSString *const AWSCognitoUserPoolEndpoint = @"Endpoint"; static NSString *const AWSPinpointContextKeychainService = @"com.amazonaws.AWSPinpointContext"; static NSString *const AWSPinpointContextKeychainUniqueIdKey = @"com.amazonaws.AWSPinpointContextKeychainUniqueIdKey"; + (void)loadCategories { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ awsbigint_loadBigInt(); }); } + (instancetype)defaultCognitoIdentityUserPool { static AWSCognitoIdentityUserPool *_defaultUserPool = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ AWSServiceConfiguration *serviceConfiguration = nil; AWSServiceInfo *serviceInfo = [[AWSInfo defaultAWSInfo] defaultServiceInfo:AWSInfoCognitoUserPool]; if (serviceInfo) { AWSEndpoint *endpointOverride = [AWSCognitoIdentityUserPool resolveEndpointOverrideFromServiceInfo:serviceInfo]; if (endpointOverride) { serviceConfiguration = [[AWSServiceConfiguration alloc] initWithRegion:serviceInfo.region endpoint:endpointOverride credentialsProvider:nil localTestingEnabled:NO]; } else { serviceConfiguration = [[AWSServiceConfiguration alloc] initWithRegion:serviceInfo.region credentialsProvider:nil]; } } AWSCognitoIdentityUserPoolConfiguration *configuration = [AWSCognitoIdentityUserPool buildUserPoolConfiguration:serviceInfo]; _defaultUserPool = [[AWSCognitoIdentityUserPool alloc] initWithConfiguration:serviceConfiguration userPoolConfiguration:configuration]; }); return _defaultUserPool; } + (void)registerCognitoIdentityUserPoolWithUserPoolConfiguration:(AWSCognitoIdentityUserPoolConfiguration *)userPoolConfiguration forKey:(NSString *)key { if (![AWSServiceManager defaultServiceManager].defaultServiceConfiguration) { @throw [NSException exceptionWithName:NSInternalInconsistencyException reason:@"`defaultServiceConfiguration` is `nil`. You need to set it before using this method." userInfo:nil]; } [self registerCognitoIdentityUserPoolWithConfiguration:[AWSServiceManager defaultServiceManager].defaultServiceConfiguration userPoolConfiguration:userPoolConfiguration forKey:key]; } + (void)registerCognitoIdentityUserPoolWithConfiguration:(AWSServiceConfiguration *)configuration userPoolConfiguration:(AWSCognitoIdentityUserPoolConfiguration *)userPoolConfiguration forKey:(NSString *)key { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ _serviceClients = [AWSSynchronizedMutableDictionary new]; }); AWSCognitoIdentityUserPool *identityProvider = [[AWSCognitoIdentityUserPool alloc] initWithConfiguration:configuration userPoolConfiguration:userPoolConfiguration]; [_serviceClients setObject:identityProvider forKey:key]; } + (instancetype)CognitoIdentityUserPoolForKey:(NSString *)key { return [_serviceClients objectForKey:key]; } + (void)removeCognitoIdentityUserPoolForKey:(NSString *)key { [_serviceClients removeObjectForKey:key]; } - (instancetype)init { @throw [NSException exceptionWithName:NSInternalInconsistencyException reason:@"`- init` is not a valid initializer. Use `+ defaultCognitoIdentityProvider` or `+ CognitoIdentityProviderForKey:` instead." userInfo:nil]; return nil; } + (AWSCognitoIdentityUserPoolConfiguration *)buildUserPoolConfiguration:(AWSServiceInfo *) serviceInfo { NSString *poolId = [serviceInfo.infoDictionary objectForKey:AWSCognitoUserPoolId] ?: [serviceInfo.infoDictionary objectForKey:AWSCognitoUserPoolIdLegacy]; NSString *clientId = [serviceInfo.infoDictionary objectForKey:AWSCognitoUserPoolAppClientId] ?: [serviceInfo.infoDictionary objectForKey:AWSCognitoUserPoolAppClientIdLegacy]; NSString *clientSecret = [serviceInfo.infoDictionary objectForKey:AWSCognitoUserPoolAppClientSecret] ?: [serviceInfo.infoDictionary objectForKey:AWSCognitoUserPoolAppClientSecretLegacy]; NSString *pinpointAppId = [serviceInfo.infoDictionary objectForKey:AWSCognitoUserPoolPinpointAppId]; NSNumber *migrationEnabled = [serviceInfo.infoDictionary objectForKey:AWSCognitoUserPoolMigrationEnabled]; BOOL migrationEnabledBoolean = NO; if (migrationEnabled != nil) { migrationEnabledBoolean = [migrationEnabled boolValue]; } if (!poolId || !clientId) { @throw [NSException exceptionWithName:NSInternalInconsistencyException reason:@"The service configuration is `nil`. You need to configure `Info.plist` before using this method." userInfo:nil]; } return [[AWSCognitoIdentityUserPoolConfiguration alloc] initWithClientId:clientId clientSecret:clientSecret poolId:poolId shouldProvideCognitoValidationData:YES pinpointAppId:pinpointAppId migrationEnabled:migrationEnabledBoolean ]; } // Internal init method - (instancetype)initWithConfiguration:(AWSServiceConfiguration *)configuration userPoolConfiguration:(AWSCognitoIdentityUserPoolConfiguration *)userPoolConfiguration; { if (self = [super init]) { if (configuration) { _configuration = [configuration copy]; } else { if (![AWSServiceManager defaultServiceManager].defaultServiceConfiguration) { @throw [NSException exceptionWithName:NSInternalInconsistencyException reason:@"`defaultServiceConfiguration` is `nil`. You need to set it before using this method." userInfo:nil]; } _configuration = [[AWSServiceManager defaultServiceManager].defaultServiceConfiguration copy]; } _isCustomAuth = NO; _userPoolConfiguration = [userPoolConfiguration copy]; _client = [[AWSCognitoIdentityProvider alloc] initWithConfiguration:_configuration]; _userPoolConfiguration = userPoolConfiguration; _keychain = [AWSUICKeyChainStore keyChainStoreWithService:[NSString stringWithFormat:@"%@.%@", [NSBundle mainBundle].bundleIdentifier, [AWSCognitoIdentityUserPool class]]]; [_keychain migrateToCurrentAccessibility]; //If Pinpoint is setup, get the endpoint or create one. if(userPoolConfiguration.pinpointAppId) { AWSUICKeyChainStore *pinpointKeychain = [AWSUICKeyChainStore keyChainStoreWithService:AWSPinpointContextKeychainService]; _pinpointEndpointId = [pinpointKeychain stringForKey:AWSPinpointContextKeychainUniqueIdKey]; //if there is no endpoint in the keychain, create a new one in the location Pinpoint looks for it if(_pinpointEndpointId == nil) { _pinpointEndpointId = [[[NSUUID UUID] UUIDString] lowercaseString]; pinpointKeychain[AWSPinpointContextKeychainUniqueIdKey] = _pinpointEndpointId; } } } return self; } - (void) dealloc { _delegate = nil; } - (AWSTask<AWSCognitoIdentityUserPoolSignUpResponse *>*) signUp: (NSString*) username password: (NSString*) password userAttributes: (NSArray<AWSCognitoIdentityUserAttributeType *> *) userAttributes validationData: (NSArray<AWSCognitoIdentityUserAttributeType *> *) validationData clientMetaData:(nullable NSDictionary<NSString *,NSString *> *)clientMetaData { AWSCognitoIdentityProviderSignUpRequest* request = [AWSCognitoIdentityProviderSignUpRequest new]; request.clientId = self.userPoolConfiguration.clientId; request.username = username; request.password = password; request.userAttributes = userAttributes; request.validationData = [self getValidationDataAsArray:validationData]; request.secretHash = [self calculateSecretHash:username]; request.analyticsMetadata = [self analyticsMetadata]; AWSCognitoIdentityUser *contextUser = [[AWSCognitoIdentityUser alloc] initWithUsername:username pool:self]; request.userContextData = [self userContextData:username deviceId:[contextUser asfDeviceId]]; request.clientMetadata = clientMetaData; return [[self.client signUp:request] continueWithSuccessBlock:^id _Nullable(AWSTask<AWSCognitoIdentityProviderSignUpResponse *> * _Nonnull task) { AWSCognitoIdentityUser * user = [[AWSCognitoIdentityUser alloc] initWithUsername:username pool:self]; if([task.result.userConfirmed boolValue]) { user.confirmedStatus = AWSCognitoIdentityUserStatusConfirmed; } else { user.confirmedStatus = AWSCognitoIdentityUserStatusUnconfirmed; } AWSCognitoIdentityUserPoolSignUpResponse *signupResponse = [AWSCognitoIdentityUserPoolSignUpResponse new]; [signupResponse aws_copyPropertiesFromObject:task.result]; signupResponse.user = user; return [AWSTask taskWithResult:signupResponse]; }]; } - (AWSTask<AWSCognitoIdentityUserPoolSignUpResponse *>*) signUp: (NSString*) username password: (NSString*) password userAttributes: (NSArray<AWSCognitoIdentityUserAttributeType *> *) userAttributes validationData: (NSArray<AWSCognitoIdentityUserAttributeType *> *) validationData { return [self signUp:username password:password userAttributes:userAttributes validationData:validationData clientMetaData:nil]; } - (AWSCognitoIdentityUser*) currentUser { return [[AWSCognitoIdentityUser alloc] initWithUsername:[self currentUsername] pool: self]; } - (NSString*) currentUsername { return self.keychain[[self currentUserKey]]; } - (NSString *) currentUserKey { return [NSString stringWithFormat:@"%@.%@", self.userPoolConfiguration.clientId, AWSCognitoIdentityUserPoolCurrentUser]; } - (void) setCurrentUser:(NSString *) username { self.keychain[[self currentUserKey]] = username; } - (AWSCognitoIdentityUser*) getUser { return [[AWSCognitoIdentityUser alloc] initWithUsername:nil pool:self]; } - (AWSCognitoIdentityUser*) getUser:(NSString *) username { return [[AWSCognitoIdentityUser alloc] initWithUsername:username pool:self]; } - (AWSCognitoIdentityProviderAnalyticsMetadataType *) analyticsMetadata { if(self.pinpointEndpointId){ AWSCognitoIdentityProviderAnalyticsMetadataType *metadata = [AWSCognitoIdentityProviderAnalyticsMetadataType new]; metadata.analyticsEndpointId = self.pinpointEndpointId; return metadata; } return nil; } - (AWSCognitoIdentityProviderUserContextDataType *) userContextData: (NSString * _Nonnull) username deviceId:(NSString * _Nullable) deviceId { AWSCognitoIdentityProviderUserContextDataType *userContextData = [AWSCognitoIdentityProviderUserContextDataType new]; userContextData.encodedData = [AWSCognitoIdentityProviderASF userContextData:self.userPoolConfiguration.poolId username:username deviceId:deviceId userPoolClientId:self.userPoolConfiguration.clientId]; return userContextData; } - (void) clearLastKnownUser { NSString * currentUserKey = [self currentUserKey]; if(currentUserKey){ [self.keychain removeItemForKey:[self currentUserKey]]; } } - (void) clearAll { NSArray *keys = self.keychain.allKeys; NSString *keyChainPrefix = [NSString stringWithFormat:@"%@.", self.userPoolConfiguration.clientId]; for (NSString *key in keys) { if([key hasPrefix:keyChainPrefix]){ [self.keychain removeItemForKey:key]; } } } #pragma mark identity provider - (NSString *) identityProviderName { return [NSString stringWithFormat:@"cognito-idp.%@.amazonaws.com/%@", [AWSEndpoint regionNameFromType:self.client.configuration.endpoint.regionType], self.userPoolConfiguration.poolId]; } - (AWSTask<NSString*>*) token { return [[[self currentUser] getSession] continueWithSuccessBlock:^id _Nullable(AWSTask<AWSCognitoIdentityUserSession *> * _Nonnull task) { return [AWSTask taskWithResult:task.result.idToken.tokenString]; }]; } - (AWSTask<NSDictionary<NSString *, NSString *> *> *)logins { return [self.token continueWithSuccessBlock:^id _Nullable(AWSTask<NSString *> * _Nonnull task) { return [AWSTask taskWithResult:@{self.identityProviderName:task.result}]; }]; } #pragma mark internal - (NSString *) calculateSecretHash: (NSString*) userName; { if(self.userPoolConfiguration.clientSecret == nil) return nil; const char *cKey = [self.userPoolConfiguration.clientSecret cStringUsingEncoding:NSASCIIStringEncoding]; const char *cData = [[userName stringByAppendingString:self.userPoolConfiguration.clientId] cStringUsingEncoding:NSUTF8StringEncoding]; unsigned char cHMAC[CC_SHA256_DIGEST_LENGTH]; CCHmac(kCCHmacAlgSHA256, cKey, strlen(cKey), cData, strlen(cData), cHMAC); NSData *HMAC = [[NSData alloc] initWithBytes:cHMAC length:CC_SHA256_DIGEST_LENGTH]; return [HMAC base64EncodedStringWithOptions:kNilOptions]; } AWSCognitoIdentityUserAttributeType* attribute(NSString *name, NSString *value) { AWSCognitoIdentityUserAttributeType *attr = [AWSCognitoIdentityUserAttributeType new]; attr.name = name; attr.value = value; return attr; } - (NSDictionary<NSString *,NSString *>*)cognitoValidationData { UIDevice *device = [UIDevice currentDevice]; NSBundle *bundle = [NSBundle mainBundle]; NSString *bundleVersion = [bundle objectForInfoDictionaryKey:(NSString*)kCFBundleVersionKey]; NSString *bundleShortVersion = [bundle objectForInfoDictionaryKey:@"CFBundleShortVersionString"]; NSMutableDictionary * result = [NSMutableDictionary new]; NSArray * atts = @[ attribute(@"cognito:iOSVersion", device.systemVersion), attribute(@"cognito:systemName", device.systemName), attribute(@"cognito:deviceName", device.name), attribute(@"cognito:model", device.model), attribute(@"cognito:idForVendor", device.identifierForVendor.UUIDString), attribute(@"cognito:bundleId", bundle.bundleIdentifier), attribute(@"cognito:bundleVersion", bundleVersion), attribute(@"cognito:bundleShortV", bundleShortVersion) ]; for (AWSCognitoIdentityUserAttributeType *att in atts) { if(att.value != nil) { [result setObject:att.value forKey: att.name]; } } return result; } - (NSDictionary<NSString*, NSString *>*) getValidationData:(NSArray<AWSCognitoIdentityUserAttributeType*>*)devProvidedValidationData clientMetaData:(nullable NSDictionary<NSString *,NSString *> *)clientMetaData { NSMutableDictionary *result = [NSMutableDictionary new]; if (self.userPoolConfiguration.shouldProvideCognitoValidationData) { [result addEntriesFromDictionary:[self cognitoValidationData]]; } if (clientMetaData != nil) { [result addEntriesFromDictionary:clientMetaData]; } if (devProvidedValidationData != nil) { for (AWSCognitoIdentityUserAttributeType * att in devProvidedValidationData) { [result setObject:att.value forKey: att.name]; } } return result; } - (NSArray<AWSCognitoIdentityUserAttributeType*>*) getValidationDataAsArray:(NSArray<AWSCognitoIdentityUserAttributeType*>*)devProvidedValidationData { NSDictionary * dictionary = [self getValidationData:devProvidedValidationData clientMetaData:nil]; NSMutableArray * result = [NSMutableArray new]; [dictionary enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL* stop) { [result addObject:attribute(key,value)]; }]; return result; } - (NSString*) strippedPoolId { return [self.userPoolConfiguration.poolId substringFromIndex:[self.userPoolConfiguration.poolId rangeOfString:@"_" ].location+1]; } + (nullable AWSEndpoint *)resolveEndpointOverrideFromServiceInfo:(nonnull AWSServiceInfo *)serviceInfo { NSString *endpointOverride = [serviceInfo.infoDictionary objectForKey:AWSCognitoUserPoolEndpoint]; if (!endpointOverride) { return NULL; } NSURLComponents *components = [NSURLComponents new]; components.scheme = @"https"; // NSURLComponents will happily interpret a string like "https://foo.com" as a valid hostname if // we set it to the `host` property. By assigning to `percentEncodedHost`, NSURLComponents will // raise an exception for incorrectly escaped hosts. At that point, it's likely to fail later // when an actual request is made, but this strikes a reasonable balance between early failure // detection and overly complex and error-prone validation logic. components.percentEncodedHost = endpointOverride; NSURL *endpointURL = [components URL]; if (!endpointURL) { NSString *failureMessage = [NSString stringWithFormat:@"Invalid Endpoint value '%@'. Expected a fully-qualified hostname.", endpointOverride]; @throw [NSException exceptionWithName:NSInvalidArgumentException reason:failureMessage userInfo:nil]; } AWSEndpoint *endpoint = [[AWSEndpoint alloc] initWithRegion:serviceInfo.region service:AWSServiceCognitoIdentityProvider URL:endpointURL]; return endpoint; } @end @implementation AWSCognitoIdentityUserPoolConfiguration - (instancetype)initWithClientId:(NSString *)clientId clientSecret:(nullable NSString *)clientSecret poolId:(NSString *)poolId { return [self initWithClientId:clientId clientSecret:clientSecret poolId:poolId shouldProvideCognitoValidationData:YES]; } - (instancetype)initWithClientId:(NSString *)clientId clientSecret:(nullable NSString *)clientSecret poolId:(NSString *)poolId shouldProvideCognitoValidationData:(BOOL)shouldProvideCognitoValidationData { return [self initWithClientId:clientId clientSecret:clientSecret poolId:poolId shouldProvideCognitoValidationData:shouldProvideCognitoValidationData pinpointAppId:nil]; } - (instancetype)initWithClientId:(NSString *)clientId clientSecret:(nullable NSString *)clientSecret poolId:(NSString *)poolId shouldProvideCognitoValidationData:(BOOL)shouldProvideCognitoValidationData pinpointAppId:(nullable NSString *)pinpointAppId { return [self initWithClientId:clientId clientSecret:clientSecret poolId:poolId shouldProvideCognitoValidationData:shouldProvideCognitoValidationData pinpointAppId:pinpointAppId migrationEnabled:NO]; } - (instancetype)initWithClientId:(NSString *)clientId clientSecret:(nullable NSString *)clientSecret poolId:(NSString *)poolId shouldProvideCognitoValidationData:(BOOL)shouldProvideCognitoValidationData pinpointAppId:(nullable NSString *)pinpointAppId migrationEnabled:(BOOL)migrationEnabled { if (self = [super init]) { _clientId = clientId; _clientSecret = clientSecret; _poolId = poolId; _shouldProvideCognitoValidationData = shouldProvideCognitoValidationData; _pinpointAppId = pinpointAppId; _migrationEnabled = migrationEnabled; } return self; } - (id)copyWithZone:(NSZone *)zone { AWSCognitoIdentityUserPoolConfiguration *configuration = [[[self class] allocWithZone:zone] initWithClientId:self.clientId clientSecret:self.clientSecret poolId:self.poolId shouldProvideCognitoValidationData:self.shouldProvideCognitoValidationData pinpointAppId:self.pinpointAppId migrationEnabled:self.migrationEnabled]; return configuration; } @end @implementation AWSCognitoIdentityPasswordAuthenticationInput -(instancetype) initWithLastKnownUsername: (NSString *) lastKnownUsername { self = [super init]; if(nil != self){ _lastKnownUsername = lastKnownUsername; } return self; } @end @implementation AWSCognitoIdentityMultifactorAuthenticationInput -(instancetype) initWithDeliveryMedium: (NSString*) deliveryMedium destination:(NSString *) destination { self = [super init]; if(nil != self){ if ([deliveryMedium isEqualToString:@"SMS"]) { _deliveryMedium = AWSCognitoIdentityProviderDeliveryMediumTypeSms; }else if ([deliveryMedium isEqualToString:@"EMAIL"]) { _deliveryMedium = AWSCognitoIdentityProviderDeliveryMediumTypeEmail; }else { _deliveryMedium = AWSCognitoIdentityProviderDeliveryMediumTypeUnknown; } _destination = destination; } return self; } @end @implementation AWSCognitoIdentityPasswordAuthenticationDetails -(instancetype) initWithUsername: (NSString *) username password: (NSString *) password { self = [super init]; if(nil != self){ _username = username; _password = password; } return self; } @end @implementation AWSCognitoIdentityCustomAuthenticationInput -(instancetype) initWithChallengeParameters: (NSDictionary<NSString*,NSString*> *) challengeParameters { self = [super init]; if(nil != self){ _challengeParameters = challengeParameters; } return self; } @end @implementation AWSCognitoIdentityCustomChallengeDetails -(instancetype) initWithChallengeResponses:(NSDictionary<NSString *,NSString *> *)challengeResponses { self = [super init]; if(nil != self){ _challengeResponses = challengeResponses; } return self; } @end @implementation AWSCognitoIdentityNewPasswordRequiredInput -(instancetype) initWithUserAttributes: (NSDictionary<NSString*,NSString*> *) userAttributes requiredAttributes: (NSSet<NSString*>*) requiredAttributes { self = [super init]; if(nil != self){ _userAttributes = userAttributes; _requiredAttributes = requiredAttributes; } return self; } @end @implementation AWSCognitoIdentityNewPasswordRequiredDetails -(instancetype) initWithProposedPassword: (NSString *) proposedPassword userAttributes:(NSDictionary<NSString*,NSString*> *) userAttributes { NSMutableArray *userAttributesArray = [NSMutableArray<AWSCognitoIdentityUserAttributeType *> new]; if(userAttributes){ [userAttributes enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL* stop) { AWSCognitoIdentityUserAttributeType * att = [[AWSCognitoIdentityUserAttributeType alloc] initWithName: key value: value]; [userAttributesArray addObject:att]; }]; } return [self initWithProposedPassword:proposedPassword userAttributesArray:userAttributesArray]; } -(instancetype) initWithProposedPassword: (NSString *) proposedPassword userAttributesArray:(NSArray<AWSCognitoIdentityUserAttributeType*> *) userAttributesArray { self = [super init]; if(nil != self){ _userAttributes = userAttributesArray; _proposedPassword = proposedPassword; } return self; } @end @implementation AWSCognitoIdentityMfaCodeDetails -(instancetype) initWithMfaCode: (NSString *) mfaCode { self = [super init]; if(nil != self){ _mfaCode = mfaCode; } return self; } @end @implementation AWSCognitoIdentityUserPoolSignUpResponse @end @implementation AWSCognitoIdentitySoftwareMfaSetupRequiredInput -(instancetype) initWithSecretCode:(NSString *)secretCode username:(NSString *) username{ self = [super init]; if(nil != self){ _secretCode = secretCode; _username = username; } return self; } @end @implementation AWSCognitoIdentitySoftwareMfaSetupRequiredDetails -(instancetype) initWithUserCode:(NSString *)userCode friendlyDeviceName:(NSString *)friendlyDeviceName { self = [super init]; if(nil != self){ _userCode = userCode; _friendlyDeviceName = friendlyDeviceName; } return self; } @end @implementation AWSCognitoIdentitySelectMfaInput -(instancetype) initWithAvailableMfas:(NSDictionary<NSString *, NSString*> *)availableMfas { self = [super init]; if(nil != self){ _availableMfas = availableMfas; } return self; } @end @implementation AWSCognitoIdentitySelectMfaDetails -(instancetype) initWithSelectedMfa:(NSString *)selectedMfa { self = [super init]; if(nil != self){ _selectedMfa = selectedMfa; } return self; } @end