Authentication Best Practices in the Web Applications
In my past working with different teams, I have realized that developers (sometimes including me, I am not the perfect guy) do not take the most crucial processes of authentication seriously and because of this, it leaves security vulnerabilities in the application.
In this and my upcoming post on
What is authentication?
Let's understand with a very obvious example what does authentication means in the web application. Suppose you are going to the nightclub to have a beer and the person in charge ask for your identity to confirm your age which is required to enter. Now if you have this and the age is above that of what the government has decided, you are "allowed" to enter the club and you will be stamped on your hand. Whenever you are supposed to "prove your identity" to another party, the process is known as authentication.
Similarly, in the computer world, the client (browser or device) is supposed to prove its identity to the server (the other party) to access the protected resources on the server. To prevent different resources interact with the authentication resource again and again to validate the user identity and its permissions, after successful authentication a serialized identity is returned by the resource which is usually understood by other resources. This way the authentication overhead is avoided and this information is exchanged over multiple resources securely.
How does authentication differ from authorisation?
I see people often confused with authentication and authorisation. Well at some point I also got confused but later it seemed a thin line between these two. Let's take the same club example and explore this.
Suppose you are willing to go inside the club and explore its resources, but you forgot to carry the identity card. In that case, you have no right or access to its infrastructure. One can also say that "Hey you are not authorised to enter the club". Or even though you have passed the first process of authentication, but still there are some areas where only the staff of the club are allowed to enter (like the kitchen or behind the bartender table). So whenever "right to access" comes into the frame, you are talking about authorisation.
If we see from the top, the authentication is also a form of authorisation which will give you right to access the resources that you are initially not allowed to.
Understanding cookies in detail
The session is stored on the server-side and the public identity of the session is saved on the client side every time there is a successful call to the login route. The server instructs the client by sending the
Set-Cookie header in the response with some extra data that instruct the browser on how to store this information.
Let's try sending an authentication request to a live server and see how it responds.
Well as you can see in the response I have the cookie name
PHPSESSID and its value
Once this cookie is set successfully on the browser storage, it is automatically mapped with the current domain name (here authenticationtest.com). So whenever the request will be made to the resources on this domain, the browser will automatically include the cookie name and its value in the
Cookie header which will be then used by these resources to identify the user.
Note: Cookies are also used by tracking services like google ads, facebook pixel and etc. So when you enable anti-trackers on the browser, they simply disallow the browser setting these cookies.
Setting the Expiration Configuration
Max-Age option in the Set-Cookie header tells the browser after how many seconds automatically expire this cookie and delete it from its storage. This is optional because there is also another option by setting the
Expires option which accepts the UTC format of date and time exactly when to expire the cookies on the client-side.
Max-Age is zero or a negative number, it will expire the cookie immediately after storing and when the
Expires option is present along with this, the
Max-Age has more precedence.
Some of the examples of the Set-Cookie header with this configuration are shown below
Set-Cookie: MYCOOKIE=Hello World; Max-Age=60 // This will be expired after 1 minute Set-Cookie: MYCOOKIE=Hello World; Max-Age=-1 // This will be expired immediately Set-Cookie: MYCOOKIE=Hello World; Max-Age=0 Set-Cookie: MYCOOKIE=Hello World; Expires=Wed, 1 Mar 2023 00:00:00 UTC // This will be expired on 1st march 2023 UTC time Set-Cookie: MYCOOKIE=Hello World; Max-Age=60; Expires=Mon, 26 Mar 2018 17:04:05 UTC // The Max-Age configuration will use and the cookie will be expired in 1 minute
Sending the Cookie on a Specific Document Path
Suppose you have two cookies, one is supposed to send on all the requests and another is to be sent on a specific document. How would you control this since they are automatically sent by the browsers? This feature is implemented in the
Path option of the Set-Cookie header.
When the path is only
/, the cookie will be sent for all the requests, but when the valid path exists in the option, it will be only sent if the document location matches with the path in the form of "starts with" regex. Let me explain to you with an example – Suppose the path of the cookie is set to the
/secret, then this cookie will be sent for all the resources starting with "/secret", including /secret/, /secret/doc, /secret/doc/ and so on.
Some of the examples are shown below
Set-Cookie: MYCOOKIE=Hello World; Path=/ // This will be sent on all the resource requests Set-Cookie: MYCOOKIE=Hello World; Path=/secret // This will be sent on all the resource requests whose document location starts with /secret
This option can be used to provide the special permissions (authorization) on the specific path to the specific users.
Sending the Cookies on Secure Connection
When the request is made over a secure connection such as an HTTPS connection whether the network packets are signed by a secure hashing function a certificate, it becomes hard for the attacker to perform a man-in-the-middle attack to read or tamper with the request.
Therefore to provide security from MITM attacks in the network, the server can instruct the browser to send the cookie only if the request is made in a secure environment under HTTPS. This can be done by providing
Secure option in the Set-Cookie header as demonstrated below
Set-Cookie: MYCOOKIE=Hello World // This will be sent on requests made in both Http and Https connection Set-Cookie: MYCOOKIE=Hello World; Secure // This will be sent only on requests made in Https connection
Allowing Only HTTP Requests to Read Cookies
document.cookie and which contains your proof of identity of the website and use it to perform actions on your behalf.
Need not worry, the browser got you covered. You can set a
Set-Cookie: MYCOOKIE=Hello World; // This can be accessed by document.cookie API Set-Cookie: MYCOOKIE=Hello World; HttpOnly // This can only be accessed while making http connections Set-Cookie: MYCOOKIE=Hello World; HttpOnly; Secure // This can only be accessed while making secure http (https) connections
Best practices for the developers
- The users do not log out of the application and the sessions are kept on the login state. Make sure that there should be an expiration for the cookies or tokens. This will prevent the infinite login time for the user reminding them to log in to the applications. I would recommend you having 7 - 14 days of expiration time
- The users often rely on the external password manager like 1Password or browser built-in features. This helps them to use strong passwords without remembering all of them. The forms with proper names and inputs should be used so that password managers recognise them and automatically save and fill them. This will remove time to enter the password which can be seen by someone (kind of eavesdropping)
- When the user clicks on the logout button, the backend request should be made to invalidate cookies, tokens. This is a step ahead of security measures for the first point. Just in the case through XSS the cookies are stolen, it should be invalidated in the backend (associated session) so that it now becomes useless for the attackers.
- Even if you think the information is not as sensitive, always encrypt the cookies to a specific algorithm and same as decryption logic in the server. I would rather recommend you use a hashing algorithm and associate the user id with it on the sessions table. When the cookie is present in the protected resources, try to get the user from user id associated with that cookie hash.
- Apply rate-limiting to the requests brute-forcing cookie header to avoid accidentally guessing the correct cookie for a user on your application.
- Use of
Securecookies are 10 times more secure than other cookies as it allows the browser to send the cookies only when the HTTP connection is made to that domain and document and secure will ensure that the protocol is secured by TLS so that there is no chance of MITM attack
Note: If you have any more of them or want to improve the existing, send me an email about it.