gh_UserManager/apps/api/apps/authentication/tokens.py
bermooda-company 1f995295a6 last changes
2026-10-22 16:58:51 +03:30

42 lines
1.3 KiB
Python

"""JWT issuance helpers.
``rest_framework_simplejwt`` signs tokens without a ``kid`` header, which forces
consumers to try every published key and makes rotation impossible. Tokens are
therefore encoded here with the current key's ``kid`` attached.
"""
import jwt
from django.conf import settings
from rest_framework_simplejwt.exceptions import TokenError
from rest_framework_simplejwt.tokens import AccessToken
from .keys import signing_jwk
def encode(payload):
"""Sign ``payload`` with the platform key, tagging the JWS header with ``kid``."""
jwk = signing_jwk()
if jwk is None:
raise TokenError(
"No signing key is configured. Run `python manage.py "
"generate_signing_keys` before issuing tokens."
)
algorithm = settings.SIMPLE_JWT.get("ALGORITHM", "RS256")
token = jwt.encode(
payload,
settings.SIMPLE_JWT["SIGNING_KEY"],
algorithm=algorithm,
headers={"kid": jwk["kid"]},
)
return token.decode() if isinstance(token, bytes) else token
class IdentifiedAccessToken(AccessToken):
"""``AccessToken`` whose encoded form carries the signing key's ``kid``.
Decoding is unchanged: an unknown header parameter is ignored by PyJWT, so
existing ``AccessToken(token)`` reads keep working.
"""
def __str__(self):
return encode(self.payload)