'Sending cookies/sessions to subdomains
As the title says, I'm trying to set cookies/sessions on the browser.
To preface:
Frontend: https://www.example.com
Backend: https://api.example.com
Frontend makes a request to the backend, the backend creates a session, and a cookie is sent back to the frontend in the response.
Problem:
The request is successful and the response shows that there is a session, however it was not set. The error message is as follows:
This attempt to set a cookie via a Set-Cookie header was blocked because its Domain attribute was invalid with regards to the current host url.
Research:
Based off this and this, it appears that:
cookies can be shared is that both domains have the same main-domain
Which is the case for my scenario. The main domain is example.com
and the subdomains are www.example.com
and api.example.com
.
In addition, Mozilla official documentation states that:
if a domain is specified, then subdomains are always included
Implementation
The frontend is developed in React and the backend is developed in Python (Flask). Both are hosted Heroku. Domain registrar is with GoDaddy and I'm using Cloudflare as my DNS to re-route traffic and setting the correct domains.
A sample request looks like this:
const headers = {
'Content-Type': 'application/json',
'X-CSRF-Token': csrfToken
};
...
const handleFormSubmission = async e => {
e.preventDefault();
await axios.post('https://backend.com/add-results', { tokenId: tokenId }, { withCredentials: true, headers: headers })
}
And the backend has the following settings:
...
CORS(app, origins=["https://www.example.com"], expose_headers=["Content-Type", "X-CSRFToken"], supports_credentials=True)
...
app.config['SESSION_COOKIE_SECURE'] = True
app.config['SESSION_COOKIE_HTTPONLY'] = True
app.config['REMEMBER_COOKIE_SECURE'] = True
app.config['REMEMBER_COOKIE_HTTPONLY'] = True
app.config['SESSION_COOKIE_DOMAIN'] = 'example.com'
Was wondering if anyone has experienced a similar problem and found a solution. I got the idea of using subdomains from here, but I have had no luck with my implementation.
Here's a screen shot of what I'm getting
Solution 1:[1]
The fix was actually pretty simple:
CORS(app, origins=["https://www.example.com", "https://example.com"], expose_headers=["Content-Type", "X-CSRFToken"], supports_credentials=True)
app.config['SECRET_KEY'] = os.environ.get('SECRET_KEY')
app.config['SESSION_COOKIE_SECURE'] = True
app.config['SESSION_COOKIE_HTTPONLY'] = True
app.config['REMEMBER_COOKIE_SECURE'] = True
app.config['REMEMBER_COOKIE_HTTPONLY'] = True
app.config['SESSION_COOKIE_SAMESITE'] = 'None'
app.config['SESSION_COOKIE_DOMAIN'] = '.example.com'
app.config['WTF_CSRF_SSL_STRICT'] = False
Main changes were:
app.config['SESSION_COOKIE_SAMESITE'] = 'None'
And:
app.config['WTF_CSRF_SSL_STRICT'] = False
SESSION_COOKIE_SAMESITE needed to be 'None' to avoid the default value of 'Lax' which would prevent the cookie from being received and set on the browser.
WTF_CSRF_SSL_STRICT was set to false because the origins of the request and the server needed to be the same (same origin policy). However, I have configured a whitelist of allowed origins in my CORS configuration. That said, I think that covers that case.
Also, I cleared my caches on my browser and the DNS. In addition, I restarted my servers where the frontend and backend were hosted.
Hopes this helps others, cheers!
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 |