简体   繁体   中英

Unauthenticated access is not supported for this identity pool with user pool

I have a Cognito User Pool to sign up/in my users from an app and then use Cognito Identity to provide authentication. I have disabled unauthenticated users. Once the user sign up, the user is created in the Pool. When he signs in, the identity is created in the Identity pool and I can see that this identity is linked to the user pool (linked login). However, when the user tried to get access to AWS resources (Dynamo, Lambda function, etc.) the call returns "Unauthenticated access is not supported for this identity pool" . I am however able to get the user details and the identity id which is the one created in the identity pool.

This is the code I use:

func cognitoUserPoolInit(window:UIWindow, debugLogFiles: DebugLogFiles) {
    self.window = window

    //Configure Cognito Identity User Pool. Edit ConstantAWS to change pool
    let serviceConfiguration = AWSServiceConfiguration(region: K.COGNITO_REGIONTYPE, credentialsProvider: nil)
    let userPoolConfiguration = AWSCognitoIdentityUserPoolConfiguration(clientId: K.COGNITO_USER_POOL_APP_CLIENT_ID, clientSecret: K.COGNITO_USER_POOL_APP_CLIENT_SECRET, poolId: K.COGNITO_USER_POOL_ID)

    AWSCognitoIdentityUserPool.registerCognitoIdentityUserPoolWithConfiguration(serviceConfiguration, userPoolConfiguration: userPoolConfiguration, forKey: "UserPool")

    self.pool = AWSCognitoIdentityUserPool(forKey: "UserPool")
    self.pool!.delegate = self
    self.cognitoIdentityUser = self.pool!.currentUser()
}

func getCognitoUserPoolUserId() {
            self.cognitoIdentityUser!.getDetails().continueWithBlock() { (task) in
                dispatch_async(dispatch_get_main_queue()) {
                    self.needtoGetCognitoUserId = false
                    if task.error != nil {  // some sort of error
                        let alert = UIAlertController(title: "", message: task.error?.userInfo["message"] as? String, preferredStyle: UIAlertControllerStyle.Alert)
                        alert.addAction(UIAlertAction(title: "Click", style: UIAlertActionStyle.Default, handler: nil))

                        NSLog("Domain: " + (task.error?.domain)! + " Code: \(task.error?.code)")

                        if task.error?.code == NSURLErrorNotConnectedToInternet {
                            self.lastError = (task.error?.code)!
                            //no internet connection. Fire a timer to get our credential as soon as network is back
                            let internetOfflineTimer:NSTimer =  NSTimer.scheduledTimerWithTimeInterval(10.0, target: self, selector: #selector(UserPool.internetOffline), userInfo: nil, repeats: false)
                            dispatch_async(dispatch_get_main_queue(), {() -> Void in
                                NSRunLoop.mainRunLoop().addTimer(internetOfflineTimer, forMode: NSDefaultRunLoopMode)
                            })
                        } else {
                            if task.error?.userInfo["message"] != nil {
                                NSLog(task.error?.userInfo["message"] as! String)

                            }
                        }
                    } else {
                        // I got no error
                        // i got the username earlier - use it
                        self.lastError = 0
                        if let response: AWSCognitoIdentityUserGetDetailsResponse = task.result as? AWSCognitoIdentityUserGetDetailsResponse {
                            var sub: String?
                            for attribute in response.userAttributes! {
                                if attribute.name == "sub" {
                                    sub = attribute.value
                                    NSLog("sub:" + sub!)
                                    break;
                                }

                            }
                            //if the user Id, then go ahead and get the dynamoDB table
                            if sub != nil {
                                self.cognitoUserPoolUserId = sub
                                self.getCognitoIdentity()
                            } else {
                                NSLog("UserId not found in response")
                            }
                        }
                    }
                }


                return nil
            }

      }


    func getCognitoIdentity() -> Bool {
    // Initialize the Amazon Cognito credentials provider

    //get pool id from plist (Federated Identieis pool not User pool)
    var myDict: NSDictionary?
    var identityPoolID: String?
    var region: String?
    //PoolId points to TestIDPool in the Federated Identitied/West region for test purpose
    if let path = NSBundle.mainBundle().pathForResource("Info", ofType: "plist") {
        myDict = NSDictionary(contentsOfFile: path)
        identityPoolID = myDict!.objectForKey("AWS")!.objectForKey("CredentialsProvider")!.objectForKey("CognitoIdentity")!.objectForKey("Default")!.objectForKey("PoolId")! as? String;
        region = myDict!.objectForKey("AWS")!.objectForKey("CredentialsProvider")!.objectForKey("CognitoIdentity")!.objectForKey("Default")!.objectForKey("Region") as? String;
    } else {
        return false
    }

    self.credentialsProvider = AWSCognitoCredentialsProvider(regionType: region!.aws_regionTypeValue(), identityPoolId: identityPoolID!, identityProviderManager:self.pool)
    AWSServiceManager.defaultServiceManager().defaultServiceConfiguration = AWSServiceConfiguration(region: .USWest2, credentialsProvider: self.credentialsProvider)

    transferManager = AWSS3TransferManager.defaultS3TransferManager()


    // Retrieve your Amazon Cognito ID
    self.credentialsProvider!.getIdentityId().continueWithBlock { (task: AWSTask!) -> AnyObject! in
        if (task.error != nil) {
            print("Error: " + task.error!.localizedDescription)
        }
        else {
            // the task result will contain the identity id
            print("cognitoId: " + self.credentialsProvider!.identityId!)
            //At this point we get the identity to query the database
            self.queryLatestItem()
        }
        return nil
    }
    return true
}


func queryLatestItem() {
        let dynamoDBObjectMapper = AWSDynamoDBObjectMapper.defaultDynamoDBObjectMapper()

        let queryExpression = AWSDynamoDBQueryExpression()
    queryExpression.scanIndexForward = false
    queryExpression.limit = 1
    queryExpression.keyConditionExpression = "userId = :UID"
    queryExpression.expressionAttributeValues = [":UID" : (self.cognitoUserPoolUserId)!]

    dynamoDBObjectMapper .query(StatisticsDB.self, expression: queryExpression) .continueWithExecutor(AWSExecutor.mainThreadExecutor(), withBlock: { (task:AWSTask!) -> AnyObject! in
        if (task.error != nil) {
            print("Error: \(task.error)") --> this is where i get the unauthenticated error.....
...

cognitoUserPoolInit() is called from the appDelegate and getCognitoUserPoolUserId() when the user get to the UI requiring DynamoDB data.

If I select "Enable access to unauthenticated identities" in the federated pool, it works fine.

Also, I have a web app and can sign in, authenticated correctly and get access to AWS services without any problem. So too me, my AWS/roles configuration should be good and probably something wrong is happening on the app side.

I do not understand how I could get the user details and correct identity id (from print("cognitoId: " + self.credentialsProvider!.identityId!) ) and get an unauthenticated error.

Restarting again the app gives slightly different error:

{
    Connection = "keep-alive";
    "Content-Length" = 129;
    "Content-Type" = "application/x-amz-json-1.1";
    Date = "Sun, 29 Jan 2017 20:04:06 GMT";
    "x-amzn-ErrorMessage" = "Access to Identity 'us-west-2:714eccXXXa5-42d8-8b29-5e2XXXXXXX' is forbidden.";
    "x-amzn-ErrorType" = "NotAuthorizedException:";
    "x-amzn-RequestId" = "16fc81c2-e65e-11e6-9643-756bf858abb7";
}

Added role permissions for auth I use:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "mobileanalytics:PutEvents",
                "cognito-sync:*",
                "cognito-identity:*",
                "dynamodb:*",
                "lambda:*",
                "s3:*"
            ],
            "Resource": [
                "*"
            ]
        }
    ]
}

and the trust relationship

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "Federated": "cognito-identity.amazonaws.com"
      },
      "Action": "sts:AssumeRoleWithWebIdentity",
      "Condition": {
        "StringEquals": {
          "cognito-identity.amazonaws.com:aud": "us-west-2:7cXXXX5f-b91e-4fc9-a72c-6f91XXXXXXX"
        },
        "ForAnyValue:StringLike": {
          "cognito-identity.amazonaws.com:amr": "authenticated"
        }
      }
    }
  ]
}

I was able to find the root cause. The following line will re-init the service configuration previously set:

let dynamoDBObjectMapper = AWSDynamoDBObjectMapper.defaultDynamoDBObjectMapper()

So I replaced this previous line with:

let objectMapperConfiguration = AWSDynamoDBObjectMapperConfiguration()        
serviceConfig = AWSServiceConfiguration(region: .USWest2, credentialsProvider: self.credentialsProvider)
AWSDynamoDBObjectMapper.registerDynamoDBObjectMapperWithConfiguration(serviceConfig!, objectMapperConfiguration: objectMapperConfiguration, forKey: "USWest2DynamoDBObjectMapper")

let dynamoDBObjectMapper = AWSDynamoDBObjectMapper(forKey: "USWest2DynamoDBObjectMapper")

See "Configure AWS Credentials in Your Files Using Amazon Cognito" http://docs.aws.amazon.com/amazondynamodb/latest/gettingstartedguide/GettingStarted.Js.Summary.html In that example, they create an unauthenticated role for that type of access. Hopefully that helps you.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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