amazon-archives / aws-serverless-auth-reference-app

Serverless reference app and backend API, showcasing authentication and authorization patterns using Amazon Cognito, Amazon API Gateway, AWS Lambda, and AWS IAM.
Other
754 stars 193 forks source link

Multi tenancy with cognito user pool. #20

Closed outmarch closed 6 years ago

outmarch commented 7 years ago

Thanks for very nice reference app. I am planning to use Cognito user pool, federated identities with APIG and lambda. In my case I am planning to use this for multi-tenant SaaS application. I will have different Cognito user pool per tenant so that I will have flexibility to configure different rules for different tenants . I saw that in config file you have all USER_POOL_ID, CLIENT_ID, IDENTITY_POOL_ID constants which are used in cognito SDK to make calls like authenticate users.

My question is, in my case as I will have different USER_POOL_IDs per tenant how do I handle this in client app? I don't want to update client app as we add new tenants. If I make a API service wrapper for cognito then I need to send password over wire. What is the best practice to handle this use case?

admin-cloudinertia commented 7 years ago

I use S3 to statically host the app i.e. "example.com" which is my frontend website to acquire new tenants. At my admin application "console.example.com". I automate provisioning resources for new tenants from default template configuration objects "infrastructure as code" so that route53, cloudfront, s3, api gateway, lambda, iam, acm, dynamodb, and cognito are updated for "wildcard.example.com" where each unique subdomain is a tenant. Your application would be dynamically deployed as a new s3 static site per tenant. In this case along with i.e. "config/config.ts" from this demo would be part of the default configuration objects unique to each tenant. I use a lambda function node.js runtime to dynamically create custom configuration objects per tenant that are stored in dynamodb table provisioned per tenant or dynamodb stores pointers to s3 locations that contain the configuration objects. I use a regular expression on tenant attributes to direct the user to the proper app they are a member of "wildcard.example.com". No matter which frontend a user logins in at they are directed to the correct app. Take a look at IAM policy variables, and configuring wildcard domains with cloudfront s3 and route53. From "console.example.com" you can administer all your tenants configurations and users similar to a dynamic CMS, "content management system or cloud management system". You need to establish a hierarchy of default permissions on resource access i.e. so that your tenants can have pseudo-admins. I wouldn't suggest using Cognito as the sole service alone to delegate access and manage a multi-tenant SaaS application. Take a look at the whitepapers on architecting multi-tenant SaaS applications in the resources section of aws.amazon.com.

outmarch commented 7 years ago

@admin-cloudinertia thanks a lot for the detailed response, very much appreciated.

A couple of clarifications, are your creating different S3 sites , dynamo tables etc for every tenant? Looks like from AWS white papers your are using "Tenant Isolation at the Amazon VPC Layer". I am trying to achieve "Tenant Isolation at the Application Layer" where all tenants will share same code base and DB. I have tenantId in DB tables.

I have a process of tenant provisioning, so looks like I need to dynamically update "config/config.ts" file as we add more tenant.

I am planning to use Cognito and federated identities with role-based access control authentication and authorization. Below is the URL for AWS article. https://aws.amazon.com/blogs/aws/new-amazon-cognito-groups-and-fine-grained-role-based-access-control-2/

You mentioned, "I wouldn't suggest using Cognito as the sole service alone to delegate access and manage a multi-tenant SaaS application”. Could you please more elaborate how you are achieving this in your application?

Thanks a lot for your help.

ETFairfax commented 7 years ago

Hi outmarch. I'd be really interested to here if/how you achieved this as it's exactly what I'm facing at the moment.

I've followed this tutorial from serverless which is similar to this repository.

The cognito UserPool and ClientApp ids are configured for the front end (here) - again similar to the config file in this project.

Exactly like you I'm planning on having a different Cognito user pool per tenant so need this configuration to be dynamic depending on the tenant.

More than happy to collaborate with you on a demo project which would extend the flows in this project to include the registration of a new tenant.

Many thanks,

ETFairfax

justonian commented 6 years ago

Hi all-

Apologies for the slow response to your question.

Having multiple user pools has benefits for scalability both in total size (although a single pool can be quite large) and in requests rates, as it spreads the load over multiple partitions. Multiple user pools can also be advantageous if you want to keep data for users in their own geography.

The two main downsides of multiple user pools are 1) you can’t do a single list/search for users across all the pools, and 2) your app needs to know which user pool a user belongs to before it can sign them in.

That said, unless you need different configuration settings for different customers (ex. password policies, etc.) I would try to minimize the total number of user pools as much as possible due to the management overhead. Also, with the new SAML integration capabilities, a single user pool can federate directly with multiple SAML providers then provision users from different companies/SAML providers user accounts in the same user pool, making it easier to use a single user pool, as well.

Let me know if you have further questions on the options here.

Justin