从unauth切换到开发人员身份validation的authentication用户 – AWS iOS SDK
总体问题:我的前端(iOS)使用开发人员身份validation身份存在问题。 我知道我的后端产生正确的标记和身份ID,但我的刷新方法永远不会被调用。 我也看了一下这个例子,但是对于一切事情我都有些困惑。 stream说明:目前我有一个login屏幕,有一个loginbutton。 用户按下loginbutton,然后我的api类获取凭证,encryption密码并将其存储在钥匙串中(现在注释掉,因为它在模拟器上不起作用)。 我的DeveloperAuthenticatedIdentityProvider被称为我的应用程序BusytimeAuthenticated。 我已经完成了所有的方法(我正在使用AWS lambda和DynamoDB对用户进行身份validation),我以未经身份validation的访问开始,允许我仅访问两种方法,即login和注册。 然后我想假设我的身份validation的用户允许我打电话给我的其他方法。
我的API代码:
[AWSLogger defaultLogger].logLevel = AWSLogLevelVerbose; id<AWSCognitoIdentityProvider> identityProvider = [[BusytimeAuthenticated alloc] initWithRegionType:AWSRegionUSEast1 identityId:nil identityPoolId:@"SOMEIDENTITYPOOLID" logins:@{@"SOMEPROVIDERNAME": @"SOMEUSERNAME"} providerName:@"SOMEPROVIDERNAME" ]; credentialsProvider = [[AWSCognitoCredentialsProvider alloc] initWithRegionType:AWSRegionUSEast1 identityProvider:identityProvider unauthRoleArn:nil authRoleArn:nil]; configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:self.credentialsProvider]; AWSServiceManager.defaultServiceManager.defaultServiceConfiguration = configuration; [[credentialsProvider refresh] continueWithBlock:^id(BFTask *task){ [self testAuth]; return nil; }];
我的DeveloperAuthenticatedIdentityProvider代码(BusytimeAuthenticated):
#import "BusytimeAuthenticated.h" @interface BusytimeAuthenticated() @property (strong, atomic) NSString *providerName; @property (strong, atomic) NSString *token; @end @implementation BusytimeAuthenticated @synthesize providerName=_providerName; @synthesize token=_token; - (instancetype)initWithRegionType:(AWSRegionType)regionType identityId:(NSString *)identityId identityPoolId:(NSString *)identityPoolId logins:(NSDictionary *)logins providerName:(NSString *)providerName{ if (self = [super initWithRegionType:regionType identityId:identityId accountId:nil identityPoolId:identityPoolId logins:logins]) { self.providerName = providerName; } return self; } // Return the developer provider name which you choose while setting up the // identity pool in the Amazon Cognito Console - (BOOL)authenticatedWithProvider { return [self.logins objectForKey:self.providerName] != nil; } // If the app has a valid identityId return it, otherwise get a valid // identityId from your backend. - (BFTask *)getIdentityId { // already cached the identity id, return it if (self.identityId) { return [BFTask taskWithResult:nil]; } // not authenticated with our developer provider else if (![self authenticatedWithProvider]) { return [super getIdentityId]; } // authenticated with our developer provider, use refresh logic to get id/token pair else { return [[BFTask taskWithResult:nil] continueWithBlock:^id(BFTask *task) { if (!self.identityId) { return [self refresh]; } return [BFTask taskWithResult:self.identityId]; }]; } } // Use the refresh method to communicate with your backend to get an // identityId and token. - (BFTask *)refresh { if (![self authenticatedWithProvider]) { return [super getIdentityId]; }else{ // KeychainWrapper *keychain = [[KeychainWrapper alloc]init]; AWSLambdaInvoker *lambdaInvoker = [AWSLambdaInvoker defaultLambdaInvoker]; NSDictionary *parameters = @{@"username" : @"SOMEUSERNAME", @"password":@"SOMEENCRYPTEDPASS", @"isError" : @NO}; NSLog(@"Here"); [[lambdaInvoker invokeFunction:@"login" JSONObject:parameters] continueWithBlock:^id(BFTask* task) { if (task.error) { NSLog(@"Error: %@", task.error); } if (task.exception) { NSLog(@"Exception: %@", task.exception); } if (task.result) { self.identityId = [task.result objectForKey:@"IdentityId" ]; self.token = [task.result objectForKey:@"Token" ]; // [keychain mySetObject:[task.result objectForKey:@"Token" ] forKey:@"Token"]; // [keychain mySetObject:[task.result objectForKey:@"IdentityId" ] forKey:@"IdentityId"]; NSLog(@"Result: %@", task.result); } return [BFTask taskWithResult:self.identityId]; }]; } return NULL; } @end
总结问题:不幸的是,当我testing新的priveleges时,我从错误中看到:“Unauth_Role / CognitIdentityCredentials未被授权执行:lambda:InvokeFunction”。 显然我没有正确地切换。 我在我的刷新方法中放置了一个断点,看它是否被调用。 不是。 我不太了解如何正确切换。 任何帮助得到这个工作非常感谢。
注意:我做了一个很大的改变,就是我拿出了“DeveloperAuthenticationClient”类,因为我认为我没有它可以做。
最根本的问题是您正试图调用Lambda函数(需要凭据)来获取凭据。 由于您使用的是“默认”客户端configuration,因此当您的开发者身份validation客户端返回响应时,它将覆盖用于访问您的Lambda函数的凭据。 另外,一旦这个ID已经过渡到authentication,你将无法使用它来获取凭证在一个非法的stream程,并需要生成一个新的未经身份validation的身份证,只是为了再次authentication,然后回到您的身份validation的ID。
我强烈build议您在Lambda函数前面设置API网关以删除此循环依赖项。
根据问题中的新信息更新…这里有几件事:1.避免像while(!finished)
这样的代码等待asynchronous任务完成。 在最好的情况下,这种忙碌的等待方式将消耗100%的CPU /内核,而对电池寿命没有任何有用的影响,并且只会损害您的应用的性能。 相反,请使用块通知。 由于在这个例子中你已经有了一个AWSTask
,所以不要在[credentialsProvider refresh] continueWithBlock...
结尾处返回nil
,只要在那里调用你的[self testAuth]
就可以了。 2.在您的getIdentityId
实现中,第一个if条件检查是否存在identityId,如果存在则返回nil
。 我猜你的目标是在身份validation成功之后caching身份标识并返回,以便每次调用getIdentityId时都不必调用后端。 如果是这样的话,很确定你想返回identityId
而不是nil
3.我不认为这是你的问题的原因,但会简化的事情:只要你已经configuration身份池与Auth / UnAuthangular色在控制台中,在初始化AWSCognitoCredentialsProvider
时不必显式使用它们。
一旦这些问题得到解决,如果您仍然遇到问题,请更详细地debugging代码,并告诉我们如下内容:刷新方法是否被调用? 如果是这样,你的if语句的哪个部分进入,结果是什么? 它是否曾经进入else块并调用你的后端标识提供者? 它是否成功检索身份证并将其退回?
如果你进一步发现,但是遇到一个稍微不同的问题,那么请回答这个问题,并发布一个单独的问题,而不是继续编辑这个问题。 这将有助于保持清楚(这个问题/答案变得相当长,并已改变)。
最初发布的问题/代码的原始答案 AWSCognitoCredentialsProvider的getIdentity方法返回一个AWSTask (即BFTask )。 所以你需要调用诸如continueWithBlock之类的东西来实际执行这个方法。 在上面的第一个代码块看起来你没有这样做。