Is session authentication more secure than token-based authentication? - security

I've been trying to understand the real differences between session and token authentication.
What I have gathered so far:
In token authentication, nothing is stored in the server side. What this means is, that the actual token includes the password and username, as well as other possible information. And the server just decrypts the token, and then checks whether the username and password are correct. Am I right about this?? If the token includes the password and username, then how can the token still be different everytime?
In session-based authentication, the session token is just a random (unique in time) id, that is mapped to the user in the server side. So that when the server receives the session_id (in cookie for example), it will check whether it maps to any user, and if it does, then the user is authenticated. So the session_id does not contain any user related information, that could be decrypted?
In session authentication, the server will send back the user related information (not password) without encryption (unless https is used).
In token authentication, the server will not send back direct user information, but just the token, which contains the user information, once decrypted?
I have a feeling that I haven't really understood how token and session authentication works. Something is definitely wrong in the statements above.
But, let's play along that the statements would be correct. Then wouldn't session-based authentication be more secure? Because in session based authentication, you do not reveal user password (in browser for example). Since it's just a random id, one cannot get information from it. But this is not the case with Token authentication. Since token authentication contains the password, if someone manages to decrypt it, he will get your password. So isn't the session authentication actually more safe than the token authentication, as it doesn't reveal password nor username information?

Your question has not an absolute answer YES/NO. For example session cookies are vulnerable to CSRF and tokens can be stolen with XSS injection. Both mechanism are also vulnerable to ManInTheMiddle if you do not use HTTPS. Therefore additional security measures are needed usually for each solutions. Depends on your use case.
I guess you are talking about a token mechanism like JWT which is self-contained and protected to alterations because you said
In token authentication, nothing is stored in the server side.
But you are confusing some concepts. I will try to answer your additional questions using JWT tokens as reference. If not, most concepts also can be applied to opaque tokens
In token authentication, nothing is stored in the server side. What this means is, that the actual token includes the password and username, as well as other possible information. And the server just decrypts the token, and then checks whether the username and password are correct. Am I right about this??
The token is issued by server (not client) requiring users to present their credentials and digitally signed with server private key. The token includes an identifier of the principal in the sub claim and other fields of interest like expiration time or issuer. Never the password
When the client send to token to authenticate, the server verifies the signature to determine the authenticity an has not been altered
If the token includes the password and username, then how can the token still be different everytime?
The token does not include the password. The token will be different due to some variant claims like expiration time exp or issued at iat. Also the computed signature will be different
So the session_id does not contain any user related information, that could be decrypted?
Yes, it is a ramdom sequence. Relationship with user server is stored on server
In token authentication, the server will not send back direct user information, but just the token, which contains the user information, once decrypted?
The JWT token includes some user information, but it is not encrypted, it is signed. If you need to hide the payload, JWT also allows to use JWE encryption
But, let's play along that the statements would be correct. Then wouldn't session-based authentication be more secure? Because in session based authentication, you do not reveal user password (in browser for example). Since it's just a random id, one cannot get information from it. But this is not the case with Token authentication. Since token authentication contains the password, if someone manages to decrypt it, he will get your password. So isn't the session authentication actually more safe than the token authentication, as it doesn't reveal password nor username information?
The base approach is wrong. Password is never included in the token. If you do not want to reveal user data you can use opaque tokens or JWE encryption with JWT. The proper solution depends on your use case. See my first paragraph

Sensitive information such as password or items like Social Security Numbers shouldn't be stored in a token.
A typical example of token signing is this
function createToken(user) {
 return jwt.sign(_.omit(user, 'password'), config.secret, { expiresIn: 60*60*5 });
}
Here, we are creating a signed token with the user's details but we are leaving out the password.
I gave a very detailed information about this in this thread How is JSON Web Token more secure than cookie/session?
Check it out. I hope this information helps!

Related

JWT tokens: questions best practices and risk of symmetric keys

First a little background on my use of JWT tokens.
Users (via a web frontend) login to my service through a login HTTP endpoint that includes a username and a password in the request body. Two factor authentication will be added in the future, but can be ignored for now.
The API verifies the login information and issues a JWT token in the response. This token is signed with a symmetric key and includes a userId (UUID) that uniquely identifies the user.
In subsequent API calls, the user includes that token in the Authorization HTTP header as a bearer token. The API verfies the signature of the token and then uses the userId to make sure that the user is authorized by checking the roles of the user (stored in a database).
The token can expire, forcing the user to login again, or they can use a refresh endpoint that verifies the token and issues a new one to bypass logging in each time the token would expire.
What are the best practices for JWT authentication/authorization? Are there flaws with my approach? Is there a risk of using symmetric keys here? I am open to suggestions on better approaches as well.

For user verification, you do need to store data on server side even when using JWT correct?

While I understand how jwt works for authentication, I'm trying to build registration.
Registration has a step that requires verification.
User enters the phone number
Code is sent via sms to user
User enters the code and device is verified
Since it's an API for mobile app there is no session/cookie built in.
I'm wondering if I can not implement cookie like system for mobile. And just make it work with JWT. But I don't have much experience with this.
This is my current flow:
User makes a POST request with Phone #
I respond with JWT (Time:Number)
I also send code via SMS
User sends the code via POST and JWT
Problem:
I don't know if code belongs to user or not, as I didn't save the code in DB.
I can't put into payload as it's just encoded not encrypted. (why is it not encrypted, what's the point of sending plain payload, what's even the point of JWT & didn't signed cookies already do that? they had session string encrypted so you couldn't change session string without invalidating the cookie)
JWT is overcome authentication/authorization mostly in APIs. JWT Access Token/Refresh Token is nothing but a JSON data in an encrypted form. JWTs can be signed using a secret (with the HMAC algorithm) or a public/private key pair using RSA or ECDSA. Key pair using RSA or ECDSA is more preferable as a security point of view. You can check authentication/authorization by decryption JWTs.
JWT token itself contains expiry date, so you can just configure expiration time to it. Access tokens are to check that user is authorized or not. Refresh tokens is necessary to get a new access token, generally used when the old access tokens are expired. Refresh token and Access token both expire but refresh token is long-lived compare to access tokens.
Generally developers use access token only but it is preferable to use access and refresh token both.

does JWT containing userID need verification from the database?

I sign a JWT (JSON Web Token) with userID and iat (issues at) like so
jwt.encode({sub: user.id, iat: timestamp}, jwtSecret);
When I receive a JWT from the client, I decode it to extract the userID. Do I need to validate the userID by checking its existence in the database every time I need to allow the user to access a secure route (see first example)? Or can I just assume that the user is who she says she is, and allow her to access the secure path?
My feeling is that I need to access the database to validate the user on every request, this would be expensive and defeat the purpose of using a JWT.
Your token is signed. If someone changes the token on client side, it would fail validation and the server side framework would reject it. Therefore you can trust your token.
Of course, the jwtSecret should be a secret only known by your authentication server and resource server.
You generate the token only if you trust the user who requested it.
You trust the token as long as it has not expired and can be verified with the secret.
The whole idea of JWT is that can verify the integrity of the claims contained within it. If you can decode successfully the token you can be sure that this token contains information previously encoded by you. For someone to pass malformed data has to also know the secret you use to sign the tokens.
For more information read this.

JWT: How much I can trust to my payloads

suppose I create a jwt token for a user and set a payload as:
['userID'=>1, 'role'=>'user']
In case of using HTTPS and SSL, Is it safe to send role or any other sensitive information via payload? Is it possible for sender to manipulate payload values?
UPDATE: Now I know that JWT tokens are decodable. But because they carrying a signature, any update on the values shall invalidate the token. If you want the payload be totally encrypted, try JWE!
Claims in the payload can not be manipulated with out the key, a common example is admin=false, both the client and server can see that this user is not an admin. If the user was to try and manipulate the token (to become an admin) it would not validate correctly. This is why its critically important you validate your tokens before reading any claims from them.
However you wouldn’t normally put sensitive information (like credit card numbers) in them because the claims are not encrypted however no one should be able to access your token otherwise they would be able to take over your session.
Have a play with manipulating tokens here https://jwt.io/
JWT tokens are digitally signed by the issuer, so they cannot be modified without invalidating the signature.
HTTPS is only required to prevent the token from being stolen.

Token Based Authentication advantages?

In token-based-authentication, some information is encoded into a token and that token is sent to the client (usually as an http-only cookie). The client responds with the same token, and the token is decoded to the server to verify that the client is who they say they are.
I have a couple of questions that I can't google the answers to, so was hoping to get some coherent help :)
Is there anything in the token that ties it to the specific client? i.e. if Alice copies Bob's token then can Alice send authenticated requests to the server?
Given that, is the token actually providing anything that can't be provided with a random token stored on the server database? i.e. my server generates a random UUID, stores a hash of it in a cache with Alice's data, sends it to the client. Client responds with the same token, server looks it up in the cache and gets the credentials.
In other words, is JWT just an expensive way of generating a UUID? (I'm assuming you can't encode all the client data you want into the token and will have to do a database/cache lookup on the server end even with a token).
Yes, a JWT token typically has a number of claims. The Subject claim would typically identify the user that was authenticated. If Alice copies Bob's token, she can use the API/application as if she were Bob. That's why it is important to use https to prevent bearer tokens from being stolen.
'iss' => Issuer of the token (Authority)
'sub' => Subject identifying the principal, typically the authenticated user
'aud' => Audience, the application trying to use the token
'exp' => Expiration, until when the token is valid.
See here for more info on the JWT token used in OAuth 2.0.
The thing that security tokens have over session tokens as you describe is that they can be validated without having to go back to the issuer (or central database). The issuer signs the token with its private key. The application is configured with the corresponding public key and can verify that the token was not compromised without going to the issuer.

Resources