将DynamoDB与Cognito一起使用:令牌不是来自此身份池

时间:2016-06-20 03:20:05

标签: ios swift amazon-dynamodb amazon-cognito

我正在使用此项目作为示例实现我的iOS应用的注册和登录过程:

https://github.com/awslabs/aws-sdk-ios-samples/tree/75ada5b6283b7c04c1214b2e1e0a6394377e3f2b/CognitoYourUserPools-Sample/Objective-C/CognitoYourUserPoolsSample

以前,我的应用程序可以使用我的AppDelegate didFinishLaunchingWithOptions方法中设置的凭据提供程序来访问DynamoDB资源。但是,在更改我的项目以包含登录和功能之后,我看到错误:

"__type":"NotAuthorizedException","message":"Token is not from a supported provider of this identity pool."

AppDelegate中设置credentialsProvider的代码目前如下所示:

let serviceConfiguration = AWSServiceConfiguration(region: .USEast1, credentialsProvider: nil)
    let userPoolConfiguration = AWSCognitoIdentityUserPoolConfiguration(clientId:APP_CLIENT_ID, clientSecret: APP_CLIENT_SECRET, poolId: USER_POOL_ID)
    AWSCognitoIdentityUserPool.registerCognitoIdentityUserPoolWithConfiguration(serviceConfiguration, userPoolConfiguration: userPoolConfiguration, forKey: USER_POOL_NAME)
    let pool = AWSCognitoIdentityUserPool(forKey:USER_POOL_NAME)
    pool.delegate = self
    self.storyboard = UIStoryboard(name: "Main", bundle: nil)
    let credentialsProvider = AWSCognitoCredentialsProvider(regionType: .USEast1, identityPoolId: IDENTITY_POOL_ID, identityProviderManager:pool)
    let configuration = AWSServiceConfiguration(region:.USEast1, credentialsProvider:credentialsProvider)

我也无法通过我的应用访问任何DynamoDB数据。

根据控制台输出,注册过程似乎正常,但我不确定登录过程。在我看来,我已将区域从存储DynamoDB资源的EU-West-1更改为US-East-1。为了解释这一变化,我重复了我最初允许我的应用访问DynamoDB的相同步骤:

  • 我创建了Auth和Unauth角色,这两个角色都可以访问与以前工作过的角色相同的操作,但是改为使用EU-West-1资源。
  • 我将这些角色设置为我在"未经身份验证的角色"下设置注册时创建的用户池。和#34;经过身份验证的角色"。

如果它有所作为,我应该注意到我没有使用我链接的示例项目中概述的完全相同的登录过程。相反,我使用了显式登录过程,如下所示:

    let name = usernameField.text!
    let user = pool!.getUser(name)
    lock()
    user.getSession(name, password: passwordField.text!, validationData: nil, scopes: nil).continueWithExecutor(AWSExecutor.mainThreadExecutor(), withBlock: {
        (task:AWSTask!) -> AnyObject! in
        if task.error != nil {
            self.sendErrorPopup("ERROR: Unable to sign in. Error description: " + task.error!.description)
        } else {
            print("Successful Login")
            dispatch_async(dispatch_get_main_queue()){
                self.performSegueWithIdentifier("mainViewControllerSegue", sender: self)
            }
        }
        self.unlock()
        return nil
    })

方法lock()unlock()sendErrorPopup()是我制作的严格与UI相关的方法,因此登录过程的开始和结束将更直观。控制台输出始终读取"成功登录",但我想知道此代码是否实际上正确地签署了用户,因为错误消息使得听起来好像用户可能没有被正确授权。

我想到美国西部的桌子可能没有正确设置,但即使在尝试创建新桌子时我也会遇到同样的问题,所以我不认为这是问题所在。在为用户提供对DynamoDB的访问权限方面,我是否可能错过了哪些步骤?是否已使用AWS Cognito的新beta用户池系统更改了流程?

编辑2:

我修复了上一期,有一段时间,我的应用程序运行正常。但是,我在登录时突然停止加载DynamoDB数据,并显示错误消息:invalid login token. Can't pass in a Cognito token.目前,我的AppData代码如下所示:

let serviceConfiguration = AWSServiceConfiguration(region: .USEast1, credentialsProvider: nil)
    let userPoolConfiguration = AWSCognitoIdentityUserPoolConfiguration(clientId:APP_CLIENT_ID, clientSecret: APP_CLIENT_SECRET, poolId: USER_POOL_ID)
    AWSCognitoIdentityUserPool.registerCognitoIdentityUserPoolWithConfiguration(serviceConfiguration, userPoolConfiguration: userPoolConfiguration, forKey: USER_POOL_NAME)
    let pool = AWSCognitoIdentityUserPool(forKey:USER_POOL_NAME)
    pool.delegate = self
    self.storyboard = UIStoryboard(name: "Main", bundle: nil)
    self.credentialsProvider = AWSCognitoCredentialsProvider(regionType: .USEast1, identityPoolId: IDENTITY_POOL_ID, identityProviderManager:pool)
    let manager = IdentityProviderManager(tokens: [NSString:NSString]())
    self.credentialsProvider = AWSCognitoCredentialsProvider(regionType: .USEast1, identityPoolId: IDENTITY_POOL_ID, identityProviderManager: manager)
    let configuration = AWSServiceConfiguration(region:.USEast1, credentialsProvider:credentialsProvider!)
    AWSServiceManager.defaultServiceManager().defaultServiceConfiguration = configuration

...我的登录代码如下所示:

if locked { return }
    trimRegistrationValues()
    let name = usernameField.text!
    let user = pool!.getUser(name)
    lock()
    user.getSession(name, password: passwordField.text!, validationData: nil, scopes: nil).continueWithExecutor(AWSExecutor.mainThreadExecutor(), withBlock: {
        (task:AWSTask!) -> AnyObject! in

        if task.error != nil {
            self.sendErrorPopup("ERROR: Unable to sign in. Error description: " + task.error!.description)
        } else {
            print("Successful Login")

            let loginKey = "cognito-idp.us-east-1.amazonaws.com/" + USER_POOL_ID
            var logins = [NSString : NSString]()
            self.credentialsProvider!.identityProvider.logins().continueWithBlock { (task: AWSTask!) -> AnyObject! in

                if (task.error != nil) {
                    print("ERROR: Unable to get logins. Description: " + task.error!.description)

                } else {
                    if task.result != nil{
                        let prevLogins = task.result as! [NSString:NSString]
                        print("Previous logins: " + String(prevLogins))
                        logins = prevLogins
                    }
                    logins[loginKey] = name
                    let manager = IdentityProviderManager(tokens: logins)
                    self.credentialsProvider!.setIdentityProviderManagerOnce(manager)
                    self.credentialsProvider!.getIdentityId().continueWithBlock { (task: AWSTask!) -> AnyObject! in

                        if (task.error != nil) {
                            print("ERROR: Unable to get ID. Error description: " + task.error!.description)

                        } else {
                            print("Signed in user with the following ID:")
                            print(task.result)
                            dispatch_async(dispatch_get_main_queue()){
                                self.performSegueWithIdentifier("mainViewControllerSegue", sender: self)
                            }
                        }
                        return nil
                    }
                }
                return nil
            }
        }
        self.unlock()
        return nil
    })

我的app在工作和不工作之间没有任何改变。我确实造成了太多密码重置"测试密码重置功能时出错,但即使我在我的应用上创建了一个新用户帐户,问题仍然存在,所以我不认为这是原因。我正确处理登录吗?如果是这样,我应该在哪里寻找此问题的其他可能原因?

2 个答案:

答案 0 :(得分:1)

如果您已授予Cognito登录但未启用身份池以使用该登录提供程序,则通常会抛出该异常。如果还没有,请转到Cognito Federated Identities控制台并打开您尝试使用的任何提供程序(看起来像用户池),此错误应该消失。

如果您确定已将其设置完毕,是否可以提供有关如何设置登录信息的代码段?

答案 1 :(得分:1)

您在登录时设置ID令牌的密钥的格式应为cognito-idp.<region>.amazonaws.com/<YOUR_USER_POOL_ID>,而不是您的USER_POOL_NAME。 This blog以及我们的开发指南帖子中的链接应该解释您需要的步骤和代码。

对于已弃用的登录字典的解决方案,您需要使用this constructor来创建凭据提供程序。这里的 identityProviderManager 应该是AWSIdentityProviderManager Protocol的实现,而 logins 方法应该将您的提供者名称的字典映射返回给令牌。凭证提供程序将在每次需要身份提供者令牌时调用此方法。查看this answer了解详情。