Limit usage of AWS unauth cognito user - amazon-web-services

I am making a web application where a user can get a text (they have to enter) read.
The user doesn't have to identify / login before using the service.
The text is read thank to AWS Polly (with a cognito unauth role called via javascript by the user browser).
I did followed this tutorial:
https://docs.amazonaws.cn/en_us/sdk-for-javascript/v2/developer-guide/getting-started-browser.html
Nonetheless I would like to give a kind of quota to the users.
I am afraid a single user uses the service too many times because I will have to pay for the many AWS Polly requests.
I don't know how to create quotas for each unauth user...
Any idea ?

Shortly, this is impossible.
AWS Cognito controls whether or not a set of credentials is allowed to make a particular API call. The credentials can be time-limited and API calls can be restricted by things like IP address, but it is not possible to limits API calls by quantity. This is true both for authenticated and unauthenticated users.
You can overcome this problem by having users call an API through AWS API Gateway which will trigger your own code on AWS Lambda. The Lambda function then verifies whether to allow the action and then makes the API call on behalf of the client.
Passing through the API Gateway will also allow you to have more control on the user actions (tracking per-user usage, restricting functionalities).

Related

Could I use multiple AWS Cognito app clients to give API access to my users?

So, I know the answer is "yes I can", but is this the right path?
I have a Cognito userpool within all my platform users, now we would like to open specific API Gateway endpoints to specific users, so I just thought about using a Cognito app client for each user who wants these special access.
If a user wants to use the API will need an app client setup with its id/secret keys, then I can create an authorizer in the API Gateway pointing to this userpool and add it to specific endpoints.
Then the user will use his/her id/secret keys to generate a token to be used against specific API endpoints.
This seems to be clean and neat, but there is a big problem: Cognito limits to 10k app client per userpool
We don't actually have so much users wanting to access our API but who knows in the future.
So is this still the right path?

Suggestion: Integrating Amazon Cognito with AWS DynamoDB

I've built an application which is connected with Amazon Cognito to take the sign in and sign-ups of users. Currently, application support three different subscriptions (Free, Basic, Premium). If the user signs in for basic Subscriptions, I want to give them least access to DynamoDB for download the parts of applications which is required to run the application service.
How to connect DynamoDB with Cognito directly
I am not sure, what's the best approach to follow this scenario?
(Please note- this is not a mobile-based application, so do not give suggestion to use AWS Amplify or relatable services)
When I was first learning about Cognito, I had made the same set of assumptions you are currently making. I knew that User Pools could act as my application's user directory, and Identity Pools would magically unlock all my authorization needs. I was mistaken :)
At the risk of oversimplifying, AWS Cognito exists to answer two questions:
Who are you? (authentication)
What can you do? (authorization)
Cognito addresses these concerns with two distinct offerings: User Pools (authentication) and Identity Pools (authorization).
At a high level, User Pools let you handle user registration, authentication, account recovery, and supports authentication with third-party identity providers like Facebook, Google, etc. Sounds like you might have this part figured out.
Cognito Identity Pools, on the other hand, provides a way to authorize users to use various AWS services. You can think of it as a vending machine for handing out AWS credentials. For example, if you needed to give your users access to upload a file to an S3 bucket or to invoke an endpoint in API Gateway, you could do so with an Identity Pool. You can even allow item-level access to DynamoDB based on an Amazon Cognito ID. However, this might not work the way you expect since your application users are probably not directly connecting to DynamoDB.
In most web/mobile applications, users are not connecting directly to DynamoDB. Instead, they are interacting with a web/mobile app that communicates to the back-end of your application via an API. That API would then communicate with DynamoDB. If your stack is in AWS, the path may look something like this:
Client (web/mobile app) <-> API Gateway <-> Lambda <-> DynamoDB
In this architecture, your users would authenticate via Cognito. Cognito would then authorize the user to make calls to API Gateway. API Gateway would execute your lambda, which would then interact with DynamoDB. The "user" of DynamoDB in this example is your Lambda, not the user of your application.
That last bit is important, so I'll repeat it: Unless your users are directly connecting to DynamoDB (not recommended), they are not the "user" operating on DynamoDb. Therefore, restricting DynamoDB access based on a user's Cognito ID is not going to be an option for you.
So, what can you do? Your application needs to provide the business logic around what effect your users can have on DynamoDB. Perhaps free users have read-only access to a specific partition, while premium users can modify the same partition. That logic has to be handled directly by you.
I know you said you weren't looking for Amplify suggestions since your application is not mobile-based. However, Amplify offers SDKs that aren't specific to mobile development. The folks at Serverless have made a fantastic tutorial on building a full-stack serverless web app, which includes a very readable chapter on serverless auth with Cognito. They use Amplify in a web app to integrate with Cognito, S3, and API Gateway. If that's something you are trying to do, I'd recommend checking it out.

AWS cognito custom user roles for authorization

AWS cognito's documentation suggest all the roles around IAM. How to make meaningful role that my application (resource-server) understands?
I have used AWS Cognito extensively in my applications and I can try helping you here.
Whatever you are saying is possible using Cognito. I believe you are trying to figure one pattern to map your application roles to Cognito/AWS IAM roles.
All Cognito users in the pool can be segregated under different Cognito Groups. documentation is here -> https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-user-groups.html
Each Cognito user group has to be mapped with corresponding IAM Role (permissions you can customize).
Now, these groups need to have one to one mapping with the user role/group in the application.
These groups can be leveraged in 2 different ways. We are considering the design pattern with UI layer (eg:AngularJS) -> AWS APi Gateway -> RestAPI (Lambda/hosted as an application in Beanstalk/container/Ec2/etc.)
The UI controls need to be displayed according to the user group. For example, a super admin will see all the links and menus, full privilege. But for normal end-user, limited links and menus will be visible. In order to achieve this, you can use some of the plugins for AngularJS (may be different in your case) to control the rendering of UI based on group information.
The API layer can be protected by introducing an authorization layer by setting the Authorizer configuration of API Gateway as IAM/Cognito. So before a request hits the API hosted in back-end, API gateway will check whether the requested user group has permission to access the API.
I hope this helps.
Not sure what you mean too much, but roles are for accessing AWS resources. Cognito can be used with an Identity Pool to grant temporary credentials to AWS resources. This means you can put your server/ec2 instance behind an API gateway configured with IAM authentication, and create an authenticated role in your Identity Pool which allows HTTP calls to your API GW.

How to use both service-to-service AND Cognito auth for API Gateway

I have a RESTful API being accessed via AWS API Gateway. I want both human users (authenticated via Cognito) AND other (internal) services to be able to call the API. There exists plenty of documentation of how to do either, but not for how to do both.
I have tried using unauthenticated Cognito federated identities to authorize services. I have also used Cognito user pools to authenticate people. However, API Gateway only allows for a single authorizer (in this case, either AWS_IAM or a Cognito authorizer). However, I don't see a way to do both.
I imagine I will need a custom Lambda authorizer, but I'm having a lot of trouble finding accurate information on how to write an authorizer using IAM or Cognito.
Surely we can't be the first people to want to allow both services and humans access to an API. The dearth of documentation on doing so leads me to believe I'm either missing something painfully obvious or that this is a use case that is best avoided (in which case, what IS best practice?).
Is there any way of doing both? Is there a Lambda authorizer example that can point me in the right direction? Is there something built-in that I'm missing?
We have rejected the idea of "pretending" that a Cognito user is a human, when in fact it's actually a service, as it seems to us to be a misuse of Cognito user pools and identity federation. Likewise, the opposite, where a Cognito user is federated to act as an IAM role shared by both users and services, seems like a misuse of user authentication.
Is there a canonical way to do this? If not, is there existing documentation of how to write a custom Lambda authorizer to do both?
The short answer is: you (probably) don't need to use API Gateway for either case.
API Gateway, as the name suggests, is just a gateway. It takes a request (often HTTP) and forwards it to another location (a Lambda function, an EC2 instance, another AWS service, or another HTTP endpoint). This is great if you need users who do not have an associated IAM role to access AWS services.
Users who are authenticated through Cognito have an associated IAM role through the associated Cognito Identity Pool. Just give them access to the AWS services this way, no need to go through API Gateway.
AWS services that need access to other AWS services don't need to go through API Gateway, they need to be given permission through their IAM role.
If for some reason you must use API Gateway for both your users and your services, make two API Gateways that point to the same resources that use different authentication methods.

AWS Cognito and API gateway using Lambda authorizer

I am trying to create APIs using API gateway and Lambda functions.
Based on the user group ( not the Cognito user groups ), I want to provide access to separate DynamoDB tables.
The approach I am following is, I am creating a separate Cognito user pool for every group of users.
When the user logs in, he is authenticated with the appropriate user pool.
For calling the subsequent APIs, I am planning to make use of Lambda authorizer.
The user will pass the ID token in the HTTP header request and I want to validate this ID token.
Is this the right approach? Or if there is any better approach for implementing this workflow.
Can we make use of Cognito user groups and will it be a secure approach?
I want to strictly separate the tables of one user group from another.
I came across the below link, to verify the ID token.
https://github.com/awslabs/aws-support-tools/blob/master/Cognito/decode-verify-jwt/decode-verify-jwt.js
There are some proven architectures and tools provided by AWS to simplify the above usecase.
There is no need of multiple user pools for the above usecase. This can be handled with a single user pool itself.
A simple architecture can be UI->API gateway->Lambda->DynamoDB
Users in Cognito user pool can be added into groups and set with IAM policies. Then API Gateway can be configured for IAM or cognito authorizer. Each Lambda writen for accessing different DynamoDb tables can be authorised at API Layer.
There is no need for a custom authorizer in this case.
Use AWS Amplify for user authentication and all other communication. Amplify will handle the token passing part by itself with any extra code written. JWT tokens can be read/validated and logically used in the client UI layer as well as in server code (lambda) seemlessly in this approach. The same token is used in API gateway for authorization by default (without any code written).
Cognito user pool and identity pool are enterprise-grade AWS solutions and AWS Amplify compliments the high secure implementation of Sigv4, SRP, etc. protocols which are very tough and complicated to implement using custom code.