I am interested in the theory about properly securing and integrating Vue CLI app with any generic backend framework using JWT.
Let's get straight to the questions:
Is there something like a response Authorization header which the backend can use to set the token automatically in Axios? (I only found a guide to set it manually from the response body)
Does the browser create a new instance of an app if I refresh and/or reopen a tab? Does this mean that the whole app including custom Axios instance with Authorization header is destroyed and the new one needs to set it once again (from local storage)?
Is Axios with (manually) set Authorization header CSRF safe? The point here is that the header isn't browser provided, but rather app provided (only visible to custom Axios instance in the application), right? So an attacker simply cannot get to the token, right?
And so while he can still make a call, it won't get authorized, right?
Short answers:
No you would need to set the Authorization header manually when you get the tokens, jwt is implemented by the client and server, not the browser
If you store jwt in cookies, you don't have to bother about re-setting the authorization header when the page reloads
Only Cookie-based jwt is vulnerable to CSRF exploits
Related
I'm thinking of a proper pattern for implementing refresh tokens, but on few steps, I have some questions. I am using nextjs with axios on the frontend and express with cookie-session on the backend.
Here are steps I'm thinking of:
Client sends a log-in request. After logging in I put the access token in the session object and the refresh token into res.cookie, both secure and httpOnly.
// for simplicity options are left out
req.session = { accessToken };
res.cookie("refreshToken", refreshToken)
On every request with axios I supply just the access token. Here's where the first question arises. How would I supply only the access token, without sending the refresh token too, if both are httpOnly?
If the access token is valid do whatever is needed. If not, need to get the refresh token and compare it to a stored one, and so on. Here's the second question. While I understand I need to retrieve the refresh token in this step, how would I do it properly?
Any more advice would be great, thanks.
[EDIT] After some thought I realised that making access token not httpOnly would allow me to send just access token, which would solve my problem. But if that is incorrect please let me know.
Here is the standard pattern - as in this code of mine:
Client sends access token (which may be in an HTTP Only cookie)
When it expires they try to refresh the access token by calling a /refresh endpoint
If the refresh succeeds they retry the API request with the new access token
Otherwise the client redirects the user to sign in again
Don't make the access token non HTTP Only, since any malicious code could then grab it from document.cookie.
This also allows you to set a path of /refresh for the RT cookie, so that it is only sent on refresh requests.
Also ensure that cookies containing tokens are strongly encrypted (AES256) using a symmetric key only known server side. This Express library will do the work for you.
Description: I'm trying to set the jwt token at login using
flask_jwt_extended.set_access_cookies and flask_jwt_extended.set_refresh_cookies but the issue is that I cannot set this at the /login endpoint because that is auto created by flask-security. What would be the best way to do this? Would the best way to do this be overriding the /login endpoint and set them there? Or can this be done in the validate method of ExtendedLoginForm even though I would need to add it to a request and not the True or False value that validate requires be returned?
End Result: Use regular cookies (to authenticate) to interact with flask related endpoints. Use JWT tokens (encoded in a cookie) to interact with a react-native compiled code.
My first thought would be to step back - cookies (session) are an easy and secure way to manage all this - why have a JWT that is part of a cookie?
If you really want an Authentication-Token sent with every request - Flask-Security already offers that.
Now - to actually answer your question - You can attach to the "user-authenticated" signal and create your token and cookie there.
I am currently using httponly cookie based authentication to authenticate users through a website. On top of this I am creating a react native app which also has to authenticate users, ideally through the same endpoint. At this point users are able to log in through the app and the cookie is correctly send on each subsequent request using credentials: 'include' (fetch). However, if the app is restarted, the cookie does not persist.
So far my searching has led me to the following possible workarounds:
Manage cookies manually by extracting the cookie through something like webview or react-native-cookies, saving the cookie to storage and manually adding it to each subsequent request.
Implement a new endpoint that returns a token and have two authentication flows, one for the website and one for the app.
Have anyone been in a similar situation? Can you point me in the right direction, so not to over complicate my code base and ensure that I am not vulnerable to XSS or other token/cookie theft.
Thanks in advance.
To be honest I never implemented cookie based authentication in react native. How do you handle cookies now ? Basically the flow should be like this:
You authenticate with username and password.
Server will respond with a header "Set-Cookie: sessionIdExample=1234"
Next time when you make a request you should also send that cookie, meaning you have to set a header "Cookie: sessionIdExample=1234"
From your question I guess you don't manually set that cookie, so most probably the http client is doing this for you. Now when you close the app that cookie value is lost as you said. Notice that switching to a token based authentication won't help with this. So what should you do:
Login with username and password.
When you receive that session cookie persist it. You can check async-storage or the more secure react-native-keychain for persisting data.
For the following requests set the session cookie manually.
When you close the app and then open it again, check in your async-storage or keychain if you already have a cookie saved there. If so, set that cookie and everything should work fine.
I have a Vuejs application created using Nuxtjs. I am also using Django as the backend server, and I made an API to interact with the backend server (Django) and front-end app (Vuejs/Nuxtjs). And any API related fetch are done in the AsyncData function of the page to render the data on the server-side using axios. Also, I am using json web token authentication, and the API generates a jwt token after successful login which is stored in the cookie. So on the backend, it will always check for the request's authorization header for the token. If the request is from a logged in user (authorized token) then return authenticated json data, or else return non authenticated data.
The problem:
When the user navigates to the app, I would like to check if the user is authenticated. If the user is authenticated, render the authenticated page. If not then display non authenticated page.
My thoughts:
When the fetch is done from the App on the AsyncData function, I would check whether there is any value for the cookie. If there is then send the token with the request's authorization header. But, since the page will be rendered on the server first, and not on the client side (where the cookie actually is) it will never find the token for the authorization.
How can I check if the user is already logged in or not so that I can get authenticated and non authenticated data respectively from the API?
Update
When I successfully log in (post authorized email and password), I get a json response back with the token, which I set in the cookie like this:
this.$cookie.set('my_auth_token', this.token, {expires: 15})
How can I retrieve client side cookie and into the nuxt server for server side rendering?
Cookies are exposed in the (Express) Nuxt server through middleware.
Specifically, they can be read from the req.headers.cookie property. You can see an example implementation of this in the Nuxt documentation.
Regarding your implementation: fetching the privileged data from your API using Node would seem to be the ideal way to delegate session handling to that single service (rather than both) and provide SSR for your users.
If you've chosen to instead implement your session handling on the Django service then you'll need to "forward" your cookies by passing them into your axios request headers.
I did something similar using Firebase authentication. There is an example project on Github as well as a blog entry outlining the important files and configuration used in the application.
Since we updated our project to Swift 2 and Alamofire to version 2.0 we observe the following behavior regarding base auth: When we send a request (no matter what kind of) with authentication set, the request is always sent without authentication header the first time. After the backend answers with status code 401, alamofire adds the authentication header and and resends the request once again. We send the request using the following snipped:
Alamofire.request(request).authenticate(user: Config.serviceAuthUser, password: Config.serviceAuthPassword)
Is there a way to force Alamofire to include the authentiation header in every request? We want to avoid this kind of auth challenge for every request to lower network and server traffic. We had one solution working for iOS8, where we added the auth header in the session config of the shared instance of Alamofires Manager as follows:
Alamofire.Manager.sharedInstance.session.configuration.HTTPAdditionalHeaders = authHeader
But with iOS9 this does not work anymore, since only a copy of the configuration object is returned and modified.
Is there another way to avaoid this auth challenge process and force Alamofire to include the auth header with every request?
Making two requests is how the underlying URL Loading System was designed by Apple. The Alamofire authenticate methods simply allow you to provide the credentials to supply to the challenge if it occurs.
If you want to provide the header directly, the use the headers parameter on the request method. Additionally, you could insert the user:password credentials directly into the URL.