I have a netlify frontend at app.mydomain.com
, and a django ninja REST API at api.mydomain.com
. When I submit to my login endpoint, the api returns successfully with the access key (which I store in app state) and a refresh token in the form of a secure, httponly cookie. I can see this cookie is returned by looking in the response headers in dev tools. The cookie however is not stored by the browser at all, I've gone through numerous other questions/answers and I believe I have implemented everything required, but it's still not working.
My login API call from the frontend is:
await fetch(
AUTH_URL_OBTAIN,
{
method: RequestMethod.POST,
headers: {"Content-Type": "application/json"},
body: JSON.stringify({username: formData.email, password: formData.password}),
credentials: "include",
},
);
On the backend, the cookie is set like this:
response.set_cookie(
key="refresh",
value=refresh_token,
expires=datetime.fromtimestamp(refresh_token_payload["exp"], timezone.utc),
httponly=True,
samesite="none",
secure=True,
path="/api/auth/web/token-refresh",
domain=".mydomain.com",
)
I also have the following settings set (substituting the values in for environment variables):
CSRF_TRUSTED_ORIGINS = ["https://app.mydomain.com"]
CORS_ALLOWED_ORIGINS = ["https://app.mydomain.com"]
CORS_ORIGIN_WHITELIST = ["https://app.mydomain.com"]
CORS_ALLOW_CREDENTIALS = True
The login response provides the access token (which works as expected - I am able to make API calls using this just fine, and have credentials: include
on all fetch
requests) and the response headers are below:
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: https://app.mydomain.com
Content-Length: 661
Content-Type: application/json; charset=utf-8
Cross-Origin-Opener-Policy: same-origin
Date: Thu, 06 Jun 2024 14:06:22 GMT
Referrer-Policy: same-origin
Server: daphne
Set-Cookie: refresh=ey...3uQ; Domain=.mydomain.com; expires=Sat, 06 Jul 2024 14:06:22 GMT; HttpOnly; Max-Age=2592000; Path=/api/auth/web/token-refresh; SameSite=none; Secure
Vary: origin
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
I'm at a bit of a loss at this point - any advice would be very appreciated, thank you!
It has nothing to do with either Django or React. It is the way how you set the cookie.
path
can be set anywhere but accessible only on that path and its child. So you can only see the cookie when visiting the page /api/auth/web/token-refresh
Max-Age
over Expires
since it is less error-prone. This is the quote from MDN page:
Expires
has been available for longer thanMax-Age
, howeverMax-Age
is less error-prone, and takes precedence when both are set. The rationale behind this is that when you set anExpires
date and time, they're relative to the client the cookie is being set on. If the server is set to a different time, this could cause errors.
https
or localhost