fastapi-factory-utilities 0.8.1__tar.gz → 0.8.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/PKG-INFO +1 -1
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/pyproject.toml +1 -1
- fastapi_factory_utilities-0.8.2/src/fastapi_factory_utilities/core/security/__init__.py +5 -0
- fastapi_factory_utilities-0.8.2/src/fastapi_factory_utilities/core/security/abstracts.py +42 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/security/jwt/services.py +10 -27
- fastapi_factory_utilities-0.8.2/src/fastapi_factory_utilities/core/security/kratos.py +98 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/services/status/exceptions.py +1 -1
- fastapi_factory_utilities-0.8.1/src/fastapi_factory_utilities/core/security/__init__.py +0 -5
- fastapi_factory_utilities-0.8.1/src/fastapi_factory_utilities/core/security/flags.py +0 -10
- fastapi_factory_utilities-0.8.1/src/fastapi_factory_utilities/core/security/kratos.py +0 -98
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/LICENSE +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/README.md +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/__main__.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/__init__.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/api/__init__.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/api/tags.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/api/v1/sys/__init__.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/api/v1/sys/health.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/api/v1/sys/readiness.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/app/__init__.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/app/application.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/app/builder.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/app/config.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/app/enums.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/app/exceptions.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/app/fastapi_builder.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/exceptions.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/plugins/__init__.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/plugins/abstracts.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/plugins/aiopika/__init__.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/plugins/aiopika/abstract.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/plugins/aiopika/configs.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/plugins/aiopika/depends.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/plugins/aiopika/exceptions.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/plugins/aiopika/exchange.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/plugins/aiopika/listener/__init__.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/plugins/aiopika/listener/abstract.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/plugins/aiopika/message.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/plugins/aiopika/plugins.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/plugins/aiopika/publisher/__init__.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/plugins/aiopika/publisher/abstract.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/plugins/aiopika/queue.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/plugins/odm_plugin/__init__.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/plugins/odm_plugin/builder.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/plugins/odm_plugin/configs.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/plugins/odm_plugin/depends.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/plugins/odm_plugin/documents.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/plugins/odm_plugin/exceptions.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/plugins/odm_plugin/helpers.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/plugins/odm_plugin/plugins.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/plugins/odm_plugin/repositories.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/plugins/opentelemetry_plugin/__init__.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/plugins/opentelemetry_plugin/builder.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/plugins/opentelemetry_plugin/configs.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/plugins/opentelemetry_plugin/exceptions.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/plugins/opentelemetry_plugin/helpers.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/plugins/opentelemetry_plugin/instruments/__init__.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/plugins/opentelemetry_plugin/plugins.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/plugins/taskiq_plugins/__init__.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/plugins/taskiq_plugins/configs.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/plugins/taskiq_plugins/depends.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/plugins/taskiq_plugins/exceptions.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/plugins/taskiq_plugins/plugin.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/plugins/taskiq_plugins/schedulers.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/protocols.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/security/jwt/__init__.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/security/jwt/configs.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/security/jwt/decoders.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/security/jwt/exceptions.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/security/jwt/objects.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/security/jwt/stores.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/security/jwt/types.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/security/jwt/verifiers.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/services/hydra/__init__.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/services/hydra/exceptions.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/services/hydra/objects.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/services/hydra/services.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/services/kratos/__init__.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/services/kratos/enums.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/services/kratos/exceptions.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/services/kratos/objects.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/services/kratos/services.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/services/status/__init__.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/services/status/enums.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/services/status/health_calculator_strategies.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/services/status/readiness_calculator_strategies.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/services/status/services.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/services/status/types.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/utils/configs.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/utils/importlib.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/utils/log.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/utils/status.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/utils/uvicorn.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/core/utils/yaml_reader.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/example/__init__.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/example/__main__.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/example/api/__init__.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/example/api/books/__init__.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/example/api/books/responses.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/example/api/books/routes.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/example/app.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/example/application.yaml +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/example/entities/books/__init__.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/example/entities/books/entities.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/example/entities/books/enums.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/example/entities/books/types.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/example/models/__init__.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/example/models/books/__init__.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/example/models/books/document.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/example/models/books/repository.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/example/services/books/__init__.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/example/services/books/services.py +0 -0
- {fastapi_factory_utilities-0.8.1 → fastapi_factory_utilities-0.8.2}/src/fastapi_factory_utilities/py.typed +0 -0
|
@@ -3,7 +3,7 @@ name = "fastapi_factory_utilities"
|
|
|
3
3
|
homepage = "https://github.com/DeerHide/fastapi_factory_utilities"
|
|
4
4
|
repository = "https://github.com/DeerHide/fastapi_factory_utilities"
|
|
5
5
|
keywords = ["python", "fastapi", "beanie", "taskiq", "opentelemetry", "microservices"]
|
|
6
|
-
version = "0.8.
|
|
6
|
+
version = "0.8.2"
|
|
7
7
|
description = "Consolidate libraries and utilities to create microservices in Python with FastAPI, Beanie, Taskiq, AioPika and OpenTelemetry."
|
|
8
8
|
authors = ["miragecentury <victorien.vanroye@gmail.com>"]
|
|
9
9
|
maintainers = ["miragecentury <victorien.vanroye@gmail.com>"]
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"""Provides the security authentication abstract classes."""
|
|
2
|
+
|
|
3
|
+
from abc import ABC, abstractmethod
|
|
4
|
+
|
|
5
|
+
from fastapi import Request
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class AuthenticationAbstract(ABC):
|
|
9
|
+
"""Authentication abstract class."""
|
|
10
|
+
|
|
11
|
+
def __init__(self, raise_exception: bool = True) -> None:
|
|
12
|
+
"""Initialize the authentication abstract class.
|
|
13
|
+
|
|
14
|
+
Args:
|
|
15
|
+
raise_exception (bool): Whether to raise an exception or return None.
|
|
16
|
+
"""
|
|
17
|
+
self._raise_exception: bool = raise_exception
|
|
18
|
+
self._errors: list[Exception] = []
|
|
19
|
+
|
|
20
|
+
def has_errors(self) -> bool:
|
|
21
|
+
"""Check if the authentication has errors.
|
|
22
|
+
|
|
23
|
+
Returns:
|
|
24
|
+
bool: True if the authentication has errors, False otherwise.
|
|
25
|
+
"""
|
|
26
|
+
return len(self._errors) > 0
|
|
27
|
+
|
|
28
|
+
def raise_exception(self, exception: Exception) -> None:
|
|
29
|
+
"""Raise the exception if the authentication has errors.
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
exception (Exception): The exception to raise.
|
|
33
|
+
"""
|
|
34
|
+
if self._raise_exception:
|
|
35
|
+
raise exception
|
|
36
|
+
else:
|
|
37
|
+
self._errors.append(exception)
|
|
38
|
+
|
|
39
|
+
@abstractmethod
|
|
40
|
+
async def authenticate(self, request: Request) -> None:
|
|
41
|
+
"""Authenticate the request."""
|
|
42
|
+
raise NotImplementedError()
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
"""Provides the JWT bearer authentication service."""
|
|
2
2
|
|
|
3
|
-
from
|
|
3
|
+
from http import HTTPStatus
|
|
4
4
|
from typing import Generic, TypeVar
|
|
5
5
|
|
|
6
|
-
from fastapi import Request
|
|
6
|
+
from fastapi import HTTPException, Request
|
|
7
|
+
|
|
8
|
+
from fastapi_factory_utilities.core.security.abstracts import AuthenticationAbstract
|
|
7
9
|
|
|
8
10
|
from .configs import JWTBearerAuthenticationConfig
|
|
9
11
|
from .decoders import JWTBearerTokenDecoder, JWTBearerTokenDecoderAbstract
|
|
@@ -16,7 +18,7 @@ from .verifiers import JWTNoneVerifier, JWTVerifierAbstract
|
|
|
16
18
|
JWTBearerPayloadGeneric = TypeVar("JWTBearerPayloadGeneric", bound=JWTPayload)
|
|
17
19
|
|
|
18
20
|
|
|
19
|
-
class JWTAuthenticationServiceAbstract(
|
|
21
|
+
class JWTAuthenticationServiceAbstract(AuthenticationAbstract, Generic[JWTBearerPayloadGeneric]):
|
|
20
22
|
"""JWT authentication service.
|
|
21
23
|
|
|
22
24
|
This service is the orchestrator for the JWT bearer authentication.
|
|
@@ -45,9 +47,7 @@ class JWTAuthenticationServiceAbstract(ABC, Generic[JWTBearerPayloadGeneric]):
|
|
|
45
47
|
# Runtime variables
|
|
46
48
|
self._jwt: JWTToken | None = None
|
|
47
49
|
self._jwt_payload: JWTBearerPayloadGeneric | None = None
|
|
48
|
-
|
|
49
|
-
self._raise_exception: bool = raise_exception
|
|
50
|
-
self._errors: list[Exception] = []
|
|
50
|
+
super().__init__(raise_exception=raise_exception)
|
|
51
51
|
|
|
52
52
|
@property
|
|
53
53
|
def verifier(self) -> JWTVerifierAbstract[JWTBearerPayloadGeneric]:
|
|
@@ -102,20 +102,12 @@ class JWTAuthenticationServiceAbstract(ABC, Generic[JWTBearerPayloadGeneric]):
|
|
|
102
102
|
raise InvalidJWTError(message="Invalid Credentials")
|
|
103
103
|
return JWTToken(authorization_header.split(sep=" ")[1])
|
|
104
104
|
|
|
105
|
-
def has_errors(self) -> bool:
|
|
106
|
-
"""Check if the service has errors.
|
|
107
|
-
|
|
108
|
-
Returns:
|
|
109
|
-
bool: True if the service has errors, False otherwise.
|
|
110
|
-
"""
|
|
111
|
-
return len(self._errors) > 0
|
|
112
|
-
|
|
113
105
|
@property
|
|
114
106
|
def payload(self) -> JWTBearerPayloadGeneric | None:
|
|
115
107
|
"""Get the JWT bearer payload.
|
|
116
108
|
|
|
117
109
|
Returns:
|
|
118
|
-
JWTBearerPayloadGeneric | None: The JWT bearer payload.
|
|
110
|
+
JWTBearerPayloadGeneric | None: The JWT bearer payload, or None if not authenticated yet.
|
|
119
111
|
"""
|
|
120
112
|
return self._jwt_payload
|
|
121
113
|
|
|
@@ -139,26 +131,17 @@ class JWTAuthenticationServiceAbstract(ABC, Generic[JWTBearerPayloadGeneric]):
|
|
|
139
131
|
authorization_header = self.extract_authorization_header_from_request(request=request)
|
|
140
132
|
self._jwt = self.extract_bearer_token_from_authorization_header(authorization_header=authorization_header)
|
|
141
133
|
except (MissingJWTCredentialsError, InvalidJWTError) as e:
|
|
142
|
-
|
|
143
|
-
self._errors.append(e)
|
|
144
|
-
return
|
|
145
|
-
raise
|
|
134
|
+
return self.raise_exception(HTTPException(status_code=HTTPStatus.UNAUTHORIZED, detail=str(e)))
|
|
146
135
|
|
|
147
136
|
try:
|
|
148
137
|
self._jwt_payload = await self._jwt_decoder.decode_payload(jwt_token=self._jwt)
|
|
149
138
|
except (InvalidJWTError, InvalidJWTPayploadError) as e:
|
|
150
|
-
|
|
151
|
-
self._errors.append(e)
|
|
152
|
-
return
|
|
153
|
-
raise
|
|
139
|
+
return self.raise_exception(HTTPException(status_code=HTTPStatus.FORBIDDEN, detail=str(e)))
|
|
154
140
|
|
|
155
141
|
try:
|
|
156
142
|
await self._jwt_verifier.verify(jwt_token=self._jwt, jwt_payload=self._jwt_payload)
|
|
157
143
|
except NotVerifiedJWTError as e:
|
|
158
|
-
|
|
159
|
-
self._errors.append(e)
|
|
160
|
-
return
|
|
161
|
-
raise
|
|
144
|
+
return self.raise_exception(HTTPException(status_code=HTTPStatus.FORBIDDEN, detail=str(e)))
|
|
162
145
|
|
|
163
146
|
return
|
|
164
147
|
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"""Provide Kratos Session and Identity classes."""
|
|
2
|
+
|
|
3
|
+
from http import HTTPStatus
|
|
4
|
+
|
|
5
|
+
from fastapi import HTTPException, Request
|
|
6
|
+
|
|
7
|
+
from fastapi_factory_utilities.core.security.abstracts import AuthenticationAbstract
|
|
8
|
+
from fastapi_factory_utilities.core.services.kratos import (
|
|
9
|
+
KratosOperationError,
|
|
10
|
+
KratosService,
|
|
11
|
+
KratosSessionInvalidError,
|
|
12
|
+
KratosSessionObject,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class KratosSessionAuthenticationService(AuthenticationAbstract):
|
|
17
|
+
"""Kratos Session class."""
|
|
18
|
+
|
|
19
|
+
DEFAULT_COOKIE_NAME: str = "ory_kratos_session"
|
|
20
|
+
|
|
21
|
+
def __init__(
|
|
22
|
+
self, kratos_service: KratosService, cookie_name: str = DEFAULT_COOKIE_NAME, raise_exception: bool = True
|
|
23
|
+
) -> None:
|
|
24
|
+
"""Initialize the KratosSessionAuthentication class.
|
|
25
|
+
|
|
26
|
+
Args:
|
|
27
|
+
kratos_service (KratosService): Kratos service object.
|
|
28
|
+
cookie_name (str): Name of the cookie to extract the session.
|
|
29
|
+
raise_exception (bool): Whether to raise an exception or return None.
|
|
30
|
+
"""
|
|
31
|
+
self._kratos_service: KratosService = kratos_service
|
|
32
|
+
self._cookie_name: str = cookie_name
|
|
33
|
+
self._session: KratosSessionObject
|
|
34
|
+
super().__init__(raise_exception=raise_exception)
|
|
35
|
+
|
|
36
|
+
def _extract_cookie(self, request: Request) -> str | None:
|
|
37
|
+
"""Extract the cookie from the request.
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
request (Request): FastAPI request object.
|
|
41
|
+
|
|
42
|
+
Returns:
|
|
43
|
+
str | None: Cookie value or None if not found.
|
|
44
|
+
|
|
45
|
+
Raises:
|
|
46
|
+
HTTPException: If the cookie is missing.
|
|
47
|
+
"""
|
|
48
|
+
return request.cookies.get(self._cookie_name, None)
|
|
49
|
+
|
|
50
|
+
@property
|
|
51
|
+
def session(self) -> KratosSessionObject:
|
|
52
|
+
"""Get the Kratos session.
|
|
53
|
+
|
|
54
|
+
Returns:
|
|
55
|
+
KratosSessionObject: Kratos session object.
|
|
56
|
+
"""
|
|
57
|
+
return self._session
|
|
58
|
+
|
|
59
|
+
async def authenticate(self, request: Request) -> None:
|
|
60
|
+
"""Extract the Kratos session from the request.
|
|
61
|
+
|
|
62
|
+
Args:
|
|
63
|
+
request (Request): FastAPI request object.
|
|
64
|
+
kratos_service (KratosService): Kratos service object.
|
|
65
|
+
|
|
66
|
+
Returns:
|
|
67
|
+
None: If the authentication is successful or not raise_exception is False.
|
|
68
|
+
|
|
69
|
+
Raises:
|
|
70
|
+
HTTPException: If the session is invalid and raise_exception is True.
|
|
71
|
+
"""
|
|
72
|
+
cookie: str | None = self._extract_cookie(request)
|
|
73
|
+
if not cookie:
|
|
74
|
+
return self.raise_exception(
|
|
75
|
+
HTTPException(
|
|
76
|
+
status_code=HTTPStatus.UNAUTHORIZED,
|
|
77
|
+
detail="Missing Credentials",
|
|
78
|
+
)
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
try:
|
|
82
|
+
self._session = await self._kratos_service.whoami(cookie_value=cookie)
|
|
83
|
+
except KratosSessionInvalidError:
|
|
84
|
+
return self.raise_exception(
|
|
85
|
+
HTTPException(
|
|
86
|
+
status_code=HTTPStatus.UNAUTHORIZED,
|
|
87
|
+
detail="Invalid Credentials",
|
|
88
|
+
)
|
|
89
|
+
)
|
|
90
|
+
except KratosOperationError:
|
|
91
|
+
return self.raise_exception(
|
|
92
|
+
HTTPException(
|
|
93
|
+
status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
|
|
94
|
+
detail="Internal Server Error",
|
|
95
|
+
)
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
return
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
"""Provide Kratos Session and Identity classes."""
|
|
2
|
-
|
|
3
|
-
from enum import StrEnum
|
|
4
|
-
from typing import Annotated
|
|
5
|
-
|
|
6
|
-
from fastapi import Depends, HTTPException, Request
|
|
7
|
-
|
|
8
|
-
from fastapi_factory_utilities.core.services.kratos import (
|
|
9
|
-
KratosOperationError,
|
|
10
|
-
KratosService,
|
|
11
|
-
KratosSessionInvalidError,
|
|
12
|
-
KratosSessionObject,
|
|
13
|
-
depends_kratos_service,
|
|
14
|
-
)
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
class KratosSessionAuthenticationErrors(StrEnum):
|
|
18
|
-
"""Kratos Session Authentication Errors."""
|
|
19
|
-
|
|
20
|
-
MISSING_CREDENTIALS = "Missing Credentials"
|
|
21
|
-
INVALID_CREDENTIALS = "Invalid Credentials"
|
|
22
|
-
INTERNAL_SERVER_ERROR = "Internal Server Error"
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
class KratosSessionAuthentication:
|
|
26
|
-
"""Kratos Session class."""
|
|
27
|
-
|
|
28
|
-
DEFAULT_COOKIE_NAME: str = "ory_kratos_session"
|
|
29
|
-
|
|
30
|
-
def __init__(self, cookie_name: str = DEFAULT_COOKIE_NAME, raise_exception: bool = True) -> None:
|
|
31
|
-
"""Initialize the KratosSessionAuthentication class.
|
|
32
|
-
|
|
33
|
-
Args:
|
|
34
|
-
cookie_name (str): Name of the cookie to extract the session
|
|
35
|
-
raise_exception (bool): Whether to raise an exception or return None
|
|
36
|
-
"""
|
|
37
|
-
self._cookie_name: str = cookie_name
|
|
38
|
-
self._raise_exception: bool = raise_exception
|
|
39
|
-
|
|
40
|
-
def _extract_cookie(self, request: Request) -> str | None:
|
|
41
|
-
"""Extract the cookie from the request.
|
|
42
|
-
|
|
43
|
-
Args:
|
|
44
|
-
request (Request): FastAPI request object.
|
|
45
|
-
|
|
46
|
-
Returns:
|
|
47
|
-
str | None: Cookie value or None if not found.
|
|
48
|
-
|
|
49
|
-
Raises:
|
|
50
|
-
HTTPException: If the cookie is missing.
|
|
51
|
-
"""
|
|
52
|
-
return request.cookies.get(self._cookie_name, None)
|
|
53
|
-
|
|
54
|
-
async def __call__(
|
|
55
|
-
self, request: Request, kratos_service: Annotated[KratosService, Depends(depends_kratos_service)]
|
|
56
|
-
) -> KratosSessionObject | KratosSessionAuthenticationErrors:
|
|
57
|
-
"""Extract the Kratos session from the request.
|
|
58
|
-
|
|
59
|
-
Args:
|
|
60
|
-
request (Request): FastAPI request object.
|
|
61
|
-
kratos_service (KratosService): Kratos service object.
|
|
62
|
-
|
|
63
|
-
Returns:
|
|
64
|
-
KratosSessionObject | KratosSessionAuthenticationErrors: Kratos session object or error.
|
|
65
|
-
|
|
66
|
-
Raises:
|
|
67
|
-
HTTPException: If the session is invalid and raise_exception is True.
|
|
68
|
-
"""
|
|
69
|
-
cookie: str | None = self._extract_cookie(request)
|
|
70
|
-
if not cookie:
|
|
71
|
-
if self._raise_exception:
|
|
72
|
-
raise HTTPException(
|
|
73
|
-
status_code=401,
|
|
74
|
-
detail=KratosSessionAuthenticationErrors.MISSING_CREDENTIALS,
|
|
75
|
-
)
|
|
76
|
-
else:
|
|
77
|
-
return KratosSessionAuthenticationErrors.MISSING_CREDENTIALS
|
|
78
|
-
|
|
79
|
-
try:
|
|
80
|
-
session: KratosSessionObject = await kratos_service.whoami(cookie_value=cookie)
|
|
81
|
-
except KratosSessionInvalidError as e:
|
|
82
|
-
if self._raise_exception:
|
|
83
|
-
raise HTTPException(
|
|
84
|
-
status_code=401,
|
|
85
|
-
detail="Invalid Credentials",
|
|
86
|
-
) from e
|
|
87
|
-
else:
|
|
88
|
-
return KratosSessionAuthenticationErrors.INVALID_CREDENTIALS
|
|
89
|
-
except KratosOperationError as e:
|
|
90
|
-
if self._raise_exception:
|
|
91
|
-
raise HTTPException(
|
|
92
|
-
status_code=500,
|
|
93
|
-
detail="Internal Server Error",
|
|
94
|
-
) from e
|
|
95
|
-
else:
|
|
96
|
-
return KratosSessionAuthenticationErrors.INTERNAL_SERVER_ERROR
|
|
97
|
-
|
|
98
|
-
return session
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|