jamlib 3.1.0__tar.gz → 3.2.0b0__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.
Files changed (121) hide show
  1. {jamlib-3.1.0/src/jamlib.egg-info → jamlib-3.2.0b0}/PKG-INFO +1 -1
  2. {jamlib-3.1.0 → jamlib-3.2.0b0}/pyproject.toml +1 -1
  3. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/__base__.py +29 -22
  4. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/__deprecated__.py +1 -1
  5. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/__init__.py +1 -1
  6. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/aio/__base__.py +28 -0
  7. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/aio/instance.py +39 -0
  8. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/exceptions/__init__.py +24 -21
  9. jamlib-3.2.0b0/src/jam/exceptions/jose.py +23 -0
  10. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/exceptions/jwt.py +4 -2
  11. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/instance.py +72 -10
  12. jamlib-3.2.0b0/src/jam/jose/__algorithms__.py +1161 -0
  13. jamlib-3.2.0b0/src/jam/jose/__base__.py +348 -0
  14. jamlib-3.2.0b0/src/jam/jose/__init__.py +19 -0
  15. jamlib-3.2.0b0/src/jam/jose/jwe.py +197 -0
  16. jamlib-3.2.0b0/src/jam/jose/jwk.py +504 -0
  17. jamlib-3.2.0b0/src/jam/jose/jws.py +192 -0
  18. jamlib-3.2.0b0/src/jam/jose/jwt.py +498 -0
  19. jamlib-3.2.0b0/src/jam/jose/lists/__base__.py +40 -0
  20. jamlib-3.2.0b0/src/jam/jose/lists/__init__.py +11 -0
  21. jamlib-3.2.0b0/src/jam/jose/lists/json.py +136 -0
  22. jamlib-3.2.0b0/src/jam/jose/lists/memory.py +111 -0
  23. jamlib-3.2.0b0/src/jam/jose/lists/redis.py +161 -0
  24. {jamlib-3.1.0/src/jam/jwt → jamlib-3.2.0b0/src/jam/jose}/utils.py +3 -2
  25. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/jwt/__base__.py +2 -0
  26. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/jwt/lists/__base__.py +3 -0
  27. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/jwt/lists/json.py +2 -0
  28. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/jwt/lists/redis.py +2 -0
  29. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/jwt/module.py +2 -0
  30. jamlib-3.2.0b0/src/jam/jwt/utils.py +36 -0
  31. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/tests/clients.py +56 -0
  32. {jamlib-3.1.0 → jamlib-3.2.0b0/src/jamlib.egg-info}/PKG-INFO +1 -1
  33. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jamlib.egg-info/SOURCES.txt +14 -0
  34. {jamlib-3.1.0 → jamlib-3.2.0b0}/LICENSE.md +0 -0
  35. {jamlib-3.1.0 → jamlib-3.2.0b0}/README.md +0 -0
  36. {jamlib-3.1.0 → jamlib-3.2.0b0}/setup.cfg +0 -0
  37. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/__base_encoder__.py +0 -0
  38. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/aio/__init__.py +0 -0
  39. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/aio/jwt/__init__.py +0 -0
  40. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/aio/oauth2/__base__.py +0 -0
  41. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/aio/oauth2/__init__.py +0 -0
  42. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/aio/oauth2/builtin/__init__.py +0 -0
  43. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/aio/oauth2/builtin/github.py +0 -0
  44. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/aio/oauth2/builtin/gitlab.py +0 -0
  45. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/aio/oauth2/builtin/google.py +0 -0
  46. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/aio/oauth2/builtin/yandex.py +0 -0
  47. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/aio/oauth2/client.py +0 -0
  48. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/aio/sessions/__base__.py +0 -0
  49. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/aio/sessions/__init__.py +0 -0
  50. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/aio/sessions/json.py +0 -0
  51. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/aio/sessions/redis.py +0 -0
  52. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/cli/__init__.py +0 -0
  53. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/cli/cli.py +0 -0
  54. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/cli/commands/__init__.py +0 -0
  55. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/cli/commands/keys.py +0 -0
  56. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/cli/commands/password.py +0 -0
  57. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/encoders.py +0 -0
  58. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/exceptions/base.py +0 -0
  59. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/exceptions/oauth2.py +0 -0
  60. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/exceptions/paseto.py +0 -0
  61. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/exceptions/plugins.py +0 -0
  62. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/exceptions/sessions.py +0 -0
  63. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/ext/__init__.py +0 -0
  64. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/ext/fastapi/__init__.py +0 -0
  65. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/ext/flask/__init__.py +0 -0
  66. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/ext/flask/extensions.py +0 -0
  67. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/ext/flask/objects.py +0 -0
  68. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/ext/litestar/__init__.py +0 -0
  69. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/ext/litestar/middleware.py +0 -0
  70. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/ext/litestar/objects.py +0 -0
  71. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/ext/litestar/plugins.py +0 -0
  72. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/ext/starlette/__init__.py +0 -0
  73. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/ext/starlette/backends.py +0 -0
  74. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/ext/starlette/objects.py +0 -0
  75. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/jwt/__algorithms__.py +0 -0
  76. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/jwt/__init__.py +0 -0
  77. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/jwt/__types__.py +0 -0
  78. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/jwt/lists/__init__.py +0 -0
  79. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/logger.py +0 -0
  80. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/oauth2/__base__.py +0 -0
  81. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/oauth2/__init__.py +0 -0
  82. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/oauth2/builtin/__init__.py +0 -0
  83. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/oauth2/builtin/github.py +0 -0
  84. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/oauth2/builtin/gitlab.py +0 -0
  85. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/oauth2/builtin/google.py +0 -0
  86. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/oauth2/builtin/yandex.py +0 -0
  87. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/oauth2/client.py +0 -0
  88. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/otp/__base__.py +0 -0
  89. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/otp/__init__.py +0 -0
  90. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/otp/hotp.py +0 -0
  91. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/otp/totp.py +0 -0
  92. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/paseto/__base__.py +0 -0
  93. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/paseto/__init__.py +0 -0
  94. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/paseto/utils.py +0 -0
  95. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/paseto/v1.py +0 -0
  96. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/paseto/v2.py +0 -0
  97. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/paseto/v3.py +0 -0
  98. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/paseto/v4.py +0 -0
  99. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/py.typed +0 -0
  100. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/sessions/__base__.py +0 -0
  101. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/sessions/__init__.py +0 -0
  102. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/sessions/json.py +0 -0
  103. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/sessions/redis.py +0 -0
  104. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/tests/__init__.py +0 -0
  105. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/tests/fakers.py +0 -0
  106. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/utils/__init__.py +0 -0
  107. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/utils/aes.py +0 -0
  108. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/utils/await_maybe.py +0 -0
  109. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/utils/basic_auth.py +0 -0
  110. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/utils/config_maker.py +0 -0
  111. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/utils/ed.py +0 -0
  112. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/utils/otp_keys.py +0 -0
  113. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/utils/rsa.py +0 -0
  114. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/utils/salt_hash.py +0 -0
  115. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/utils/symmetric.py +0 -0
  116. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/utils/xchacha20poly1305.py +0 -0
  117. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jam/utils/xor.py +0 -0
  118. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jamlib.egg-info/dependency_links.txt +0 -0
  119. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jamlib.egg-info/entry_points.txt +0 -0
  120. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jamlib.egg-info/requires.txt +0 -0
  121. {jamlib-3.1.0 → jamlib-3.2.0b0}/src/jamlib.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: jamlib
3
- Version: 3.1.0
3
+ Version: 3.2.0b0
4
4
  Summary: Simple and universal library for authorization.
5
5
  Author-email: Makridenko Adrian <adrianmakridenko@duck.com>, Ksenia Travnikova <kseniatravnikova@duck.com>
6
6
  License: Apache-2.0
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "jamlib"
3
- version = "3.1.0"
3
+ version = "3.2.0b0"
4
4
  description = "Simple and universal library for authorization."
5
5
  authors = [
6
6
  {name = "Makridenko Adrian",email = "adrianmakridenko@duck.com"},
@@ -6,7 +6,7 @@ from typing import Any, Literal
6
6
 
7
7
  from jam.encoders import BaseEncoder, JsonEncoder
8
8
  from jam.exceptions import JamConfigurationError
9
- from jam.jwt.__base__ import BaseJWT
9
+ from jam.jose.__base__ import BaseJWT
10
10
  from jam.logger import BaseLogger, JamLogger
11
11
  from jam.oauth2.__base__ import BaseOAuth2Client
12
12
  from jam.otp.__base__ import BaseOTP, OTPConfig
@@ -189,36 +189,41 @@ class BaseJam(ABC):
189
189
  raise JamConfigurationError(message="Unknown OTP type.")
190
190
 
191
191
  @abstractmethod
192
- def jwt_make_payload(
193
- self, exp: int | None, data: dict[str, Any]
194
- ) -> dict[str, Any]:
195
- """Make JWT-specific payload.
196
-
197
- Args:
198
- exp (int | None): Token expire, if None -> use default
199
- data (dict[str, Any]): Data to payload
200
-
201
- Returns:
202
- dict[str, Any]: Payload
203
- """
204
- raise NotImplementedError
205
-
206
- @abstractmethod
207
- def jwt_create(self, payload: dict[str, Any]) -> str:
208
- """Create JWT token.
192
+ def jwt_encode(
193
+ self,
194
+ iss: str | None = None,
195
+ sub: str | None = None,
196
+ aud: str | None = None,
197
+ exp: int | None = None,
198
+ nbf: int | None = None,
199
+ *,
200
+ payload: dict[str, Any] | None = None,
201
+ header: dict[str, Any] | None = None,
202
+ ) -> str:
203
+ """Encode the JWT with the given expire, header, and payload.
209
204
 
210
205
  Args:
211
- payload (dict[str, Any]): Data payload
206
+ exp (int | None): The expiration time in seconds.
207
+ nbf (int | None): The not-before time in seconds.
208
+ iss (str | None): The issuer.
209
+ sub (str | None): The subject.
210
+ aud (str | None): The audience.
211
+ header (dict[str, Any] | None): The header to include in the JWT.
212
+ payload (dict[str, Any] | None): The payload to include in the JWT.
212
213
 
213
214
  Returns:
214
- str: New token
215
-
215
+ str: The encoded JWT.
216
216
  """
217
217
  raise NotImplementedError
218
218
 
219
219
  @abstractmethod
220
220
  def jwt_decode(
221
- self, token: str, check_exp: bool = True, check_list: bool = True
221
+ self,
222
+ token: str,
223
+ check_exp: bool = True,
224
+ check_list: bool = True,
225
+ check_nbf: bool = False,
226
+ include_headers: bool = False,
222
227
  ) -> dict[str, Any]:
223
228
  """Verify and decode JWT token.
224
229
 
@@ -226,6 +231,8 @@ class BaseJam(ABC):
226
231
  token (str): JWT token
227
232
  check_exp (bool): Check expire
228
233
  check_list (bool): Check white/black list. Docs: https://jam.makridenko.ru/jwt/lists/what/
234
+ check_nbf (bool): Check not-before time
235
+ include_headers (bool): Include headers in the decoded payload
229
236
 
230
237
  Returns:
231
238
  dict[str, Any]: Decoded payload
@@ -8,7 +8,7 @@ def deprecated(replacement: str | None = None):
8
8
  """Mark funcs are deprecated."""
9
9
 
10
10
  def decorator(func):
11
- msg = f"Function {func.__name__}() is deprecated."
11
+ msg = f"{func.__name__}() is deprecated."
12
12
  if replacement:
13
13
  msg += f" {replacement}"
14
14
 
@@ -12,5 +12,5 @@ from jam.encoders import JsonEncoder
12
12
  from jam.instance import Jam
13
13
 
14
14
 
15
- __version__ = "3.0.0"
15
+ __version__ = "3.2.0b0"
16
16
  __all__ = ["Jam", "JsonEncoder", "BaseJam", "BaseEncoder"]
@@ -45,6 +45,34 @@ class BaseAsyncJam(BaseJam):
45
45
  """
46
46
  raise NotImplementedError
47
47
 
48
+ @abstractmethod
49
+ async def jwt_encode(
50
+ self,
51
+ iss: str | None = None,
52
+ sub: str | None = None,
53
+ aud: str | None = None,
54
+ exp: int | None = None,
55
+ nbf: int | None = None,
56
+ *,
57
+ payload: dict[str, Any] | None = None,
58
+ header: dict[str, Any] | None = None,
59
+ ) -> str:
60
+ """Encode the JWT with the given expire, header, and payload.
61
+
62
+ Args:
63
+ exp (int | None): The expiration time in seconds.
64
+ nbf (int | None): The not-before time in seconds.
65
+ iss (str | None): The issuer.
66
+ sub (str | None): The subject.
67
+ aud (str | None): The audience.
68
+ header (dict[str, Any] | None): The header to include in the JWT.
69
+ payload (dict[str, Any] | None): The payload to include in the JWT.
70
+
71
+ Returns:
72
+ str: The encoded JWT.
73
+ """
74
+ raise NotImplementedError
75
+
48
76
  @abstractmethod
49
77
  async def jwt_decode( # type: ignore[override]
50
78
  self, token: str, check_exp: bool = True, check_list: bool = True
@@ -68,6 +68,45 @@ class Jam(BaseAsyncJam):
68
68
 
69
69
  return token
70
70
 
71
+ async def jwt_encode(
72
+ self,
73
+ iss: str | None = None,
74
+ sub: str | None = None,
75
+ aud: str | None = None,
76
+ exp: int | None = None,
77
+ nbf: int | None = None,
78
+ *,
79
+ payload: dict[str, Any] | None = None,
80
+ header: dict[str, Any] | None = None,
81
+ ) -> str:
82
+ """Encode the JWT with the given expire, header, and payload.
83
+
84
+ Args:
85
+ exp (int | None): The expiration time in seconds.
86
+ nbf (int | None): The not-before time in seconds.
87
+ iss (str | None): The issuer.
88
+ sub (str | None): The subject.
89
+ aud (str | None): The audience.
90
+ header (dict[str, Any] | None): The header to include in the JWT.
91
+ payload (dict[str, Any] | None): The payload to include in the JWT.
92
+
93
+ Returns:
94
+ str: The encoded JWT.
95
+ """
96
+ assert self.jwt is not None
97
+ token = self.jwt.encode(
98
+ iss=iss,
99
+ sub=sub,
100
+ aud=aud,
101
+ exp=exp,
102
+ nbf=nbf,
103
+ payload=payload,
104
+ header=header,
105
+ )
106
+ if self.jwt.list and self.jwt.list.__list_type__ == "white":
107
+ self.jwt.list.add(token)
108
+ return token
109
+
71
110
  async def jwt_decode(
72
111
  self, token: str, check_exp: bool = True, check_list: bool = True
73
112
  ) -> dict[str, Any]:
@@ -1,49 +1,48 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
- """
4
- All Jam exceptions
5
- """
3
+ """All Jam exceptions"""
6
4
 
7
- from .base import JamError, JamConfigurationError, JamValidationError
8
-
9
- from .oauth2 import (
10
- JamOAuth2Error,
11
- JamOAuth2EmptyRaw,
12
- JamOAuth2ProviderNotConfigured,
5
+ from .base import JamConfigurationError, JamError, JamValidationError
6
+ from .jose import (
7
+ JamJWEEncryptionError,
8
+ JamJWEDecryptionError,
9
+ JamJWKValidationError,
10
+ JamJWSVerificationError,
13
11
  )
14
-
15
12
  from .jwt import (
13
+ JamJWTEmptyPrivateKey,
14
+ JamJWTEmptySecretKey,
16
15
  JamJWTExpired,
17
16
  JamJWTInBlackList,
18
17
  JamJWTNotInWhiteList,
19
- JamJWTEmptyPrivateKey,
20
- JamJWTEmptySecretKey,
21
18
  JamJWTUnsupportedAlgorithm,
22
19
  JamJWTValidationError,
23
20
  )
24
-
21
+ from .oauth2 import (
22
+ JamOAuth2EmptyRaw,
23
+ JamOAuth2Error,
24
+ JamOAuth2ProviderNotConfigured,
25
+ )
25
26
  from .paseto import (
26
- JamPASETOInvalidSymmetricKey,
27
- JamPASETOInvalidRSAKey,
28
27
  JamPASETOInvalidED25519Key,
29
- JamPASETOInvalidSecp384r1Key,
30
- JamPASTOKeyVerificationError,
31
28
  JamPASETOInvalidPurpose,
29
+ JamPASETOInvalidRSAKey,
30
+ JamPASETOInvalidSecp384r1Key,
31
+ JamPASETOInvalidSymmetricKey,
32
32
  JamPASETOInvalidTokenFormat,
33
+ JamPASTOKeyVerificationError,
33
34
  )
34
-
35
35
  from .plugins import (
36
36
  JamFlaskPluginConfigError,
37
37
  JamFlaskPluginError,
38
38
  JamLitestarPluginConfigError,
39
39
  JamLitestarPluginError,
40
40
  JamStarlettePluginConfigError,
41
- JamStarlettePluginError
41
+ JamStarlettePluginError,
42
42
  )
43
-
44
43
  from .sessions import (
45
- JamSessionNotFound,
46
44
  JamSessionEmptyAESKey,
45
+ JamSessionNotFound,
47
46
  )
48
47
 
49
48
 
@@ -61,6 +60,10 @@ __all__ = [
61
60
  "JamJWTEmptySecretKey",
62
61
  "JamJWTUnsupportedAlgorithm",
63
62
  "JamJWTValidationError",
63
+ "JamJWSVerificationError",
64
+ "JamJWKValidationError",
65
+ "JamJWEEncryptionError",
66
+ "JamJWEDecryptionError",
64
67
  "JamPASETOInvalidSymmetricKey",
65
68
  "JamPASETOInvalidRSAKey",
66
69
  "JamPASETOInvalidED25519Key",
@@ -0,0 +1,23 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ from .base import JamValidationError
4
+
5
+
6
+ class JamJWSVerificationError(JamValidationError):
7
+ default_message = "JWS signature verification failed."
8
+ default_code = "jws.verification_error"
9
+
10
+
11
+ class JamJWKValidationError(JamValidationError):
12
+ default_message = "JWK validation failed."
13
+ default_code = "jwk.validation_error"
14
+
15
+
16
+ class JamJWEEncryptionError(JamValidationError):
17
+ default_message = "JWE encryption failed."
18
+ default_code = "jwe.encryption_error"
19
+
20
+
21
+ class JamJWEDecryptionError(JamValidationError):
22
+ default_message = "JWE decryption failed."
23
+ default_code = "jwe.decryption_error"
@@ -1,6 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
- from .base import JamError, JamValidationError, JamConfigurationError
3
+ from .base import JamConfigurationError, JamError, JamValidationError
4
4
 
5
5
 
6
6
  class JamJWTExpired(JamError):
@@ -24,7 +24,9 @@ class JamJWTEmptySecretKey(JamConfigurationError):
24
24
 
25
25
 
26
26
  class JamJWTEmptyPrivateKey(JamConfigurationError):
27
- default_message = "For asymmetric encryption, you must specify `private_key`."
27
+ default_message = (
28
+ "For asymmetric encryption, you must specify `private_key`."
29
+ )
28
30
  default_code = "jwt.config.empty_private_key"
29
31
 
30
32
 
@@ -5,9 +5,9 @@ from typing import Any
5
5
  import uuid
6
6
 
7
7
  from jam.__base__ import BaseJam
8
+ from jam.__deprecated__ import deprecated
8
9
  from jam.exceptions import (
9
10
  JamConfigurationError,
10
- JamJWTExpired,
11
11
  JamJWTInBlackList,
12
12
  JamJWTNotInWhiteList,
13
13
  )
@@ -17,18 +17,24 @@ class Jam(BaseJam):
17
17
  """Main instance."""
18
18
 
19
19
  MODULES: dict[str, str] = {
20
- "jwt": "jam.jwt.create_instance",
20
+ "jwt": "jam.jose.JWT",
21
21
  "session": "jam.sessions.create_instance",
22
22
  "oauth2": "jam.oauth2.create_instance",
23
23
  "paseto": "jam.paseto.create_instance",
24
24
  "otp": "jam.otp.__base__.OTPConfig",
25
25
  }
26
26
 
27
+ @deprecated(
28
+ "This method is deprecated; the JWT payload is generated automatically in accordance with the specification."
29
+ )
27
30
  def jwt_make_payload(
28
31
  self, exp: int | None, data: dict[str, Any]
29
32
  ) -> dict[str, Any]:
30
33
  """Make JWT-specific payload.
31
34
 
35
+ !!! Deprecated
36
+ This method is deprecated; the JWT payload is generated automatically in accordance with the specification.
37
+
32
38
  Args:
33
39
  exp (int | None): Token expire
34
40
  data (dict[str, Any]): Data to payload
@@ -44,9 +50,13 @@ class Jam(BaseJam):
44
50
  payload = payload | data
45
51
  return payload
46
52
 
53
+ @deprecated("Use jam.jwt_encode")
47
54
  def jwt_create(self, payload: dict[str, Any]) -> str:
48
55
  """Create JWT token.
49
56
 
57
+ !!! Deprecated
58
+ Use Jam.jwt_encode
59
+
50
60
  Args:
51
61
  payload (dict[str, Any]): Data payload
52
62
 
@@ -68,8 +78,52 @@ class Jam(BaseJam):
68
78
 
69
79
  return token
70
80
 
81
+ def jwt_encode(
82
+ self,
83
+ iss: str | None = None,
84
+ sub: str | None = None,
85
+ aud: str | None = None,
86
+ exp: int | None = None,
87
+ nbf: int | None = None,
88
+ *,
89
+ payload: dict[str, Any] | None = None,
90
+ header: dict[str, Any] | None = None,
91
+ ) -> str:
92
+ """Encode the JWT with the given expire, header, and payload.
93
+
94
+ Args:
95
+ exp (int | None): The expiration time in seconds.
96
+ nbf (int | None): The not-before time in seconds.
97
+ iss (str | None): The issuer.
98
+ sub (str | None): The subject.
99
+ aud (str | None): The audience.
100
+ header (dict[str, Any] | None): The header to include in the JWT.
101
+ payload (dict[str, Any] | None): The payload to include in the JWT.
102
+
103
+ Returns:
104
+ str: The encoded JWT.
105
+ """
106
+ assert self.jwt is not None
107
+ token = self.jwt.encode(
108
+ iss=iss,
109
+ sub=sub,
110
+ aud=aud,
111
+ exp=exp,
112
+ nbf=nbf,
113
+ payload=payload,
114
+ header=header,
115
+ )
116
+ if self.jwt.list and self.jwt.list.__list_type__ == "white":
117
+ self.jwt.list.add(token)
118
+ return token
119
+
71
120
  def jwt_decode(
72
- self, token: str, check_exp: bool = True, check_list: bool = True
121
+ self,
122
+ token: str,
123
+ check_exp: bool = True,
124
+ check_list: bool = True,
125
+ check_nbf: bool = False,
126
+ include_headers: bool = False,
73
127
  ) -> dict[str, Any]:
74
128
  """Verify and decode JWT token.
75
129
 
@@ -77,6 +131,8 @@ class Jam(BaseJam):
77
131
  token (str): JWT token
78
132
  check_exp (bool): Check expire
79
133
  check_list (bool): Check white/black list. Docs: https://jam.makridenko.ru/jwt/lists/what/
134
+ check_nbf (bool): Check not-before time
135
+ include_headers (bool): Include headers in the decoded payload
80
136
 
81
137
  Returns:
82
138
  dict[str, Any]: Decoded payload
@@ -91,15 +147,21 @@ class Jam(BaseJam):
91
147
  f"Verifying JWT token (length: {len(token)} chars), check_exp={check_exp}, check_list={check_list}"
92
148
  )
93
149
  assert self.jwt is not None
94
- payload = self.jwt.decode(token)
150
+ data = self.jwt.decode(token, include_headers)
151
+
152
+ if include_headers:
153
+ payload = data
154
+ else:
155
+ payload = data
156
+ if isinstance(payload, bytes):
157
+ import json
158
+
159
+ payload = json.loads(payload)
160
+
95
161
  self._logger.debug(
96
162
  f"JWT token verified successfully, payload keys: {list(payload.keys())}"
97
163
  )
98
164
 
99
- if check_exp:
100
- if payload["exp"] < datetime.datetime.now().timestamp():
101
- raise JamJWTExpired
102
-
103
165
  if check_list:
104
166
  if not self.jwt.list:
105
167
  raise JamConfigurationError(
@@ -391,9 +453,9 @@ class Jam(BaseJam):
391
453
  Returns:
392
454
  dict: Payload
393
455
  """
394
- from jam.paseto.utils import payload_maker
456
+ from jam.paseto.utils import payload_maker as pm
395
457
 
396
- return payload_maker(expire=exp, data=data)
458
+ return pm(expire=exp, data=data)
397
459
 
398
460
  def paseto_create(
399
461
  self,