将 DynamoDB 与 Cognito 结合使用:令牌不是来自此身份池的受支持提供者
Using DynamoDB With Cognito: Token is not from a supported provider of this identity pool
我正在为我的 iOS 应用实现注册和登录,以这个项目为例:
以前,我的应用程序能够通过使用在我的 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 资源。
- 我将这些角色设置为我在 "unauthenticated role" 和 "authenticated role" 下设置注册时创建的用户池。
如果有所不同,我应该注意我没有使用我链接的示例项目中概述的完全相同的登录过程。相反,我使用了显式登录过程,如下所示:
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 相关方法,因此登录过程的开始和结束视觉上会更清晰。控制台输出总是显示 "successful login",但我想知道这段代码是否真的让用户正确登录,因为错误消息听起来好像用户可能没有得到正确授权。
我想到美国西部表可能没有正确设置,但即使在尝试创建新表时我也遇到了同样的问题,所以我认为这不是问题所在。就授予用户对 DynamoDB 的访问权限而言,我可能错过了哪些步骤? AWS Cognito 的新测试版用户池系统是否改变了流程?
编辑 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
})
我的应用程序工作和不工作之间没有任何改变。我在测试密码重置功能时确实导致了 "too many password resets" 错误,但即使我在我的应用程序上创建了一个新的用户帐户,问题仍然存在,所以我认为这不是原因。我是否正确处理登录?如果是这样,我应该在哪里寻找导致此问题的其他可能原因?
如果您已为 Cognito 提供登录名但未启用您的身份池以使用该登录提供程序,通常会抛出该异常。如果没有,请转到 Cognito Federated Identities 控制台并打开您尝试使用的任何提供程序(看起来像用户池),此错误应该会消失。
如果你确定你已经设置了它,你能提供一个代码片段来说明你是如何设置登录的吗?
您在登录时设置 ID 令牌所针对的密钥的格式应该是 cognito-idp.<region>.amazonaws.com/<YOUR_USER_POOL_ID>
而不是您的 USER_POOL_NAME。 This blog 连同您 post 中的 link 我们开发指南应该解释您需要的步骤和代码。
关于已弃用的登录字典的解决方案,您需要使用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. The credentials provider will call this method every time it needs the identity provider token. Check 了解更多详情。
我正在为我的 iOS 应用实现注册和登录,以这个项目为例:
以前,我的应用程序能够通过使用在我的 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 资源。
- 我将这些角色设置为我在 "unauthenticated role" 和 "authenticated role" 下设置注册时创建的用户池。
如果有所不同,我应该注意我没有使用我链接的示例项目中概述的完全相同的登录过程。相反,我使用了显式登录过程,如下所示:
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 相关方法,因此登录过程的开始和结束视觉上会更清晰。控制台输出总是显示 "successful login",但我想知道这段代码是否真的让用户正确登录,因为错误消息听起来好像用户可能没有得到正确授权。
我想到美国西部表可能没有正确设置,但即使在尝试创建新表时我也遇到了同样的问题,所以我认为这不是问题所在。就授予用户对 DynamoDB 的访问权限而言,我可能错过了哪些步骤? AWS Cognito 的新测试版用户池系统是否改变了流程?
编辑 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
})
我的应用程序工作和不工作之间没有任何改变。我在测试密码重置功能时确实导致了 "too many password resets" 错误,但即使我在我的应用程序上创建了一个新的用户帐户,问题仍然存在,所以我认为这不是原因。我是否正确处理登录?如果是这样,我应该在哪里寻找导致此问题的其他可能原因?
如果您已为 Cognito 提供登录名但未启用您的身份池以使用该登录提供程序,通常会抛出该异常。如果没有,请转到 Cognito Federated Identities 控制台并打开您尝试使用的任何提供程序(看起来像用户池),此错误应该会消失。
如果你确定你已经设置了它,你能提供一个代码片段来说明你是如何设置登录的吗?
您在登录时设置 ID 令牌所针对的密钥的格式应该是 cognito-idp.<region>.amazonaws.com/<YOUR_USER_POOL_ID>
而不是您的 USER_POOL_NAME。 This blog 连同您 post 中的 link 我们开发指南应该解释您需要的步骤和代码。
关于已弃用的登录字典的解决方案,您需要使用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. The credentials provider will call this method every time it needs the identity provider token. Check