A Typical SaaS Application

Hey Folks,

I’m working on a typical SaaS application. There is a user facing page: https://portal.example.com and in internal page for admins: https://admin.example.com. Backend is node.js application. The same backend application is handling requests both for user as well as admin requests.

In auth0 I have two applications, one for clients another for admins. Admins are using internal database, and clients use Google Connect. I had to set identical audience for both applications (the reason will come below).

Added a rule which adds an admin role to the accessToken.

 function (user, context, callback) {
  if(context.clientName === 'ExampleAdmin'){
    context.accessToken[`https://example/roles`] = ['example-admin'];
  }
  return callback(null, user, context);
}

Inside the backend I’m validating and parsing the JWT token using express-jwt and jwks-rsa modules.

jwt({
    secret: JwksRsa.expressJwtSecret({
        cache: true,
        rateLimit: true,
        jwksRequestsPerMinute: 5,
        jwksUri: `https://example.auth0.com/.well-known/jwks.json`,
    }),
    audience: 'https://example.com/'
    issuer: 'https://example.auth0.com/',
    algorithms: ['RS256'],
})

There is another middleware which checks the presence of https://example/roles = example-admin and therefore allows access to all users.

While I’ve got it working I’m not sure if this is the right way of doing things. This should be a pretty common scenario for majority of SaaS applications since the internal admin portal is a must to build a successful business. Here are my questions:

  1. Should there be a separate Admin application in Auth0 or a separate Admin tenant?
  2. Should the audience be different for Admin vs User application?
  3. What is the best way for node.js backend to validate & accept both admin as well as user JWT tokens?

Thanks,
Ruben

Hi @rubenhak

You are on the right track:

You should have 1 API - the audience belongs to the API, not the application. You only have 1 API, that is your node.js backend.

You should have two applications in the same tenant - one for the admin app and one for the user app. Each app should only be enabled for one connection (the internal db for admins, the Google for users).

Each application should request the audience when they authorize.

Since it is the same audience, your code will work for verifying the JWT in the backend. No changes needed there.

John

1 Like

hi @john.gateley,

Thanks for quick response. Things are slightly different. While I have one backend (in reality more, but for sake of this discussion, lets consider one microservice), it is accessible from outside by two different paths:

  1. https://portal.example.com/api/
  2. https://admin-portal.example.com/api/

I that sense they look like two different backends. Why do you think two separate Tenants isn’t a better option? I looked to “jsonwebtoken” npm package and it supports validation of multiple audiences. I guess in this case there would be a need to combine JWKS from two tenants.

Wanted to hear your thoughts on this.

Also, I’m having an issue that once I log in to admin portal, it logs out from the user facing portal and vice-versa. My guess is that they are pointing to same Auth0 domain and one is overwriting token of another one.

Thanks,
Ruben

Hi @rubenhak

You can do two tenants in this case, and it should fix your admin/user login logout problem. There is only one session per tenant, so when you log in as admin, it kills your user session. Having two tenants would solve that.

John

1 Like