Add ability to specify separator used in proxy headers (#18336)

This commit is contained in:
Josh Hawkins 2025-05-21 07:02:13 -05:00 committed by GitHub
parent 2a8b62acb1
commit 49c6073de6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 25 additions and 4 deletions

View File

@ -97,11 +97,12 @@ python3 -c 'import secrets; print(secrets.token_hex(64))'
### Header mapping
If you have disabled Frigate's authentication and your proxy supports passing a header with authenticated usernames and/or roles, you can use the `header_map` config to specify the header name so it is passed to Frigate. For example, the following will map the `X-Forwarded-User` and `X-Forwarded-Role` values. Header names are not case sensitive. Multiple values can be included in the role header, but they must be comma-separated.
If you have disabled Frigate's authentication and your proxy supports passing a header with authenticated usernames and/or roles, you can use the `header_map` config to specify the header name so it is passed to Frigate. For example, the following will map the `X-Forwarded-User` and `X-Forwarded-Role` values. Header names are not case sensitive. Multiple values can be included in the role header. Frigate expects that the character separating the roles is a comma, but this can be specified using the `separator` config entry.
```yaml
proxy:
...
separator: "|" # This value defaults to a comma, but Authentik uses a pipe, for example.
header_map:
user: x-forwarded-user
role: x-forwarded-role

View File

@ -91,6 +91,8 @@ proxy:
auth_secret: None
# Optional: The default role to use for proxy auth. Must be "admin" or "viewer"
default_role: viewer
# Optional: The character used to separate multiple values in the proxy headers. (default: shown below)
separator: ","
# Optional: Authentication configuration
auth:

View File

@ -202,9 +202,15 @@ async def get_current_user(request: Request):
def require_role(required_roles: List[str]):
async def role_checker(request: Request):
proxy_config: ProxyConfig = request.app.frigate_config.proxy
# Get role from header (could be comma-separated)
role_header = request.headers.get("remote-role")
roles = [r.strip() for r in role_header.split(",")] if role_header else []
roles = (
[r.strip() for r in role_header.split(proxy_config.separator)]
if role_header
else []
)
# Check if we have any roles
if not roles:
@ -269,7 +275,8 @@ def auth(request: Request):
# if comma-separated with "admin", use "admin", else use default role
success_response.headers["remote-role"] = (
"admin"
if role and "admin" in [r.strip() for r in role.split(",")]
if role
and "admin" in [r.strip() for r in role.split(proxy_config.separator)]
else proxy_config.default_role
)

View File

@ -1,6 +1,6 @@
from typing import Optional
from pydantic import Field
from pydantic import Field, field_validator
from .base import FrigateBaseModel
from .env import EnvString
@ -33,3 +33,14 @@ class ProxyConfig(FrigateBaseModel):
default_role: Optional[str] = Field(
default="viewer", title="Default role for proxy users."
)
separator: Optional[str] = Field(
default=",",
title="The character used to separate values in a mapped header.",
)
@field_validator("separator", mode="before")
@classmethod
def validate_separator_length(cls, v):
if v is not None and len(v) != 1:
raise ValueError("Separator must be exactly one character")
return v