Skip to main content
Authentication Tokens and Sessions
Authentication Overview
- Registration
- User sends username and password
- Validate password strength
- Store bcrypt salted hash of the password
- Authentication
- User sends username/password
- Retrieve the stored salt and salted hash for the username
- Salt and hash the provided password
- If both salted hashes are identical, the user is authenticated
Authentication
- With authentication, we want users to be able to:
- Access their private data
- Make authenticated posts to the server
- When you take these actions on a web app:
- The app should verify that you made the request
- Only serve your private data to you
- Do not let anyone else make posts in your name
Authentication
- How does the server verify that you are the one who made a specific request?
- We only have authentication
- Users would have to type their username and password with every single protected request
- No! Terrible user experience
- Some apps make authenticated requests every few seconds to load more content while users doom scroll
- You would not use this app if you have to type your password constantly
Authentication
- Insecure Idea:
Store the username/password in cookies and send them on every request
- Password is stored client-side in plain text
- No! Never store passwords in plain text
- Not even client-side! Don't do it.
- Never trust your users, not even with their own security
- Best case, increases attack surface area since the password is handled much more often in requests
Authentication Tokens
- Instead of authenticating the username/password on every request:
- Issue an authentication token
- When a user is authenticated, generate a random authentication token
- Store [a hash of] this token in your database and mark the username of the account that was authenticated
- Set the token as a cookie for that user
- Whenever a request comes with that token, treat them as the user associated with that token
- By looking up the token in your database
Authentication Tokens
- With authentication tokens:
- We now have a login system! 🎉
- As long as the user has the authentication token as their cookie, they are logged in
- All their requests are authenticated by the server
- You can/should set these tokens to expire
- Expire client-side (cookie expiration)
- Expire server-side (storing an expiration timestamp in your database and ignoring the token after that timestamp)
- The token might expire in years, depending on your application
Authentication w/ Tokens
- Once a token is generated, set it as a cookie
- Now the token will be sent with all subsequent requests
- Use the token to lookup the user
- The possession of the token verifies that this user did authenticate in the past
Authentication w/ Tokens
- Check each request for a cookie with a token
- Lookup the hash of the token in the database
- If the token is found, read the associated username
- Proceed as though this request was made by that user
- If the token is invalid or no cookie is set
- Do not respect the request and return a 400-level response code:
- 401 Unauthorized - User is not logged in
- 403 Forbidden - User in logged in, but trying to do something that they are not allowed to do
- Ensure all sensitive pages/features are secured this way!
- The front end cannot be trusted (NEVER trust your users)
- All checks must be performed server-side
Logging Out
- When a user logs out:
- Invalidate the token
- This needs to done server-side
- Remove the token from your database, or mark it as revoked
- If you see a logged out token again, do not treat the request as authenticated
- If a token is stolen, this allows the user to regain control of their account
- Delete the cookie
- Set it with an expiration date in the past, or max-age of 0
- The browser should delete the cookie
Authentication Tokens
- Authentication tokens need to be random and unguessable
- The token must have enough entropy that they cannot be guessed by an attacker
- Eg. An attacker should not be able to send requests with random tokens until one matches a logged in user
- Generally, there should be at least 2^80 unique tokens that could be generated (80 bits of entropy)
- Since you are generating these tokens, and no human has to remember them, you can simply choose the entropy
- Generate a random hex value of length 10?
- You already have 160 bits of entropy
- Why not generate length 50 and have 800 bits of entropy 🤷
Storing Authentication Tokens
- (Caution: These tokens need to be stored on the server){.yellow}
- These tokens are about as sensitive as passwords!
- Stealing a token and setting a cookie with that value grants access to an account without even needing a password
- Protection: Only store hashes of the tokens
- Anyone with access to the database cannot hijack anyone's Sessions
- With such high entropy, no known attacks can find the tokens given the hashes
Storing Authentication Tokens
- Do not salt auth tokens
- With arbitrarily high entropy, even rainbow tables are useless
- Salting does not add any protection when attacks are already effectively impossible
- Salting would make your job more difficult
- You id a user based solely on their token
- You don't know the salt for a user without looking up their account
- You need to test all users in your database making every request O(n) where n is the number of registered users
- brcrypt is made for passwords. Don't use it for tokens
Cookie Hijacking
- We're now using cookies for authentication
- The possession of the token verifies that this user did authenticate in the past
- What if someone steals your cookies?
- They can authenticate as you without needing your password!
Recall the SameSite Directive
SameSite
- Determines when the cookie will be sent on 3rd party requests
Lax - Cookie only sent when navigating to your page -and- all 1st party requests
- The default setting if
SameSite is not set
Strict - The cookie is only sent on 1st party requests
- ie. The cookie is only sent to your server when browsing your page
None - The cookie is always sent. Requires the Secure directive to also be set
Set-Cookie: id=X6kAwpgW29M; SameSite=Lax
Set-Cookie: id=X6kAwpgW29M; SameSite=Strict
Set-Cookie: id=X6kAwpgW29M; SameSite=None; Secure
SameSite Specifics
- Auth tokens are typically lax, so we must understand the rules of when the token is sent
- All 1st party requests contain lax cookies
- As long as the site making the request is the same as the site that set the cookie, it will be sent
- Here "site" means the protocol and host combination. Not the port
- Example: A request from localhost:5000 to localhost:8080 is considered SameSite
- A 3rd party requests contain lax cookies if it both:
- Is a GET request
- Navigates to your app
- This is a major reason why GET requests should not change the state of your app
- A GET request should only get information
- Since the user is navigating to your app, an attacker cannot see the response