I am designing a product which would be deployed to AWS. It will use Cognito for user authentication. It will be a multi-tenant application.
The application has many modules/features. The pricing depends on the features selected by the client.
Please provide guidance on how can I implement a check if the feature is licensed or not. I don't want to put the logic inside each web api endpoint.
You should create an application microservice (callable via a API, but with access locked down to your own application) that receives information such as:
Authenticated User ID
Service wanting to be accessed
Resource-level information in case you want fine-grained access control
The authentication microservice would consult a database, apply appropriate business logic and return a success indicator.
Preferably:
Each request should be logged in an audit trail
If access is denied, return an error message that could hint at the reason why (eg 'This feature is requires subscription to the XYZ module')
Use some form of cache to make the queries super-fast (eg DAX for DynamoDB, or ElastiCache)
Licensing systems can often be more complex than actual applications!
Related
I am working on a NodeJS application which exposes some APIs. This APIs can be accessed by different vendors (Without any browser). Now I want to know what is the best way to Authentic/Authorize these vendors using AWS Cognito service?
Should I give a client ID (Username) and API_KEY (Password) to my vendors and Validate it through cognito for every subsequent requests. (As of now it is already implemented from the Database)
[OR]
Should I generate a access and Id token for the vendor with MAX validity and give it to the vendor. (I understand this isn't the best practice)
So what should be the best way to achieve this?
Define app clients in your user pool, one for each of the "foreign" servers. When you create them Cognito will generate an app client id and a secret (if you check that box...and you should check it). In "App client settings" (AWS Console for Cognito) you tell it the client will use "Client credentials." Finally, define whatever custom scopes you think you can leverage to provide finer control of access. These can be different for each client.
Now the foreign server can authenticate/get-authorization by passing in the app client id and the secret, etc., etc. Usual Cognito stuff.
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.
My current project is in AWS, using Cognito and microservices with Lambda. We have designed the microservices using DDD and are in the process of implementing basic functionality.
However, there is a business need for users of the API to be able to be categorised into the client company that they work for, and only be able to access data for that client company as well as any role-based authentication we will have.
This isn't a full multi-tenant solution as every user will be working with the same website, but their account will have been associated with a particular client.
Everything I have read about doing something like this in AWS suggests using one user role or pool per client and associating users with it when they are created, however we do not want to do this, as the clients typically consist of 2-3 users and there are many clients. This would quickly become unmaintainable in terms of number of user pools.
I tried to think of ways around this issue using "conventional" means, such as adding a domain service into the architecture which was solely designed to add client data to each request by a particular user by calling into the user microservice, but this seems overly complex. I also considered changing the architecture to include basic user and role information in each microservice, but that seems messy.
My question is are there any officially supported ways to add data into an AWS Cognito profile programmatically, and in such a way that this could be changed through a front-end website by a client admin after the account has been created? Even if it's just a clientId field in the token.
If not, then what would anybody who has experienced a similar issue recommend as an alternative to the user pools suggestion.
Thank you.
EDIT:
I have also been investigating several ways to do this using attributes on Cognito profiles, as mentioned here. It seems like this is the way to do more or less what I'm trying to achieve, but I'd still like to hear about alternatives or advice.
The solution we will use for this issue will be to use custom attributes as part of the Cognito user set-up. We will have text fields for additional attributes or groups that the user belongs to.
The way this should be implemented can be found at the following links:
Managing SaaS Identity Through Custom Attributes and Amazon Cognito
Managing SaaS Users with Amazon Cognito
SaaS identity and isolation with Amazon Cognito (Example Guide)
SaaS Storage Strategies
With this data being automatically passed into each service as part of the Cognito credentials, we will be able to check that the user has the valid credentials for accessing data specific to each client.
Examples of how to work with Cognito in a NodeJS application (sometimes with Serverless) include:
https://serverless-stack.com/chapters/login-with-aws-cognito.html
https://serverless-stack.com/chapters/add-a-create-note-api.html#configure-the-api-endpoint
This seems to be most easily achieved by using the aws-amplify package, which is primarily designed for front-end authentication, but which can be used in NodeJS for back-end authentication as specified here.
So I may be barking up the wrong tree here, but I have got the api manager working against rest services and can provision users through LDAP.
I can restrict access to certain services by role.
All good so far, however as many users will authenticate through a SPA (AngularJS) and the application will call multiple Rest Services, what I don't want users to have to do, is go to the store and subscribe to all relevant APIs, I would like the users from the LDAP server to be subscribed to all relevant services and have the roles they have limit access to the service.
Is there a way to have authentication done by just being in the identity store and authorization to be managed by the restrict by role setting.
Does this need scripting, is it a setting, or is it impossible?
Thanks in advance
Your requirement isn't supported OOTB in API Manager, still you can do it with little effort.
API Manager provides REST API to subscribe APIs. You can write a client which call the REST API onbehalf of the user and subscribe him.
Have a look on REST API
I'd like to run some stateless Java services on the Bitnami stack on AWS that will be consumed by apps... and of course to access these I'd need some type of authentication and authorization.
Previously with this type of architecture I've chucked an API gateway in front of them, to which the developer would subscribe. And AWS provides an API gateway, nice.
HOWEVER, while reading up on how to set this up on AWS I came across 'AWS Cognito' which is supposedly designed specifically for this same purpose.
So my question is are these two solutions comparable - are they doing the same thing?
And if-so, then what are the pros and cons of each, when would choose one over the other?
Basically because you are targeting the user level you should use Cognito; as it does provide you with authentication, reseting passwords for the user, and of course
signing up workflow. Moreover it provides user information to the admin, as well as two factor authentication, by using the user's mobile phone.
If you want to authorize the application to use an api then you use the API Gateaway.
The Cognito, is designed for user interaction it has an api for Java, JavaScript, iOS, and Android, so you can
implement the interaction with it at any level; as you wish. You also not getting changed if your user base is less than 50k.