Browser fails to set cookies even with Set-Cookie response header - express

I am trying to get my Express backend to set a site-wide cookie on my NextJS frontend, each of which is running on separate virtual machines. The relevant backend and frontend configurations are:
In the frontend, I initate the following HTTP request:
fetch('http://192.168.1.<Express virtual machine>:3000/service', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({...}),
credentials: 'include'
}).then(res => res.json()).then(data => {console.log(data)});
In the backend, the following Express application is running with a global CORS middleware configured:
app.use(cors({origin: 'http://192.168.1.<Frontend virtual machine>:3000', credentials: true}));
app.post('/service', (req, res) => {
res.cookie('token', token, {
secure: false,
httpOnly: false,
sameSite: 'none'
});
res.json({...});
});
Upon initiating the HTTP request to /service, the Cookies section of my frontend application in the Storage (Firefox) or Application (Chrome) tab shows that there are no cookies set. However, in the network tab, the Cookies tab on my HTTP request shows that there is both a response cookie and a request cookie. The response cookie has path property set to '/' suggesting that it should have been set site-wide.

Related

cookie cannot be set due to user preference - withCredentials true, CORS set up

response cookie screenshot
response header
My site is able to save cookies if the frontend and backend are localhost:3000 talking to localhost:4000, but once I deploy them, it's no longer saving the cookies.
I am using Axios and Express to handle the http requests.
Frontend:
const axiosConfig = axios.create({
baseURL: process.env.REACT_APP_baseURL || "http://localhost:4000" ,
withCredentials: true
});
Backend cookie sending:
const token = jwt.sign(
{
user: existingUser._id,
sciper: input_sciper,
role: role
},
process.env.JWT_SECRET,
{ expiresIn: '1d' }
)
console.log("path /login correct")
res.cookie("token", token, {
httpOnly: true,
secure: true,
sameSite: "None"
}).send()
Express setup:
app.use(cors({
origin: [
"http://192.168.43.169:3000",
"http://localhost:3000",
"https://epfl-course-rank.herokuapp.com",
"https://www.coursefinder.ch"
],
credentials: true,
}));
The screenshot says that the cookie is sent, as it's in the response header, but not set by chrome (nor any other browser). If I hover over the yellow "!" button, it says "the set cookie is blocked because user preferences."
So if I change my cookie preferences to allow all cookies, my site works -- it still doesn't save cookie into Applications but at least it logs in and sends with requests.
I know there are lots of questions asked on CORS/Cookie setting already, but I am still lost after reading through dozens of them.
I set the credentials, the requests are sent with credentials as well.
It's also really bizarre that when I set my chrome setting to "allow all cookies", then my site works. Does this mean that chrome considers my cookie as third party instead of first-party?
Any help /explanations would be greatly appreciated.

get CORS problem when ty to get a token in keycloak with vuejs and axios

I trying to access one keycloak with axios in my vuejs app, but I receive the cors error, can someone help me please? (If I make a post from POSTMAN to my keycloak works fine)
I using this code:
const params = new URLSearchParams();
params.append("grant_type", "password");
params.append("client_id", "notas-front");
params.append("username", usuario.value);
params.append("password", password.value);
console.log(params);
const config = {
// withCredentials: true,
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
};
axios.defaults.headers.common["Access-Control-Allow-Origin"] =
"http://localhost:8080";
axios
.post(
"http://localhost:8082/auth/realms/lumera/protocol/openid-connect/token",
params,
config
)
.then((response) => {
console.log(response);
});
and get this error:
but when I look the request I can't find the error:
the OPTIONS returns 200
but the POST dont
Postman doesn't care about Same Origin Policy, browser do. That's why your request is working in Postman but not in the browser.
Access-Control-Allow-Origin is a response header, you can't set it on the client request. And as you can see from the OPTIONS response headers your server is returning: Access-Control-Allow-Origin: http://localhost:8080
In a development environment the best way to solve this is setting a proxy in your vue configuration. Otherwise you should configure the server to allow requests from localhost:8080
Configure Web Origins properly in the Keycloak notas-front client config.

set-cookie returned in response headers, cors origin is not wildcarded, but cookie is not stored in browser

This question has been asked a million times, but I've tried it all and nothing seems to work.
My situation:
I've deployed a node/express backend as a Google Cloud Run service.
I am running my frontend locally, trying to login to my backend in the cloud. Frontend is served on http, backend on https. I have enabled cors on the backend. My config is:
app.use(cors({
origin: 'http://localhost:3000',
credentials: true,
}));
I am using axios, and I have set withCredentials: true:
axios.defaults.baseURL = ApiURL;
const { data } = await axios({
method: 'post',
url: `/api/login`,
data: {
username: this.state.username,
password: this.state.password,
keepLoggedIn: this.state.keepLoggedIn,
},
withCredentials: true,
});
This setup works perfectly when I run my backend locally, but of course there is no cors then. When I try to log in when the frontend is pointed at the Cloud Run service, I get a response from the backend with a set-cookie header as expected, but no cookie ever appears in the Storage > Cookies section of the Chrome dev console as it does with my local backend. There is then of course nothing sent with the rest of my axios requests, which need the cookie.
I've been at this for a full day and its driving me nuts. I'm sure there is something simple I'm missing. Any ideas?

vue-cli frontend not setting CSRF cookie from Sanctum

I am developing a new frontend using Vue to access my existing Laravel 7 app, which uses Sanctum for authentication.
The frontend sits on app.example.com, with the backend being moved to api.example.com. The CORS middleware and Sanctum are properly configured to allow app.example.com, and so far so good.
The GET to /sanctum/csrf-cookie looks fine, however, it doesn't seem to be actually setting the cookies, causing the subsequent request to the API to return a 419.
const config = { withCredentials: true };
const api = process.env.NODE_ENV === 'production' ? 'https://api.example.com' : 'http://localhost:9000';
axios.get(api + '/sanctum/csrf-cookie', config)
.then(() => axios.post(api + '/login', data, config))
.then(response => response.json())
.then(response => { console.log('json', response); });
Console log:
Response headers from /sanctum/csrf-cookie:
No cookies are listed in devtools:
UPDATE 1: Didn't notice this earlier; the warning icons next to each Set-Cookie in the response headers display "This set-cookie's Domain attribute was invalid with respect to the current host url."
Short answer: Ports should not be specified in cookie domain attributes.
Long answer: Laravel Sanctum uses the VerifyCsrfToken middleware to both send and verify the CSRF token, which uses session config values when adding the cookie to the response:
protected function addCookieToResponse($request, $response)
{
$config = config('session');
if ($response instanceof Responsable) {
$response = $response->toResponse($request);
}
$response->headers->setCookie(
new Cookie(
'XSRF-TOKEN', $request->session()->token(), $this->availableAt(60 * $config['lifetime']),
$config['path'], $config['domain'], $config['secure'], false, false, $config['same_site'] ?? null
)
);
return $response;
}
In config/session.php:
'domain' => env('SESSION_DOMAIN', null),
In .env:
SESSION_DOMAIN=localhost:8080
Cookies on the same host ARE NOT distinguishable by ports. Because I had specified the port in the cookie domain, the browser had flagged the cookie as having an invalid domain. Removing the port did the trick.
For me to solve the problem I changed my vue cli host which was 127.0.0.1:8080 to localhost:8080 in browser,and within axios the base url is now http://localhost:7000 which is for laravel api.
after that I then set SESSION_DOMAIN=localhost in .env laravel

CORS issue with Express Server API to Next.js

I have a user authentication server setup using Express and Node.js in my localhost Port 3333 and I am trying to connect to the endpoint in Next.js port 3000 using isomorphic-unfetch for the fetch. I am getting a CORS 401 error, I have done a fair bit of research already but just wanted to know whether it was possible connecting to a Express server on localhosts? I have tried adding "Access-Control-Allow-Origin": "*", "Content-Type": "multipart/form-data" to a header object. The express server has cors setup already.
This function below is called on click of a button.
onLoginClick = async () => {
let header = new Headers({
"Access-Control-Allow-Origin": "*",
"Content-Type": "multipart/form-data"
});
const res = await fetch("http://localhost:3333", {
method: "POST",
header,
body: JSON.stringify({
username: "USER",
password: "PASSWORD"
})
});
}
Error message -
http://localhost:3333/ 401 (Unauthorized)
Response {type: "cors", url: "http://localhost:3333/", redirected: false, status: 401, ok: false, …}
First of all, CORS is configured on the server side. You configure your server to allow calls from specific origins.
In your code, onLoginClick is a client-side code, it runs on the browser, client cannot decide which origin the server should allowed to, that would defeat the purpose of having CORS.
Usually you don't need to change the cors configuration in a Next.js app, because you would be calling the API from the same origin that hosted the client side app.
By default, Next.js only support same-origin for API Routes, if you need to customize it, you can use micro-cors.