discord-oauth and flask (quart) set-cookie failing - flask

I have a quart (basically flask) web-app that is doing OAuth2 with discord. It seems to be working in the cloud, but locally the set-cookie header that appears in the http response after discord authorizes the user is being IGNORED by the browser.
there is an HTTP response with set-cookie. the next request is the callback uri and it has a different session cookie! This is a serious problem and I'm completely stumped. It only seems to be happening on local host? I've read some about browsers ignoring set-cookie, but I have no domain in the set-cookie field and my path is "/"
Response from discord
session=<cookie_A>; Expires=Thu, 08-Oct-2020 19:22:57 GMT; HttpOnly; Path=/
request for callback url
session=<cookie_B>

Related

Is it possible to set the Expires/Max-Age of an existing cookie with the Set-Cookie header?

I'm trying to have the expiration of an existing cookie on a site update from "Session" to some date in the future using the Set-Cookie header.
I believe my issue has to do with limitations on how browsers interpret the Path directive on the Set-Cookie header but I'm not sure nor can I find a use case quite like mine.
Example use case:
Browser navigates to:
GET / HTTP/2
Host: example.com
Server replies:
HTTP/2 200
set-cookie: PHPSESSID=abcd; Path=/; SameSite=None; Secure
Browser performs action and navigates to:
POST /some/path HTTP/2
Cookie: PHPSESSID=abcd;...
Server replies:
HTTP/2 302
Set-Cookie: PHPSESSID=dcba; expires=Mon, 17-Aug-2020 19:08:24 GMT; Max-Age=7776000; path=/
Location: /somewhere-else
All following requests from the browser contain the updated cookie value:
Cookie: PHPSESSID=dcba;...
Yet, upon inspecting the cookies with the dev tools (or simply closing the browser) I noticed that the Expires/Max-Age of the cookie is still "Session" (tried on Chrome and Firefox).
Is being able to update the value but not the expiration of a cookie through a Set-Cookie header a known/expected behavior? Or is there perhaps something wrong with how it's formed?
For any that come across this question/issue:
I discovered(?) that with each Set-Cookie header received: the browser will update the Expiration/Max-Age of that cookie to "Session" if it is absent but will not update other directive values to anything else if they are absent (such as the Secure flag or the value for SameSite).
This revealed that the underlying issue was that, in the next page, there was a request happening with the Set-Cookie header but did not have any value for the expires/Max-Age directives thus resetting the expiration to "Session", making the solution to ensure every Set-Cookie response header has a deliberate value (or absence) for the expires and/or Max-Age directive.
Explained with raw http, continuing the example in the question:
If the response for say an ajax request comes back with:
HTTP/2 200
Set-Cookie: PHPSESSID=efgh; Path=/; SameSite=None; Secure
Then the browser will update the cookie's value and set its expiration from "17-Aug-2020 19:08:24 GMT" to "Session".
Making the solution, as mentioned before, to ensure that the response contains the correct (or deliberate) value for the expires or Max-Age directive, so the correct response for the ajax call that accidentally set the expiration to "Session" in the example above would be something like:
HTTP/2 200
Set-Cookie: PHPSESSID=efgh; expires=Mon, 17-Aug-2020 19:08:24 GMT; Max-Age=7775900; Path=/

Safari not storing cookie set through Angular HttpClient / XMLHttpRequest

We have an Angular app that makes a request to a resource on another domain (a headless cms api). The flow is as follows:
Spartacus=Angular, OCC=Java backend, Episerver=.Net backend
Call nr 10 looks like this:
getExternalCmsAuthCookie(jwt: string): Observable<any> {
const url = `${this.episerverBaseUrl}/externalauth`;
const requestOptions = {
headers: new HttpHeaders({
Authorization: 'Bearer ' + jwt
}),
withCredentials: true
};
return this.http.post(url, {}, requestOptions);
}
The in the server response we see the header
Set-Cookie: role-token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1NzUxMTE0OTQsInJvbGVzIjpbIkFwaUNvbnN1bWVycyIsIlBhcnRuZXJQb3J0YWxVc2VycyJdLCJ1c2VySWQiOiI4Nzk2MDk0NzkxNjg0In0.Mbvwe5qPIGSvUS-sFzxzPq7PAMed3LJaVeP8hK7eHQI; expires=Sat, 30 Nov 2019 10:58:15 GMT; domain=api.ourepiserver.com; path=/;SameSite=None; secure; httponly
After that all requests to the cms include the cookie and are let through by the server that sends some cms content back. This content can include tags pointing to episerver. This is the reason we need the cookie beause we can't add any custom http headers to resources the browser is downloading through tags.
This is working in all browsers except Safari. There are some duplicate questions (but not as elaborately explaind) but none seems to have any good answers.
Versions of Safari on MacOS 10.14 and iOS 12 have a bug where they will erroneously treat cookies marked with SameSite=None as if they were marked SameSite=Strict. You may be hitting this issue if you are not on the most recent version.
Potentially, this is also just an ITP limitation if you're trying to set a cookie from a third-party domain that the user has never visited in a first-party context.
I would test this by sending a cookie without the SameSite=None attribute to see if it's passed by Safari. If it is, then this is probably a SameSite compatibility issue. If not, it's likely something else.
I'm also assuming your domains are genuinely different sites and not just different origins. e.g. img.example.com and api.example.com are still the same-site. example.com and service.elsewhere.api are cross-site.
If you're hitting SameSite compatibility, you can mitigate this by setting two versions of the cookie or using useragent sniffing. More details on https://web.dev/samesite-cookie-recipes.

what's the difference between request cookie and reponse cookie

http://i.stack.imgur.com/4XK7k.png
i used cookie for login,but sometimes it's mismatched.
Is cookie available for the same domain with each request?
Request cookies are cookies that are created on client side. They are sent to server in Cookie HTTP header in every request matching with cookie domain(ie. .com,.org,subdomain.com) and path (ie. /login, /questions) and protocol(HTTP, HTTPS). So stackoverflow will not receive cookies of facebook.
Server may choose to do something when it receives the cookies or may choose to ignore them. This kind of cookies can be used to store shopping cart type data.
Response cookies are the cookies created on server side. These are sent in Set-Cookie HTTP header from the server to client. HTTP clients (like browsers) are expected to read this header and create cookies contained in the value of this header. Every subsequent request to the server will be made with the these cookies (matching domain/path/protocol). Since server already knows about this cookie it can match from it's cookie store and check if this request is coming from the same host thus providing assigning state to the request. This kind of cookies can be used to validate user session.
Response cookies are sent once in first response from the server and client cookies are sent in every request to the server.
See example server response with cookies
HTTP/1.0 200 OK
Content-type: text/html
Set-Cookie: theme=light
Set-Cookie: sessionToken=abc123; Expires=Wed, 09 Jun 2021 10:18:14 GMT
Subsequent request from client would be something like below
GET /spec.html HTTP/1.1
Host: www.example.org
Cookie: theme=light; sessionToken=abc123
Request Cookie = Cookie You send along with your request.
Response Cookies = Http header name Set-Cookie which basically contains "Request Cookie" value for future requests.

cookie issue with same domain same port but different path

I have a situation where my web application will respond with cookie Rules=abcdefg for each request.
Request 1:
http : //hostname:8080/teja/axftyo (for this request I am setting cookie path as below, response from server)
Set-Cookie: Rules=HCE0F290B77137721C2F6107DD4B62F28;Path="/teja/axftyo"
Request 2:
http : //hostname:8080/teja/bcdefg
I assume that for request 2 Rules cookie should not be sent, but still the browser is sending this cookie in to the server.
How can I achieve the functionality of browser sending different cookies based on the path (/bcdefg) rather by my application name /teja
Thank you.
Cookie paths only work on a directory level. /dir/a and /dir/b are considered to be in the same scope for cookies.
/dir/a/ and /dir/b/, on the other hand, are distinguishable, so you could consider adding trailing slashes to your URLs.

set-cookie header not working

I'm developing a small site w/ Go and I'm trying to set a cookie from my server.
I'm running the server on localhost, with 127.0.0.1 aliased to subdomain-dev.domain.com on port 5080.
My When I receive the response for my POST to subdomain-dev.domain.com:5080/login I can see the set-cookie header. The response looks like this:
HTTP/1.1 307 Temporary Redirect
Location: /
Set-Cookie: myappcookie=encryptedvalue==; Path=/; Expires=Fri, 13 Sep 2013 21:12:12 UTC; Max-Age=900; HttpOnly; Secure
Content-Type: text/plain; charset=utf-8
Content-Length: 0
Date: Fri, 13 Sep 2013 20:57:12 GMT
Why isn't Chrome or Firefox recording this? In Chrome it doesn't show up in the Resources tab. In FF I can't see it either. And in neither do I see it in future Request headers.
See that Secure string in the cookie?
Yeah, me too. But only after a few hours.
Make sure you're accessing your site by SSL (https:// at the beginning of the URL) if you've got the Secure flag set.
If you're developing locally and don't have a cert, make sure you skip that option.
In my case, I had to add this to my response:
access-control-expose-headers: Set-Cookie
I found here that my Set-Cookie header was not accessible to my client unless I added it to the exposed-header header.
Hope this can help someone!
Found related github issue response cookies not being sent that helped.
In my case I am running react app under https (with mkcert tool) and making cross origin fetch request and get response. Cookies of the response is not set until I
specify credentials: 'include' for fetch request
example fetch api
fetch('https://example.com', {
credentials: 'include'
});
Specify these response headers from server
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: https://localhost:3000
Access-Control-Allow-Origin header has value of the url of my react app.
add these attributes of Set-Cookie Header Path=/; HttpOnly; Secure; SameSite=None using http cookies
Hope it helps someone!