Auth cookie different domain issue - http

I am trying to implement SSO with a vendor, and they require I send a HTTP request. In this HTTP request, there is a custom header for username and password, which is where I pass in the u/p info. If the user is authenticated, then they send back an 'auth cookie'. I'm trying to understand a few things:
What exactly is this auth cookie? Is this a standard thing? or all it means is that its a cookie that has authentication information?
The HTTP request is sent to a domain which is different than mine. i.e., the script that sends the request is on a.com and the URL where I need to send the HTTP request is b.com. The vendor is saying that I am supposed to just 'send' the cookie they return in the response back to the user. This is not working, but I need to understand why - what will the domain of the cookie be? Will it be a.com or b.com? If its b.com, will that work, because the script that is actually making the call will be in a.com, and most browsers don't allow third-party domain cookie. Or is it failing because I am trying to write a cookie with a.com, where the cookie already has data for b.com?

Figured this out. The HTTP returned is just another custom header value, and not a cookie. So, we have to write our own cookie. However, obviously, the other domain doesn't recognise the cookie. So we actually build a reverse proxy in IIS, so that the domain a.com accesses the site through the proxy, called x.a.com, and never see b.com. So the cookie written is recognized by that domain.

Related

Cookie does not persist across redirect in production

I'm building a web application that uses cookies to track the user session. These cookies work flawlessly in development on localhost but they aren't working correctly in production. I suspect this is because I have some cookie settings misconfigured but I'm not sure which.
One thing to note is that the webapp runs at app.goldsky.com and the api runs at api.goldsky.io (note the different TLDs).
The application I'm building uses a tool called WorkOS for user authentication.
The authentication flow is as follows:
User visits website, enters their email and presses the login button
Request is sent to backend (api.goldsky.io)
Backend generates an authentication URL using the WorkOS SDK (of the form api.workos/...) and sends this to the frontend
the frontend navigates to this WorkOS authentication URL and proceeds through the auth flow
If successful, WorkOS redirects the user to my backend (api.goldsky.io/auth/workos/callback)
My backend generates a session token, sets a secure, httpOnly, path=/ cookie with the session token (goldsky_session=...) and redirects the user back to the webapp (app.goldsky.com)
In localhost this all works flawlessly. However, in production I don't see the cookie persist after step 6 completes.
In production, the response to step 5 contains the cookie
however after the redirect back to the webapp, the cookie seems to disappear. Here's the request to app.goldsky.com (the redirect from step 6) and it doesn't have the cookie header.
and just for completeness, here's a screenshot of the cookies for app.goldsky.com - it's empty:
By comparison, the final redirect on localhost contains the cookie:
How come my cookie does not persist after redirecting from api.goldsky.io to app.goldsky.com? Do I need to set the Domain attribute for the cookie? If so, what should I set it to? Maybe this is a SameSite problem?
Turns out I had an nginx misconfiguration issue which was rejecting requests to specific paths. Nginx was only allowing requests to /auth and a few others. My login logic was under /auth but the user query was at /user which nginx was rejecting.

Are all cookies passed in an HTTP request?

I am having trouble understanding how a session is restored via cookies. How do the client know which sessionID cookie to send to the server via the HTTP request the first time? Does the client send all cookies and the server accepts the one that it also knows?
For example, let's say there are websites A and B (both using PHP), and I logged into both websites and then closed my browser. Now I open the browser again and go to site A and see that I am kept logged in. In this scenario, when my browser sends the HTTP request, the cookie whose file name contains the session ID for site A must have been included in the header. However I have two sessionID cookies for both site A and B. As far as I understand, the host name is usually not stored in the cookie, at least in many PHP tutorials of the setcookie() function. How do my browser know which sessionID cookie is for site A? Does the browser just send all cookies to A and let A figure out which is the right one by comparing all the received session IDs with stored session IDs? This does not sound right to me.

How client know which cookies should be send to the server

When I go to the HTTPS server, I can see in Developer tools (or in Fiddler) a request cookies that are send to the server by client. But how client know, which cookies should be sent, if no response cookies are sent by server. At least I canĀ“t see any response cookies in Developer tools or Fiddler.
First up each domain has its own cookies in a cookie jar / cookie store. Whenever a request is made by the browser to the server all cookies in the store for that domain or subdomain will be sent to the server.
secure cookies vs insecure cookies
Secure cookies will be sent only on connections that are made over ssl(https protocol). Normal cookies will be sent on both http and https protocols.
session cookies vs. persistent cookies
session cookies - These cookies persist as long as the browser session is open. This means that Once you have cleared cache or closed the browser they get lost.
persistent cookies - These will persist even if the browser is closed and opened again unless you have set the browser to clear cookies on exit in which case they will behave just like session cookies.
First party cookies vs. Third party cookies.
First party cookies - generated by the domain currently open as main document - this means they have same domain as the one displayed in your browser.
Third party cookies - generated by a different domain then currently opened by the browser(in the addressbar) but which are managed inside an iframe or various resource calls like css, script, media(images, videos or other embedded media)
CORS - cross domain calls via xhttp ajax calls - this case arises when you create a domain requests resources from another domain via xhttp(ajax calls). In this case the browser makes a preflight check to see if the receiving domain accepts queries from the origin domain(origin headers are sent to the domain to check the cross domain policy). The server must necessarily respond with a valid options header and the server may allow identity data which is short for cookie data. If the remote domain has answered correctly with an "Access-Control-Allow-Origin" header that allows your domain or "*" then you are allowed to send cookies via this request. And these will behave just like normal calls.
To read more about cors:
https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
To directly answer the question: the client sends back all cookie data it has for that domain and path.
If you do not see any Set-Cookie header in any HTTP response, it may be because the cookie has been issued by server and stored on your computer before you started looking at Dev Tools or Fiddler. It could have been up to a few days, weeks, even months ago.
In Firefox, if you navigate to about:preferences#privacy and click Manage Data, you can see which domains already have cookies issued and stored on your computer. The Storage tab in Firefox Dev Tools can show you details of all cookies. The expiry of the cookie is determined by the server, using the Expires or Max-Age directive in the Set-Cookie header.
How a cookie first ended up on the client computer:
Client makes its first ever HTTP request to server, e.g. GET www.example.com
Server creates a cookie and sends it back in the HTTP response, e.g. the response headers contains a line: Set-Cookie: sessionID=1234567; path=/; Max-Age=31536000
The client receives HTTP response and stores the cookie in the "jar" for domain www.example.com.
How server uses cookies to identify the client
In subsequent HTTP requests to domain www.example.com, the client sends back all cookies in the jar that matches the path or sub-path. For example, the client wishes to issue a request GET www.example.com/about, sees that the URL is a sub-path of / in domain www.example.com, so it sends the cookie as a line in the HTTP request header, i.e. Cookie: sessionID=1234567.
The server sees the cookie and knows exactly which client made this request.

basic HTTP authentication on subsequent requests

The image below depicts basic HTTP authentication. The client requests /family resource and it is asked to identify itself. It does and now it can access the /family. The client then also asks for /family/photos/kids resource which is in the family realm.
The client already identified itself for /family resource, but not also for /family/photos/kids. They are in the same realm, but the server doesn't know that the same client issued a request. Or does it? How does the server know that this particular client is also allowed to access /family/photos/kids on subsequent request? Is the password and username send on every request after the user has authenticated? Is the client asked for via pop-up for every request he/she makes? Are cookies set upon first authentication?
Basic authentication requires a header sent by client. No cookies or server session
When the client requests a resource, sends the Authorization header
GET /family
Authorization: Basic token
Where token is base64(username: password). Username followed by ':' and password encoded in base 64
If you are requesting a protected resourced from your browser for example a GET request, and you do not provide the header, the browser shows the autenticathion form and remember it for subsequent requests in the same domain

MVC3 Cookie not included in request until after refresh or visiting a second page

BACKGROUND:
I'm using two MVC3 websites for mixed mode authentication. I'm authenticating a person using windows authentication in Site1, and then forwarding that person onto Site2 which uses Forms authentication. My solution was to gather user information in site1 once the user is authenticated via windows auth. I would then write this info to a cookie, and then redirect to Site 2. Site 2 would then use the info found in the cookie to automatically log in the user using Forms Auth. Both applications are in the same domain and should be able to share cookies, however the cookie isn't available after the redirect until the page is refreshed or by clicking on a link in the site (visiting a 2nd page).
Anyway, here's my problem. I create the cookie and then forward the user to Site2 from Site1.
...{cookie created here and added to response}...
HttpContext.Response.Redirect("http://site2.mydomain.com")
When I do this, there isn't a cookie in the request. However, once on the home page of Site2, I can hit refresh, and then my cookie is part of the request and my authentication works.
I need my Response to write the cookie to the client, then get that cookie added in the request, but it seems to skip that when using Response.Redirect...
UPDATE:
I've read that the request will only have cookies included when the cookie exists before the request is made. Since I'm writing the cookie into the response for the request, only subsequent requests will contain the cookie. So, what I need is a way to force a second request, once they get my response from the initial request. So...
User sends request ---> response returns with cookie ---> force another request (should contain cookie) ---> return requested page.
Can I do this using javascript? Can the javascript check the response for a cookie of a certain name, and when found, cause a redirect to the current page?
If you have to force the refresh to get a second request, you could perhaps append a Query String parameter from Site1's redirect HttpContext.Response.Redirect("http://site2.mydomain.com?refresh=1"), then in Site2, cause a redirect to the same page sans query string parameter.
That's not really ideal though. Could you put that cookie information into a query string for a one off authentication URL that then stores a new cookie and redirects to Site2's homepage?

Resources