How to inject cookies in the Authorization header when they are store in httpOnly - vue.js

I store my token in cookies this way (server side) :
res.cookie('access_token', token. access_token, { httpOnly: true });
Therefore on the client side I could not inject it into the Authorization header since they're stored in httpOnly, anyone has an issue ? Or i'm required to extract the token manually on the server side to put it in the header ?

You can't access HttpOnly tokens from JavaScript, that is the purpose of that attribute.
A better approach is to not handle tokens at all in the browser and instead use the BFF-pattern (Backends for Frontends) as described in this video:
alert‘OAuth 2 0’; // The impact of XSS on OAuth 2 0 in SPAs

Related

Avoid refresh token for authentication when using HttpOnly cookie

I have a solution for an authentication system without using refresh token. Please tell me where are the vulnerabilities of this method.
I assume the following:
Client and Server are on the same domain.
Client is a browser that support HttpOnly cookie.
Client is using a Single Page Application.
The steps are:
User login by making a request to /api/auth with the credentials.
Server authenticate the user and send back a Set-Cookie Header with an HttpOnly cookie containing a JWT.
Client receive and set the HttpOnly cookie. Client also set in Local Storage a variable logged: true.
After sometime User reopen the browser. The Single Page Application check if the variable logged in Local Storage is == true. If so check if it still has the HttpOnly cookie by making a request to /api/check-cookie.
Server respond with true if it find the HttpOnly cookie and it is valid. Otherwise false.
Client, if receive false from /api/check-cookie, will prompt the user with the login.
With this approach the JWT can have a long expiration date and there is no need to keep track of refresh tokens.
Am I missing something?
I like your thinking and had similar ideas, particularly with setting a local storage variable to reflect the state as logged in so I could check that before making a pointless server call to refresh a token that potentially doesn't exist, however, I'm still using the refresh token.
I believe the crux of your issues will be when the user updates on the server side, it won't be reflected on the client side until the user re-authenticates with a new long-lasting, singular token as opposed to when the short-lived access token refreshes, setting the user again with the updated data.

Proper way to do jwt refresh tokens with express

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.

How to send cookies using Hasura

I am using Hasura to interface with a graphql endpoint on my django project using Graphene. I need to ensure that the user has authenticated for all calls to the graphql endpoint. In a typical rest api all you'd need to do is pass a session cookie back and forth and I would assume it's the same process with GraphQL.
I can interface with the graphql endpoint just fine using Postman, first authenticating with a rest endpoint then passing the cookies I received when making calls to the graphql endpoint. When I copy the cookie to hasuras headers I am not receiving any cookies on the backend. This is effectively what I am setting the header to on hasura:
Set-Cookie : session=iLCJhbGciOiJIUzeyJ0eXAiOiJKV1QI1NiJ9.eyJzZXNzaW9uX2lkIjoiMzUzYWI5M2EtZmVmMi00ZjkyLTllYmItYjlmMDM3ODFkNzMwIiwiZXhwaXJlc19pbiI6IjIwMjAtMDUtMTJUMTk6MTM6MDkuOTc5MjA3WiIsImZpbmdlcnByaW50IjoiT3RoZXIgLyBPdGhlciAvIE90aGVyIiwiY3JlYXRlZF9hdCI6IjIwMjAtMDUtMTJUMTg6NTg6MDkuOTg1NzQ0WiIsImlwIjoiMTI3LjAuMC4xIiwidXNlciI6IjYwNjYwMjgyLTI1ZGEtMTFlYS04YjAzLTRhN2I0YjZmMmYyYSJ9.WCm3GbbLXk-2kbhvKSUpNS-8ggHbEHrDi7YPuLtpvik; path=/; domain=localhost; HttpOnly; Expires=Wed, 13 May 2020 02:58:09 GMT;
I am trying to confirm I have cookies by inserting this code into a resolver but all that is printed is an empty dict.
print(info.context.COOKIES)
I am using Hasura in Heroku and running a Vuejs + Node.js application, I'm creating a cookie(HttpOnly, Secure) with a JWT as value, had setup the hasura HASURA_GRAPHQL_JWT_SECRET to:
{"type":"HS256", "key": "secret","header":{"type": "Cookie", "name": "namecookie" } }
Always returnig 'no cookie name in the header JWT', I'm sending a fetch from Vue direct to Hasura, I want to! even if it is unsafe. but it does not work.

Using Firebase for server side authentication

I have Firebase authentication set up on the client side, and on the server side I can take a JWT token and decode the account ID. But how does this work when I want each page load to be authenticated on the server before the page is generated?
On login or each page load, can I simply store the last JWT token into cookies so that I can read them on my server? Aside from that, I don't know how else for my server to get that information aside from each link being an AJAX call.
This seems to be the only way to do it presuming you're using the firebase auth library to decode and verify the tokens on the server and not some kind of JWT parsing library.
Firebase admin includes methods for decoding and verifying id tokens and extrapolating all the information. This prevents cookie forgery and keeps firebase auth as your single source of truth for whether or not a user is authenticated.
for example (in node):
const admin = require("firebase-admin");
admin.initalizeApp({
credential: admin.credential.cert(yourServiceAccountJsonHere),
databaseURL: "http://YOURDATABASE.firebaseio.com/"
});
admin.verifyIdToken("usertokenasastring") //returns a promise
.then(function(decodedToken){
//process the decoded user token somehow
});
Firebase makes a call to your database, and makes sure that that user is logged in and that all the other information in the JWT makes sense, so you don't have to worry about implementing any kind of verification server side.

How do I store JWT and send them with every request using react

So happy right know because I got my basic registration/authentication system going on.
so basically I got this :
app.post('/login', function(req,res) {
Users.findOne({
email: req.body.email
}, function(err, user) {
if(err) throw err;
if(!user) {
res.send({success: false, message: 'Authentication Failed, User not found.'});
} else {
//Check passwords
checkingPassword(req.body.password, user.password, function(err, isMatch) {
if(isMatch && !err) {
//Create token
var token = jwt.sign(user,db.secret, {
expiresIn: 1008000
});
res.json({success: true, jwtToken: "JWT "+token});
} else {
res.json({success: false, message: 'Authentication failed, wrong password buddy'});
}
});
}
});
});
Then I secure my /admin routes and with POSTMAN whenever I send a get request with the jwt in the header everything works perfectly.
Now here is the tricky part, basically When i'm going to login if this a sucess then redirect me to the admin page, and everytime I try to access admin/* routes I want to send to the server my jwToken but the problem is, how do I achieve that ? I'm not using redux/flux, just using react/react-router.
I don't know how the mechanic works.
Thanks guys
Do not store the token in localStorage, the token can be compromised using xss attack.
I think the best solution will be to provide both access token and refresh token to the client on login action.
save the access token in memory (e.g redux state) and the refresh token should be created on the server with httpOnly flag (and also secure flag if possible).
The access token should be set to expire every 2-3 minutes.
In order to make sure that the user will not have to enter his credentials every 2-3 minutes I have an interval which calls the /refreshToken endpoint before the current token expires (silent refresh token).
that way, the access token cannot be compromised using xss/csrf.
but using an xss attack, the attacker can make a call on your behalf to the /refreshToken endpoint, but this will not be harmful because the returned token cannot be compromised.
1- login component send a login request to the API server endpoint
2- server API endpoint returns a token
3- I save the token in user's localStorage
4- all the API calls from now on will have in the header
Example: https://github.com/joshgeller/react-redux-jwt-auth-example
Security update:
As #Dan mentioned in the comment, tokens should not be stored in Localstorage because every javascript script has access to that one, which means third party scripts you don't own could access tokens and do whatevery they want with it.
A better place is to store it as a Cookie with HttpOnly flag.
Since saving the JWT in localStorage is vulnerable to XSS attacks, the other way can be saving it inside a httpOnly cookie but too bad that you cannot do that in frontend, check this post.
The only option you have is to configure your server-side to return you a the JWT in a httpOnly cookie and also accept the token inside httpOnly cookie. You'll also have to think of how you want to deal with token expiry.
NOTE:
While modern browsers support and prevent reading/writing via httpOnly cookies, but I am not sure about old browsers.