shellking4
shellking4

Reputation: 149

HttpOnly cookie is not set in Chrome using FastAPI

I have an api built in FastAPI running on localhost:8000 and a NextJS frontend running on localhost:3000. I'm using HttpOnly cookie to store the JWT token after user authentication. But for some reason the cookie is not set in chrome and subsequent requests are not authenticated. When I test the mechanism in insomnia it is working, but on the frontend it doesn't. Here is my actual setup.

The login endpoint:

@router.post("/signin", response_model=SigninResponseSchema)
def sign_in(
    response: Response,
    *,
    user_credentials: SigninSchema,
    db: Session = Depends(database.get_db),
) -> any:
    signin_infos = auth_service.authenticate_user(db, user_credentials=user_credentials)
    sign_in_response = SigninResponseSchema(
        status="successful", 
        access_token=signin_infos["access_token"],
        user_data=signin_infos["user_data"],
        user_roles=signin_infos["user_roles"]
    )
    token = jsonable_encoder(sign_in_response.access_token)
    response.set_cookie(
        "Authorization",
        value=f"Bearer {token}",
        httponly=True,
        secure=True,
        samesite="none",
        max_age=1800,
        expires=1800,
    )
    return sign_in_response

The cors setup:

origins = [
    "http://localhost:3000" 
]

app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,
    allow_credentials=True,
    allow_methods=["GET", "POST", "HEAD", "OPTIONS"],
    allow_headers=["Access-Control-Allow-Headers", "Content-Type", "Authorization", "Access-Control-Allow-Origin","Set-Cookie"],
)

How do I solve the problem? I've already taken a look to several solutions on the internet but none of them is working. What could be the problem ?

Upvotes: 3

Views: 5072

Answers (1)

JBarnden
JBarnden

Reputation: 25

Your setup on the FastAPI side looks good, the issue is likely in your front-end application.

One thing that jumps out is that you're making your requests from http://localhost:3000 which isn't over HTTPS, and you're setting your cookie with secure=True. Ideally you should be running your front-end app locally over HTTPS and making requests from https://localhost:3000.

Here's a couple more things to check on the client side:

  • In your request, make sure you've set the XMLHttpRequest.withCredentials flag to true (this was my problem), this can be achieved in different ways depending on the request-response library used:
    • jQuery 1.5.1 xhrFields: {withCredentials: true}
    • ES6 fetch(): credentials: 'include'
    • axios: withCredentials: true
  • Your request headers should include "Access-Control-Allow-Origin": "http://localhost:3000"

Credit: This answer to a similar question got me unstuck from a similar issue

Upvotes: 2

Related Questions