CognitoIdentityCredentials is not authorized to access this resource

Hi There,

I have been following https://serverless-stack.com/chapters/create-a-cognito-user-pool.html this tutorial to create a react app that connects to an authenticated API. All of it is working fine with the exception of authenticating via the API. I’ve setup the Cognito User pool, Identity Pool and client ID. I’m able to login via the app but I keep getting the error below:

CognitoIdentityCredentials is not authorized to access this resource

My config for the API is:

   Policies:
        - PolicyName: 'CognitoAuthorizedPolicy'
            PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: 'Allow'
                Action:
                  - 'mobileanalytics:PutEvents'
                  - 'cognito-sync:*'
                  - 'cognito-identity:*'
                    Resource: '*'
              
              # Allow users to invoke our API
              - Effect: 'Allow'
                Action:
                  - 'execute-api:Invoke'
                Resource:
                  Fn::Join:
                    - ''
                    -
                      - 'arn:aws:execute-api:'
                      - Ref: AWS::Region
                      - ':'
                      - Ref: AWS::AccountId
                      - ':'
                      - Ref: ApiGatewayRestApi
                      - '/*'

I’m not sure what else I need to add to my serverless.yml. Any help is appreciated.

Sean

I think the issue is that execute-api API Gateway permissions are more complicated than that. They have the form arn:aws:execute-api:region:account-id:api-id/stage-name/HTTP-VERB/resource-path and last time I tried something like this, a wildcard right after the api-id portion was not enough.
So you probably want something like

Fn::Join:
	- ''
	-
	  - 'arn:aws:execute-api:'
	  - Ref: AWS::Region
	  - ':'
	  - Ref: AWS::AccountId
	  - ':'
	  - Ref: ApiGatewayRestApi
	  - '/'
	  - ${self:provider.stage} (or wherever you get your serverless stage variable from)
	  - '/'
	  - '*'
	  - '/'
	  - '*'

Don’t quote me on this, but I also think that if your resource-path also has / in it, then you need to build out the permission so that it has the same number of / as your resource. So if your API has a GET and POST to /x/y/z then the policy statement would have to look like arn:aws:execute-api:region:account-id:api-id/stage-name/*/*/*/*. I vaguely remember having to have permissions like

arn:aws:execute-api:region:account-id:api-id/stage-name/*/*
arn:aws:execute-api:region:account-id:api-id/stage-name/*/*/*
arn:aws:execute-api:region:account-id:api-id/stage-name/*/*/*/*
etc

to match the levels in all my resources. I could be wrong though so YMMV

See:
https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html#arn-syntax-apigateway
https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-iam-policy-examples-for-api-execution.html

Thanks for the comprehensive answer. I will need to do some reading by the looks of it.

Sean