How to make relationship between Amazon Cognito and other microservice? - amazon-web-services

I am new to AWS and making some large application with microservice architecture. I am using Cognito user + identity pools for authorization. Organizations have branches, branches have positions, e.g Project Manager, Financial Manager, and a user belong to one of these branches and positions. Users are stored in the Cognito User Pool. I've EC2 and RDS for organization microservice and I'm going to use AWS API gateway with IAM Role-Based Access Control to communicate between microservices but how can I make a relationship between the organization and user microservices?
I was going to use Cognito custom attributes, e.g custom:branch=branchId but if I needed to get the users of this branch that would be impossible. From Cognito docs:
Custom attributes are not searchable.
Should I use DynamoDB table, for relation cognito_user_id | branch_id, or what's the better approach?
How to get single branch users, how to get single organization users and where to write this code ? AWS lambda with DynamoDB ?

If you have no restriction to add table on RDS at organization micro-service, I will say do not use dynamodb as it is an extra component and your system supports relational better than NoSQL. Besides, one more prerequisite for dynamodb is one must be aware of data access pattern.
Create Organizations and Branchs table having one-to-many relation as seperate micro-service. User will be assigned to Branch.
You should write those shared logic to lambda as a service and that lambda will be called by both org and user services. I know that will cost extra integration effort. However, it is far better than adding new service like dynamodb.

Related

Is it possible to use Amazon Cognito groups to set permissions on AW resources such as Amazon DynamoDB and Amazon S3?

In my application I want to users to be able to create an organization i.e. (OrgA) and then have users sign up under said organization using either an invite code or token. Users in OrgA should have access to an Amazon S3 directory (which stores images and files) and access to a database table that has been created for the said organization.
I could not find a solution on how to implement this online and was wondering if using Amazon Cognito groups was a good idea to meet requirements.
This is supported by the Amazon Cognito Service. That is, you can use Amazon Cognito to control permissions for different user groups in your app. This ensures that users have appropriate access to backend resources, determined by the group they belong to. For more information, see Building fine-grained authorization using Amazon Cognito User Pools groups.

AWS Serverless: Best way to store permissions of users on different resources

Users have different permissions on different resources(They are called sites in our app) (which can grow over time). Also, there is a separate microservice that stores sites information in a separate dynamodb table. Permissions are calculated based on the groups a user is in. The backend will need to check for permissions always before an action is performed. I am looking to find the most efficient way to store permissions so that the permission check won't be redundant/taxing on the application.
So far our backend is all REST microservices. These are the options I have considered:
JWT Token: Do not wish to store permission on each resource in JWT token because the resource list will grow and it may hit the 8Kb header limit. That is risky.
DynamoDB: If we were to store permissions of each user in a DynamoDB table that is owned by the User microservice, that will mean a REST call to the endpoint from every other microservice which creates tight coupling between other microservices and user microservice and also adds an additional network trip.
DAX: Same issue as above
Elastic cache: Is it not managed so we will need to introduce a VPC in the application which I personally don't like.
API gateway caching: I guess it will do Authorization caching i.e requests with the same JWT token will be able to leverage the cache. Our JWT tokens are only cached for 5 minutes though so I am guessing it will hit the DB and calculate every 5 minutes. Also, this will again mean a REST call to the endpoint from every other microservice which creates tight coupling between other microservices and user microservice(that will have this endpoint) and also adds an additional network trip
Custom authorizer: Caches the policy for 5 minutes but we want the change in permissions to be real-time. Also, we have a strict policy that DynamoDB tables are owned by their respective microservices and that we do not read/write to DynamoDB from outside of the service. Since the authorizer is not going to be writing to the table, it will not be the owners and thus becomes dependent on a microservice that owns the table.also leads to cyclic dependency because all our microservices depend on the custom authorizer.
Am I missing something? What's the best way to handle this?

Control access to Amazon DynamoDB entries using an entitlements table for federated users

I want to build an AWS architecture for a serverless application which stores files in a DynamoDB.
This database stores data which relates to a given perimeter. On the other hand I have data (M:N links) which link users of my application to some perimeters.
I want to make sure that my users (Authenticated on Amazon Cognito via a federated OIDC provider) only access to the data related to one of their perimeters.
What is the best practice to implement this kind of access control logic with Amazon bricks ?
Is it possible to accomplish such access control logic with IAM policies at the Dynamo DB level ?
You can add a table
UserPerimeter
---
id (hash key)
userId (index - hash key)
perimeterId
And as part of your validation in your Lambda, you do a query on the index with the the user id from JWT/Cognito. This will check if he has access to the requested parameter. So basically protect your DB from your code (which is the only point of access).
You can achieve this from IAM, (check this article) but it adds too much complexity for my taste. This would be useful if the DB is used by multiple products/components/companies (which isn't a good practise anyway).

Custom app-specific permissions for RBAC on AWS

Amazon Cognito provides capabilities for Role Based Access Control (RBAC) that allows an admin to either permit or deny user access to various AWS resources. However, suppose I have a serverless webapp that runs on AWS Lambda and uses Cognito for user management. My app has its own set of app-specific actions (eg add a widget, delete a wombat, update a foo). My database objects have relationships with each other (eg every wombat owns multiple foo's). I want to have record level permissions (eg this user can only delete this foo if the user owns the wombat to which this foo belongs). These are app-specific permissions. It would be a giant pain to map each of these app-specific permissions (which I can easily understand in my head as the developer of the webapp) to the underlying AWS services. Furthermore, if I ever want to switch to a different AWS service or switch to some other cloud service provider, I would have to completely redo all my permissions. It would be much better to have a way to have the app admin/designer (eg me) create my app-specific set of semantically meaningful permissions and have a service that I can query to see if the given user has a given permission for the requested action on this object. Does AWS provide such a service, or would I have to maintain my own app-specific permission/role database tables and roll my own functionality to provide this?
Any suggestions? I'm using python for the backend language and MYSQL on Amazon RDS for the DB.

Best practice to store users "plan" and control their permission in AWS Cognito

Assume I have a web app application and I use aws cognito users-pool to manage my users. Also assume some of the users are just "Guests", some are in a "Regular" paid plan and some are under "Premium" paid plan.
Where is the best place to store the users plan information? Is it better to store it as a Cognito user attribute or in some key:value DB (e.g Dynamodb)?
How should I control what a user can do according to his plan? Should i check the user ID against his "plan type" value in Cognito user pool/DB for each http request he makes to the server? Is there a cheaper (resource wise) way to accomplish this?
Thanks
If your application is single tenant and you are using the particular Userpool only for this application, you can store the 'plan' in an custom attribute.
This would be difficult to manage if you use the same user pool for multiple applications or having multi-tenancy with different 'plans' for a single user.
To store the plan you can use either Dynamodb or Cognito Sync Storage.