Fix CSRF SameSite=Strict breaking login on iPad/Safari
Safari (iPadOS/iOS) blocks SameSite=Strict cookies on the initial top-level navigation when it considers the request cross-site (links from messengers, email, QR codes). The CSRF cookie was therefore never set on first visit, and the subsequent login POST failed with 403 "CSRF failed". Switch the CSRF cookie to SameSite=Lax — this is the OWASP recommended default and matches industry practice. The auth (session) cookie keeps SameSite=Strict, since it is only issued after a successful first-party login POST and needs the stricter binding.
This commit is contained in:
+4
-4
@@ -507,7 +507,7 @@ def issue_csrf_cookie(response: RedirectResponse) -> str:
|
|||||||
value=token,
|
value=token,
|
||||||
httponly=False,
|
httponly=False,
|
||||||
secure=True,
|
secure=True,
|
||||||
samesite="strict",
|
samesite="lax",
|
||||||
max_age=COOKIE_MAX_AGE,
|
max_age=COOKIE_MAX_AGE,
|
||||||
path="/",
|
path="/",
|
||||||
)
|
)
|
||||||
@@ -1846,7 +1846,7 @@ def index(request: Request, user: Optional[User] = Depends(get_current_user), db
|
|||||||
"session_notice": session_notice,
|
"session_notice": session_notice,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
response.set_cookie(CSRF_COOKIE, csrf, httponly=False, secure=True, samesite="strict", path="/")
|
response.set_cookie(CSRF_COOKIE, csrf, httponly=False, secure=True, samesite="lax", path="/")
|
||||||
return response
|
return response
|
||||||
|
|
||||||
services = db.scalars(
|
services = db.scalars(
|
||||||
@@ -2073,7 +2073,7 @@ def login(
|
|||||||
},
|
},
|
||||||
status_code=401,
|
status_code=401,
|
||||||
)
|
)
|
||||||
response.set_cookie(CSRF_COOKIE, csrf, httponly=False, secure=True, samesite="strict", path="/")
|
response.set_cookie(CSRF_COOKIE, csrf, httponly=False, secure=True, samesite="lax", path="/")
|
||||||
return response
|
return response
|
||||||
if not user_is_valid(user):
|
if not user_is_valid(user):
|
||||||
csrf = request.cookies.get(CSRF_COOKIE) or secrets.token_urlsafe(24)
|
csrf = request.cookies.get(CSRF_COOKIE) or secrets.token_urlsafe(24)
|
||||||
@@ -2086,7 +2086,7 @@ def login(
|
|||||||
},
|
},
|
||||||
status_code=403,
|
status_code=403,
|
||||||
)
|
)
|
||||||
response.set_cookie(CSRF_COOKIE, csrf, httponly=False, secure=True, samesite="strict", path="/")
|
response.set_cookie(CSRF_COOKIE, csrf, httponly=False, secure=True, samesite="lax", path="/")
|
||||||
return response
|
return response
|
||||||
|
|
||||||
response = RedirectResponse(url="/", status_code=303)
|
response = RedirectResponse(url="/", status_code=303)
|
||||||
|
|||||||
Reference in New Issue
Block a user