JSON Web Token exp time confusion - json

What is a good expiration time for a JWT so that a user will never get logged out unless he cliks log out? Note that the node.js server could be up and running forever

This is not the right way to Do it.
Never make your jwt have too much expiration time. If your token is stolen then attacker will get the more access because this token never expires.
JWT is private key based matching. Until the secret is not changed your source is accessible by that key.
Use refresh_token instead. Which will have expire no expire time.
Use your refresh_token to get new access_token.
You can expire refresh_token based on device also.

Related

OAuth2 Session Timeout vs Session ID Timeout and Refresh Tokens

In my app, I allow my users to authenticate with their existing google, microsoft, etc accounts via OAuth2.
Everything runs smoothly. Upon getting callback to local redirect url, I successfully request and receive bearer token from endpoint. With access token in hand, I then request UserInfo from user info endpoint. I then compare email address in UserInfo JSON object with the email address registered in user record and if they match, I consider user signed in.
Now, my question is regarding bearer token and session timeouts.
Google bearer token looks like it authorizes for 60 minutes; while my server session lasts 30 minutes (I haven't changed the default).
Since user already got successfully authenticated, the session id will remain active and alive while there's activity within every 30 minutes. However the bearer token expiration will have expired after an hour.
I would normally assume that I need to refresh the access token before it expires so long as there's activity within the established server session. However, google does not appear to have a refresh token endpoint.
But even if it did, would it be desirable to do this?
Or since the fact that I have an active session id from an authenticated user is enough to allow access to protected resources while only the session id is 'alive'?
I'm assuming it is, since some websites allow customers to maintain their sessions for days at a time, at which time, bearer token would have expired long before.
And lastly, how long would you recommend I keep my users (customers, really) with an open session? My website is on online store.
Thanks to all!
Your session can be completely detached from Google's session. You should only be concerned whether your session is still active. The validity of the access token from Google is not relevant here. Remember that the expiration time of an access token has, in fact, nothing to do with a user's session at all. E.g. you log in a user using Google. The user authenticates at Google and you get an access token, which is valid for 60 minutes. The user then logs out at Google. Your access token will still be valid until that 60 minutes pass, even though the user logged out from Google, and her session is no longer valid there.
As for the length of the session, this is really up to you. If you know your customers are likely to come back often, and you want to make it easier for them you can even keep a session indefinitely. In such a scenario you should think about security and privacy - if the user leaves their account logged in on a shared computer, how much could it hurt them if someone else manages to use their session after a week or so. If you know your customers are likely to come back every few weeks or months to your store, then it really doesn't matter if you keep the session open for a day or five. Most of them will have to log in again anyway.
So to answer the question of the length of the session you should study the behavior of your users and take into account security and privacy issues.

Is it secure to send username and password in a Json object in the body of a post request?

I am building a web application and my web server is secure, meaning that it uses an ssl cert with the front end to encrypt the connection.
When a user logs in, a JSON object which looks like this is created, and sent to the server.
{
username:"the user's username",
password:"the user's password"
}
On the server this is verified with a hashing algorithm that uses a salt. Once it is verified an api token is created which is valid for a certain amount of time, and is passed back and forth in the header in order to verify the user when requests are being made. Is sending the username and password like this best practice/secure, or is it better to send it in the header?
Lets divide it to many points:
1) you use a valid SSL certificate to secure the communication between the user and the server (It must be valid)
2) Sending the username and password in the body of the POST request is the best practice (Never use GET to send sensitive information such as Credentials)
3) Sending the api token in the HTTP request and response headers is the best practice (Again never use GET to send sensitive information such as session tokens)
So based on the points above, it seems that there is no risk in this implementation but you need to take the following points in your consideration:
1) The time out of the API token should be short in case of idle user. (5 ~ 15 mins are the averages based on the criticality of the application)
2) The length of the API token should be long string approx. 30 ~ 40 characters.
3) The API token generation must be randomized and hard to predict to protect from (session prediction attacks.)
Hope this help you.
What you are describing is basically HTTP basic authentication.
Is sending the username and password like this best practice/secure, or is it better to send it in the header?
In security point of view I cannot think of a big difference whether you send the credentials in the body or in the header. Basically whoever manages to read the clear text message, can see the credentials in both components. The common practice when using the basic authentication is to use the HTTP header though:
Authorization: Basic VGVzdFVzZXI6UGFzc3dvcmQxMjM0
where VGVzdFVzZXI6UGFzc3dvcmQxMjM0 is your base64-encoded credentials. The decoded string in this case is: TestUser:Password1234
It is important to realize that in your case the TLS is the only protection for the credentials in transit so you must identify all the nodes in the communication channel that could potentially expose the clear message. For example if you are using proxies that would terminate the TLS, those proxies are potential vectors for MITM attacks.
If you want to increase the security for the credentials in transit, one option could be to implement asymmetric end-to-end encryption so that you would encrypt the credentials with an authenticated public key on the client-side (e.g. certificate signed by a trusted CA) and then decrypt it at the destination with the private key known only for your server. In this case you would not need to worry too much what happens to the message in-transit.

Invalidating JWTs on Permissions

Do people typically store permissions in a JWT? I've seen example that might have admin: true or scopes: ['add_foo', 'delete_foo', 'read_foo']. And this seems fine, other that the potentially large size that the JWT could become if there are a lot of permissions/scopes. It seems like it would be really useful as you wouldn't need to hit a DB or cache to get the users permissions as long as the JWT can be verified.
My main question though is how these would be invalidated in the event of a permissions change.
For example, sys admin Joe, revokes the 'add_foo' and 'delete_foo' permissions from user Bob, but keeps the 'read_foo' permission. In this scenario user Bob should not have his token entirely invalidated and need to log back in, he should basically be forced to get a new JWT with the new permissions and carry on as normal.
I've seen examples explaining issuing a new JWT in the event of a password change, but the difference here is that sys admin Joe does the update to user Bob. Thus, there is no opportunity in this workflow for user Bob to get the new token immediately.
Most examples suggest for invalidation maintaining a black list of revoked tokens, or changing a DB record ID so the token is no longer valid, or having a per-user secret and changing that.
I see that all of these would work for the revoking of the token and test that its invalid, but how does the user then get a new token? their current JWT is now invalid? Trying to do anything with it should fail.
I've seen mention of a "refresh token". Are these widely use? Are they secure on the web or mainly used for mobile apps where the refresh token is harder to obtain. It seems like it would be reasonably easy to steal a refresh token via browser dev tools or similar and then someone would have access forever to that account until the unauthorized access was noticed and the refresh token revoked.
Maybe in this scenario forcing user Bob to re-authenticate is not such a big deal? Permissions probably don't change too often.
Thanks, Mike.
You can set expiration date (for Web app we are usually using 15 min - 30 min, for mobile 1 week). When you set Issued at claims parameter ("iat"). Then every time when you validate token you should check the token's "age". If it older than 5 min you load data from DB and create new token with current "iat" value.
When permissions change you should invalidate the issued tokens for this user. There are different techniques to use. See Invalidating client side JWT session
But consider that revoking tokens is not a recommended practice because you lose one of the main advantages of JWT: It does not require server storage.
The objective of Refresh tokens, as defined in Oauth2.0, is allow applications to obtain a new access token without re-authenticate
Refresh tokens are credentials used to obtain access tokens. Refresh tokens are issued to the client by the authorization server and are used to obtain a new access token when the current access token becomes invalid or expires,
If the permissions do not change frequently it may be easier to re-authenticate user, and if they change much consider whether they really should be included in the token

JWT (JSON Web Token) if someone sniff the token, could send the same Post?

What happend if someone sniff the network and catch my entire request from my REST with the token? This person could send again the same packet and Impact without any problem right? Of course he's not going to know from which user is that packet, but he could impact anyway right? is this possible? How can lead with this situation?
Thanks!
Matt.
What happend if someone sniff the network and catch my entire request from my REST with the token?
The JWT is the authentication token, so he could impersonate the user.
This person could send again the same packet and Impact without any problem right?
The same packet or any other because if has the authentication token. It is the same case as if the user had lost your username / password
Of course he's not going to know from which user is that packet, but he could impact anyway right?
Yes, he can know the user, it could know simply decoding the 'sub' field of the token. This field, as defined in RFC , identifies the principal that is the
subject of the JWT. The attacker could use your own api to obtain or modify any information to which it has access
is this possible? How can lead with this situation?
Mainly use HTTPS to avoid man-in-the-middle and keep the tokens private. Set also expiration and renew tokens periodically
Of course, the attacker can use the token and get the same access as the victim.
If you want to limit attacker's actions, you need to perform several conditions:
Set expire time of the token as small as possible(5 min, 30 min, nor months neither years).
Use refresh token to get a new token and update refresh token every time you update old token (and when user is logged in, no doubt)
Use https (oh yes!)
Do not store passwords, credit card numbers and any confidential informations in the token ( I'm shure, you know it :) )

Outdated information in jwt token payload

As written in jwt.io "The payload contains any arbitrary information in the form of claims that we as developers find useful for our applications.". So i think it would be convenient to put there username, email, and so on. In this case i have no need to get this information from database or file system during authentication process. It is being touted as an advantage if app is distributed across many servers.
But I see here is one annoying obstacle. What if a payload was changed as a result of changing user account information? All old issued tokens stays valid since a signature is still valid. So i'll get wrong user account information from old token payload.
I missed something in idea behind jwt tokens?
There's an optional claim exp for JWTs that specifies the expiry time after which tokens render invalid and should be rejected by the receiver. The idea behind JWT tokens is that you issue them with an exp timestamp that says until when the information in the JWT is valid.
If your user account information changes on a daily basis, the exp should be no longer than 24 hours ahead of the JWTs issuance time. After that timestamp the sender should go out and get a new JWT before sending it to the recipient so the information in the new JWT is fresh.