User seperation

Hi there,

I want to port an existing project [1] to serverless architecture, but I am having sleepless nights trying to figure out how to do it.

For example I want the UX to be, admin signs up and chooses a domain: “foobar”

a subdomain like “foobar.example.com” is created

the “foobar” domain in itself has it’s own user pool. And basically uses a bunch of lambda functions & JS code with docclient to set and retrieve things in DynamoDB tables.

Hopefully you have the idea. But how do I implemented this in my AWS account that each new domain is isolated? A new AWS account everytime, which sounds impractical. Or am I missing some technique?

[1] https://github.com/kaihendry/myresponder

You’re talking about building a multi-tenant web application. I wouldn’t try deploying separate applications for each tenant (sub-domain). You normally do better building the application so that data is scoped to the current tenant.

For example: In DynamoDB you could use a range key on the tenant (subdomain) and email or create your own hash key using a composite value like “subdomain|email” (i.e. “foobar|john@example.com”).

Thank your for your reply Rich. The DynamoDB suggestion sounds plausible. But can my serverless functions move between Cognito user pools and such? I at least what isolation there… I think. Scoping sounds too painful.

Hendry,

At one of startups I work at we built a system like this. I’m going to have one of my fellow engineers speak to the details on the Route 53 configuration used to route the traffic.

Within the application code the tenancy would be determined at the time of authentication, and the sub domain obviously determines which tenant it is. We are currently moving authentication over to use Auth0, so I’ll speak to that possible solutions there.

  1. You can define a client for each tenant via their management API. This client will then return a client ID which you can use in your system to track which tenant they belong to.

  2. You can have a single client, but then use rules to determine if a user is able to authenticate into the particular domain they are attempting to login to. First rule would attach the subdomain to the users app_metadata on first login, the second rule would enforce matching between the domains.

  3. You can use roles and permission definitions on the user object as described here https://auth0.com/docs/tutorials/using-auth0-with-multi-tenant-apps

Any of the above would work. I can provide details if you dig into any one of them and need more.

2 Likes

Would love to hear about the Route53 setup. The thought of editing CF and pointing Route53 to it makes me have cold sweats, since there will be a long delay and a poor UX, right?

I was avoiding auth0 in favour of straight up Cognito, but I guess it must have some convenience that I am seeking.

Thank you Matt,

Hendry,

Do you have any specific reason for thinking that Route53 will result in a long delay and poor UX? Want to make sure I’m not missing anything. My experience so far, with this setup, has my API calls responding on average ~200ms, with some exceptions around cold starts on the lambda functions.

Here is my best explanation, hopefully someone will correct any mistakes I make in here.

  1. Define your domain in Route 53
  2. Define the sub domains you want, api.x.com or docs.x.com, and route them accordingly.
  3. Define your wildcard sub domain (reference https://forums.aws.amazon.com/message.jspa?messageID=210564)
  4. Define your cloud formation definition with a wildcard for sub domain (reference https://aws.amazon.com/about-aws/whats-new/2013/09/18/amazon-cloudfront-announces-wildcard-cname-support/)
  5. Make sure you forward the correct headers in your cloud formation behaviors. Your function should receive the domain in the ‘request’ of the event object. This is off the top of my head and could be wrong.

Sorry its not more detailed.

Regarding Auth0, it was a lot easier to implement than I found for incognito. Comes with out of the box login form (though its bulky and big) and with the JWT token the authorizer for your functions is about a dozen lines of code end executes incredibly fast. Incognito you dont need an authorizer for, but maintaining the user identities were not nearly as straight forward, which to me was a greater concern given the ease of configuration for both. Performance is more or less the same across the two IIRC, but its been a while since I compared.