In a javascript single page application, on first request of the user to the front-end, a cookie is set with Node JS Express.
Credentials are included to requests by adding the "credentials: include" option to Fetch API.
The first render is server-side with React server side rendering.
I can see the cookie in developer tools. It is sent on every request to the front-end, but not to the backend.
Front-end and backend are both node servers. In development they are on differents ports of localhost, (also tried setting a domain in hosts file but no difference). In staging the api server is on a subdomain of the front-server domain. Neither works.
Can they share the same cookie or should I create one cookie for each? I can't seem to set the cookie for the requests to the backend, either because different port in dev or different subdomain in staging.
Ok so I think I figured it out.
Cookies were sent on some requests but not on others. Checking the request method, turns out cookies are not sent when method type is "OPTIONS", which is preflight, and apparently this is normal.
The workaround is to avoid checking cookies if request method is OPTIONS and just send a 200 empty response in this case, so that the real request can proceed, during which cookies will be sent.
Related
I am creating a project for school, and I need to create a backend in spring boot and a frontend in vanilla JS +HTML+ CSS. Since both are on localhost but on different Origins namely on port 8080/5500 respectively ,I am having some issues with CORS in that my cookies are not saved in the browser so no session is created between backend and frontend. This leads to the problem that after login in I will not be able to access securised endpoints because it will require me to log in again since no session is established.
What solution do I have for making this work / saving the cookies?
Further I will give several details and images about the issue that I have.
The backend uses MySQL, spring boot and RestControllers. It basically is a simple CRUD that I also added spring security to. Now this is how my Spring Config looks like
and this is how my CORS config looks like
and this is how my fetch request looks like in the frontend.
Also the request to /save
The flow is as follows : I make a request to /login, than I should be able to use the /save endpoint. This works flawlessly on postman since accessing /save works only after /login was successfully otherwise I get unauthorized, but it does not work in the browser because the cookie that is send with the first response is not saved as below. In the following image the response provides the JSESSION cookie after successfully authentication.
But then when I check cookies section, the cookie is not there.
And when I make a request to the /save endpoint I get the following issue
I also tried the answer over here How to set cookie domain and path with Spring boot but cookies are still not saved.
The browser refuses to allow a URL whose host is [::1] to set a cookie with a Domain attribute of 127.0.0.1. Why? Simply because, even though [::1] is the IPv6 equivalent of 127.0.0.1, the latter doesn't domain-match the former.
Anyway, why would you want to set a cookie with an IP address for the Domain attribute? You seem to be misunderstanding the purpose of that attribute; read what the MDN Web Docs page entitled Using HTTP Cookies has to say about it:
The Domain attribute specifies which hosts can receive a cookie. If unspecified, the attribute defaults to the same host that set the cookie, excluding subdomains. If Domain is specified, then subdomains are always included. Therefore, specifying Domain is less restrictive than omitting it. However, it can be helpful when subdomains need to share information about a user.
In your case, the host of the URL that sets the cookie is an IP address and not a domain. Therefore, specifying a Domain attribute for that cookie is pointless, simply because an IP address doesn't have subdomains.
Since XSRF validation involves matching of cookie/token sent in the UI request with the request header as part of that same request, what are the options for testing locally?
So assuming I run my UI locally and I am pointed to server hosted in a different place, the cookie would never be able to read on localhost (since it is a different host). What is the best-practice in this case - is it adding logic on server to identify the Origin and bypassing the check if Origin is localhost ?
What I usually do in such a case is to use /etc/hosts and use a subdomain for my code running locally. E.g. the UI is run on www.example.com and the server is on api.example.com, then in my hosts file I point www.example.com to localhost.
If the cookies are not samesite cookies and the server has proper CORS settings, then in fact it shouldn't be a problem using them from localhost. Your UI won't have access to them, but the browser should send them together with any request to the server. (CORS should allow credentials and the http client of your UI should use something like a withCredentials: true flag)
I am working with an MVC server with IIS express on port x.
I run my client code using express server on port y, and send my requests for data to the server on localhost:x
The issue here is that the SessionId cookie is not sent back to the server on every request due to CORS.
I read that the cookie will not be sent to a different domain in case the cookie is not set to SameSite->none but in order to set it to None you also need to set it as Secure as i read from here https://web.dev/samesite-cookies-explained/
Is there an alternative in case I want to work with HTTP and i want the client to send the cookies to the server
Well there are 2 possible solutions for this matter:
You can set the cookie as secure + SameSite->None to make the browser automatically send the cookies for every request
You can tell the browser to send the cookies yourself on each request via:
Ajax
Fetch API
I'm developing a web service that have following structure:
Web Server: this is implemented with NextJS which do Server-Side Rendering and serve server-side rendered webpage data to Client.
API Server: and this one is implemented with NestJS. Clients will send graphql queries/mutations to this server.
Client: any clients can visit my web service and sign in (or sign up)
and I want to implement authentication feature for my web server, but problem is came up here. how can I share the auth data between Web Server, API Server, Client? if you signed in on your own browser, eventually a signing request will be sent to the API server.
but there's literally no way to know whether the client is signed in or not from Web Server. I mean, auth data (whether if user has signed in or not) will be stored only at API Server.
I had searched and spent a lot of time about this and I've got an answer that I have to use JWT Token but there were several ways to store it:
Storing it on clients' web storage: I don't think this can be an answer since the Web Server shouldn't able to get clients' web storage data. this means SSR (server-side rendering) wouldn't work well.
Storing it on Cookie: this is bad too. because we send a signing in request to the API Server that will be on different container (or server) and domain. we cannot set cookies from different domain with proper way. and if we get token and store it cookies directly from client side (setting cookie from javascript), It will be really huge security issue since attackers can take users' token with XSS.
Using Cookie but set from other subdomains with specifying Domain: we can specify domain for setting cookie. as far as I know, a response from api.example.com can set cookies for example.com with specifying Domain property of Set-Cookies value. read this
yeah, method 3 seems pretty neat to have but I absolutely don't know that setting cookies from another sub-domains will cause big security hole. my web service will process about users' money so security issues will come very critical.
someone I know advised me that I can use reverse proxy with paths not domain. I mean, if API Server was serving on api.example.com, we can serve it on example.com/api/* so now we can share the cookies between all the server and client. but we should store cookies on web storage too since cookies will be flagged as HttpOnly. this will cause increasing complexity of development.
In this case, which method will be the best answer for my case? are these methods I've mentioned above are really safe to do?
I am building a web application using ASP.NET Web API and SignalR. I have a pretty good understanding of HTTP but this problem is beyond me.
Currently, I am setting a cookie on all AJAX requests to this API. Subsequent AJAX requests to the API send the cookie without issue.
However, I would like this cookie to also be used in the SignalR requests that establish a connection, but according to Chrome, the cookie is not being sent in these requests. I have the cookie set as HTTPOnly. Currently, everything is running locally; all requests go to localhost:port. The domain on the cookie is being set to localhost as well.
My SignalR connections look like this:
var connection = $.connection("/updates");
/* set handlers here */
connection.start(function () {
console.log("connection started!");
});
It seems as if Chrome thinks this is a CORS request and is withholding the cookies. The requests are on the same domain however, so this does not make much sense.
Turns out I don't understand cookies well enough. Browsers seem to have trouble handling TLDs like localhost as the cookie domain. Therefore, I left the domain undefined, so that the cookie will default to the domain of the request.
However, the path parameter needed to be set to / in order to make sure the cookie is sent in all requests.
Once I made these changes, everything worked as expected, and my cookies were plainly visible in SignalR.