How Authentication and Password Hashing Are Configured in Frigate
Frigate configures authentication using JWT-based sessions with PBKDF2-SHA256 password hashing (600,000 iterations by default), role-based access control, and declarative settings in AuthConfig.
Frigate is an open-source Network Video Recorder (NVR) that protects its web interface and API with native authentication mechanisms. Understanding how authentication and password hashing are configured in Frigate helps administrators secure video streams and user credentials effectively. The implementation is distributed across configuration models, API utilities, and database layers within the blakeblackshear/frigate repository.
AuthConfig Declarative Settings
All authentication behavior is governed by the AuthConfig class defined in [frigate/config/auth.py](https://github.com/blakeblackshear/frigate/blob/dev/frigate/config/auth.py#L10-L68). This Pydantic model validates settings at startup and exposes the following key fields:
enabled– Globally toggles authentication on or off.hash_iterations– Configurable work factor for PBKDF2 (default600000, aligning with OWASP recommendations).roles– Dictionary mapping role names (e.g.,admin,viewer) to lists of authorized cameras; an empty list grants access to all cameras.session_length– JWT token lifetime in seconds (default86400).refresh_time– Window before expiry to refresh tokens (default1800).cookie_secure– Sets theSecureflag on JWT cookies; must beTruewhen serving over TLS.cookie_name– Configurable name for the session cookie (defaultfrigate_token).
These values are sourced from your main config.yml and are immutable until the next restart.
PBKDF2-SHA256 Password Hashing
Password hashing and verification are implemented in [frigate/api/auth.py](https://github.com/blakeblackshear/frigate/blob/dev/frigate/api/auth.py#L64-L84) using Python’s standard library. Frigate uses PBKDF2-HMAC-SHA256 with a configurable iteration count and a random 16-byte salt.
Hash Generation
The hash_password function generates strings in the format pbkdf2_sha256$<iterations>$<salt>$<base64_hash>:
def hash_password(password: str, salt=None, iterations=600000):
if salt is None:
salt = secrets.token_hex(16) # 16-byte random salt
pw_hash = hashlib.pbkdf2_hmac(
"sha256",
password.encode("utf-8"),
salt.encode("utf-8"),
iterations
)
b64_hash = base64.b64encode(pw_hash).decode("ascii").strip()
return f"{PASSWORD_HASH_ALGORITHM}${iterations}${salt}${b64_hash}"
PASSWORD_HASH_ALGORITHMis the constantpbkdf2_sha256.iterationsdefaults to600000but is overridden byAuthConfig.hash_iterationswhen creating users.saltis generated viasecrets.token_hex(16)to ensure cryptographic randomness.
Hash Verification
The verify_password function prevents timing attacks by using secrets.compare_digest and validates the stored hash structure before computation:
def verify_password(password, password_hash):
if (password_hash or "").count("$") != 3:
return False
algorithm, iterations, salt, b64_hash = password_hash.split("$", 3)
iterations = int(iterations)
assert algorithm == PASSWORD_HASH_ALGORITHM
compare_hash = hash_password(password, salt, iterations)
return secrets.compare_digest(password_hash, compare_hash)
This ensures constant-time comparison and rejects malformed hashes immediately.
JWT Session and Secret Management
Frigate issues JSON Web Tokens (JWT) upon successful login. The signing secret is retrieved by get_jwt_secret() in [frigate/api/auth.py](https://github.com/blakeblackshear/frigate/blob/dev/frigate/api/auth.py#L30-L61) using the following precedence:
FRIGATE_JWT_SECRETenvironment variable.- Docker secrets (mounted files).
- Home Assistant add-on context.
- A persistent file named
.jwt_secretin the configuration directory (auto-generated on first run).
The create_encoded_jwt function generates tokens that are stored in HTTP-only cookies. The cookie name and security attributes are controlled by AuthConfig.cookie_name and AuthConfig.cookie_secure.
Role-Based Access Control
Frigate enforces coarse-grained authorization through the require_role dependency. Roles are resolved from the remote-role header (or proxy-mapped headers) and compared against the mappings defined in AuthConfig.roles.
The resolve_role helper translates proxy-provided claims into Frigate role definitions. Endpoints declare required roles via FastAPI dependencies; if the user’s role is absent from the required list, the request is rejected with a 403 error.
User Model and Lifecycle
Persistent user data is defined in [frigate/models.py](https://github.com/blakeblackshear/frigate/blob/dev/frigate/models.py#L44-L51) by the User SQLAlchemy model:
class User(Model):
username = CharField(unique=True)
role = CharField()
password_hash = CharField()
When the application starts, [frigate/app.py](https://github.com/blakeblackshear/frigate/blob/dev/frigate/app.py#L520-L560) checks for the existence of an admin user or the reset_admin_password flag. If a new user is created or the admin password is reset, the backend invokes hash_password with iterations=self.config.auth.hash_iterations and commits the resulting string to the password_hash column.
Summary
- Configuration:
AuthConfiginfrigate/config/auth.pycentralizes hash iterations, session timing, and cookie settings. - Hashing: PBKDF2-SHA256 with 600,000 default iterations produces hashes in
algorithm$iterations$salt$base64_hashformat. - Security: Constant-time verification via
secrets.compare_digestmitigates timing attacks. - Sessions: JWT tokens are signed with secrets from environment variables or filesystem storage and transmitted via configurable cookies.
- Storage: User credentials reside in the
Usermodel (frigate/models.py), populated during startup logic infrigate/app.py.
Frequently Asked Questions
What hashing algorithm does Frigate use for passwords?
Frigate uses PBKDF2-HMAC-SHA256 with a default of 600,000 iterations, which aligns with current OWASP guidelines. The iteration count is configurable via the hash_iterations field in AuthConfig (frigate/config/auth.py).
How does Frigate store and retrieve the JWT signing secret?
Frigate attempts to load the JWT secret from the FRIGATE_JWT_SECRET environment variable first. If undefined, it checks Docker secrets, Home Assistant add-on contexts, or generates a random secret and persists it to a .jwt_secret file in the configuration directory (implemented in frigate/api/auth.py).
Can I enforce secure cookies and customize session timeouts?
Yes. Set cookie_secure: True in your config.yml to enforce the Secure flag on cookies (required for HTTPS deployments). Adjust session_length (default 86400 seconds) and refresh_time (default 1800 seconds) within AuthConfig to control token lifetimes.
Where are user passwords stored in the database?
User credentials are stored in the User table defined in frigate/models.py, specifically within the password_hash column. This column stores the complete PBKDF2 string including algorithm, iterations, salt, and hash, which is generated during user creation in frigate/app.py.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →