'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

enter image description here

enter image description here



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