【问题标题】:Can't assume authenticated role with Developer Authentication Swift Cognito无法使用开发人员身份验证 Swift Cognito 承担经过身份验证的角色
【发布时间】:2016-03-12 17:50:55
【问题描述】:

我可以从 LambdAuth(我的开发人员身份验证)成功检索令牌和身份,但是当我尝试使用服务时,Cognito 会承担未经身份验证的角色。这是我的错误:

Error Domain=com.amazonaws.AWSDynamoDBErrorDomain Code=1 "(null)" UserInfo={Message=User: arn:aws:sts::xxxxxxxxxx:assumed-role/Cognito_LambdAuthUnauth_Role/CognitoIdentityCredentials is not authorized to perform: dynamodb:ListTables on resource: *, __type=com.amazon.coral.service#AccessDeniedException}

我期待的角色是 CognitoLambdAuthAuth_Role。

这是我的身份提供者代码:

//  MyIdentityProvider.swift

import Foundation
import AWSCore
import AWSCognito
import AWSLambda

class MyIdentityProvider: AWSAbstractCognitoIdentityProvider {
    var _token: String!
    var _logins: [ NSObject : AnyObject ]!

    var email: String!
    var password: String!

    override var token: String {
        get {
            return _token
        }
    }

    override var logins: [ NSObject : AnyObject ]! {
        get {
            return _logins
        }
        set {
            _logins = newValue
        }
    }

    override func getIdentityId() -> AWSTask! {

        if self.identityId != nil {
            return AWSTask(result: self.identityId)
        }else{
            return AWSTask(result: nil).continueWithBlock({ (task) -> AnyObject! in
                if self.identityId == nil {
                    return self.refresh()
                }
                return AWSTask(result: self.identityId)
            })
        }
    }

    override func refresh() -> AWSTask! {

        let invocationRequest = AWSLambdaInvokerInvocationRequest()
        invocationRequest.functionName = "LambdAuthLogin"
        invocationRequest.invocationType = AWSLambdaInvocationType.RequestResponse
        invocationRequest.payload = ["email" : "me@example.com", "password" : "password"]

        //self.activeSearchRequest = invocationRequest

        let lambdaInvoker = AWSLambdaInvoker.defaultLambdaInvoker()
        let task = lambdaInvoker.invoke(invocationRequest).continueWithSuccessBlock() { (task) -> AWSTask! in
            if (task.error != nil) {
                // failed to retrieve token.
                print("Error invoking lambda function: ", task.error)
            } else {
                //print("response: ", task.result)
                if let payload = task.result.payload as? [String: AnyObject] {
                    if(payload["login"] as! Int == 1) {
                        // The following 3 lines are required as referenced here: http://stackoverflow.com/a/26741208/535363
                        var tmp = NSMutableDictionary()
                        tmp.setObject(self.email, forKey: "cognito-identity.amazonaws.com")
                        self.logins = tmp as [NSObject : AnyObject]

                        self.identityId = payload["identityId"] as! String
                        self._token = payload["token"] as! String

                    }
                    print("id", payload["identityId"])
                    print("token: ", payload["token"])
                    print("logins map", self.logins)
                }
            }
            return task
        }
        return task            
    }
}

这里是我调用生成错误的 DynamoDB 调用的地方:

let dynamoDB = AWSDynamoDB.defaultDynamoDB()
let listTableInput = AWSDynamoDBListTablesInput()
print("listing dynamoDB tables..")
let finalTask = dynamoDB.listTables(listTableInput).continueWithBlock{ (task: AWSTask!) -> AnyObject! in
    if (task.error != nil) {
        // failed to retrieve identityId.
        if let handler = completionHandler {
            print("Store Data Error occurred: \(task.error)")
            handler(false)
        }
        return task
    } else {
        print("Store Data Succeeded...")
        let listTablesOutput = task.result as! AWSDynamoDBListTablesOutput

        for tableName : AnyObject in listTablesOutput.tableNames {
            print("\(tableName)")
        }
        if let handler = completionHandler {
            handler(true)
        }
        return task
    }
}

以及在调用 DynamoDB 之前检索身份的代码:

    func getAuthCognitoId(email: String, password: String, identityProvider: MyIdentityProvider)->AWSTask! {
        identityProvider.email = email
        identityProvider.password = password
        // TODO: Store to a keychain

        let task = identityProvider.getIdentityId().continueWithSuccessBlock() { (task) -> AWSTask! in

            let credentialsProvider = AWSCognitoCredentialsProvider(regionType: AWSRegionType.USEast1, identityProvider: identityProvider, unauthRoleArn: Constants.ARNUnauth.value, authRoleArn: Constants.ARNAuth.value)
            let defaultServiceConfiguration = AWSServiceConfiguration(region: .USEast1, credentialsProvider: credentialsProvider)
            AWSServiceManager.defaultServiceManager().defaultServiceConfiguration = defaultServiceConfiguration
            return task
        }
        return task
    }

2015 年 12 月 8 日编辑:

我在 lambda 函数前添加了 API Gateway,但仍然无法获得授权角色。它成功地检索了令牌和身份 ID,但是:

override func refresh() -> AWSTask! {

    let task = AWSTaskCompletionSource()
    let request = AFHTTPRequestOperationManager()
    request.requestSerializer.setValue(email, forHTTPHeaderField: "email")
    request.requestSerializer.setValue(password, forHTTPHeaderField: "password")
    request.GET(Constants.loginUrl.value, parameters: nil, success: { (request: AFHTTPRequestOperation!, response: AnyObject!) -> Void in
        print("request: ", request)
        // The following 3 lines are required as referenced here: http://stackoverflow.com/a/26741208/535363
        self.logins = [self.developerProvider: self.email]

        // Get the properties from my server response
        print("response: ", response)
        let identityId = response.objectForKey("identityId")as! String
        let token = response.objectForKey("token")as! String

        // Set the identityId and token for the ExampleAppIdentityProvider
        self.identityId = identityId
        self._token = token

        task.setResult(self.identityId)
        }, failure: { (request: AFHTTPRequestOperation?, error: NSError!) -> Void in
            task.setError(error)
    })
    return task.task
}

【问题讨论】:

  • 看来我必须将 Lambda 函数放在 API 网关后面,我会确认它是否正常工作:forums.aws.amazon.com/thread.jspa?messageID=676446&#676446
  • 所以您使用 Lambda 来创建注册或登录到您的 ios 应用程序而不是 cognito 或两者都使用?
  • @Lamar cognito 与使用 lambda 构建的开发人员身份验证结合使用。

标签: ios swift amazon-web-services aws-sdk amazon-cognito


【解决方案1】:

问题是您使用未经身份验证的凭据调用 lambda

let lambdaInvoker = AWSLambdaInvoker.defaultLambdaInvoker()

由于它将这些凭据存储在钥匙串中以供后续请求使用,并且仅在它们过期时刷新它们,因此您在调用 DDB 时仍在使用 unauth 凭据。尝试使用 api-gateway 将您的 lambda 身份验证放在前面,这样您就不需要像您的评论中提到的那样从 unauth 凭据开始,如果您仍然有问题,请告诉我。

【讨论】:

  • 我在 Lambda 前面使用了 API Gateway,但仍然无法获得经过身份验证的身份。我正在尝试查看是否需要根据 docs.aws.amazon.com/cognito/devguide/identity/… 执行 credentialsProvider.refresh()
  • 还是没有运气。它不会更改为经过身份验证的角色。我已经将它设置为在另一个平台上使用 javascript 工作,因此后端代码很好,并且设置了 Cognito 角色。
  • 我试图重现这个,但一切正常。需要检查 2 件事,Constants.ARNAuth.value 设置是否正确?在调用 APIGateway 和 Dynamo 之前,您是否调用了任何其他 AWS 服务?
  • 没有明确说明,有没有办法在调试中调用 DynamoDB 之前检查 AWS 是否为我分配了身份?像 AWSServiceConfiguration 对象?
  • 您是否拥有身份不是问题,更多的是与该身份相关联的凭据。如果您有凭据,您应该能够从凭据提供程序对象中获取您的 accessKey/secretKey。您是否确认未将 Constants.ARNAuth.value 设置为您的 UnAuth 角色 arn?
猜你喜欢
  • 2016-12-22
  • 2014-12-05
  • 2016-06-29
  • 1970-01-01
  • 2015-05-10
  • 2015-04-15
  • 2018-05-17
  • 1970-01-01
  • 2015-10-12
相关资源
最近更新 更多