整体问题: 我在前端(iOS)使用开发人员身份验证身份时遇到问题。我知道我的后端会产生正确的令牌和身份ID,但我的刷新方法永远不会被调用。我也查看了样本,但我对所发生的一切感到有些困惑。 流程说明: 目前我有一个登录屏幕,其中有一个登录按钮。用户按下登录按钮,然后我的api类获取凭据,加密密码并将其存储在钥匙串中(暂时注释掉,因为它在模拟器上不起作用)。我的DeveloperAuthenticatedIdentityProvider被称为我的应用程序BusytimeAuthenticated。我已经完成了所有方法(我使用AWS lambda和DynamoDB对用户进行身份验证)我从未经身份验证的访问开始,这使我只能访问两种方法,登录和注册。然后我想假设我认证的用户允许我调用我的其他方法。
我的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
摘要问题: 不幸的是,当我测试我的新priveleges时,我从错误中看到:“Unauth_Role / CognitoIdentityCredentials无权执行:lambda:InvokeFunction”。显然我没有正确切换。我在刷新方法中放置了一个断点,看它是否被调用。不是。我不太了解我如何正确切换。任何帮助我们开展此工作都非常感激。
注意:我做过的一个重大改变是我拿出了“DeveloperAuthenticationClient”类,因为我认为没有它我就能做到。
答案 0 :(得分:1)
根本问题在于您尝试调用Lambda函数(需要凭据)来获取凭据。因为您正在使用&#34;默认&#34;客户端配置,当您的开发人员经过身份验证的客户端返回响应时,它将覆盖用于访问Lambda函数的凭据。此外,一旦该ID已转换为经过身份验证,您将无法使用它来获取unauth流中的凭据,并且需要生成一个新的未经身份验证的ID,以便再次进行身份验证,然后返回到经过身份验证的身份验证
我强烈建议您在Lambda函数前设置API Gateway以删除此循环依赖项。
答案 1 :(得分:0)
根据问题中的新信息进行更新...
这里有几件事:
1.避免像while(!finished)
这样的代码等待异步任务完成。在最好的情况下,这种忙碌的等待将消耗100%的CPU /核心,同时不做任何有用的事情并对电池寿命产生不利影响,只会损害应用程序的性能。而是使用带有块的通知。由于您在此实例中已经有AWSTask
,而不是在nil
的末尾返回[credentialsProvider refresh] continueWithBlock...
,只需在此处调用您的[self testAuth]
并取消已完成/代码。
2.在getIdentityId
实现中,第一个if条件检查是否存在identityId,如果是,则返回nil
。我在这里猜测你的目标是在成功验证后缓存identityId并返回,这样你就不必在每次调用getIdentityId时调用你的后端。如果是这种情况,请确保您要返回identityId
而不是nil
3.我不认为这是您的问题的原因,但会简化操作:只要您在控制台中使用Auth / UnAuth角色配置了您的身份池,您就不必在初始化AWSCognitoCredentialsProvider
时明确使用它们。
如果您继续遇到问题,请解决这些问题,请更详细地调试代码,并告诉我们以下内容: 刷新方法是否被调用?如果是这样,if语句的哪些部分会输入,结果是什么?是否曾进入else块并致电您的后端身份提供商?它是否成功检索到身份ID并将其返回?
如果您越走越远但开始遇到稍微不同的问题,请将此问题标记为已回答并发布单独的问题,而不是继续编辑此问题。这将有助于保持清晰(这个问题/答案变得非常长并且已经改变)。
初始发布的问题/代码的原始答案... getIdentity method of the AWSCognitoCredentialsProvider返回AWSTask(即BFTask)。因此,您需要调用continueWithBlock之类的内容才能实际执行该方法。在上面的第一段代码中,您似乎并没有这样做。