Cookies not set for cross domain requests
See original GitHub issueFirst check
- I added a very descriptive title to this issue.
- I used the GitHub search to find a similar issue and didn’t find it.
- I searched the FastAPI documentation, with the integrated search.
- I already searched in Google “How to X in FastAPI” and didn’t find any information.
- I already read and followed all the tutorial in the docs and didn’t find an answer.
tldr; Cookies are not set on SPA frontend.
Fastapi version: 0.65.1 Safari 14.1.1
Problem description
I have a SPA frontend at mydomain.com which communicates with a backend at api.mydomain.com. I am using the fastapi cors middleware which seems to work fine except for cookies. When I do a post request with axios
no cookies are set in the frontend. However, it works fine on localhost with slightly different cookie settings (no secure).
EDIT: Sometimes cookies are set for a split second. When I inspect them in the browser I can’t see them but immediately after my signup call which sets the cookie is immediately followed by another call which requires cookies. Sometimes the second call goes through.
Axis config
const api = Axios.create({
baseURL: "URL_BLABLA",
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
withCredentials: true,
})
Fastpi cors config
app = FastAPI(docs_url=None, redoc_url=None, openapi_url=None)
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
app.include_router(authentification.router)
app.include_router(users.router)
app.include_router(queries.router)
Fastapi route
@router.post("/signup")
async def signup_for_access_token(
user_data: UserCreate,
response: Response,
):
access_token_expires = timedelta(minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES)
access_token = "blabla"
response.set_cookie(
key="access_token",
value=access_token,
expires=int(access_token_expires.total_seconds()),
httponly=True,
secure=True,
samesite=None, # bug -> doesn't work, need to set it manually (below)
)
# just adding samesite flag to set-cookie headers
for idx, header in enumerate(response.raw_headers):
if header[0].decode("utf-8") == "set-cookie":
cookie = header[1].decode("utf-8")
if "SameSite=None" not in cookie:
cookie = cookie + "; SameSite=None"
response.raw_headers[idx] = (header[0], cookie.encode())
print(response.__dict__)
return {"msg": "successful"}
output: `print(response.dict)
{'status_code': None, 'background': None, 'body': b'', 'raw_headers': [(b'set-cookie', b'access_token=blabla_accesstoken; expires=Sat, 29 May 2021 08:59:03 GMT; HttpOnly; Path=/; Secure; SameSite=None')]}
=> HttpOnly, Secure and SameSite are set correctly.
I went through all relevant results on google and couldn’t find a solution.
Issue Analytics
- State:
- Created 2 years ago
- Reactions:2
- Comments:9
Top GitHub Comments
As for your “bug” that’s because you use samesite=None (send no value) while the cookie parameters expects “none” as a string, this is not None like the void/null value in Python.
Which domain are you using and are you using https? I use
response.set_cookie(samesite="none", secure=True)
over https in deployed envrionments but when I run it locally over http I must useresponse.set_cookie("cookie_name", "samesite"="Lax, "secure"=False)
.If you use subdomain like ‘dev.example.com’, add domain=“.example.com” in cookie, so the subdomain can access root domain cookie.