forked from Github/frigate
Auth! (#11347)
* reload the window on 401 * backend apis for auth * add login page * re-enable web linter * fix login page routing * bypass csrf for internal auth endpoint * disable healthcheck in devcontainer target * include login page in vite build * redirect to login page on 401 * implement config for users and settings * implement JWT actual secret * add brute force protection on login * add support for redirecting from auth failures on api calls * return location for redirect * default cookie name should pass regex test * set hash iterations to current OWASP recommendation * move users to database instead of config * config option to reset admin password on startup * user management UI * check for deleted user on refresh * validate username and fixes * remove password constraint * cleanup * fix user check on refresh * web fixes * implement auth via new external port * use x-forwarded-for to rate limit login attempts by ip * implement logout and profile * fixes * lint fixes * add support for user passthru from upstream proxies * add support for specifying a logout url * add documentation * Update docs/docs/configuration/authentication.md Co-authored-by: Nicolas Mowen <nickmowen213@gmail.com> * Update docs/docs/configuration/authentication.md Co-authored-by: Nicolas Mowen <nickmowen213@gmail.com> --------- Co-authored-by: Nicolas Mowen <nickmowen213@gmail.com>
This commit is contained in:
@@ -3,6 +3,7 @@ import datetime
|
||||
import logging
|
||||
import multiprocessing as mp
|
||||
import os
|
||||
import secrets
|
||||
import shutil
|
||||
import signal
|
||||
import sys
|
||||
@@ -19,13 +20,14 @@ from playhouse.sqliteq import SqliteQueueDatabase
|
||||
from pydantic import ValidationError
|
||||
|
||||
from frigate.api.app import create_app
|
||||
from frigate.api.auth import hash_password
|
||||
from frigate.comms.config_updater import ConfigPublisher
|
||||
from frigate.comms.detections_updater import DetectionProxy
|
||||
from frigate.comms.dispatcher import Communicator, Dispatcher
|
||||
from frigate.comms.inter_process import InterProcessCommunicator
|
||||
from frigate.comms.mqtt import MqttClient
|
||||
from frigate.comms.ws import WebSocketClient
|
||||
from frigate.config import FrigateConfig
|
||||
from frigate.config import AuthModeEnum, FrigateConfig
|
||||
from frigate.const import (
|
||||
CACHE_DIR,
|
||||
CLIPS_DIR,
|
||||
@@ -49,6 +51,7 @@ from frigate.models import (
|
||||
Regions,
|
||||
ReviewSegment,
|
||||
Timeline,
|
||||
User,
|
||||
)
|
||||
from frigate.object_detection import ObjectDetectProcess
|
||||
from frigate.object_processing import TrackedObjectProcessor
|
||||
@@ -338,6 +341,7 @@ class FrigateApp:
|
||||
Regions,
|
||||
ReviewSegment,
|
||||
Timeline,
|
||||
User,
|
||||
]
|
||||
self.db.bind(models)
|
||||
|
||||
@@ -587,6 +591,42 @@ class FrigateApp:
|
||||
f"The current SHM size of {available_shm}MB is too small, recommend increasing it to at least {min_req_shm}MB."
|
||||
)
|
||||
|
||||
def init_auth(self) -> None:
|
||||
if self.config.auth.mode == AuthModeEnum.native:
|
||||
if User.select().count() == 0:
|
||||
password = secrets.token_hex(16)
|
||||
password_hash = hash_password(
|
||||
password, iterations=self.config.auth.hash_iterations
|
||||
)
|
||||
User.insert(
|
||||
{
|
||||
User.username: "admin",
|
||||
User.password_hash: password_hash,
|
||||
}
|
||||
).execute()
|
||||
|
||||
logger.info("********************************************************")
|
||||
logger.info("********************************************************")
|
||||
logger.info("*** Auth is enabled, but no users exist. ***")
|
||||
logger.info("*** Created a default user: ***")
|
||||
logger.info("*** User: admin ***")
|
||||
logger.info(f"*** Password: {password} ***")
|
||||
logger.info("********************************************************")
|
||||
logger.info("********************************************************")
|
||||
elif self.config.auth.reset_admin_password:
|
||||
password = secrets.token_hex(16)
|
||||
password_hash = hash_password(
|
||||
password, iterations=self.config.auth.hash_iterations
|
||||
)
|
||||
User.replace(username="admin", password_hash=password_hash).execute()
|
||||
|
||||
logger.info("********************************************************")
|
||||
logger.info("********************************************************")
|
||||
logger.info("*** Reset admin password set in the config. ***")
|
||||
logger.info(f"*** Password: {password} ***")
|
||||
logger.info("********************************************************")
|
||||
logger.info("********************************************************")
|
||||
|
||||
def start(self) -> None:
|
||||
parser = argparse.ArgumentParser(
|
||||
prog="Frigate",
|
||||
@@ -664,6 +704,7 @@ class FrigateApp:
|
||||
self.start_record_cleanup()
|
||||
self.start_watchdog()
|
||||
self.check_shm()
|
||||
self.init_auth()
|
||||
|
||||
def receiveSignal(signalNumber: int, frame: Optional[FrameType]) -> None:
|
||||
self.stop()
|
||||
|
||||
Reference in New Issue
Block a user