From 62d4e87e5d9b580c88790f18c1babf2017d31fb7 Mon Sep 17 00:00:00 2001 From: nulledy <254504350+nulledy@users.noreply.github.com> Date: Tue, 14 Jul 2026 06:35:51 -0400 Subject: [PATCH] Add logout endpoint to Nginx configuration to prevent a new token on logout (#23678) * Add logout endpoint to Nginx configuration to prevent logout from silently generating a new frigate_token cookie * Change JWT cookie expiration to use max_age and have the appropriate expiration time based on JWT_SESSION_LENGTH * ruff formatting --- .../rootfs/usr/local/nginx/conf/nginx.conf | 7 +++++++ frigate/api/auth.py | 18 +++++++++++++----- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/docker/main/rootfs/usr/local/nginx/conf/nginx.conf b/docker/main/rootfs/usr/local/nginx/conf/nginx.conf index d0b18ff805..399dba5736 100644 --- a/docker/main/rootfs/usr/local/nginx/conf/nginx.conf +++ b/docker/main/rootfs/usr/local/nginx/conf/nginx.conf @@ -274,6 +274,13 @@ http { include proxy.conf; } + location /api/logout { + auth_request off; + rewrite ^/api(/.*)$ $1 break; + proxy_pass http://frigate_api; + include proxy.conf; + } + # Allow unauthenticated access to the first_time_login endpoint # so the login page can load help text before authentication. location /api/auth/first_time_login { diff --git a/frigate/api/auth.py b/frigate/api/auth.py index a6a4c65b68..204702e3ac 100644 --- a/frigate/api/auth.py +++ b/frigate/api/auth.py @@ -415,7 +415,7 @@ def create_encoded_jwt(user, role, expiration, secret): ) -def set_jwt_cookie(response: Response, cookie_name, encoded_jwt, expiration, secure): +def set_jwt_cookie(response: Response, cookie_name, encoded_jwt, max_age, secure): # TODO: ideally this would set secure as well, but that requires TLS # SameSite is intentionally left unset (browsers default to Lax). Setting # SameSite=Lax/Strict would stop the cookie from being sent in cross-origin @@ -427,7 +427,7 @@ def set_jwt_cookie(response: Response, cookie_name, encoded_jwt, expiration, sec key=cookie_name, value=encoded_jwt, httponly=True, - expires=expiration, + max_age=max_age, secure=secure, ) @@ -762,7 +762,7 @@ def auth(request: Request): success_response, JWT_COOKIE_NAME, new_encoded_jwt, - new_expiration, + JWT_SESSION_LENGTH, JWT_COOKIE_SECURE, ) @@ -875,7 +875,11 @@ def login(request: Request, body: AppPostLoginBody): encoded_jwt = create_encoded_jwt(user, role, expiration, request.app.jwt_token) response = Response("", 200) set_jwt_cookie( - response, JWT_COOKIE_NAME, encoded_jwt, expiration, JWT_COOKIE_SECURE + response, + JWT_COOKIE_NAME, + encoded_jwt, + JWT_SESSION_LENGTH, + JWT_COOKIE_SECURE, ) # Clear admin_first_time_login flag after successful admin login so the # UI stops showing the first-time login documentation link. @@ -1037,7 +1041,11 @@ async def update_password( ) # Set new JWT cookie on response set_jwt_cookie( - response, JWT_COOKIE_NAME, encoded_jwt, expiration, JWT_COOKIE_SECURE + response, + JWT_COOKIE_NAME, + encoded_jwt, + JWT_SESSION_LENGTH, + JWT_COOKIE_SECURE, ) return response