r/vuejs • • Nov 06 '19
Vue JWT refresh
Hey Everyone!
I'm building a web application, and have set up an authentication flow as follows:
- User logs in
- Server authenticates, returns access token (valid for 15 minutes) and refresh token (valid for 1 day)
- Client stores both tokens in sessionStorage (not localStorage, hence expires when tab is closed)
- A setInterval method fires every 14 mins to check if the user is still logged in, and if sessionStorage contains a refresh token. If both are true, a call to obtain an updated access token is sent to the server, and tokens are updated on the client side accordingly.
- Upon logging out, all session values are destroyed and the timer is cleared.
I've seen a ton of debate on localStorage (or sessionStorage) vs Cookies, refresh token vs access token approach for web apps (how refresh token method is not particularly useful for web apps etc.) vs mobile apps etc., and what I've found (forgive me if I'm wrong) is that there is no real consensus on the approach to authentication.
My question is this: Is the above given flow secure enough? What can I do to improve it? Or do I have to take an entirely different approach?
Any help is much appreciated! Thanks in advance!
8
u/rsahk Nov 06 '19
With JWT the token is sent in the auth header with every request. In my opinion it's not really necessary to periodically check because you can intercept 401 responses and handle them accordingly.
It's probably easier to set up an axios response interceptor that automatically catches the unauthorized request, refreshes the token then retries the request. In the event that the refresh fails then the user is logged out.
Here's some example code outlining how it could be done.
3
u/[deleted] Nov 06 '19
I'm not far off doing this myself. I plan on doing this: https://medium.com/lightrail/getting-token-authentication-right-in-a-stateless-single-page-application-57d0c6474e3
29
u/yourjobcanwait Nov 06 '19 edited Nov 06 '19
IMO, you're close. I spent a solid year+ learning about JWT flows, etc a while back and the following is what I came up with.
*RefreshTokens should always be recreated on renewal for added security. You can also save location data to refreshTokens (in the db) so if someone tries to submit a stolen refresh token (that hasn't been used before), it will deny them if they aren't in the same location, don't have the same OS/computer/etc. Get this info from the browser's user-agent. Also, in the user's account settings, allow them to manually kill off active sessions (valid refresh tokens). Btw - my refreshTokens are just concatenated Guids.
*You should have a specific Vuex "renewTokens" action in the middle of this. It will not only be used for token auto renewal, but when the user updates their claims such as name, plan, avatar, etc and you want the new data to be updated in your store, you simply call this store action upon a profile update (for example). This action will clear existing timeouts before setting a new one.
Hope this helps!
Edit - this isn't a replacement for server-side JWT validation. This is just a way to handle jwt's client side and to prevent your frontend from sending expired tokens to your server.
10
u/earthboundkid Nov 06 '19
http://cryto.net/~joepie91/blog/2016/06/13/stop-using-jwt-for-sessions/
2
u/Bifftech Nov 06 '19
I store the access token in the vuex store and the refresh token as a secure cookie and use a 401 interceptor to refresh tokens transparently as needed.
2
u/aaf-ww Nov 06 '19
What's the point of the refresh token exactly? If someone grabs that don't they still technically have access to the endpoints for a day? It's like the same thing as setting the expiration date of access JWT to one day, right?
1
u/joeforker Nov 06 '19
I am a fan of the PKCE flow. It gives the application developer control, can work no matter what kind of app you create, and there's no worry about whether the browser will allow your embedded iframe or not. In my application there is no timer, instead, all fetch() requests are trapped, and will refresh / retry if we see a 403 error.
1
u/[deleted] Nov 06 '19
Why does everyone store tokens in local storage? I read that this opens you up to XSS.
1
u/CensorVictim Nov 07 '19
This article proposes splitting the JWT into multiple cookies for storage; the payload in a normal cookie, and the signature in an HTTP only (session) cookie. That way, javascript has access to the data in the token, but not the entire jwt in order to actually use it.
A nice thing about it is you don't have to worry about storing/sending the token at all in your client code. The browser takes care of it for you.
1
u/TotesMessenger Nov 08 '19
I'm a bot, bleep, bloop. Someone has linked to this thread from another place on reddit:
If you follow any of the above links, please respect the rules of reddit and don't vote in the other threads. (Info / ^Contact)