API Authentication with Cognito

Hi I want to make my API only accessible by users these defined in Cognito. Could anyone guide me how to do it?

Currently, I add “authorizer” under my api functions. But it is not working.

functions:
myAck:
handler: …
events:
- http:
path: …
method: get
cors: true
authorizer:
arn: arn…pool ARN…

Then I tried to access that api from postman by adding username and password of user in cognito pool with BasicAuth type.

Any solution.
Many thanks.
Kind Regards,
John

1 Like

Did you go through this website? It gives the most you asked for.

serverless-stack

Hi bill and others, I tried to follow but it doesn’t show how to add authorization in yml file (I miss the point, yes it does) and on handler side. I show only how to link pool and federated identity. I tried to use ‘amazon-cognito-identity-js’, I got errors. If someone have successfully developed api with cognito, could you guide me how to do it? The project is closed to the deadline and I am stuck in this part.
Many thanks,
John

Finally, I found the solution. Thanks @bill. My solution is that I tried to use “cognito-identity” that wrote for nodejs based on aws’s javascript module. BTW the module name that I used is “amazon-cognito-identity-js-node”.

Cheers,
John

1 Like

John, how did you solve it? So my understanding is if you list your User Pool ARN under authorizer in the YML file, it’ll result in API Gateway using that specified User Pool as the authorizer.

  restricted:
    handler: src/test.restricted
    events:
    - http:
          integration: lambda-proxy
          path: restricted
          method: get
          cors: true
          authorizer:
            arn: arn:aws:cognito-idp:ap-northeast-2:118442442266:userpool/ap-northeast-2_5L5hLqjhS

But then how did you call the API with correct authentication? Did you just put one of the three tokens in Authorization header? I’m trying to access an API that’s secured by a User Pool authorizer, and have not been able to do so.

1 Like

I found the solution. You need to include the ID token in your API.get request, after logging in. It seems that AWS.API.get() does not include the ID token automatically, but you need to include it in the header yourself:

Docs are here: https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-enable-cognito-user-pool.html

Here’s a quick run-through on how to make authenticated API requests using AWS Amplify to API Gateways that use User Pools as a custom authorizer. Essentially the use case here is that you only want users who are logged into a User Pool to have access to an API endpoint.

Step 1: Enable User Pool Authorization for a Specific Serverless Function
In your serverless.yml file, you want to specify which functions you want to keep behind a user log-in “wall”:

functions:
  unrestricted:
    handler: src/test.unrestricted
    events:
    - http:
          integration: lambda-proxy
          path: unrestricted
          method: get
          cors: true
          authorizer:
            arn: arn:aws:cognito-idp:ap-northeast-2:118442442266:userpool/ap-northeast-2_5L5hLqjhS

Essentially the “authorizer” property allows you to specify a custom authorizer. In this case, we are using the default User Pool authorizer. the ARN is your User Pool’s ARN.

Once you deploy this function, you’ll find in your API Gateway Console that the relevant function now has an Authorizer, whose name should be (by default) your user pool.

  1. Make the API.get() request using idToken
    As specified in the docs, you can either use accessToken or idToken. Simpler to just use idToken.

Sign in:

let idToken;
let await Auth.signIn("username", "password")
.then(data => idToken = data.signInUserSession.idToken.jwtToken);

API.get("dev", "/restrictedByUserPool", { headers: { Authorization: idToken }}).then(console.log);

That should be the gist of it. Took me quite a while to figure out, but if you read the AWS docs carefully (and really understand what customer authorizers are) then you should be good.

Feel free to ping me anytime about this. This community has helped me a ton, so I’ll try my best to give back what (limited) amount I can.

5 Likes

This code is helpful, thanks. The problem is, if you have a lot of endpoints (/restrictedByUserPool#1, /restrictedByUserPool#2, /restrictedByUserPool#100), how do you handle them? And how to manage the access with different methods (get/put/delete)?

I also did a demo on how to show the cognito 3 tokens easily: Id token, access token and refresh token. It helps to fully understand how authorization coginto user pool works with, how the payload and token looks like:

generate Tokens with User Pools

how does the above work with user pools + federated identities? I am a bit confused about that since I don’t have the token.