I am building a Nuxt app that uses fastify for the backend API. I am using httpOnly session-cookies for authentication. So far everything works fine but the issue i have is that Nuxt just has a hardcoded cookie timeout of 30 minutes. I have updated this to 24hrs but what i really want to do is have Nuxt refresh the timeout after each request.
I see in my database that the fastify session cookie get updated after each request and the session expiration gets updated after ANY user API request. So, this looks like the backend is functioning correctly but the frontend need to update the auth._token_expiration.local value.
You can see in the config that i manually set the maxAge to 24hrs, cant i have the frontend update the auth._token_expiration.local value automatically when making successful API requests? my token is stored as sessionId
nuxt.config.js
auth: {
redirect: false,
strategies: {
local: {
token: {
required: false,
type: false,
maxAge: 86400 // seconds - 1 day
},
user: { property: false },
endpoints: {
login: {
url: '/user/login',
method: 'post',
withCredentials: true
},
logout: {
url: '/user/logout',
method: 'post',
withCredentials: true
},
user: {
url: '/user/profile',
method: 'get',
withCredentials: true
}
}
},
localStorage: false,
cookie: true
}
},
So i discovered that the sessionId Expires data DOES get updated after each api request, so that is good. To make this function i also had to set the nuxt.config token maxAge to 0. This solved my issues.
Related
in my express i use res.cookie to post a cookie
res.cookie("jwt", token, {
expires: new Date(Date.now() + process.env.COOKIEEX * 24 * 60 * 60 * 1000),
withCredentials: true,
httpOnly: false,
});
res.status(200).json({
status: "success",
user,
token,
});
but when i send a req to that middleware from my react app using axios i find the cookie in the network > headers> set-cookie , but its not sets in the browser:
<form
onSubmit={async (e) => {
e.preventDefault();
const res = await axios.post(
"http://127.0.0.1:3000/api/v1/users/login",
{
email: "na#test.test",
password: "password#",
},
{ credentials: true }
);
}}
>
i also tried to set samesit=None and secure, its works and i can see the cookie in the browser but after refreshing the page it disappears :
res.cookie("jwt", token, {
expires: new Date(Date.now() + process.env.COOKIEEX * 24 * 60 * 60 * 1000),
withCredentials: true,
httpOnly: false,
sameSite:"None",
secure:true
});
Browsers are less and less likely to include cookies over HTTP, instead you should try to only use HTTPS when a browser is involved.
Samesite=none;secure only works over HTTPS and will not be included in requests over HTTP. When you don't include any samesite, the default is then set to Lax (I think) and that means that it will not be included in POST requests to a different site. To do cross-site requests with cookies, you need to set samesite=none;secure and use HTTPS.
As far as I know, when you work with cookies, the backend (express in your case) handle the settings of the cookies in your browser [SESSION], in an another word, you just need to set { credentials: true } in your frontend app, the token that was saved on your browser is logically saved in your DB, so whenever a request coming, there is a check on the DB if the two tokens matches [ the one coming from the req and the one is saved on your DB ].
So mainly, or again as I know it's not gettable in other word if you just need something which is included in your token, just send it explicitly.
so i have a backend which contain an endpoint to set a httponly cookie when the admin login. This is the code :
// Set the cookie
response.cookie("refreshToken", refreshToken, {
maxAge: 3.154e10,
httpOnly: true,
});
response.send(this.UtilsInstance.sendOutput(message.Success, {
accessToken : accessToken,
username : removePasswordFromAdminData.username,
role : removePasswordFromAdminData.role
}));
And this is how the frontend side :
await axios
.post('http://my_url/auth/v1/admin/login/',
{
'username': username.value,
'password': password.value
}, {
withCredentials: true
}
);
Also the kong.yaml
plugins:
- name: cors
route: auth-routes
config:
origins:
- http://localhost:3000
methods:
- GET
- POST
- PUT
- DELETE
headers:
- Accept
- Accept-Version
- Authorization
- Content-Length
- Content-MD5
- Content-Type
- Date
- X-Auth-Token
exposed_headers:
- X-Auth-Token
credentials: true
max_age: 3600
preflight_continue: false
The code runs smoothly without a single error (i got the response), but i cant see the httponly cookie on dev tool after the API being called. What am i missing here?
I have a login system that supposed to save user login into a session.
my back-end is Nodejs(express) and my front-end is Reactjs(with redux).
I'm using axios to send username and password to the back-end. my data get evaluated and user ID get saved into a session. so far so good but if I send a request to another route the user session will be gone.
I looked at some similar problems but got nothing. Here is my code:
This is my express-session
const session = require('express-session');
app.use(session({
secret: process.env.SESSION_SECRET,
resave: true,
saveUninitialized: true,
cookie: {maxAge: 259200000, httpOnly: true}
}));
This is my axios request
Note: I already set base url for url: "signin", the request is going
to http://localhost:5000/signin
axios({
method: "post",
url: "signin",
withCredentials: false,
headers: {
"Access-Control-Allow-Origin": "*",
"Content-Type": "application/json",
Accept: "application/json"
},
data:{
"username": /*username*/`,
"password": `/*password*/``
}
}).then(res => {
if(res.status === 200){
if(res.data.status){
dispatch({type: "LOGGED_IN"}) // just changes the state{authenticated : true}
}else{
dispatch({type: "NOT_LOGGED_IN"}) // just changes the state{authenticated : false}
}
}
})
}
In signin route, after my username and password get evaluated I save user ID into session:
req.session.user = user._id
next()
In the next middleware I still have req.session.user.
I have an API for checking the user session
if(req.session.user){
res.send(true);
}else{
res.send(false);
}
If I make a request to that after login, I get false
When I login and make the request with postman it returns true but with axios I get false
my axios request to that API is :
axios({
method: "post",
url: "checklogin",
withCredentials: false,
headers: {
"Access-Control-Allow-Origin": "*",
"Content-Type": "application/json",
Accept: "application/json"
}
}).then(res => {
if(res.status === 200){
if(res.data){
dispatch({type: "LOGGED_IN"})
}else{
dispatch({type: "NOT_LOGGED_IN"})
}
}
})
OK, problem solved. I set withCredentials to false because when it was true I was keep getting CORS error. If my origins (in cors module setting ) be equal to "*" credentials is not allowed so I changed my origin to my front-end domain and set credentials to true (in cors module setting) and now I'm getting true response.
For the authentication my server (nestjs) sends back a cookie with the token.
This is done like this:
#SetCookies()
#Post("account/signin")
async signin(#Body() dto: LoginDto, #Req() req, ){
const token = await this._authService.signin(req.user);
const options: CookieOptions = {
expires: moment().add(10, "days").toDate(),
signed: false,
secure: false,
sameSite: false,
httpOnly: true,
};
req._cookies = [
{
name: "SESSIONID",
value: token,
options: options,
}
];
}
And it works! At least postman shows me that the cookie was successfully created and send back.
But when Angular calls the API like this:
public signin(dto: LoginDto): Observable<any>{
return this._httpClient.post("http://localhost:3000/account/signin", {
username: dto.username,
password: dto.password,
}, {
withCredentials: true,
})
}
The set-cookie is send back visible in the network tab of the devtools.
Chrome devtools response headers
But the cookie is not stored in on the disk. The user is logged in but no cookie is persisted. EditThisCookie shows nothing and after a reload no cookie is send when a request to the server is made.
In other questions the problem got resolved by setting the secure attribute of the cookie to false, which i already tried.
I have setup cors with credentials = true on the server, without any errors on both sides while signing in.
I read Hapijs's guide on cookies and tried to implement it. In my main index.js file I put the configuration as suggested:
server.state('data', {
ttl: null,
isSecure: true,
isHttpOnly: true,
encoding: 'base64json',
clearInvalid: false,
strictHeader: true
});
And then in my route I set the cookie "data" with some data to test it, like this:
{
method: 'POST',
path: '/create',
handler: function (request, reply) {
reply('hello').state('data', { firstVisit: true });
}
}
When I check under cookies in the chrome debug tool, it doesn't show the cookie. What's strange is that it does reply with hello and it doesn't output any errors either. Does anybody know what I'm doing wrong?
Thanks!
#devinivy from https://gitter.im/hapijs/hapi explained it:
isSecure tells the browser not to honor the cookie if there isn't a secured connection.
So the solution is as simple as making isSecure to false while not on HTTPS (at least for development purposes).