first commit
This commit is contained in:
@@ -0,0 +1,133 @@
|
||||
import json
|
||||
from json import JSONEncoder, JSONDecoder
|
||||
from collections.abc import Collection
|
||||
from ._rfc7519.claims import (
|
||||
convert_claims,
|
||||
Claims,
|
||||
ClaimsOption,
|
||||
BaseClaimsRegistry,
|
||||
JWTClaimsRegistry,
|
||||
)
|
||||
from ._rfc7519.security import check_sensitive_data
|
||||
from .jws import (
|
||||
JWSRegistry,
|
||||
serialize_compact,
|
||||
deserialize_compact,
|
||||
)
|
||||
from .jwe import (
|
||||
JWERegistry,
|
||||
encrypt_compact,
|
||||
decrypt_compact,
|
||||
)
|
||||
from .jwk import KeyFlexible
|
||||
from .errors import InvalidPayloadError
|
||||
from .util import to_bytes
|
||||
from .registry import Header
|
||||
|
||||
__all__ = [
|
||||
# types
|
||||
"Claims",
|
||||
"ClaimsOption",
|
||||
# modules
|
||||
"BaseClaimsRegistry",
|
||||
"JWTClaimsRegistry",
|
||||
"Token",
|
||||
# methods
|
||||
"encode",
|
||||
"decode",
|
||||
"check_sensitive_data",
|
||||
]
|
||||
|
||||
|
||||
class Token:
|
||||
"""The extracted token object, which contains ``header`` and ``claims``.
|
||||
|
||||
:param header: the header part of the JWT
|
||||
:param claims: the payload part of the JWT
|
||||
"""
|
||||
|
||||
def __init__(self, header: Header, claims: Claims):
|
||||
#: header in dict
|
||||
self.header = header
|
||||
#: payload claims in dict
|
||||
self.claims = claims
|
||||
|
||||
|
||||
def encode(
|
||||
header: Header,
|
||||
claims: Claims,
|
||||
key: KeyFlexible,
|
||||
algorithms: Collection[str] | None = None,
|
||||
registry: JWSRegistry | JWERegistry | None = None,
|
||||
encoder_cls: type[JSONEncoder] | None = None,
|
||||
default_type: str | None = "JWT",
|
||||
) -> str:
|
||||
"""Encode a JSON Web Token with the given header, and claims.
|
||||
|
||||
:param header: A dict of the JWT header
|
||||
:param claims: A dict of the JWT claims to be encoded
|
||||
:param key: key used to sign the signature
|
||||
:param algorithms: a collection (list, tuple, or set) of allowed algorithms
|
||||
:param registry: a ``JWSRegistry`` or ``JWERegistry`` to use
|
||||
:param encoder_cls: A JSONEncoder subclass to use
|
||||
:param default_type: default value of the ``typ`` header parameter
|
||||
"""
|
||||
if default_type is not None:
|
||||
_header = {"typ": default_type, **header}
|
||||
else:
|
||||
_header = {**header}
|
||||
payload = convert_claims(claims, encoder_cls)
|
||||
if isinstance(registry, JWERegistry):
|
||||
return encrypt_compact(_header, payload, key, algorithms, registry)
|
||||
else:
|
||||
return serialize_compact(_header, payload, key, algorithms, registry)
|
||||
|
||||
|
||||
def decode(
|
||||
value: bytes | str,
|
||||
key: KeyFlexible,
|
||||
algorithms: Collection[str] | None = None,
|
||||
registry: JWSRegistry | JWERegistry | None = None,
|
||||
decoder_cls: type[JSONDecoder] | None = None,
|
||||
) -> Token:
|
||||
"""Decode the JSON Web Token string with the given key, and validate
|
||||
it with the claims requests.
|
||||
|
||||
:param value: text of the JWT
|
||||
:param key: key used to verify the signature
|
||||
:param algorithms: a collection (list, tuple, or set) of allowed algorithms
|
||||
:param registry: a ``JWSRegistry`` or ``JWERegistry`` to use
|
||||
:param decoder_cls: A JSONDecoder subclass to use
|
||||
:raise BadSignatureError: when signature verification fails
|
||||
:raise InvalidPayloadError: when payload is not a valid JSON object
|
||||
"""
|
||||
_value = to_bytes(value)
|
||||
header: Header
|
||||
payload: bytes
|
||||
if isinstance(registry, JWERegistry):
|
||||
header, payload = _decode_jwe(_value, key, algorithms, registry)
|
||||
else:
|
||||
header, payload = _decode_jws(_value, key, algorithms, registry)
|
||||
|
||||
try:
|
||||
claims: Claims = json.loads(payload, cls=decoder_cls)
|
||||
except (TypeError, ValueError):
|
||||
raise InvalidPayloadError()
|
||||
|
||||
return Token(header, claims)
|
||||
|
||||
|
||||
def _decode_jwe(
|
||||
value: bytes, key: KeyFlexible, algorithms: Collection[str] | None = None, registry: JWERegistry | None = None
|
||||
) -> tuple[Header, bytes]:
|
||||
jwe_obj = decrypt_compact(value, key, algorithms, registry)
|
||||
assert jwe_obj.plaintext is not None
|
||||
return jwe_obj.headers(), jwe_obj.plaintext
|
||||
|
||||
|
||||
def _decode_jws(
|
||||
value: bytes, key: KeyFlexible, algorithms: Collection[str] | None = None, registry: JWSRegistry | None = None
|
||||
) -> tuple[Header, bytes]:
|
||||
jws_obj = deserialize_compact(value, key, algorithms, registry)
|
||||
assert jws_obj.payload is not None
|
||||
return jws_obj.headers(), jws_obj.payload
|
||||
Reference in New Issue
Block a user