mirror of
https://github.com/blakeblackshear/frigate.git
synced 2025-12-06 13:34:13 +03:00
add helper and simplify auth conditions
This commit is contained in:
parent
07d158aac2
commit
d96169eb47
@ -39,15 +39,14 @@ def require_admin_by_default():
|
|||||||
|
|
||||||
This is set as the default dependency on the FastAPI app to ensure all
|
This is set as the default dependency on the FastAPI app to ensure all
|
||||||
endpoints require admin access unless explicitly overridden with
|
endpoints require admin access unless explicitly overridden with
|
||||||
allow_public(), allow_any_authenticated(), or allow_viewer().
|
allow_public(), allow_any_authenticated(), or require_role().
|
||||||
|
|
||||||
Port 5000 (internal) always has admin role set by the /auth endpoint,
|
Port 5000 (internal) always has admin role set by the /auth endpoint,
|
||||||
so this check passes automatically for internal requests.
|
so this check passes automatically for internal requests.
|
||||||
|
|
||||||
Certain paths are exempted from the global admin check because they have
|
Certain paths are exempted from the global admin check because they must
|
||||||
their own route-level authorization dependencies (allow_public(),
|
be accessible before authentication (login, auth) or they have their own
|
||||||
allow_any_authenticated(), etc). The route-level dependencies handle the
|
route-level authorization dependencies that handle access control.
|
||||||
actual authorization for these paths.
|
|
||||||
"""
|
"""
|
||||||
# Paths that have route-level auth dependencies and should bypass global admin check
|
# Paths that have route-level auth dependencies and should bypass global admin check
|
||||||
# These paths still have authorization - it's handled by their route-level dependencies
|
# These paths still have authorization - it's handled by their route-level dependencies
|
||||||
@ -106,6 +105,7 @@ def require_admin_by_default():
|
|||||||
return
|
return
|
||||||
|
|
||||||
# For all other paths, require admin role
|
# For all other paths, require admin role
|
||||||
|
# Port 5000 (internal) requests have admin role set automatically
|
||||||
role = request.headers.get("remote-role")
|
role = request.headers.get("remote-role")
|
||||||
if role == "admin":
|
if role == "admin":
|
||||||
return
|
return
|
||||||
@ -118,6 +118,17 @@ def require_admin_by_default():
|
|||||||
return admin_checker
|
return admin_checker
|
||||||
|
|
||||||
|
|
||||||
|
def _is_authenticated(request: Request) -> bool:
|
||||||
|
"""
|
||||||
|
Helper to determine if a request is from an authenticated user.
|
||||||
|
|
||||||
|
Returns True if the request has a valid authenticated user (not anonymous).
|
||||||
|
Port 5000 internal requests are considered anonymous despite having admin role.
|
||||||
|
"""
|
||||||
|
username = request.headers.get("remote-user")
|
||||||
|
return username is not None and username != "anonymous"
|
||||||
|
|
||||||
|
|
||||||
def allow_public():
|
def allow_public():
|
||||||
"""
|
"""
|
||||||
Override dependency to allow unauthenticated access to an endpoint.
|
Override dependency to allow unauthenticated access to an endpoint.
|
||||||
@ -139,47 +150,31 @@ def allow_any_authenticated():
|
|||||||
"""
|
"""
|
||||||
Override dependency to allow any authenticated user (bypass admin requirement).
|
Override dependency to allow any authenticated user (bypass admin requirement).
|
||||||
|
|
||||||
The user must have valid remote-user and remote-role headers, but any role
|
Allows:
|
||||||
is accepted. Port 5000 requests have "admin" role so they also pass.
|
- Port 5000 internal requests (have admin role despite anonymous user)
|
||||||
|
- Any authenticated user with a real username (not "anonymous")
|
||||||
|
|
||||||
|
Rejects:
|
||||||
|
- Port 8971 requests with anonymous user (auth disabled, no proxy auth)
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
@router.get("/authenticated-endpoint", dependencies=[Depends(allow_any_authenticated())])
|
@router.get("/authenticated-endpoint", dependencies=[Depends(allow_any_authenticated())])
|
||||||
"""
|
"""
|
||||||
|
|
||||||
async def auth_checker(request: Request):
|
async def auth_checker(request: Request):
|
||||||
if not request.headers.get("remote-user"):
|
# Port 5000 requests have admin role and should be allowed
|
||||||
raise HTTPException(
|
role = request.headers.get("remote-role")
|
||||||
status_code=401,
|
if role == "admin":
|
||||||
detail="Authentication required",
|
return
|
||||||
)
|
|
||||||
|
# Otherwise require a real authenticated user (not anonymous)
|
||||||
|
if not _is_authenticated(request):
|
||||||
|
raise HTTPException(status_code=401, detail="Authentication required")
|
||||||
return
|
return
|
||||||
|
|
||||||
return auth_checker
|
return auth_checker
|
||||||
|
|
||||||
|
|
||||||
def allow_viewer():
|
|
||||||
"""
|
|
||||||
Override dependency to allow viewer or higher roles (admin, custom roles with cameras).
|
|
||||||
|
|
||||||
This is useful for read-only endpoints that should allow non-admin authenticated users.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
@router.get("/viewer-endpoint", dependencies=[Depends(allow_viewer())])
|
|
||||||
"""
|
|
||||||
|
|
||||||
async def viewer_checker(request: Request):
|
|
||||||
role = request.headers.get("remote-role")
|
|
||||||
if not role:
|
|
||||||
raise HTTPException(
|
|
||||||
status_code=401,
|
|
||||||
detail="Authentication required",
|
|
||||||
)
|
|
||||||
# Any role is allowed (admin, viewer, or custom roles)
|
|
||||||
return
|
|
||||||
|
|
||||||
return viewer_checker
|
|
||||||
|
|
||||||
|
|
||||||
router = APIRouter(tags=[Tags.auth])
|
router = APIRouter(tags=[Tags.auth])
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user