diff --git a/docs/docs/configuration/authentication.md b/docs/docs/configuration/authentication.md index 5699491c8..a48b03b48 100644 --- a/docs/docs/configuration/authentication.md +++ b/docs/docs/configuration/authentication.md @@ -26,9 +26,7 @@ In the event that you are locked out of your instance, you can tell Frigate to r ## Login failure rate limiting -# TODO: Rui Update to use FastAPI - -In order to limit the risk of brute force attacks, rate limiting is available for login failures. This is implemented with Flask-Limiter, and the string notation for valid values is available in [the documentation](https://flask-limiter.readthedocs.io/en/stable/configuration.html#rate-limit-string-notation). +In order to limit the risk of brute force attacks, rate limiting is available for login failures. This is implemented with SlowApi, and the string notation for valid values is available in [the documentation](https://limits.readthedocs.io/en/stable/quickstart.html#examples). For example, `1/second;5/minute;20/hour` will rate limit the login endpoint when failures occur more than: diff --git a/frigate/api/auth.py b/frigate/api/auth.py index efe2a5530..37f8b5e7b 100644 --- a/frigate/api/auth.py +++ b/frigate/api/auth.py @@ -33,6 +33,19 @@ logger = logging.getLogger(__name__) router = APIRouter(tags=[Tags.auth]) +class RateLimiter: + _limit = "" + + def set_limit(self, limit: str): + self._limit = limit + + def get_limit(self) -> str: + return self._limit + + +rateLimiter = RateLimiter() + + def get_remote_addr(request: Request): route = list(reversed(request.headers.get("x-forwarded-for").split(","))) logger.debug(f"IP Route: {[r for r in route]}") @@ -299,14 +312,8 @@ def logout(request: Request): limiter = Limiter(key_func=get_remote_addr) -def get_rate_limit(request: Request): - return request.app.frigate_config.auth.failed_login_rate_limit - - @router.post("/login") -# Ideally, this would be a decorator @limiter.limit(limit_value=get_rate_limit) but that way the request object is not passed to the method -# See: https://github.com/laurentS/slowapi/issues/41 -# @limiter.limit(limit_value=get_rate_limit) +@limiter.limit(limit_value=rateLimiter.get_limit) def login(request: Request, body: AppPostLoginBody): JWT_COOKIE_NAME = request.app.frigate_config.auth.cookie_name JWT_COOKIE_SECURE = request.app.frigate_config.auth.cookie_secure diff --git a/frigate/api/fastapi_app.py b/frigate/api/fastapi_app.py index 94fffa1e7..39f8d0f65 100644 --- a/frigate/api/fastapi_app.py +++ b/frigate/api/fastapi_app.py @@ -13,9 +13,9 @@ from starlette_context.plugins import Plugin from frigate.api import app as main_app from frigate.api import auth, event, export, media, notification, preview, review from frigate.api.auth import get_jwt_secret, limiter +from frigate.config import FrigateConfig from frigate.embeddings import EmbeddingsContext from frigate.events.external import ExternalEventProcessor -from frigate.plus import PlusApi from frigate.ptz.onvif import OnvifController from frigate.stats.emitter import StatsEmitter from frigate.storage import StorageMaintainer @@ -39,14 +39,13 @@ class RemoteUserPlugin(Plugin): def create_fastapi_app( - frigate_config, + frigate_config: FrigateConfig, database: SqliteQueueDatabase, embeddings: Optional[EmbeddingsContext], detected_frames_processor, storage_maintainer: StorageMaintainer, onvif: OnvifController, external_processor: ExternalEventProcessor, - plus_api: PlusApi, stats_emitter: StatsEmitter, ): logger.info("Starting FastAPI app") @@ -80,6 +79,7 @@ def create_fastapi_app( return response # Rate limiter (used for login endpoint) + auth.rateLimiter.set_limit(frigate_config.auth.failed_login_rate_limit) app.state.limiter = limiter app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler) app.add_middleware(SlowAPIMiddleware) @@ -101,7 +101,6 @@ def create_fastapi_app( app.storage_maintainer = storage_maintainer app.camera_error_image = None app.onvif = onvif - app.plus_api = plus_api app.stats_emitter = stats_emitter app.external_processor = external_processor app.jwt_token = get_jwt_secret() if frigate_config.auth.enabled else None diff --git a/frigate/app.py b/frigate/app.py index 86119ebd8..e7e1ec2b4 100644 --- a/frigate/app.py +++ b/frigate/app.py @@ -655,7 +655,6 @@ class FrigateApp: self.storage_maintainer, self.onvif_controller, self.external_event_processor, - self.plus_api, self.stats_emitter, ), host="127.0.0.1",