Explore our platform and learn how it can help your application shine.
Learn about modern authentication techniques and best practices.
Learn about access management practices and technologies.
Learn to manage user accounts and access at scale.
Understand multi-tenancy, a foundation of shared computing.
Learn how to design and build successful SaaS applications.
Understand what is required to provide an enterprise-ready product.
Understand the uses and benefits of Attribute-Based Access Control.
Learn how Single Sign On (SSO) can improve security and UX.
Learn about OpenID Connect, an open authentication protocol.
Learn about SAML, a popular SSO protocol.
Learn about our history, our team, and our mission.
In the previous post, we dealt with the persistence of the JWT tokens. We went over how to maintain a secure session with the in-memory approach and the use of http-only tokens for the refresh operation.
But how did we get to a state where the user is able to authenticate in the first place?
How did the user reach a state where he can login? In other words: how do we securely save users on the DB, enabling the user to set his own password, etc?
Today, most SaaS multi-tenant applications include (or should include) an invite mechanism.
The idea is that each administrator on the SaaS account can collaborate with other users and invite them to the SaaS application under a different role.
Sounds familiar, right? We’re all used to getting emails inviting us to collaborate on an account. After we click on the email we land on a “new password screen”, set our new password, and Boom! Our account is activated.
But what happens behind the scenes on this flow?
The flow (which is orchestrated by the backend) for user invite:
Because user flows are very sensitive in terms of security, there are some issues to consider:
Learn first hand how easy it is to get your SaaS enterprise ready.
As you’ve probably noticed, we keep mentioning “hashing”. When discussing the major items related to the activation flows for users on the DB, we’re “hashing” the passwords and activation token on the DB.
But what exactly does it mean?
Why are we hashing? And Is it the same thing as encrypting?
Hashing is a one-way function where data is mapped to a fixed-length value. One of the primary uses of hashing is for authentication use cases.
The idea is simple. Pass a string via a hash function and get an output of hash values.
Seems pretty simple. And the implementation (Node.JS sample below) is very easy as well:
But is it enough?
Let’s assume we have 100 users on the DB. John and Bob both used User123456! as their password.
In that case both of their passwords will be the same on the DB (one-way hash):
John ([email protected]) → d9df80dcfc3a7096ebebc461398a2427Bob ([email protected]) → d9df80dcfc3a7096ebebc461398a2427
So in case John’s password has leaked and the attacker has access to our DB, that means that the attacker can now login on behalf of Bob as well…
How should we protect ourselves? How about adding some salt?
Salt is a term in cryptography which means “adding random data as an additional input to a one-way function that hashes data, passwords or passphrase”.
Most of the use cases we find for salting one-way functions is for safeguarding passwords when storing them on the DB.
Again, this is rather easy to implement (with performance cost) using Node.JS (this sample uses the great bcrypt library):
Running the hashing algorithm using salt now generates the following:
John ([email protected]): $2b$10$pcNJ7bce6yAnVt7Dg.5OUelTWh3lq7bNpyPlP05DqfZJK7Tk2HQFBob ([email protected]): $2b$10$QsLPnQBD3gCKEcdAjPphc.onryQ93ToIvov2WGjDirwGJci06QjKK
Security loophole closed! ????
How NOT to salt
There are a few common errors when using salt mechanisms which you should try to avoid:
One of the more common mistakes would be to use the same salt (either by hardcoding it to the source code OR by generating it once and reusing it).
This brings us straight back to the hashing problem, where we might have salted the one-way function but still all users with the same password will have the same value on the DB. In case of a DB hijack and a password breach, our users will all be exposed to an account takeover.
So the trick, of course, is to use a new salt for every password / token save to the database
An additional common mistake is using salt expressions that are too short. While there is a price to pay in terms of performance, using a short salt exposes the application to brute-force attacks using a lookup table for possible salt values.
Wanna get mathematical? Let’s say we use a salt of only three ASCII characters. This brings us to 857,375 possible salts (95 *95 *95).
Sounds a lot right? But if each lookup table contains only 1MB of the most common passwords, collectively they will be only 837GB, which is not a lot considering 1000GB hard drives can be bought for under $100 today.
So, How to salt properly? Follow the three simple guidelines below and you should be fine:
In this post we discussed how to handle passwords and activation tokens on your multi-tenant SaaS application and how to store them on the database using hashing and salting mechanisms.
At Frontegg, we leverage these methods in order to securely manage these essential SaaS flows using the secured SaaS building blocks we’re developing for our customers. If you have any hashing questions or salt considerations, we’re the guys to ask!