Skip to content

Commit c524402

Browse files
committed
feat(jwt): extend Token.encode() to support custom headers and encoder options
1 parent f12580b commit c524402

2 files changed

Lines changed: 30 additions & 1 deletion

File tree

litestar/security/jwt/token.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,12 @@
1111
from litestar.exceptions import ImproperlyConfiguredException, NotAuthorizedException
1212

1313
if TYPE_CHECKING:
14+
import json
15+
16+
from jwt.algorithms import AllowedPrivateKeys
1417
from typing_extensions import Self
1518

19+
1620
__all__ = (
1721
"JWTDecodeOptions",
1822
"Token",
@@ -192,12 +196,22 @@ def decode(
192196
) as e:
193197
raise NotAuthorizedException("Invalid token") from e
194198

195-
def encode(self, secret: str, algorithm: str) -> str:
199+
def encode(
200+
self,
201+
secret: AllowedPrivateKeys | str | bytes,
202+
algorithm: str,
203+
headers: dict[str, Any] | None = None,
204+
json_encoder: type[json.JSONEncoder] | None = None,
205+
sort_headers: bool = True,
206+
) -> str:
196207
"""Encode the token instance into a string.
197208
198209
Args:
199210
secret: The secret with which the JWT is encoded.
200211
algorithm: The algorithm used to encode the JWT.
212+
headers: Optional headers to include in the JWT (e.g., {"kid": "..."}).
213+
json_encoder: Optional custom JSON encoder class to serialize the payload.
214+
sort_headers: Whether to sort the JWT headers before encoding. Defaults to True.
201215
202216
Returns:
203217
An encoded token string.
@@ -210,6 +224,9 @@ def encode(self, secret: str, algorithm: str) -> str:
210224
payload={k: v for k, v in asdict(self).items() if v is not None},
211225
key=secret,
212226
algorithm=algorithm,
227+
headers=headers,
228+
json_encoder=json_encoder,
229+
sort_headers=sort_headers,
213230
)
214231
except (jwt.DecodeError, NotImplementedError) as e:
215232
raise ImproperlyConfiguredException("Failed to encode token") from e

tests/unit/test_security/test_jwt/test_token.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,3 +222,15 @@ def decode_payload(
222222
_secret = secrets.token_hex()
223223
encoded = CustomToken(exp=datetime.now() + timedelta(days=1), sub="foo").encode(_secret, "HS256")
224224
assert CustomToken.decode(encoded, secret=_secret, algorithm="HS256").sub == "some-random-value"
225+
226+
227+
def test_token_encode_includes_custom_headers() -> None:
228+
token = Token(exp=datetime.now() + timedelta(days=1), sub="some-random-value")
229+
custom_headers = {"kid": "key-id"}
230+
encoded = token.encode(secret=secrets.token_hex(), algorithm="HS256", headers=custom_headers)
231+
header = jwt.get_unverified_header(encoded)
232+
233+
assert header["alg"] == "HS256"
234+
assert header["typo"] == "JWT"
235+
assert "kid" in header
236+
assert header["kid"] == custom_headers["kid"]

0 commit comments

Comments
 (0)