JWT Refresh Token - security

A common scenario for user authentication follows these steps:
User registers and logs in using its credentials (username/password)
The server verifies the user's credentials and, if valid, returns an access token and a refresh token
The access token is sent on further requests and, if it is valid, the server responds with the requested resource
When the access token is no longer valid, the server requests the client to provide a refresh token in order to issue a new access token
The server receives the refresh token and two things may happen:
if the refresh token is valid, a new access token is issued to the client
if not, the server requests the user to authenticate
For the client to be able to send the access token in every request, the token should be stored either on browser storage (local/session storage) or cookies, which makes it vulnerable to XSS (Cross-Site Scripting) attacks. This problem may be mitigated if we set a short lifetime to the access token.
My question, however, is regarding to the refresh token. This token should have a long lifetime and since we use it to get new access tokens, it would be a problem if an attacker would intercept it. So storing this token on the client side might not be a good idea, right?
But, what are the alternatives?
Can we store it in a cookie set with the "httpOnly" flag? But wouldn't this make it vulnerable to CSRF (Cross-Site Request Forgery) attacks?
Is it safe to encrypt the token and still save it on browser storage?
Thank you in advance. Best regards!

which makes it vulnerable to XSS (Cross-Site Scripting) attacks.
To clarify, the cookie is only vulnerable to a XSS attack should there be a vulnerability on your site that makes this possible.
Can we store it in a cookie set with the "httpOnly" flag? But wouldn't
this make it vulnerable to CSRF (Cross-Site Request Forgery) attacks?
Although the httpOnly flag cannot be used in some forms of CSRF protection due to the need for it to be accessed client-side, flagging a cookie as httpOnly does not increase the risk to your system in any way - httpOnly is more restrictive.
Is it safe to encrypt the token and still save it on browser storage?
Not really because anyone or anything that can access browser storage can access the cookie value and present it. It doesn't matter what form it takes - encrypted or not - if it can be used directly without an external key. Don't worry about this too much - put trust in the browser to keep this secure, however ensure the rest of your site is as secure as possible.
You are right that the refresh token is viewed as more sensitive than the access token. You can store this in a cookie, however make sure that it is set to httpOnly and has the secure flag set too to ensure it is only transmitted over encrypted HTTPS connections.

Related

Should JWT refresh token and access token travel together?

I'm building a SPA and i needed to authenticate users, so i decided to use JWT tokens.
To secure them on the client instead of using browser localStorage or sessionStorage i used cookies with both httpOnly and secure flags enabled.
With this configuration access token and refresh tokens travels always together.
I'm wondering if this configuration is safe or not, because if the cookies are in some way intercepted from an attacker he has the ability to also regenerate access tokens, since he has the refresh token.
In conclusion, is it the right configuration or there is an alternative way to safe the tokens with cookies without make them travel together?
Or is there any good alternative to safe JWT tokens on a SPA?
You are on the right tracks according to current best practices. When using tokens stored in cookies, aim to follow these practices also:
Encrypted cookies, eg with AES256-GCM
SameSite=strict, to prevent malicious sites from sending the cookie via CSRF
Use a path such as /refresh for the refresh token cookie, so that it is sent less often
Use a client secret for the SPA client, via its backend for frontend, which would be unknown to an attacker
Keep cookies small, ideally by issuing reference tokens to the SPA

Token rotation refresh implementation how to persist token?

I have implemented all of the code to support token rotation/ refresh with one last hitch. How are we supposed to persist the token on the frontend to make authenticated backend calls beyond our login?
My Current workflow goes as follows:
User logs in with email and password and is returned the refresh token and the access token in an HTTP-only secure cookie.
A MongoDB (body) document along with the refresh Token and Access Token in HTTP-only, secure cookies is returned with the response.
Now moving on from here how can we persist using these cookies? Especially since we cannot access these. I am using HTTP-only cookies as that is what is recommended as it is most secure but I am struggling to see how it is possible with only HTTP cookies.
In case anyone stumbles across this. HTTP cookies persist by default. They were not persisting in my case as I had the secure property set to true and I was not over an https connection.

Why does using JWT refresh tokens protect against CSRF during authentication?

I have read a few articles regarding JWT refresh tokens, and how/why they are used. One thing i have seen mentioned here: https://hasura.io/blog/best-practices-of-using-jwt-with-graphql/#persistance and here: https://dev.to/cotter/localstorage-vs-cookies-all-you-need-to-know-about-storing-jwt-tokens-securely-in-the-front-end-15id
is that using refresh tokens mitigates against CSRF attacks. The first article states:
The refresh token is sent by the auth server to the client as an HttpOnly cookie and is automatically sent by the browser in a /refresh_token API call.
Because client side Javascript can't read or steal an HttpOnly cookie, this is a little better at mitigating XSS than persisting it as a normal cookie or in localstorage.
This approach is also safe from CSRF attacks, because even though a form submit attack can make a /refresh_token API call, the attacker cannot get the new JWT token value that is returned.
The second article says something similar:
Although a form submit to /refresh_token will work and a new access token will be returned, the attacker can't read the response if they're using an HTML form
I am struggling to see how this would prevent CSRF attacks as I am thinking the following:
A request to /refresh token from another domain to the users will return new JWT token to the user. I am going to assume this is stored in a HttpOnly cookie (as is done in the first article)
As CSRF does not involve any injection of javascript and the cookie it httpOnly, the attacker can't read the value of the new JWT token.
However, if the JWT token is stored in a cookie again, surely a CSRF attacker can just send another request using this new cookie, with the new JWT token sinde?
If my understanding is correct, I am struggling to see how CSRF attacks are prevented by using refresh tokens. Can someone please explain exactly why refresh tokens prevent CSRF attacks, and why the CSRF attacker can't just use the new JWT the user would receive for future attacks?
It seems to me that the thing that would actually be preventing a CSRF attack would be the use of a sameSite cookie, or maybe using some sort of anti-forgery token.
The new jwt would not be returned from the identity provider as a cookie. That would not make much sense as the client on a different origin would not be able to read it. Instead, the token is passed in the response body, or even the url (usually not the token in that case, but let's not delve into that).
So the idp has its httpOnly cookie to authenticate the user, issues a new token in some way that is not a cookie, and the client stores the token for the appropriate origin (not the idp) in say localstorage. This way, any call to the resource server is not vulnerable to csrf, because the token needs to be explicitly be added from localstorage. The idp can be called by attacker.com to issue a new token ("csrf"), but attacker.com will not have access to the token due to the same origin policy, so it's not exploitable.
Note that even if the new token is returned as a cookie for the idp and read from there by the client, it's still ok, because the idp will do nothing with that token, and the resource server (~api) will not receive it automatically.

Is there any benefit for storing JWT in both a cookie and local storage?

I'm attempting write an authentication system for a node.js api using express. I've noticed that if I am going to use a JWT for authentication tokens, I have two options...
1.) Store the token in a cookie, and add CSRF protection.
2.) Have the client send the token in the Auth Header and add XSS protection.
My question is, is there any benefit to storing the auth token in a cookie, and having the client send it in the Auth Header for authentication? This way if for some reason the CSRF protection fell through, the request would fail if there was no authentication token in the header. Also, if XSS protection fell through, the request would still require the auth token in a cookie. I guess my thought is that this would provide more protection, and the only way it could fail is through a successful XSS attack followed by a successful CSRF attack.
Follow up question: Are CSRF tokens a full proof protection technique against CSRF attacks?
Firstly I recommend that you go through this answer first. I hope I've bern able to address your queries about CSRF and XSS here and why and how we should use cookie.
Secondly, your approach of using localstorage along with cookie is good. The only problem I see is localstorage cannot be used across sub domains. If you use cookie and set the cookie domain as example.com (replace example with your organization domain), it will be valid across all sub domains. Thus a user authenticated by your authorization server can seamlessly login to app1.example.com and app2.example.com. You won't be able to do this with localstorage.

Storing "remember me" cookie and CSRF protection

I've been reading that "remember me" cookies are stored in "httpOnly" cookies, so they are not accessible by JavaScript/XSS. However, "httpOnly" cookies are vulnerable to CSRF attacks because they are sent with the request automatically.
To mitigate the CSRF attack, it is recommended to use the synchronized tokens pattern (have the server generate csrf tokens and crosscheck with the client) .
My question is, if a "remember me" cookie is available, is it possible for a CSRF attack (malicious JavaScript) to make a request and subsequently obtain the csrf token generated from the server? The concern is, if an attack has the cookie as well the token to send with requests, then the security of the app has been compromised.
If this is indeed possible, how could we prevent this?
No, the token cannot be read by another domain due to the Same Origin Policy.
If the request is made server-side to bypass the SOP, then the server isn't getting the token from the victim's browsing context therefore this cannot attack the logged in user (the server could only attack their own user that they used to get the token with).
Therefore, nothing to worry about (as long as you haven't enabled CORS of course).

Resources