From e14b72b7e2b15dd5719ef70409ae88bc234d978d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Boris=20Juri=C4=8D?= <74237898+BorisYourich@users.noreply.github.com> Date: Wed, 2 Apr 2025 16:33:04 +0200 Subject: [PATCH 1/6] Added basic auth support --- tesp_api/api/endpoints/endpoint_utils.py | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/tesp_api/api/endpoints/endpoint_utils.py b/tesp_api/api/endpoints/endpoint_utils.py index 5dde199..1d06ff2 100644 --- a/tesp_api/api/endpoints/endpoint_utils.py +++ b/tesp_api/api/endpoints/endpoint_utils.py @@ -1,9 +1,10 @@ import time +import secrets from typing import Optional from fastapi import status, HTTPException from fastapi.responses import Response -from fastapi.security import OAuth2PasswordBearer +from fastapi.security import OAuth2PasswordBearer, HTTPBasic, HTTPBasicCredentials from pydantic.main import BaseModel from pymonad.maybe import Nothing, Maybe from fastapi.params import Query, Depends @@ -13,6 +14,7 @@ from tesp_api.api.model.response_models import ErrorResponseModel from tesp_api.service.error import OAuth2TokenError from tesp_api.utils.token_validator import verify_token +from tesp_api.utils.basic_auth import verify_basic_auth descriptions = { "tasks-create": "Create a new task. The user provides a Task document, which the " @@ -49,6 +51,7 @@ qry_var_view = Query(TesTaskView.MINIMAL, description=query_descriptions['view']) oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token", auto_error=False) +basic_auth_scheme = HTTPBasic(auto_error=False) # Basic Auth support async def view_query_params(view: Optional[TesTaskView] = qry_var_view): @@ -67,13 +70,21 @@ async def list_query_params(name_prefix: Optional[str] = qry_var_name_prefix, } -def parse_verify_token(token = Depends(oauth2_scheme)): +def parse_verify_token( + token: str = Depends(oauth2_scheme), + basic_credentials: HTTPBasicCredentials = Depends(basic_auth_scheme) +): + if properties.basic_auth.enable: + try: + return verify_basic_auth(basic_credentials.username, basic_credentials.password) + except BasicAuthError as e: + raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail=str(e)) + if not properties.oauth.enable: return None try: - subject = verify_token(token) - return subject + return verify_token(token) except OAuth2TokenError as e: raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail=str(e)) From adb660e03e4d029a00ea6077fb5f471bc86add87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Boris=20Juri=C4=8D?= <74237898+BorisYourich@users.noreply.github.com> Date: Wed, 2 Apr 2025 16:37:52 +0200 Subject: [PATCH 2/6] Create basic_auth.py --- tesp_api/utils/basic_auth.py | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 tesp_api/utils/basic_auth.py diff --git a/tesp_api/utils/basic_auth.py b/tesp_api/utils/basic_auth.py new file mode 100644 index 0000000..791806c --- /dev/null +++ b/tesp_api/utils/basic_auth.py @@ -0,0 +1,11 @@ +import secrets +from tesp_api.service.error import BasicAuthError + +def verify_basic_auth(username: str, password: str): + valid_username = "user" + valid_password = "password" + + if secrets.compare_digest(username, valid_username) and secrets.compare_digest(password, valid_password): + return username + + raise BasicAuthError("Invalid BasicAuth credentials") From bc3b6a8f50bc89a6d8fe315c0c812a4df3670dc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Boris=20Juri=C4=8D?= <74237898+BorisYourich@users.noreply.github.com> Date: Wed, 2 Apr 2025 16:38:33 +0200 Subject: [PATCH 3/6] Update endpoint_utils.py --- tesp_api/api/endpoints/endpoint_utils.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tesp_api/api/endpoints/endpoint_utils.py b/tesp_api/api/endpoints/endpoint_utils.py index 1d06ff2..0dc57f9 100644 --- a/tesp_api/api/endpoints/endpoint_utils.py +++ b/tesp_api/api/endpoints/endpoint_utils.py @@ -1,5 +1,4 @@ import time -import secrets from typing import Optional from fastapi import status, HTTPException @@ -12,7 +11,7 @@ from tesp_api.config.properties import properties from tesp_api.repository.model.task import TesTaskView from tesp_api.api.model.response_models import ErrorResponseModel -from tesp_api.service.error import OAuth2TokenError +from tesp_api.service.error import OAuth2TokenError, BasicAuthError from tesp_api.utils.token_validator import verify_token from tesp_api.utils.basic_auth import verify_basic_auth From bca2127dbed34639b21f82bfb8f5c0985d2cf486 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Boris=20Juri=C4=8D?= <74237898+BorisYourich@users.noreply.github.com> Date: Wed, 2 Apr 2025 16:41:17 +0200 Subject: [PATCH 4/6] add basic auth support --- tesp_api/service/error.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tesp_api/service/error.py b/tesp_api/service/error.py index 92b5d9d..0fc73d9 100644 --- a/tesp_api/service/error.py +++ b/tesp_api/service/error.py @@ -27,11 +27,19 @@ class TaskExecutorError(Exception): def __init(self): super().__init__() + +class BasicAuthError(Exception): + def __init__(self, detail: str = "Invalid BasicAuth credentials"): + super().__init__(detail) + self.detail = detail + + class OAuth2TokenError(Exception): def __init(self): super().__init__() + class UnsupportedProtocolError(Exception): def __init(self): From 553182c00bebbb990eedc5bc4216df0912fa2488 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Boris=20Juri=C4=8D?= <74237898+BorisYourich@users.noreply.github.com> Date: Wed, 2 Apr 2025 16:52:36 +0200 Subject: [PATCH 5/6] Update basic_auth.py --- tesp_api/utils/basic_auth.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tesp_api/utils/basic_auth.py b/tesp_api/utils/basic_auth.py index 791806c..61c926a 100644 --- a/tesp_api/utils/basic_auth.py +++ b/tesp_api/utils/basic_auth.py @@ -1,9 +1,10 @@ import secrets +from tesp_api.config.properties import properties from tesp_api.service.error import BasicAuthError def verify_basic_auth(username: str, password: str): - valid_username = "user" - valid_password = "password" + valid_username = properties.basic_auth.username + valid_password = properties.basic_auth.password if secrets.compare_digest(username, valid_username) and secrets.compare_digest(password, valid_password): return username From b5cbd4f7f0785f8d8f9eaa833fee38ca462a1053 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Boris=20Juri=C4=8D?= <74237898+BorisYourich@users.noreply.github.com> Date: Wed, 2 Apr 2025 17:00:55 +0200 Subject: [PATCH 6/6] Added basic auth to sttings.toml --- settings.toml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/settings.toml b/settings.toml index 6bbc37b..f48cf62 100644 --- a/settings.toml +++ b/settings.toml @@ -8,7 +8,9 @@ logging.level = "DEBUG" logging.output_json = false oauth.enable = false - +basic_auth.enable = false +basic_auth.username = "user" +basic_auth.password = "password" [dev-docker] db.mongodb_uri = "mongodb://tesp-db:27017"