This post is going to be a slightly more technical one where I will talk about what authentication is, how it looks like under the hood and what you should consider if you decide (or are tasked) to implement it from scratch.
I decided to tackle this topic after I worked for a while on integrating django-allauth
for my current side-project/startup
Amethyst Platform.
First, let's see what is authentication. A common mis-conception I see around the industry is that people put authentication and authorization in the same bag. But actually, they are two totally different concepts that need to be treated differently.
First, authentication is the process through which you decide on the identity of somebody or something that interacts with your systems. A real person? A script? Are they known? Do they have a real identity? Are they anonymous?
The authentication process is usually split in two: the phase in which the user (if they are a real person) needs to prove their identity (either by providing an email together with a shared secret such as a password, or a code sent on email) and the phase where they receive a temporary proof that their identity is valid and use it in subsequent actions to attach their identity to that action.
More specific, when a user logs in on a website, they usually receive a token that asserts that they successfully logged in and proved to the system that they are indeed who they are. Then, they use that token and attach it somehow to every subsequent request they do (eg. when they click on a link, the token will be sent with the request to fetch the new page) so that the system knows what users did that action. This way, the user is allowed to do certain actions that other users that did not log in can not, and maybe even receive personalized content specially crafted for them.
This can be done in multiple ways, but they can be boiled down to three main categories:
There are more authentication methods out there (eg. biometric data), but the ones from above cover the most common 90% of them. If you will implement an authentication system from scratch, you will most certainly be required to implement one of these methods, or a combination of multiple ones for two factor apps.
After a user successfully proves their identity, they usually get back some uniquely crafted information through which the system can attach the identity of the user to some action that is performed.
I will talk mainly about how this can be done with communcation over the HTTP protocol, in the context of web applications. To better understand the next parts, you should also have a decent knowledge and understanding of how HTTP works (eg. methods/verbs, headers, body).
Sessions
Session based authentication is based on cookies (pieces of information that are automatically managed by the
browser using request headers such as Cookie
and response headers such as Set-Cookie
).
First time a user accesses a web application, they receive a session id which is unique and is stored in a cookie. On the system, there is certain data that is attached to that session id, but it is only visible for the system, it is not publicly accessible.
Once the user proves their identity, on the system, some user identifiable information (such as the internal user ID) is attached to the session id. For subsequent actions, the browser will send the same session id cookie, and the system will know that user "claimed" that session, and attach this user's information to it.
JWT
Javascript Web Token is a method that is similar to using cookies and works on the same principle with the differences:
Authorization
header.The flow works like this:
Authorization
header.The main advantage is that the system can then figure out what user did the request without any database/storage access (where the session data is stored) and can easily verify the authenticity of the token using the signature.
The signature requires a secret signing key which is only known by the server.
The main disadvantage is that JWT tokens can not be revoked, and they are available until their expiration time. This means that you will need to create extra protections to protect against token leaking. If an attacker manages to steal a token from other user, they can use it to impersonate the user until the token expires.
Plain Token
From the user's point of view, this type of authentication is the same as using JWT, with the distinction that the key is not cryptographically secured. The generated token must be saved somewhere using a dedicated storage such as a database or a cache, and must be retrieved every time.
But unlike JWT, they can be revoked. If a token can not be found in storage, then it is invalid, and the access is denied for the request.
Other
There are other types of authentication methods as well, such as Basic Authentication where the username and password
are sent in the Authorization
header encoded in base64 but it is insecure in untrusted environment and if it must
be used, it has to be over HTTPS. Base64 encoding offers absolutely no protection and you can consider that the
credentials are basically sent in plain text.
I hope this post was interesting to read, and thank you for bearing until the end. I hope this information will aid you in choosing an authentication flow suitable for your app, or if you are not building anything at the moment, aid you in learning new things.
If you enjoyed it and learned something new, or think you have people in your network that would like to read this, don't hesitate to share! It would mean a lot!