I am creating a cookie by using react babel but I am facing a problem. When I create a cookie the cookie created in the browser but when I click on the URL to authenticate then the cookies remove from the browser, and when I create it again, the two cookies with an old one and a new one is created in the browser.
When I delete a cookie and refresh the page the two cookies again created in the browser. I don't understand how is this possible?
I am using this code to create and delete a cookie-
cookies.remove("WebTimeClock", {
path: "/labor-settings",
domain: "localhost",
});
and for create a cookie I am using this-
cookies.set("WebTimeClock", currentUniqueID, {
expires: new Date(dateTime),
});
I am using "react-cookie" for this.
You can set multiple cookies of the same name if you set them against different paths. In your first example, you define the path, but in the second, you do not. Not setting a path will use the existing URL path. If I do this on stack overflow, you can see from dev tools there are now two cookies:
Related
I'm developing a frontEnd using reactJs and axios to get information from an api developed in PHP Laravel.
The backEnd login part takes place in two steps:
1 - I send the user and password in the first route and it returns me a token; - This part is working.
2 - I place the token requested in step one in Berear and send a double-factor authentication code to the second route; - This part is also working
However, after being authenticated, I can't access any more private routes from my server. Then I noticed the need to set it withCredentials: true at the time I create the axios instance (This is necessary because from what I've read this setting exchanges cookies between the front and the back automatically).
So my code looked like this:
export const api = axios.create({
baseURL: 'https://myserver.net.br/api',
withCredentials: true,
})
This configuration above works perfectly when I test my frontEnd using Firefox. But when using Chrome or Edge, it doesn't work.
I found on the forum that the problem could be because I'm running my localhost:3000 front (I don't see much sense because it works in Firefox), so I've tried using 127.0.0.1:3000 and even compiled the front and put it on the server hosting, but it still doesn't work. I can't access backEnd routes when I run front in Chrome or Edge.
Has anyone been through this situation and could you help me? I've been getting beaten for over 3 days on this! :)
Note: When I request the routes via postMan and Insominia, they also work, so it means that the CORS settings on the backEnd are correct.
Do you use a different port for the server and the client? If so, maybe your problem is the same one that I just got.
Do your Chrome and Edge save the cookies?
If not, it is probably because the browsers force use samesite as the default.
If you are using express as the backend, maybe trying to do something like this:
return res
.cookie("access_token", token, {
httpOnly: true,
secure: true,
sameSite: "none",
})
.json({your_data...});
I am still a newbie and just had the same problem, so if I misunderstood the problem, please explain.
Edit:
I just realise that you said you were using PHP, so if there is some option regarding adding SameSite=None to the cookies, maybe try that.
I have a running react web application with protected routes. We are using JSON web tokens. We also using Redux saga. I want to provide a link and This need to be open in a new tab. But when the user logged in and click on the link, the link opens in a new tab but it asks user name and password again. I want to share the current state with the app in the new tab.
How are you storing the JWT? The most common way to do it is to store the JWT in cookies which automatically get sent on every request in the same domain. As long as the JWT is in a cookie, the cookie gets passed to the server, and the server checks for and uses the JWT payload, you should be able to open a new tab just fine.
Backend
I am trying make a JWT cookie based authentication work. I am currently performing the following cookie setting as part of a login route in the backend API.
res.cookie('authCookie', token, {maxAge: 900000, httpOnly: true});
Later when I am auth(ing) any other requests, I am reading off of this cookie and testing it in a passport-jwt strategy.
I have gotten this work in postman - when I perform a login and access a secured route - it works perfectly fine + the cookie is also getting set in postman.
Frontend
Now, I am performing the following call stack in the frontend just to test the working,
axios.post("http://localhost:3001/login", logInParams, config)
.then(result => {
// User is logged in so push them to the respective dashboard
console.log(result);
axios.get("http://localhost:3001/user/profile")
.then(result => {
console.log(result);
})
.catch(err => {
console.log(err);
return;
})
})
.catch(err => {
console.log(err)
return;
});
So basically, I log the user in and that works perfectly fine - I am getting a JSON response as intended, but the call is supposed to set a cookie which it is not and hence the next axios.get call is not returning successfully. Though for some reason I see session cookie and a CSRF cookie. Only this authCookie or the jwt-cookie is not getting set.
Some extra details
I am using cors with default parameters - could this be an error of this? Or is there any changes I have to do with axios? I have seen some answers and being new to MERN I don't really understand them. Does someone know about this or have experienced it and solved it?
Are you running the server from a different port than the one that provides the client (i.e: webpack-dev-server running on localhost:3000 and Express server on localhost:3001)? This looks like a same-site cookie issue. In the latest versions of some browsers such as Chrome cookie setting is being blocked when this one comes from a different origin site. This is due to security concerns; you can learn more about same-site cookies here.
The change made in the browsers is related to the default value they give to a cookie policy property called same-site. The old workaround was treating all the cookies from a different origin as None by default, but last year it changed to consider the same-site policy as Lax when no same-site policy was not explicitly provided by the server. This is a desirable behaviour from the browser because it helps at preventing third party sites making use of the cookie provided by the server, but you can edit it by different ways:
Changing the default same-site policy of your browser settings (the article about same site cookies explains).
Sending a same-site:'None' from the server. Express has a way to do so explaind on its docs. Keep in mind browsers also have a new policy to ignore same-site:'None' when the cookie is not marked as Secure, what demands the use of HTTPS (I guess this behaviour can be edited in your browser settings if you want to check while using HTTP).
Obviously, any strategy that demands the users to change their browser settings is a no-go, so running HTTPS with Secure cookies is mandatory for same-site:'None'.
You always have the approach of making both browser and client same origin, so you won't have any issues at all with same-site (i.e. the Express server returning the index.html of the production build of your client as its main static). I haven't found any way to configure CORS module to have a default same site cookies policy (or its sole use as middleware to change it), likely not its purpose, but you can try by adding a dynamic origin config.
As far as I've seen, Postman does not support the same-site cookie property yet, so that would explain why is it working on Postman but not on the browser.
From the looks of it - it seems to be an issue with how cors works and I am adding the following answer to help anyone else coming across it. Thank me later :)
Server Side
You will have a cors in your server that looks like this,
app.use(cors());
You will have to set credentials to true and set the allowedHeaders and origin as follows,
app.use(cors({
credentials: true,
allowedHeaders: ['Content-Type', 'Authorization'],
origin: ['http://localhost:3000']
}));
This is because normally cookies are not allowed to be set in the browser if the server and the client are in the same port. To handle this the above is required on the server side.
Client Side
We also have to pass the cookies when we are sending the request and to do this with axios just add the following in the index.js of your react app as so,
axios.defaults.withCredentials = true;
I think you should write send('cookies are set') at the end in res.cookie('authCookie', token, {maxAge: 900000, httpOnly: true});
csrf_token and X-XSRF-TOKEN have been added via Angular
$http.defaults.headers.common['csrf_token'] = CSRF_TOKEN;
$http.defaults.headers.common['X-XSRF-TOKEN'] = X_XSRF_TOKEN;
The project is working fine on local server but not in production. I see TokenMismatchException after submitting a form and Auth::attempt() works fine during login. But after login when I access user's id by Auth::user()->id for other route then I see no login user.
I also checked my cookies in local server. I can see XSRF-TOKEN and laravel-session there but in production my cookie list is empty.
Update: Found out that session is not working in my project on server.
Solution
The problem why the Session was not working is that a blank line was present before PHP opening tag(<?php) in a Config file(in my case /config/google-geocoder.php) of my project. That's why Laravel was unable to create any sessions(with laravel's default XSRF-token and laravel-session also) in the cookie list. See #codesidekick's answer from the link which helped me a lot to fix this issue. CSRF - Form Token Doesn't Match Session Token
Why localhost not facing this issue?
I can't tell exactly why but my Local Server has PHP version 5.5.9-1ubuntu4.19 and Production Server has 5.5.30. I think due to some difference in configuration, I faced the problem in production.
List of issues that can generate this problem
During my investigation I found out that there are several issues that may generate this problem. I have also included my one in the list below.
If you see any blank line before <!DOCTYPE html> of your source code from browser then the related files of your page has blank line before opening PHP tag. In this case check for realted PHP files created by you for the page and if there is none then look into default loaded files (index.php, routes.php, config files etc) of Laravel and make sure there is no blank space before PHP opening tag you added mistakenly.
If there is any echo right after data store in session.
If you have any whitespace after your closing tags. See here
If you are only having token mismatch then add token globally <meta name="_token" content="{!! csrf_token() !!}"/> into your header or locally in your form <input type="hidden" name="_token" value="{ csrf_token() }">. For ajax call
$.ajaxSetup(
{
headers:
{
'X-CSRF-Token': $('input[name="_token"]').val()
}
});
Check whether /store/framework/Session has permission to store session because by default Laravel has File typed session. You may try Database session and I saw for some people it worked. You may try also to delete file cache from storage/framework/sessions and storage/framework/viewsSee #gbrock's answer
Some people said to clear cache and restart the server.
When I log into my application I get a cookie with a value of say odm7krain1ms6bic7irfvpsj91 .
as long as I stay on this tab and move through the application I'm "usually" okay. If I open another tab and go the same url, I'll get a new cookie that overwrites the old one and my old session is lost. How can I prevent this from happening?
I've seen this happen when I'm using XHR requests also which effectivly logs me out of my current session.
Try adding the following to your core.php file:
Configure::write('Session.checkAgent', false);
Configure::write('Session.ini',array('session.cookie_secure' => false, 'session.referer_check' => false));
These parameters should force the cookie to persist. This will set both PHP and CakePHP's settings to allow cookies to persist over http and https.
use $_SESSION["your session var"];