Token rotation refresh implementation how to persist token? - node.js

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.

Related

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.

Securely handling refresh token on a Vue application

I have a server backend that provides an access token and a refresh token when a user login is successful, and I want to store them somehow in the client's browser. For the access token, since it's short lived, I can store it in the browser's local storage, without having to worry too much. But for the refresh token, I'd like to set a more secure flow.
I've read this article fragment: Sending refresh token as an HttpOnly cookie, and using a cookie sounds like a safer approach to me, obviously not perfect though, so what I want to do is send the refresh token as a HttpOnly cookie to the Vue application.
So after logging in, for example, I'd like the server to set up that cookie and make the client include it with every request sent to the backend (is that how it should work?).
The problem I think I have, correct me if I am wrong please, is that since only the browser and not the javascript has access to that HttpOnly cookie, I can't make the library I use to make the requests (axios) to send the set refresh token alongside its future requests as a HttpOnly cookie as well.
How can I make that flow properly? Did I misunderstand something about how these cookies work?
Thank you in advance!

Safe Keeping Oauth Tokens in a Cookie?

I have been keeping my 3 legged auth tokens and the refresh token in cookies so then I can transfer them after reload. I am on localhost so I didn't have to think about security but soon enough I will be putting my web application on the internet. I know that you should only have a token with viewables:read as the only scope to prevent any snooping of the user's data. Can it be safe if I encrypt the token with my own encryption method or should I keep the token in a mySQL session on the server side? If I should make mySQL session, can someone give me a link to a tutorial on the mySQL session parser npm extension? I haven't got it to work in the past. Thanks.
If you have a 3-legged token that will give access only to that user data. If that token is viewables:read the user will be able to view his/her models, nothing else. You can use proxy on Viewer to avoid sending it to the client, see a NodeJS sample.
The refresh token is useless to that user, to actually refresh it the ID & secret are required (and the secret should be hidden, the ID can be exposed for BIM 360 provisioning, for instance).
Assuming the browser is not compromised and your cookie is configured to use only https, then the cookie is only exposed to the website that created it and protected during transfer.
I use cookie-session on my sample apps, like this.

JWT Refresh Token

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.

Node Js refresh auth token

How can you provide example for refresh node js auth token? I mean by what the parameters can I refresh auth token? For example if I can refresh it by login and password then where should I store this params for single-page app? As I understand store it in cookie is not good idea for security, localstorage is not good also because some of browsers not supported it. So maybe someone know another way for refresh token?
Cookies are a very secure storage mechanism, if used correctly. Local storage should never be used for authentication information. OWASP has a great write-up on storage security:
https://www.owasp.org/index.php/HTML5_Security_Cheat_Sheet#Storage_APIs
To quote the important parts:
Do not store session identifiers in local storage as the data is always accessible by JavaScript. Cookies can mitigate this risk using the httpOnly flag.
[With local storage] There is no way to restrict the visibility of an object to a specific path like with the attribute path of HTTP Cookies, every object is shared within an origin and protected with the Same Origin Policy. Avoid host multiple applications on the same origin, all of them would share the same localStorage object, use different subdomains instead.
Back to your original question: where to store the refresh token? Answer: In a HttpOnly cookie. This prevents the cookie from being stolen by XSS attacks, and it makes it very easy for your server to issue new access tokens (using the refresh token) because the server will have access to both at the same time, on the same request.
You can add another layer and encrypt the entire refresh token that is stored in the cookie.
Caution: when using cookies, you also need to protect yourself against CSRF attacks
I’ve written at length about front-end security and JWTs in these two blog posts:
Token Based Authentication for Single Page Apps (SPAs)
https://stormpath.com/blog/build-secure-user-interfaces-using-jwts/
Disclaimer : I work at Stormpath, our service gives you a secure, hosted user database with many features. Our express-stormpath module makes it very easy to get started with login and registration flows for your application. We are in the process of writing a new release, and it will be using access tokens in the way that I describe in this answer.
I created AuthToken model that contain these fields:
user_id, access_token, refresh_token, access_token_expiration
After successful user login, server side will send refresh_token and access_token to client side and store it to localstorage(cookies for old browsers).
And all subsequent requests will be sent with access_token(I use header x-access-token for $httpProvider in angular).
When token expires, client needs to send refresh_token for updating access_token, refresh_token and expiration date. Since I use sockets I can refresh access_token if it is expired in any request(for this I send z-refresh-token header also for each request) so I shouldn't send any extra request and I can keep current user request, just will return tokens via socket event after it was updated.
Hope this helps

Resources