yggdrasil.jwt¶
jwt ¶
yggdrasil JWT integration.
Parsing-only primitives for JSON Web Tokens (RFC 7519). Signature
verification is intentionally out of scope — that needs an algorithm
plug-in (PyJWT, cryptography) and a key-resolution policy, and
both belong in the caller, not in a base-install primitive.
Quick start¶
>>> from yggdrasil.jwt import JWTToken
>>>
>>> tok = JWTToken.from_("eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjMifQ.sig")
>>> tok.alg, tok.sub
('HS256', '123')
>>>
>>> # Strip the Bearer prefix from an Authorization header in one call:
>>> JWTToken.from_authorization("Bearer " + tok.raw).sub
'123'
JWTParseError ¶
Bases: ValueError
Raised when a value can't be parsed as a JWT.
Subclasses :class:ValueError so callers that already catch the
generic shape (except ValueError:) keep working.
JWTToken
dataclass
¶
JWTToken(
raw: str,
header_segment: str,
payload_segment: str,
signature_segment: str,
header: Mapping[str, Any],
payload: Mapping[str, Any],
signature: bytes,
)
A parsed JSON Web Token (RFC 7519).
Holds both the decoded view (header / payload /
signature) and the raw view (header_segment /
payload_segment / signature_segment, plus raw). The raw
segments are kept so a caller that wants to verify the signature
later has the exact bytes that were signed (header.payload)
without re-encoding — base64url round-trips aren't byte-stable
when the original token used no padding (the wire shape).
The class doesn't verify the signature — that needs an algorithm
plug-in and a key resolver, which the caller is in a better
position to wire up. Parsing alone is the common use case
(peek at exp / sub / aud before forwarding the token).
aud
property
¶
aud claim — audience.
RFC 7519 allows either a single string or an array of strings. Lists are normalized to a tuple so the value stays hashable and the token instance stays effectively immutable.
not_before_at
property
¶
nbf as a UTC :class:~datetime.datetime, or None.
signing_input
property
¶
The exact bytes a verifier feeds into the signing algorithm.
Defined by RFC 7515 §5.2 as
ASCII(BASE64URL(header)) || '.' || ASCII(BASE64URL(payload))
— the two raw segments with the dot between them, no
re-encoding. Surfaced so a future signature-verification
helper doesn't have to reconstruct it from the decoded views.
from_
classmethod
¶
Generic dispatch — parse a JWT from whatever the caller has.
Accepts:
- an existing :class:
JWTToken(returned as-is, identity short-circuit), - a :class:
str— delegated to :meth:from_str, - :class:
bytes/ :class:bytearray/ :class:memoryview— delegated to :meth:from_bytes.
Other shapes raise :class:JWTParseError with the value's
type so the caller sees what they passed.
from_str
classmethod
¶
Parse a JWT from a string.
Accepts the bare a.b.c form and the Bearer a.b.c form
from an Authorization header — the prefix is stripped
transparently. Surrounding whitespace is tolerated.
from_bytes
classmethod
¶
Parse a JWT from raw bytes — must be ASCII (base64url + dots).
from_authorization
classmethod
¶
Parse the JWT out of an Authorization header value.
Returns None when the value is empty, missing, or doesn't
carry a Bearer-style token — callers usually want a no-token
path instead of a try/except. Use :meth:from_str directly if a
missing token should raise.
is_expired ¶
Return whether the token's exp has passed.
Tokens without an exp claim are treated as non-expiring
(returns False) — the general "absence of a claim is
permissive" reading of RFC 7519. If your verifier requires
exp, gate on token.exp is None before calling this.
leeway (seconds) widens the window to absorb clock skew between issuer and verifier.
is_not_yet_valid ¶
Return whether nbf is still in the future.
Mirrors :meth:is_expired's shape — leeway widens the
window in the caller's favor. Tokens without nbf are
always valid by this check.