I am using Spring Boot in my application. While searching for some IAM tools, I actually liked Auth0, but iam not affordable their pricing. So, I found another called AWS Cognito.
Below is Auth0 to restrict our custom access api
https://auth0.com/docs/api-auth/restrict-access-api
Currently, I am trying to restrict access API using AWS cognito, but I am not finding correct documentation to achieve this. Can anyone please tell me whether restricting api access can be possible using aws cognito.
It depends on how much fine-grained control you want over the access to your api.
Allow or Deny Scenario
In some cases, you either want to block someone completely, or give them access to all of your api. In this all or nothing scenario, the simplest route would be to use Cognito User Pools on their own to authorize your users. Cognito User Pools is just used to authenticate the user (are they who they say they are), and to provide tools to make sign up, and sign in easier.
If the user passes authentication, then you can pass one of the tokens returned by cognito user pools (the identity token) to API Gateway. As long as you have set up your api methods to have the Cognito User Pools authorizer in API Gateway, then this is enough for them to accept the identity token as authorization to access the methods.
Fine-Grained Access
However, in other cases, you need more fine-grained control. You may want all authenticated users to have access to a certain subset of your api methods, but only admins to have access to more restricted methods.
In this case, you will also need to use Cognito Identity Pools, to define user roles (e.g. UNAUTHENTICATED_USER, PAID_USER, ADMIN etc), and their associated IAM roles, which will have policies that give them access, or deny them access to various parts of your api.
You then set the authorizer for your api gateway resources to be AWS_IAM (instead of Cognito User Pools as in the all or nothing example above). And API Gateway will use the role credentials obtained from the Cognito Identity Pool to determine if the current user's role has the permissions to access the requested resource.
For example, perhaps your PAID_USER user role, will have the following IAM role attached:
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "execute-api:Invoke",
"Effect": "Allow",
"Resource": [
"arn:aws:execute-api:*:*:fjfkdlsjflds/*"
]
},
{
"Action": "execute-api:Invoke",
"Effect": "Deny",
"Resource": [
"arn:aws:execute-api:*:*:fjfkdlsjflds/*/admin/*"
]
}
]
}
This gives them access to your api, apart from the api methods (resources) that you have set up under /admin/.
I highly recommend this AWS reinvent talk on Serverless Authentication and Authorization, which goes over these options with some good examples.
As I understand What you are trying to do is to resolve the authorization for your APIs. Cognito comes to picture in case of Authentication (Instead of your own database and user handling it supports everything). By using Cognito you can create a User pool and Identity pool to handle the User authentication and create the access token for the authorization for subsequent API calls. The following you need to do
1) Register with AWS Cognito and create a user management pool and Identitiy pool
2) Create a spring boot app (as you mentioned spring boot in your stack) for authentication.
3) Add spring security dependency
4) Register the appln as a resource app in COgnito
5) Do the authentication and return back the token you generated.
6) Create another application (for actual business you may have multiple microservices)
7) Register those spring boot app as resource server in cognito
8) Add the spring security dependency on the new app
9) Create a handler by extending WebSecurityConfigAdaper and override configure
10) Create a filter by extending OncePerRequestFilter
11) Authenticate the token by checking the claims
12) Restrict the API access to all calls in cofigure method of configurer
Related
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.
I have my WEB API's hosted in Docker. My Angular client will send a JWT token to access any of these API's. I wanted to make use of AWS API Gateway feature to add an Authorization check before calling the API client requested. From the docs I see that we can leverage the Lambda Authorizer concept to Achieve this. But then again I though why using Lambda Authorizer when I can come up with an DOT NET CORE API which can validate the user.
Does my Lambda Gateway makes sense for my case?
If it does, what would be the output of the lambda Authorizer? A simple true/false which says the the Token is valid or not?
I see that this is what the response should/might look like. How this should translate to in my case
{
"policyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Action": "execute-api:Invoke",
"Resource": [
"arn:aws:execute-api:us-east-1:1234567:myapiId/staging/POST/*"
],
"Effect": "Allow"
}
]
},
"principalId": "Foo"
}
What should happen in API gateway after the Lambda Authorizer executed ? Who calls my actual API which is requested by the client?
If you are using a Lambda Authorizer, returning an Allow or Deny Policy is what you are looking for.
This essentially grants API Gateway permissions to invoke the underlying target. I know it sounds weird at a first glance, but that's how it works. Think of an Allow policy as a true return statement (credentials matched) kind of thing whilst a Deny policy is more of a false return statement (credentials didn't match / not enough permissions based on your rules, etc).
To get you off ground, you can simply copy/paste the code available at the docs and modify the authentication way to your liking (the docs show an example using a header with Allow or Deny values, which is definitely not what you want, that's just meant for the sake of an example).
So, back to your question by enumerating all the answers:
Yes, but it's called a Lambda Authorizer instead of a Lambda Gateway
Either an Allow or Deny policy for valid/invalid tokens respectively.
If the Lambda Authorizer responds with an Allow policy, it will then invoke the target (which can be a Lambda function, an SNS Topic, an HTTP endpoint - this is likely your case - and so on). The authorizer will just act as an interceptor and decide whether to proxy the call to the target or not.
From what I understood as per the question, you want to validate the user who are calling your API.
You can do it in all the ways you have already mentioned.
Using Lambda Authorizers, you will get a 200 or a 403 code not true false. You can follow the following link to set up your authorizer :
https://blog.codecentric.de/en/2018/04/aws-lambda-authorizer/
You can also use AWS Cognito for managing your users, it'll simplify your work a lot.
You just add your dotnet core api to "Integration Request" tab, Choose Integration type as HTTP and mention the dotnet core api in Endpoint URL field
Amazon Cognito lets you add user sign-up, sign-in, and access control to your web and mobile apps quickly and easily. Amazon Cognito scales to millions of users and supports sign-in with social identity providers, such as Facebook, Google, and Amazon, and enterprise identity providers via SAML 2.0.
Advantages for using Cognito:
Managed service, less components to implement/monitor/scale
Easily configurable via portal, CLI and templates
Supports multiple flows for authentication (client side, server side, OAuth2, custom)
Supports Lambda triggered functions on authentication/registration events
Uses JWT signed tokens which can be passed directly to clients in session cookies and used to verify requests and passed in related API calls so a single authentication/authorisation method can be used through your stack statelessly Group membership, supplied in access token can be used for authorisation (e.g. users in group “Admin” can perform admin functions)
Handles:
User group membership and attribute storage
Email/Phone verification
User invitation
Login/Signup UI forms (customisable)
Password reset
Disadvantages:
Less control over authentication/authorisation (limits to UI/flow customisation)
Potential for lock-in (cannot export users with passwords for migration)
Amazon Cognito has three type of authorizer
Amazon Cognito user pool - User pool authorizer.
Amazon Cognito federated identities - AWS IAM Authorization.
Custom Lambda identity providers - Custom Autorizer
Setup:
AWS Amplify API w/ GraphQL
AWS Amplify Auth w/ Cognito User Pools
Say the majority of the platform should be accessible by a logged out user. E.g. they should be able to read forum Topics, but if they want to post, they need to sign in.
I see an #auth resolver that I can use, but whenever I try to make a graphQL call to my.url.amazonawscom/graphql to fetch Topics, it says "errorType": "UnauthorizedException". I'm having trouble figuring out how a logged out user can have authorization to publicly accessible data.
AWS AppSync recently launched support for multiple authorization types on the same AppSync API. So you could for example enable cognito user pools as the authorization type on your API and add API_KEY as an additional authorization provider.
After this, you would be able to use the #aws_api_key directive to make selected fields from your schema such as for example getForumTopics be api key authenticated. API Keys are in general considered to give public access.
Also Cognito User Pools and Cognito Federated Identities are separate products. Cognito Federated Identities does indeed have an unauthenticated identity role that you can use to secure top level fields in your schema but it looks like the auth type on your API is set to Cognito User Pools.
In Cognito identity pool you need to set the policy for unauthorized users. Go to Edit Identity Pool and you can see an option where role can be set for unauthorized
I'm quite new to AWS and I try to understand some basic concepts. In my Android app, I use:
Cognito User Pool and Identity Pool to allow my users to register and sign in, but also to use the app as guest users
API Gateway and AWS Lambda to create webservices that the app can call
My use case is very simple: I want some of the APIs I created in API Gateway to be available for my authenticated users and my guest users, and the other APIs available for my authenticated users only.
For the APIs available for my authenticated users only, I was thinking putting the users in a group of users (thanks to CognitoIdentityServiceProvider.adminAddUserToGroup()), that can have a common role with an IAM strategy attached to it, to allow them to access those APIs. I think it makes sense since I'll have different types of users, so I'll use a group for each type.
But for the APIs available for my authenticated users and my guest users, I'm note quite sure of what I'm supposed to do. Should the APIs be public, so they can be called by anyone including my guest users, or is it possible to make them only available for my authenticated users and my guest users, but without being public? What are the good practices and how can I achieve them?
Thanks for your help.
You should use "API Gateway Lambda Authorizers" for this. You configure the authorizer per method. So, only the endpoints reserved for authenticated users should have one set.
How do they work?
Every time a request hits an endpoint with an Authorizer configured, API Gateway will trigger it with the request information. The authorizer then checks if the request have the proper credentials. If it does, then an IAM policy is returned. The method execution call (another Lambda function for example) will consume this policy. Otherwise, the authorizer will return an error status code, say a 403 Access Denied.
In your case, since you are using Cognito, you can use a Cognito User Pool Authorizer. You can create it using Cognito's SDK or AWS cli. After you configure it the only thing you have to do is append the id or access token provided by Cognito after a user authenticates. It's usually served inside the Authorization header.
I hope it helps.
Here is how I did, using the console:
In API Gateway, click on the resource, then the method (GET, POST...)
Click on Method Request
For Authorization, choose AWS_IAM
In Cognito, choose Manage Identity Pools
Create (or edit) the identity pool you use with your Cognito User Pool
In the Unauthenticated identities block, check Enable access to unauthenticated identities
On the same page (at least if you edit the identity pool), you should also see the Authenticated role and the Unauthenticated role
Go to IAM, and in Roles, find those two roles
For each role, click on it, and in the Permissions tab, click on the policy attached to that role to view it (with the little arrow on the left)
Click on Edit policy, then the JSON tab, then add the following block (you can find the ARN by going to API Gateway, click on your API, click on your resource, click on your method: you'll find the ARN in the Method request block):
{
"Effect": "Allow",
"Action": [
"execute-api:Invoke"
],
"Resource": "<the_arn_of_your_resource_api>"
}
Click on Review policy, then Save changes
We're building an application using AWS App Sync, we're still in a very early stage.
Our application has a restricted area, through user sign-in, which is being managed via aws cognito users pool. And this is fine.
We're having issues on the public area which doesn't require any authentication.
How can we protect these public endpoints?
We're having some doubts about hard coding the api key (that we know can be rotated), is it a good practice (documentation page says that it isn't ideal for production)?
Is there any way to authorise the origin? (aka, any request coming from www.foobar.baz is ok)
I would suggest using Amazon Cognito Federated Identity to control authenticated and unauthenticated access to the api. In order to do use Amazon Cognito Federated Identity with AWS AppSync, you need to use AWS IAM based authorization.
For the authenticated access you can use Amazon Cognito User Pools and federated to Amazon Cognito Federated Identity and since the federated identity can also allow for unauthenticated users it will allow you to control some api's which can be made public via an IAM policy.
For more information please read the AWS IAM Section of our security guide here
Under your AppSync app's Settings menu, where you set the User Pool Configuration, there is an option to set a default action. You can change this to DENY and all unauthenticated requests will be rejected. The alternative approach is to ALLOW everything, and manually add #aws_auth directives to every query/mutation/subscription field that you care about restricting.