Authorizing access to specific resources - amazon-web-services

I'm trying to build a REST API using AWS API Gateway that calls into a bunch of Lambda functions.
I have now set up API Gateway to use a Cognito user pool as the authorizer, but all that's really doing is authenticating the user since I've attached the user pool to all the endpoints. I wasn't able to figure out how to specifically allow certain methods on certain endpoints.
For example, if my user is 123 and belongs to group ABC, I would only like them to be able to GET /users?group=ABC or PATCH /users/123.
Is it possible to achieve this level of control or do I need to implement those checks in the Lambda function that API Gateway calls?

I am developing a similar setup and I faced the exact same issue. My team could not find a solution to this, so we contacted an AWS solutions architect. Here is a summary of their approach to this problem.
Unfortunately there are no default built-in solutions to this specific problem. However you can use some alternative solutions.
It is possible to trigger Lambda functions during Cognito user pool workflows. You may use an extra Lambda function to authorize users by checking their user-group relationships.
Customizing User Pool Workflows with Lambda Triggers
You can use API Gateway Lambda authorizer. In this case you will have to give up the Cognito integration and apply your custom authorization logic inside the authorizer Lambda.
Use API Gateway Lambda authorizers
You can implement the authorization logic inside the lambda functions with an extra query by checking the user-group relationship. You can check the identity of the requesting (Cognito) user through requestContext.authorizer.claims.* in the Lambda event.
Hope this helps.

ofcourse yes u can do it. this will help you.. if u get stuck.. ping me back
https://aws.amazon.com/premiumsupport/knowledge-center/cognito-custom-scopes-api-gateway/

Related

Is there any way to hide AWS lambda code?

I want to publish my application and provide lambdas to other so that I want that on exporting the lambda package no one can get the lambda code.
You should create an API Gateway which will connect the application to your Lambda code. Give that API endpoint URL to the others and they will call your Lambda function through that. This way they cannot know what's going on in your Lambda code.
Ideal way is to use API gateway and use it as trigger for your Lambda and share that endpoint to the users.
However if you don't want that you should probably consider cross account access with cross account role (give permission to execute just the Lamnda you want to expose & setup trust relationship) . Let them assume this role and call this lambda.

Use custom authorization logic with AWS Cognito authentication

We have a Cognito User Pool which contains the users we would like to allow access to, to our API. Our API uses Lambda functions to service the endpoints. The Cognito pool is configured with a custom field roles which is essentially a comma-separated list of roles that user possesses.
Now, first, we want the Cognito authentication to take place (to determine whether the user does belong to our pool and the credentials are valid). Then, we somehow want to run our custom logic to run which will look at the roles field which it will receive through the claims, and then allow or deny the request based on internal business logic.
We tried using a custom authorizer to implement this logic and set it as the authorizer for our endpoints. Then, we enabled Cognito authorization for this authorizer function. The problem is that since Cognito protects API endpoints and not lambda functions per se, the Cognito authorization simply does not run when an API endpoint is hit and the custom authorizer is called.
How do we achieve our objective of using custom logic with Cognito authorization? Any help in this regard would be highly appreciated.
All of the claims in the users' token are available in the context that can be passed to your lambda function if you are using cognito authorizers under $context.authorizer.claims.property Would mapping that claim into your lambda function and checking that the roles is present at the beginning of your lambda work for you?

How to implement authorization based on user property from Cognito User Pool (or DynamoDB)?

I am relatively new to AWS but read through tons of documentation and couldn't find what I need.
I am trying to implement authentication where users pay for subscription and based on whether they have paid they get access to S3 buckets and items.
I tried using API Gateway with a Cognito authorizer but I have no idea how to add the check if a user has paid (for example by looking it up in DynamoDB). Is there any way to add custom authorization logic to Cognito authorizer? If not, is it possible to still use Cognito User Pool with a custom authorizer? And most importantly, how would you implement the whole thing?
I am open to suggestions.
I found what I was looking for.
I added a custom user attribute subscribed. Then, created a lambda function which I used as a custom authorizer, using the blueprint for custom authorizer for Amazon Cognito User Pools. I modified the code so that I also extract the custom attribute subscribed (which is prefixed by custom:, so it becomes custom:subscribed) and check if it is set to true. I uploaded the blueprint to the lambda function and set it as an authorizer to the endpoints and methods I needed.
For updating the flag I used CognitoIdentityServiceProvider. adminUpdateUserAttributes which I call in a custom location in lambda after the user successfully pays (or remove subscription with cron jobs to check if it is valid).
Articles:
https://aws.amazon.com/blogs/mobile/integrating-amazon-cognito-user-pools-with-api-gateway/
https://aws.amazon.com/blogs/compute/author/

Is it safe to authenticate a Cognito User through API Gateway to Lambda using a custom property?

I'm currently using a Cognito User Pool as an authorizer for an API Gateway endpoint, through to a Lambda function.
Can I pass the Integrated Request on to Lambda and SECURELY allow or deny from inside Lambda based on a custom attribute?
Mapping:
"administrator" : "$context.authorizer.claims['custom:administrator']",
Lambda handler:
boolean isAdmin = Boolean.parseBoolean(request.getContext().get("administrator"));
if(isAdmin) etc...
To be clear, a user that is NOT an administrator should not have access to the same API endpoints that and Administrator does..
Do I need to do anything else before/after this point?
I am sending the initial request to the API Gateway with Javascript after the user has logged into Cognito, by including the Authorization: JWToken header.
Do I need to verify the signature of the token in the Lambda function? I presume that API Gateway has already done that.
Is there a better way to manage this in terms of security?
Ideally I would like to be able to limit access to the API Endpoint based on GROUPS within the User Pool, however I don't think this is possible.
The Groups documentation talks about limiting access/permissions via AWS Identity and Access Management. If I go down this path, how do I make a request to the API Gateway? Do I still use the JWToken Authorization header, and use Cognito as the Authorizer in API Gateway?
The custom attribute/claim support included with Cognito user pools is secure and can be used for use cases such as this when used correctly. There are a couple of caveats.
First, ensure that users aren't able to modify the custom attribute themselves. When adding the customer attribute, do not mark the attribute as mutable. Also, custom attributes can be can be marked as readable or writable for each application. For this use case, you'll want to set the attribute as readable for the application the users have access to. Details about custom attributes can be found here.
The other caveat is to ensure that your request body can never by-pass your mapping template which could allow an attacker a way to directly set the administrator attribute being passed to your Lambda function. To do this, edit your integration request and set "Request body passthrough" to "Never".
There are other alternatives you could use for this use case. The cleanest approach is to provide a completely separate API for your administrators. Then you can use a separate Cognito user pool for your administrators, or you could use IAM users or groups.

How should I use Cognito User Pool API inside Lambda function?

I have a Cognito User Pool, I know it can trigger Lambda functions but I need the inverse. I need to create user, and check if user with preferred username or alias exists in my lambda functions. Should I do it using Cognito REST API, if how is authentication performed? I could not find any similar implementations or examples in the web, I wonder if I am in the wrong way.
The AWS SDK is available to use in your Lambda function. You would use the Cognito features in the SDK to perform the actions you have described.