Reputation: 159
I have an application based FastAPI Which serves as the backend for a website And currently deployed on a server with an external IP. The frontend is situated at another developer, temporarily in local hosting. At the beginning of the work we encountered a CORS problem, which was solved by using the following code I found on the Internet:
from fastapi.middleware.cors import CORSMiddleware
...
app.add_middleware(
CORSMiddleware,
allow_origins=['http://localhost:3000'],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
The addition allowed Frontend to make requests properly, but for some reason, cookies that are set to send (and work properly in the Swagger UI) are not set in Frontend. The client side look like:
axios({
method: 'POST',
baseURL: 'http://urlbase.com:8000',
url: '/login',
params: {
mail: '[email protected]',
password: 'xxxxxx'
},
withCredentials: true
}).then( res => console.log(res.data) )
.catch( err => console.log(err))
Upvotes: 6
Views: 28697
Reputation: 358
For Cross-Origin Situation Cookie Setting, Check things below 👇🏻
# main.py
app.add_middleware(
CORSMiddleware,
allow_origins=settings.ALLOWED_ORIGINS,
allow_credentials=True,
allow_methods=["GET", "POST", "HEAD", "OPTIONS"],
allow_headers=["Access-Control-Allow-Headers", 'Content-Type', 'Authorization', 'Access-Control-Allow-Origin'],
)
# cookie
response = JSONResponse(content={"message": "OK"})
expires = datetime.datetime.utcnow() + datetime.timedelta(days=30)
response.set_cookie(
key="access_token", value=token["access_token"], secure=True, httponly=True, samesite='none', expires=expires.strftime("%a, %d %b %Y %H:%M:%S GMT"), domain='.<YOUR DOMAIN>'
)
// post request that sets cookie
const response = await axios.post(
"https://<Target Backend API>",
{
param1: "123",
param2: "456",
},
{
headers: {
"Access-Control-Allow-Origin": "https://<FE DOMAIN>",
},
withCredentials: true,
},
);
if your FE use subdomain like dev.exmaple.com
and your BE also use subdomain like api.example.com
, you should set cookie domain to .example.com
so the subdomain services can access root domain cookie!!
Upvotes: 7
Reputation: 424
Remove the wildcards since wildcarding is not allowed with allow_credentials=True
:
app.add_middleware(
CORSMiddleware,
allow_origins=['http://localhost:3000'],
allow_credentials=True,
allow_methods=["GET", "POST", "OPTIONS"], # include additional methods as per the application demand
allow_headers=["Content-Type","Set-Cookie"], # include additional headers as per the application demand
)
Set samesite
to none
while setting the cookie:
# `secure=True` is optional and used for secure https connections
response.set_cookie(key='token_name', value='token_value', httponly=True, secure=True, samesite='none')
If client side is using Safari, disable Prevent cros-site tracking
in Preferences
. That's It!
Upvotes: 1
Reputation: 30421
Setting and reading cookies in FastAPI can be done through the use of the Request
class:
Setting the cookie refresh_token
from fastapi import Response
@app.get('/set')
async def setting(response: Response):
response.set_cookie(key='refresh_token', value='helloworld', httponly=True)
return True
Setting httponly=True
makes sure the cookie can't be accessed by JS. This is great for sensitive data such as a refresh token. But if your data isn't that sensitive then you can just omit it.
Reading the cookie
from fastapi import Cookie
@app.get('/read')
async def reading(refresh_token: Optional[str] = Cookie(None)):
return refresh_token
You can find more information on using cookies as parameters on the FastAPI docs here.
Upvotes: 7
Reputation: 26
In FastAPI you can set cookies via response.set_cookie
,
from fastapi import FastAPI, Response
app = FastAPI()
@app.post("/cookie-and-object/")
def create_cookie(response: Response):
response.set_cookie(key="fakesession", value="fake-cookie-session-value")
return {"message": "Come to the dark side, we have cookies"}
It should be noted though that these are NOT SECURE SESSIONS you should use something like itsdangerous to create encrypted sessions.
In response to the requests not seeming to not be sent; You should make sure the option for which urls the cookies are valid for are being set.
By default they are typically /
which means everything however your system might be setting them to a specific case with CORS setup.
Upvotes: 0