AWS Cognito 集成 swift3 Refresh 提供 ResourceNotFoundException
AWS Cognito integration swift3 Refresh provides ResourceNotFoundException
按照这里的回答:
https://github.com/aws/aws-sdk-ios/issues/357
在最底部有一个关于如何使用 swift 和认知功能的迷你指南。
我已经制作了一个 AWSCustomIdentityProvider:
import Foundation
import AWSCognitoIdentityProvider
import AWSCognito
class AWSCustomIdentityProvider: NSObject, AWSIdentityProviderManager
{
private var dict = NSDictionary()
func addToken(value:NSString)
{
dict = ["graph.facebook.com":value]
}
public func logins() -> AWSTask<NSDictionary>
{
return AWSTask(result: dict)
}
}
我有一个来自 facebook 的登录方法:
public func loginButtonDidCompleteLogin(_ loginButton: FacebookLogin.LoginButton, result: FacebookLogin.LoginResult){
switch result {
case .failed(let error):
print("FACEBOOK LOGIN FAILED: \(error)")
case .cancelled:
print("User cancelled login.")
case .success(_, _, let accessToken):
let customIdentity = AWSCustomIdentityProvider()
let token = accessToken.authenticationToken
customIdentity.addToken(value: token as NSString)
let credentialsProvider = AWSCognitoCredentialsProvider(regionType: REGIONTYPE, identityPoolId: "XXXXXXXXXXXXXXXXXXXXXXX", identityProviderManager:customIdentity)
credentialsProvider.clearKeychain()
credentialsProvider.clearCredentials()
let serviceConfiguration = AWSServiceConfiguration(region: REDIONTYPE, credentialsProvider: credentialsProvider)
AWSServiceManager.default().defaultServiceConfiguration = serviceConfiguration;
credentialsProvider.getIdentityId().continue( { (task: AWSTask!) -> AnyObject! in
if (task.error != nil) {
print("Error: " + (task.error?.localizedDescription)!)// gets called
}
else {
print(task.result)//identityid
}
return nil
})
}
}
但是我收到错误:
Error Domain=com.amazonaws.AWSCognitoIdentityErrorDomain Code=8 "(null)" UserInfo={__type=NotAuthorizedException, message=Logins don't match. Please include at least one valid login for this identity or identity pool.}
如果您对如何解决我的问题有任何想法,请告诉我。我也尝试过按照文档并直接设置登录 "credentialsProvider.logins = {"graph.facebook.com": mytoken}
这会在调用 lambda 方法时产生不同的异常,但确实会正确检索 identityID。但是,根据文档进行操作会警告我正在使用的方法已被弃用。
我得到的错误:
UserInfo={NSLocalizedDescription=serialized object is neither a valid json Object nor NSData object: }
然而,这只是偶尔发生。如果我重试,那么我可能会获得身份 ID,但在调用 lambda 方法时,我会得到同样的错误。我假设这是一个认知问题。
更新
如果我在第一部分中使用 AWSCognitoLoginProviderKey.facebook.rawValue 而不是 graph.facebook.com,那么它会为我提供 cognito ID,然后我调用 lambda 方法。我将包含 lambda 方法,以防万一我弄错了那部分,但我很确定是认知阻止了我调用 lambda 方法:
import AWSLambda
import Foundation
struct AWSHelper{
let lambda = AWSLambda.default()
let APPLICATION_NAME = "MYAPPLICATION"
init(){
}
func getFunctionName(funcName: String) -> String{
return "\(funcName)_\(APPLICATION_NAME)"
}
func login(facebookID: String, cognitoID:String, callback:@escaping (Bool) -> Void){
let req = AWSLambdaInvocationRequest();
req?.invocationType = AWSLambdaInvocationType.requestResponse
req?.payload = ["cognitoID" : cognitoID, "facebookID" : facebookID]
req?.functionName = getFunctionName(funcName: "MYFUNCNAME")
lambda.invoke(req!) { (response: AWSLambdaInvocationResponse?,error: Error?) in
print(error)
let payload = response?.payload
print(payload)
callback(true)
}
}
}
更新 2
我发现像这样调用刷新方法:
credentialsProvider.credentials().continue({ (task: AWSTask!) -> Any? in
print(task.result)
})
导致这样的错误:
AWSiOSSDK v2.4.10 [Error] AWSCredentialsProvider.m line:577 | __44-[AWSCognitoCredentialsProvider credentials]_block_invoke.352 | Unable to refresh. Error is [Error Domain=com.amazonaws.AWSCognitoIdentityErrorDomain Code=10 "(null)" UserInfo={__type=ResourceNotFoundException, message=Identity 'us-east-1:0db18266-1baa-4c59-9110-f9041dc92ead' not found.}]
我相信看起来像 identitypoolID 的大字符串实际上是我拥有的给定用户的 identityID,所以 cognito 已经分发了一个 ID 但无法查询它?
错误:
登录名不匹配。请为此身份或身份池至少提供一个有效登录信息
也可能是因为您尝试以另一个用户身份登录而不注销,因此将登录字典中的令牌与不同身份的 identityId 进行比较(并且不匹配)。这种情况下SDK一般会通过重试、清空、重新建立identityId来恢复,然后就可以正常工作了。
但在您的情况下,由于您正在构建自己的登录字典,问题更有可能是您构建了不匹配的令牌。您可以使用 https://jwt.io 检查令牌。 (尽管我承认它适用于 google 和 cognito 用户池,但不适用于 facebook 令牌(我不知道这是为什么)),
我认为不匹配意味着 identityId 记录的唯一用户与令牌中指定的不同。
您确定令牌构造正确吗?
正如您提到的...文档..好吧..我发现文档不值得看,所以我设置了我的项目以便我可以查看工作代码并设置断点。
这是来自 Mobile Hub Helper 的 Facebook AWSSignInProvider 的代码片段,其中显示了他们使用什么来获取令牌 (token.tokenstring)。
- (AWSTask<NSString *> *)token {
FBSDKAccessToken *token = [FBSDKAccessToken currentAccessToken];
NSString *tokenString = token.tokenString;
NSDate *idTokenExpirationDate = token.expirationDate;
if (tokenString
// If the cached token expires within 10 min, tries refreshing a token.
&& [idTokenExpirationDate compare:[NSDate dateWithTimeIntervalSinceNow:AWSFacebookSignInProviderTokenRefreshBuffer]] == NSOrderedDescending) {
return [AWSTask taskWithResult:tokenString];
}
AWSTaskCompletionSource *taskCompletionSource = [AWSTaskCompletionSource taskCompletionSource];
[FBSDKLoginManager renewSystemCredentials:^(ACAccountCredentialRenewResult result, NSError *error) {
if (result == ACAccountCredentialRenewResultRenewed) {
FBSDKAccessToken *token = [FBSDKAccessToken currentAccessToken];
NSString *tokenString = token.tokenString;
taskCompletionSource.result = tokenString;
} else {
taskCompletionSource.error = error;
}
}];
return taskCompletionSource.task;
}
另外...值得一提。 AWSIdentityManager 及其关联的 AWSSignInProviders 是一个很好的架构,可用于登录 Facebook 和 Google。即使您不使用 Mobile Hub Helper 的其余部分。为什么要重新发明轮子,他们在 aws-mobilehub-helper-ios
的身份部分做得很好
我在 github 上发布了该库的一个版本,它也为 Cognito 用户池添加了一个 AWSSignInProvider。 SignIn-awsmhh it requires some fixes in the aws-mobilehub-helper-ios to use cognito user pools they are here aws-mobilehub-helper-ios(因此,如果您克隆执行克隆 --recursive,您将设置为使用库中的断点进行调试)。
我认为很少有东西让它发挥作用。
我通过创建自己的 identityprovidermanager 做出了正确的举动,我认为阻止我执行 lambda 方法的主要原因实际上是我使用的是 AWSLambda 而不是 AWSLambdaInvoker。在我切换之后,它开始出现有意义的错误。
按照这里的回答: https://github.com/aws/aws-sdk-ios/issues/357 在最底部有一个关于如何使用 swift 和认知功能的迷你指南。
我已经制作了一个 AWSCustomIdentityProvider:
import Foundation
import AWSCognitoIdentityProvider
import AWSCognito
class AWSCustomIdentityProvider: NSObject, AWSIdentityProviderManager
{
private var dict = NSDictionary()
func addToken(value:NSString)
{
dict = ["graph.facebook.com":value]
}
public func logins() -> AWSTask<NSDictionary>
{
return AWSTask(result: dict)
}
}
我有一个来自 facebook 的登录方法:
public func loginButtonDidCompleteLogin(_ loginButton: FacebookLogin.LoginButton, result: FacebookLogin.LoginResult){
switch result {
case .failed(let error):
print("FACEBOOK LOGIN FAILED: \(error)")
case .cancelled:
print("User cancelled login.")
case .success(_, _, let accessToken):
let customIdentity = AWSCustomIdentityProvider()
let token = accessToken.authenticationToken
customIdentity.addToken(value: token as NSString)
let credentialsProvider = AWSCognitoCredentialsProvider(regionType: REGIONTYPE, identityPoolId: "XXXXXXXXXXXXXXXXXXXXXXX", identityProviderManager:customIdentity)
credentialsProvider.clearKeychain()
credentialsProvider.clearCredentials()
let serviceConfiguration = AWSServiceConfiguration(region: REDIONTYPE, credentialsProvider: credentialsProvider)
AWSServiceManager.default().defaultServiceConfiguration = serviceConfiguration;
credentialsProvider.getIdentityId().continue( { (task: AWSTask!) -> AnyObject! in
if (task.error != nil) {
print("Error: " + (task.error?.localizedDescription)!)// gets called
}
else {
print(task.result)//identityid
}
return nil
})
}
}
但是我收到错误:
Error Domain=com.amazonaws.AWSCognitoIdentityErrorDomain Code=8 "(null)" UserInfo={__type=NotAuthorizedException, message=Logins don't match. Please include at least one valid login for this identity or identity pool.}
如果您对如何解决我的问题有任何想法,请告诉我。我也尝试过按照文档并直接设置登录 "credentialsProvider.logins = {"graph.facebook.com": mytoken}
这会在调用 lambda 方法时产生不同的异常,但确实会正确检索 identityID。但是,根据文档进行操作会警告我正在使用的方法已被弃用。
我得到的错误:
UserInfo={NSLocalizedDescription=serialized object is neither a valid json Object nor NSData object: }
然而,这只是偶尔发生。如果我重试,那么我可能会获得身份 ID,但在调用 lambda 方法时,我会得到同样的错误。我假设这是一个认知问题。
更新
如果我在第一部分中使用 AWSCognitoLoginProviderKey.facebook.rawValue 而不是 graph.facebook.com,那么它会为我提供 cognito ID,然后我调用 lambda 方法。我将包含 lambda 方法,以防万一我弄错了那部分,但我很确定是认知阻止了我调用 lambda 方法:
import AWSLambda
import Foundation
struct AWSHelper{
let lambda = AWSLambda.default()
let APPLICATION_NAME = "MYAPPLICATION"
init(){
}
func getFunctionName(funcName: String) -> String{
return "\(funcName)_\(APPLICATION_NAME)"
}
func login(facebookID: String, cognitoID:String, callback:@escaping (Bool) -> Void){
let req = AWSLambdaInvocationRequest();
req?.invocationType = AWSLambdaInvocationType.requestResponse
req?.payload = ["cognitoID" : cognitoID, "facebookID" : facebookID]
req?.functionName = getFunctionName(funcName: "MYFUNCNAME")
lambda.invoke(req!) { (response: AWSLambdaInvocationResponse?,error: Error?) in
print(error)
let payload = response?.payload
print(payload)
callback(true)
}
}
}
更新 2
我发现像这样调用刷新方法:
credentialsProvider.credentials().continue({ (task: AWSTask!) -> Any? in
print(task.result)
})
导致这样的错误:
AWSiOSSDK v2.4.10 [Error] AWSCredentialsProvider.m line:577 | __44-[AWSCognitoCredentialsProvider credentials]_block_invoke.352 | Unable to refresh. Error is [Error Domain=com.amazonaws.AWSCognitoIdentityErrorDomain Code=10 "(null)" UserInfo={__type=ResourceNotFoundException, message=Identity 'us-east-1:0db18266-1baa-4c59-9110-f9041dc92ead' not found.}]
我相信看起来像 identitypoolID 的大字符串实际上是我拥有的给定用户的 identityID,所以 cognito 已经分发了一个 ID 但无法查询它?
错误:
登录名不匹配。请为此身份或身份池至少提供一个有效登录信息
也可能是因为您尝试以另一个用户身份登录而不注销,因此将登录字典中的令牌与不同身份的 identityId 进行比较(并且不匹配)。这种情况下SDK一般会通过重试、清空、重新建立identityId来恢复,然后就可以正常工作了。
但在您的情况下,由于您正在构建自己的登录字典,问题更有可能是您构建了不匹配的令牌。您可以使用 https://jwt.io 检查令牌。 (尽管我承认它适用于 google 和 cognito 用户池,但不适用于 facebook 令牌(我不知道这是为什么)),
我认为不匹配意味着 identityId 记录的唯一用户与令牌中指定的不同。
您确定令牌构造正确吗?
正如您提到的...文档..好吧..我发现文档不值得看,所以我设置了我的项目以便我可以查看工作代码并设置断点。
这是来自 Mobile Hub Helper 的 Facebook AWSSignInProvider 的代码片段,其中显示了他们使用什么来获取令牌 (token.tokenstring)。
- (AWSTask<NSString *> *)token {
FBSDKAccessToken *token = [FBSDKAccessToken currentAccessToken];
NSString *tokenString = token.tokenString;
NSDate *idTokenExpirationDate = token.expirationDate;
if (tokenString
// If the cached token expires within 10 min, tries refreshing a token.
&& [idTokenExpirationDate compare:[NSDate dateWithTimeIntervalSinceNow:AWSFacebookSignInProviderTokenRefreshBuffer]] == NSOrderedDescending) {
return [AWSTask taskWithResult:tokenString];
}
AWSTaskCompletionSource *taskCompletionSource = [AWSTaskCompletionSource taskCompletionSource];
[FBSDKLoginManager renewSystemCredentials:^(ACAccountCredentialRenewResult result, NSError *error) {
if (result == ACAccountCredentialRenewResultRenewed) {
FBSDKAccessToken *token = [FBSDKAccessToken currentAccessToken];
NSString *tokenString = token.tokenString;
taskCompletionSource.result = tokenString;
} else {
taskCompletionSource.error = error;
}
}];
return taskCompletionSource.task;
}
另外...值得一提。 AWSIdentityManager 及其关联的 AWSSignInProviders 是一个很好的架构,可用于登录 Facebook 和 Google。即使您不使用 Mobile Hub Helper 的其余部分。为什么要重新发明轮子,他们在 aws-mobilehub-helper-ios
的身份部分做得很好我在 github 上发布了该库的一个版本,它也为 Cognito 用户池添加了一个 AWSSignInProvider。 SignIn-awsmhh it requires some fixes in the aws-mobilehub-helper-ios to use cognito user pools they are here aws-mobilehub-helper-ios(因此,如果您克隆执行克隆 --recursive,您将设置为使用库中的断点进行调试)。
我认为很少有东西让它发挥作用。
我通过创建自己的 identityprovidermanager 做出了正确的举动,我认为阻止我执行 lambda 方法的主要原因实际上是我使用的是 AWSLambda 而不是 AWSLambdaInvoker。在我切换之后,它开始出现有意义的错误。