简体   繁体   English

将DynamoDB与Cognito一起使用:令牌不是来自此身份池的受支持提供商

[英]Using DynamoDB With Cognito: Token is not from a supported provider of this identity pool

I am in the process of implementing registration and login for my iOS app, using this project as an example: 我正在以这个项目为例,为我的iOS应用程序实现注册和登录:

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

Previously, my app was able to access DynamoDB resources by using a credentials provider set up in my AppDelegate's didFinishLaunchingWithOptions method. 以前,我的应用程序能够通过使用AppDelegate的didFinishLaunchingWithOptions方法中设置的凭据提供程序来访问DynamoDB资源。 However, after changing my project to include logging in and function like the example, I see the error: 但是,在更改项目以包括登录和功能(如示例)之后,我看到了错误:

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

The code setting the credentialsProvider in AppDelegate currently looks like this: 该代码设置credentialsProvider在AppDelegate中目前看起来是这样的:

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)

I also cannot access any DynamoDB data through my app. 我也无法通过我的应用程序访问任何DynamoDB数据。

Based on the console output, the registration process seems to work correctly, although I'm unsure about the sign-in process. 根据控制台的输出,尽管我不确定登录过程,但注册过程似乎可以正常工作。 It occurred to me that I had changed the region from EU-West-1, where the DynamoDB resources were stored, to US-East-1. 我突然想到将区域从存储DynamoDB资源的EU-West-1更改为US-East-1。 In order to account for this change, I repeated the same steps I had intially taken to allow my app to access DynamoDB: 为了解决此更改,我重复了我最初允许我的应用访问DynamoDB的相同步骤:

  • I created Auth and Unauth roles, both with access to the same actions as the role which had previously worked, but for the EU-West-1 resources instead. 我创建了Auth和Unauth角色,这两个角色都可以访问与以前工作的角色相同的动作,但是使用的是EU-West-1资源。
  • I set these roles to the user pool I created when setting up registration under "unauthenticated role" and "authenticated role". 我将这些角色设置为在“未经身份验证的角色”和“经过身份验证的角色”下设置注册时创建的用户池。

In case it makes a difference, I should note that I did not use the exact same sign-in process outlined in the example project I linked. 如果有所作为,请注意,我没有使用我链接的示例项目中概述的完全相同的登录过程。 Instead, I used the explicit sign in process, like so: 相反,我使用了显式登录过程,如下所示:

    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
    })

The methods lock() , unlock() , and sendErrorPopup() are strictly UI-related methods that I made so that the beginning and end of the sign-in process would be more visually clear. 方法lock()unlock()sendErrorPopup()是与我完全相关的与UI相关的方法,因此登录过程的开始和结束将在视觉上更加清晰。 The console output always reads "successful login", but I am wondering if this code actually signs the user in correctly, since the error message makes it sound like the user might not be properly authorized. 控制台输出始终显示“成功登录”,但是我想知道此代码是否真正正确地登录了用户,因为错误消息使用户听起来好像未得到正确的授权。

It occurred to me that the US-West tables might not have been set up correctly, but I experience the same problem even when trying to create new tables, so I don't think that's the issue. 我想到美国西部表可能没有正确设置,但是即使试图创建新表,我也遇到同样的问题,所以我认为这不是问题。 Are there steps I might have missed as far as giving the user access to DynamoDB? 就授予用户访问DynamoDB的权限而言,我可能还缺少一些步骤吗? Has the process changed with AWS Cognito's new beta user pool system? AWS Cognito的新beta用户池系统是否改变了流程?

EDIT 2: 编辑2:

I fixed the previous issue, and for a while, my app was working fine. 我修复了上一个问题,有一段时间,我的应用程序运行良好。 However, it has suddenly stopped loading DynamoDB data when I sign in, and shows the error message: invalid login token. Can't pass in a Cognito token. 但是,当我登录时,它突然停止加载DynamoDB数据,并显示错误消息: invalid login token. Can't pass in a Cognito token. invalid login token. Can't pass in a Cognito token. Currently, my AppData code looks like this: 目前,我的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

...and my sign-in code looks like this: ...而我的登录代码如下所示:

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
    })

I haven't changed anything between my app working and not working. 在我的应用程序正常工作与不正常工作之间,我没有进行任何更改。 I did cause a "too many password resets" error while testing the password reset functionality, but the issue persisted even when I created a new user account on my app, so I don't think that's the cause. 在测试密码重置功能时,确实导致了“密码重置次数过多”错误,但是即使在我的应用上创建了新的用户帐户后,该问题仍然存在,因此我认为这不是原因。 Am I handling login correctly? 我是否正确处理登录? If so, where should I look for other possible causes to this issue? 如果是这样,我应该在哪里寻找导致此问题的其他原因?

That exception is usually thrown if you've given Cognito a login but have not enabled your identity pool to consume that login provider. 如果您为Cognito提供了登录名但未启用身份池使用该登录名提供者,通常会抛出该异常。 If you haven't, go to the Cognito Federated Identities console and turn on whichever provider you are trying to use (looks like User Pools), and this error should go away. 如果还没有,请转到Cognito联合身份控制台,然后打开要尝试使用的任何提供程序(看起来像“用户池”),并且此错误应该消失。

If you're certain you have set that up, can you give a code snippet of how you're setting the logins? 如果您确定已进行设置,是否可以提供有关如何设置登录名的代码段?

The key that you set the ID token against in logins should be of the format cognito-idp.<region>.amazonaws.com/<YOUR_USER_POOL_ID> not your USER_POOL_NAME. 在登录名中设置ID令牌所针对的密钥,其格式应为cognito-idp.<region>.amazonaws.com/<YOUR_USER_POOL_ID>而不是您的USER_POOL_NAME。 This blog along with the link in your post for our dev guide should explain the steps and code you need. 该博客以及您的开发人员指南中的链接应说明您需要的步骤和代码。

As for the solution to deprecated logins dictionary, you need to use this constructor to create the credentials provider. 至于过时的登录字典的解决方案,您需要使用此构造函数来创建凭据提供程序。 The identityProviderManager here should be an implementation of AWSIdentityProviderManager Protocol and the logins method should return the dictionary mapping for your provider name to the token. 这里的identityProviderManager应该是AWSIdentityProviderManager协议的实现,并且logins方法应该将您的提供者名称的字典映射返回给令牌。 The credentials provider will call this method every time it needs the identity provider token. 凭证提供者每次需要身份提供者令牌时都会调用此方法。 Check this answer for more details. 检查此答案以获取更多详细信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM