AWS API Gateway with cognito authorization - aws-api-gateway

Currently I'm developing serverless architecture where there are set of resources and methods in AWS API gateway. I plan to add Cognito authentication(user pool) and authorization as secure layer to AWS API gateway.
There are 3 authorizer in AWS API Gateway which are IAM, Cognito User Pool and custom lambda.
For my use case, the sign-in and sign-up(authentication) are using cognito user pool via API gateway. It's perfect works. My user will given app client id and client secret to enable both processes. Once after sign-in, my intention is get user able to use the access token(returned by user pool) to access resource via api gateway.
However, my user can has different role such admin, owner or guest. User only can access the authorized api. My approach is to put user into different group in user pool, assign IAM policy to group and enable identity pool. This force me to change the authorization type in api gateway to IAM. and IAM require every request to be signed by Signature V4.
It means every requests have to sign up by session token, access key, secret (returned after exchange id token with federated pool) instead of using access token based approach. So in my use case, after my user sign-in via api gateway, my client app(web/mobile/postman tool) has to generate signature and put in Authorization header. Is there alternative ways to control authorisation in user pool group but using access token in api gateway? My understanding is access token (in Authorization header) is much easier to use than complex signed signature process.
Correct me if I'm wrong. Thanks.

Will this help instead?
Create groups in user pool and assign IAM role to the group.
And then add users to the group.
More documentation here: https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-user-groups.html

You are on the right track but you have chosen one of the paths of Authorizing the user requests on AWS. You are using IAM and Identity Pool and because of that, you are forced to sign every request using Signature V4 provided by AWS.
Instead of going for I would suggest as per my experience to choose custom Lambda Authorizer over Identity Pool. In this case, your authentication will remain as it is that you have already built. But instead of applying IAM as Authorizer in API gateway, you can create a lambda function that will receive the ARN of the API gateway that the user wanted to authorize in the request and user ID_TOKEN that you received in during authentication from User Pool.
{
...
"cognito:roles": [
"arn:aws:iam::**********:role/addBookSellerRole"
],
"exp": 1565758916,
"iat": 1565755316,
...
}
You can see you will get the roles array from the ID_TOKEN in JWT received from authentication. You can use this role to fetch the attached policies to this role. Follow this document to fetch the policies from the role.
Once you get the policy JSON you can compare it with the ARN of the method received in request with the list of policies. And this way you have to generate a Policy Document that will either Allow or Deny the request.
To read more about it visit my medium blog Authorization using Cognito + API Gateway + IAM.

Related

How to allow guest access in Cognito

We are looking to move to Cognito for user authentication. Currently we rely on our system to create the user and authenticate using JWT tokens generated internally. We also have a guest user role where anonymous users are given access to limited apis. To achieve this, we first create the guest user as a normal user in our system and mark it a guest in db. This way we can generate JWT tokens for guest users that can be used to authorize limited set of apis.
With Cognito, creating authenticated users is straightforward as userpool token (ID token) generated can be used in Api Gateway with Cognito authorizer. However, we are looking to implement guest user access as well via Cognito. Userpools does not have that support. The only option seems available is Cognito Identity pool for unauthenticated access. But this requires IAM credentials to be generated and passed to Api Gateway which is different than ID Token flow for authenticated users. Also, it does not mention how we can attach custom information to the identity (guest) so that it can be decoded at the authorizer level in Api Gateway and passed to backend service.
Is Identity pool the only approach to implement guest access? My usecase does not require access to any AWS resources except Api Gateway for guest users. Please note the Api Gateway apis used for guest users are also being used for authenticated users.

Cognito User Pool and AWS Gateway - How to configure a different set of user permissions with one app client?

I am trying to understand the use of access tokens to authorize an API fronted by API Gateway.
My current understanding of the process is as follows:
After setting up a Cognito User Pool, I can define a resource server and associated scopes (e.g. https://wibble-api.com/read, https://wibble-api.com/full).
Then, I can select the allowed custom scopes for a user pool app client.
In AWS Gateway, I can create a Cognito Authorizer to authorize incoming requests.
For each AWS Gateway resource, I can go into the Method Request and select the Cognito Authorizer and determine which OAuth scopes are necessary in order to be able to execute the API method e.g. I can enter https://wibble-api.com/read, https://wibble-api.com/full to indicate that either of those two scopes are sufficient to be allowed to execute the API resource.
When using the hosted UI, the scope parameter will include all of the allowed scopes configured for that app client, and the returned access token (if using implicit grant) will contain those scopes as part of the JWT.
What I don't understand is, I have what must be a very common scenario where I want to be able to give the read-only scope to, say, a user that hasn't paid for the service, and the full scope to a user that has paid. Yet it looks like I would need to have two separate app clients if I'm going to be using the Hosted UI, because there doesn't seem to be a way to return different scopes depending on, say, what group the user has been assigned, or some other metadata in their user profile such as department, etc. I won't know what sort of user they are until after they have been authenticated, but I still need to enter the exact scope when I am authenticating. Is there a solution for this, please?

Integrate Cognito with API Gateway and static credentials

So we built our service to give our users API Keys to access API Gateway and our service. Gateway acts as an endpoint for our Lambda functions.
The problem is, we got an email from Amazon saying that we hit our API Key limit of 500 keys. They said that we shouldn't be giving users API Keys because keys are meant for integrating with other services, not users. They said we should be using Cognito User Pools and our limit can't be increased.
The problem is, our users build HTTP requests in a tool called ManyChat - a tool for building chat bots.
Our users build dynamic requests and then save their chatbot to use that dynamic request. Our users can't go back and refresh those credentials as is necessary with Cognito tokens. The authentication method will have to use a static API Key I believe.
Is there a way to manage our users' usage while keeping the authentication credentials static?
1) Update 401 Unauthorized response template as per your need so that it contains the WWW-Authenticate header set to 'Basic'.
2) Create a custom authorizer that match your credentialand and retyrn response.
https://medium.com/#Da_vidgf/http-basic-auth-with-api-gateway-and-serverless-5ae14ad0a270

API Gateway authorization for Cognito User pool+Identity pool

I am working on a web app where users can login/signup with their personal email addresses or login with federated identities like Facebook/Twitter. I have set up Cognito User pool and identity pool for the same.
After successful login , APIs hosted on API gateway would be invoked to display some data on the application. I would like to implement authorization for every API invoke call and return the response only for authorized users.
I have created User Pool Authorizer in API Gateway and I am able to authenticate users created in userpool based on the Id Token.
As per my understanding , to authenticate users from Identity pool , I can use AWS_IAM in Api Gateway. AWS_IAM may not be right solution for my application as API can be invoked by user in userpool as well as identity pool.
I am thinking of implementing authentication using Custom Authorizer using Lambda functions.
If custom Authorizer has to be implemented , should validating policy document based on the session token be sufficient to validate the users from both Userpool/Identity Pool? Kindly suggest alternatives for custom authorization,if any.
Thanks in advance
Have you seen this blog post? https://aws.amazon.com/blogs/mobile/integrating-amazon-cognito-user-pools-with-api-gateway/
It's possible to directly integrate your Cognito user pools tokens as an authorizer for API Gateway, and it simplifies the flow you described greatly.

AWS Cognito, Lambda, User credentials in DynamoDB

I established a authentication flow with Facebook Login and AWS Cognito on the client site. Works fine. But now I need a reference of the user with its facebook id in a dynambodb table. Of course I could just call a AWS lambda function exposed via AWS API gateway, but how can I verify that the API call actually has a valid facebook id and that this facebook id matches the AWS Cognito Id. Maybe I am missing something here, I hope you guys can point me in the right direction ;) thanks!
If you can key your ddb table by cognito id instead of facebook id, you can invoke api gateway with cognito credentials. If you use callee credentials when calling lambda you can access the cognito id via the token $context.identity.cognitoIdentityId. This ensures the call was made by the owner of this id. You can further check that $context.identity.cognitoAuthenticationProvider is graph.facebook.com to ensure they authed via Facebook. Unfortunately, the facebook id is not passed in the credentials, so if you need it you will need a lookup table mapping cognito id to facebook id. For more details on the available tokens see here.
I would suggest to do the following (I'm new to AWS as well, Let me know if you have any suggestions):
Create a API Gateway /fblogin endpoint where you will POST the Facebook Access Token (You will authenticate with Facebook on the client side to get this token). That endpoint is linked to a Lambda function say fb_login.
In fb_login function you will authenticate with Amazon Cognito to get its credentials. You should have created a Federated Identity user pool in Cognito and assign appropriate roles to assume for this user pool. This helps if you want to restrict your API only to those who are authenticated and authorized. So, the result from Cognito will have IdentityId and Credentials. You can return them as a result of your request to /fblogin.
Using the above result you can sign the requests you send to your API on API Gateway (Or you can use AWS custom generated SDK for your API to handle the signing). On the API Gateway endpoints, enable CORS and authentication as AWS_IAM. This way, API Gateway verifies the user automatically by checking the signature in the request. You can get the User Id from $context.identity.cognitoIdentityId as others suggested. This way, you can be sure that the user is authorized and authenticated.
Note: Make sure you implement /fblogin endpoint on HTTPS, then the FB Access token will be secure. If not, it will be visible as plain text over HTTP.
Also, use a Dynamo DB table as a log for CognitoID - FacebookID. You can incorporate this in the Step 2 Lambda function ifself or anything you think is appropriate.