How do I secure an AWS API Gateway with Cognito?
Question: I've setup an Identity pool and using Python and boto3 I'm able to retrieve an
access key, secret key and session token, which I assume is for an
unauthenticated user:

    
    
    import boto3
    boto3.setup_default_session(region_name='us-east-1')
    identity = boto3.client('cognito-identity', 
                            region_name='us-east-1')
    
    response = identity.get_id(AccountId='12344566', IdentityPoolId='us-east-1:XXXXXX')
    identity_id = response['IdentityId']
    print ("Identity ID: %s"%identity_id)
    
    response = identity.get_open_id_token(IdentityId=identity_id)
    token = response['Token']
    print ("\nToken: %s"%(token))
    
    resp = identity.get_credentials_for_identity(IdentityId=identity_id)
    secretKey = resp['Credentials']['SecretKey']
    accessKey = resp['Credentials']['AccessKeyId']
    
    print ("\nSecret Key: %s"%(secretKey))
    print ("\nAccess Key %s"%(accessKey))
    

Once I have these details I'm then attempting to call the API Gateway. I use
javascript for this task as I haven't found an easy way to achieve the result
I want in python:

    
    
    var apigClient = apigClientFactory.newClient({
      accessKey: 'aaaaaaaa',
      secretKey: 'kkkkkkkk',
      sessionToken: 'ssssss',
      region: 'us-east-1'
    });
    
      apigClient.helloworldGet({},'')
      .then(function(result){
          console.log("success!: " + result);
        }).catch( function(result){
          console.log("FAIL: " + result);
        });
    

This fails with the response:

    
    
       No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access. The response had HTTP status code 403
    
    .
    

I've setup CORS correctly as the OPTIONS request succeeds. If I use my main
access key and secret to authenticate the script works. If I turn off the IAM
credentials requirement on the get/helloworld method the javascript runs
successfully. I've attached a policy to both the auth and unauth roles that
Cognito setup for the identity pool, this policy looks like this:

    
    
    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Sid": "dsfdsafasfdsfasdf",
                "Effect": "Allow",
                "Action": [
                    "execute-api:Invoke"
                ],
                "Resource": [
                    "arn:aws:execute-api:us-east-1:123456787:dsfsdfsdfs/dev/GET/helloworld"
                ]
            }
        ]
    }
    

I've tried attaching this both as a managed policy and an inline policy.

What am I missing here? Is it something to do with trying to access as an
unauthenticated user (even though the role assigned to that type of user has a
policy attached that should allow it to access the API)?

Note that there's no Lamda's involved here, just a simple task definition
sitting in an ECS Autoscale group that the API Gateway calls when the
helloworld method is invoked. As detailed here:
<https://aws.amazon.com/blogs/compute/using-amazon-api-gateway-with-
microservices-deployed-on-amazon-ecs/>


Answer: Turns out it was the way I was retrieving the token. I was using

    
    
    sessionToken = identity.get_open_id_token(IdentityId=identity_id)
    

I should have got the token from the response when I requested credentials:

    
    
    resp = identity.get_credentials_for_identity(IdentityId=identity_id)
    secretKey = resp['Credentials']['SecretKey']
    accessKey = resp['Credentials']['AccessKeyId']
    sessionToken = resp['Credentials']['SessionToken']
    

