I have an app for user authentication and I ran into this issue where I have user who logged in and has the JWT (JsonWebToken) stored in the cookie. I stored the cookie after I validated the user. Next I, as the admin, remove that user from the database while he/she is still logged in. The since user is still logged, the user has a valid JWT in the browser, so it still thinks that it exists because the way I validate if a user is logged in is through the webtoken. I have been thinking about how to fix this but I haven been able to come up with anything yet.
I also posted this issue on GitHub.
Take a look at Invalidating JSON Web Tokens
There are several techniques to invalidate a JWT token before its expiration when the user situation has changed and you can not not remove from localStorage/cookie: account deleted/blocked/suspended, password changed, permissions changed, user logged out by admin:
Token blacklist: Store tokens that were between logout & expiry time, mark expired and check it in every request. You need server storage. You can include only the ID or use the issued time field. Tokens issued before last update of user would be invalid
Expiry times short and rotate them. Issue a new one every few request. The problem is to maintain user logged when there are no requests (for example closing browser)
Other common techniques:
Allow change user unique ID if account is compromised with a new user&password login
Include last login date to remove old tokens
To invalidate tokens when user changes their password, sign the token with a hash of their password. If the password changes, any previous tokens automatically fail to verify. Extend this mechanism with other field of interest to sign. The downside is that it requires access to the database
One way would be to make the cookie expire by settings its expiration timestamp to a date that has already passed.
Related
I am making a react application and using JWT for authentication.
As soon as a user logs in I issue a access token and set a http only cookie named jwt and value is refresh token. As per some articles I have read online it is suggested that access token have a short validity and refresh token have a long validity, so I set validity of access token to be 1 day and refresh token to be 25 days, (numbers are not very relevant). Now as soon as refresh token expires The user is automatically logged out.
Now the app I am developing is a data entry dashboard and I do not want the user to suddenly logout after entering a lot of data even if that happens once a month, so I want to know the industry standard to manage this kind of situation
There is a way to update refresh token without login-password pair:
When a refresh token expires a client have to get a new token pair (access, refresh tokens).
The client sends its access AND refresh tokens and receives a new pair (just like when authenticating with username:password).
You should track expiry of refresh tokens to prevent their reuse.
It is as safe as your flow because when a client gets logged out it understands that someone else already used its refresh token once. So it has to authenticate using username:password and invalidate the last refresh token.
I found an article explaining this flow
Basically I have an SQL table with 3 values, username, password, and a cookie.
dog - cat - a8bfc7ec7a2b0ba10977fddd59fc403d
On login it checks if the username and password match, then it generates a random md5 hash, inserts it into the database then sets it as a cookie for the user.
Once using the site it will check if the cookie matches up with any in the database to verify they are logged in.
How secure is this system?
If I understand correctly, you are using a random md5 just as an ID to identify the client between requests without using his password. This is similar to a session cookie and will have similar security issues.
If you rely only on this cookie, anyone who steal the cookie will steal the user's account. You could extend the verification by fingerprinting the user, checking the user-agent and anything else that is unlikely to change between requests. Note that the IP may change. You could also still ask for the user's password before important actions, such as changing the user's email or password.
Note that it's not very difficult to access the user's cookies, even a browser extension can do it.
I'm developing a hybrid app where the user has the possibility to click "remember me" when logging in with username and password. In case user has only 1 "stored" account it automatically logs him in, but in case he has more than 1 "stored" account, the app shows him the list of the available accounts (like the one when logging into Gmail).
To implement the above behaviour, I have come up with this procedure:
At the first login the username and password are sent to server via HTTPS
If the credentials are correct, the server generates a token with such procedure:
merge username and password hash into a string
hash the string again with SHA and a server secret
substitute the chars in the string
create a N-char string (token) from the string
This token is then sent back to the device and the username and this token are stored to LocalStorage
From now on the user logs in with the username and this token (automatically or when clicking the account he wants to login into)
Would this be secure enough or should I improve something? I'm a bit worried though about storing usernames into LS, but that's the only information I have when showing the user what account he's logging into.
Edit: There can be several different people (for instance family members) logged in the account, because the app controls a device.
For the part about generating tokens you can look into something called JWT. As said on the page JWT is a "method for representing claims securely between two parties", which means you can use it to verify that the user using your page is in fact who he states to be. For the other parts, what you came up with is a preety standard strategy (user signs in, gets token, uses this token to use the app without needing to sign in again).
Simple explaination about JWT since you had a lot of questions:
JWT consists of three parts Header, Payload and Signature. Header and Payload are public (ie. user having the token can read them, they are only Base64 encoded), so don't store secret data inside them (althrough username and password hashed with salt should be fine). When you generate jwt, server calculates hash of header+payload+secret (secret known only to server) and puts it in the signature. Then when user tries to authenticate the signature must match with the data (since server again hashes header+payload+secret and compares it with signature) and only then it is accepted by server. This way without knowing the secret user can't change the data by himself.
JWT also implement "out of the box" one additional feature you might be interested in - expiration time. This way you can automatically logout users if they haven't used the page for certain periods of time. As to refreshing tokens there are a couple of ways and you need to deicide yourself whats the right way for you, Link
Is it a bad pattern or a best practice. Say a user has successfully changed his password after "Forgotten password". Do I need to redirect him to the login page and prompt him to log-in or should I automatically log him in to the application?
If either, why?
I can't imagine any security advantage of requiring him to login after he successfully changed password with forgotten password. However, there may be usability benefits such as: (1) reinforcing in the user's memory what their new password is, and (2) allowing their browser to store the new password so that they do not need to type it in next time they login from that browser.
It is fairly common to redirect the user to login with that new password.
The OWASP recommendation is actually:
Whenever a successful password reset occurs, the session should be
invalidated and the user redirected to the login page.
For more info see this answer:
Password reset functionality is often used when a user wishes to
secure their account.
By invalidating all existing sessions upon password reset, the system
is making sure that only the person with the new password can login.
Say, for example, an attacker that has gained access to the account
using the old password is logged in. Resetting all sessions will log
the attacker out.
This might also be used in a forgotten password scenario if the attacker has managed to update the user's password to prevent login, but for some reason hasn't updated the email to one not under the control of the real user. This could be because updating the email address causes an alert to go to the old address, and the attacker doesn't want to risk creating any unnecessary noise (although it is also good practice to send an email to the registered user upon any password change).
Actual redirection and logout isn't really necessary though. This simply needs the session identifier of the current session to be rotated, and the session identifiers of all other sessions to be revoked. This should prevent access by any attacker riding an existing session. There are a couple of advantages though as detailed in TheGreatContini's answer.
I am integrating FB Login in my website. For this purpose I am using Javascript SDK. Here are the steps which I am trying to follow.
User clicks on FB Login option, user is shown with POP UP by FB to enter his credentials.
FB sends response which includes accessToken, expire time etc.
After this user will see registration form dedicated to my website filled with email and other basic entries. He has to just choose some username and then click on signup.
As soon as user clicks on signup his details will be stored into DB, his username will be kept in session and he is signed in now.
User logs-out. Now, user again clicks on FB Login, if there is email already present in DB I am making the user log into my website by putting his username in session.
Here, are my questions now.
Shall I also store Access Token for the user in my DB in step 3? If yes then what will be the best encryption medium to send it to server-side?
Also, is there a need to store access token in cookie/session?
If answer to my Q1 is yes then will I be able to use the access token stored in DB to validate user if he uses FB Login again?
As far as I know once access token expires Javascript SDK will generate new access token. So, if user logs in after a long time then this validation might not be applicable.
Shall I also store Access Token for the user in my DB in step 3? If yes then what will be the best encryption medium to send it to server-side?
No, if you are not planning to do any automated tasks for the user with your server. In this case you'd need to change the access token to a long-lived token, but that's another thread.
Also, is there a need to store access token in cookie/session?
No, Facebook's JS SDK does all the access token handling for you.
If answer to my Q1 is yes then will I be able to use the access token stored in DB to validate user if he uses FB Login again?
No. You can save the Facebook User ID to your database, which is more constant than the email. Email can change, user id does not. So you should compare the user ID.
And just as a side-note:
Facebook also has a server-side login flow that should be used to authenticate the user. If you just use JS SDK to authenticate the user, it would be relatively easy to log in as any user imaginable from the client.