The first (and probably one of the most important) parts of every multi-tenant SaaS application is identity management. This is because the main idea of multi-tenancy is that a user belongs to one (or more) tenants. The separation of the user-tenant concept is one of the most important aspects of multi tenant applications, where several users (with different roles and permissions) can control the same application (tenant). Let’s dive into this crucial topic.
While multi-tenancy is great for SaaS applications and end-users, it creates several tiers of complexity for identity management. So as we approach the authentication “challenge”, we’re usually quickly reduced to a checklist of important items (both on the product side and the technical side) that need to be handled. This list is not exhaustive in any way, but these questions always come up sooner or later:
WOW! That’s a lot to think about and to handle.
This series of posts will tackle (using code samples) the main multi tenant identity management SaaS capabilities, from the very basic to the most advanced.
In this first post, we will focus on the very basis of the entire multi-tenant SaaS authentication — JWT authentication. We’ll discuss what JWTs are, their content and token persistence — what you need to know to get a feel of how they work.
JWT (JSON Web Tokens) is the new and de facto authentication method (loved by developers) for several, rather important, reasons. It is an open standard – RFC 7519 – highly trusted as it is digitally signed. JWTS can be signed with secret, public, or private key pairs as per your specific needs and requirements.
In a nutshell, JWT is a token generated by the server which includes several claims and a payload that represents the user and the characteristics of the token (when it was issued, when it expires, etc.). The structure of JSON Web Tokens is fixed and made up of Headers, Dynamic Payloads, and Signatures (xxxxx.yyyyy.zzzzz).
That token is sent to the client upon login and needs to be sent back to each of the servers (or microservices) upon each request, which requires valid authentication. But wait a moment. If the token is visible on the client side (and the client can decode it), what about the security aspect? What is stopping the client from generating tokens and impersonating other users?
The most important attribute of JWT tokens is their signature.
Each JWT token is signed on the back end by a private key that can be verified by clients (and other microservices) by the public key. This basic asymmetric signature method allows us to easily verify that the authenticated user is actually authenticated and not impersonated without the need for maintaining a central tokens database / session management.
And this is one of the reasons we like JWT so much. The rise of microservices created the need to decentralize authentication and verification mechanisms — and JWT based authentication matches this requirement like a glove.
When a user logs into the application, we would want to add to the JWT the notion of the tenant in order to make sure that after the verification of the JWT token, we are in the correct context of the tenant and we aren’t exposing our application to cross-tenant security issues.
So the flow is:
Another issue is the handling of the JWT tokens on our client application.
Multi-tenant SaaS applications are built today using web technologies (and most of them are Single Page Applications as well). So we know that we got the JSON Web Token from the authentication endpoint after the login is done. We know that we need to pass it on each request. And we probably want it to last after a page refresh. Why not save it to the local storage?
Saving your JWT tokens on local storage exposes your application to XSS, which has been a OWASP Top 10 regular for many years. In this case, the attacker (using a malicious code) can hijack the stored token from the localstorage, use it for calling the back end on behalf of the user and actually breach the system.
So, how should we protect ourselves?
Related: OWASP Top Ten Web Application Security Risks
The use of refresh tokens allows us to continuously refresh the sessions and to get new JWT tokens. Using refresh tokens allows us to shorten the lifetime of the actual JWT tokens while the refreshed tokens can actually “live longer”.
Using this approach we can store the JSON Web Tokens in-memory while saving the refresh tokens using http-only cookies. The refresh tokens are not vulnerable to CSRF attacks on form submits because the attacker cannot get the value of the JWT which was returned from the endpoint.
What does the flow look like in this case?
So how will the full flow look upon page load? Because the HTTP-only cookie is persisted via the browser, the flow looks similar by using the same refresh tokens alternative.
In this post, we have discussed how to handle JWT token-based authentication in your multi-tenant SaaS application and how to leverage the use of refresh tokens in order to safely persist your users’ sessions. The next post will show you how to start building a capable back end for securely storing user details and maintaining the user’s activation flows for really robust SaaS applications.