Zum Inhalt springen
ecdsa.com
Python

Authlib (authlib.jose)

Das JOSE-Modul von Authlib, die Token-Schicht unter den Clients und Servern für OAuth und OpenID Connect von Authlib: Seit 1.9 zugunsten von joserfc als veraltet markiert, dekodiert es Tokens, ohne die Claims zu prüfen, und lässt alg: none zu, sobald du es in die Liste aufnimmst.
Lizenz
BSD-3-Clause
Geprüfte Version
1.9.1 ·
Quellcode
github.com/authlib/authlib
Dokumentation
docs.authlib.org/en/latest/

Kompatibilität auf einen Blick

JOSE und JWT

JWS-Algorithmen
HS256HS384HS512RS256RS384RS512PS256PS384PS512ES256ES384ES512ES256KEdDSA

Authlib ist ein vollständiges Toolkit für OAuth 2.0 und OpenID Connect, nutzbar mit Flask, Django, Starlette und httpx, und authlib.jose ist die JWS-, JWE-, JWK- und JWT-Schicht, auf der es aufgebaut wurde. Beim Import gibt Version 1.9.1 authlib.jose module is deprecated, please use joserfc instead. aus; der JOSE-Code wurde in das separate Paket joserfc ausgelagert, und das alte Modul bleibt aus Kompatibilitätsgründen bis Version 2.0 erhalten. Bestehender Code funktioniert weiter, neuer Code sollte aber auf joserfc setzen.

Die häufigste Stolperfalle: decode() prüft nur die Signatur. Ein Token, das eine Stunde zuvor abgelaufen war, kam von decode() ohne Beanstandung zurück; Ablauf, Aussteller und Audience werden erst geprüft, wenn du claims.validate() aufrufst – wobei exp und iss in claims_options als erforderlich (essential) gekennzeichnet sein müssen, denn sonst besteht auch ein Token ohne diese Claims die Prüfung. Die Toleranz (Leeway) ist null, sofern du validate() keine übergibst.

Wie Algorithmen behandelt werden, hängt vom verwendeten Objekt ab. Das jwt auf Modulebene akzeptiert jeden Algorithmus, den es kennt, und wählt nach dem Schlüsseltyp; ein RS256-Token, das mit einem EC-Schlüssel geprüft wurde, scheiterte deshalb erst beim Schlüsselimport. Eine Instanz JsonWebToken(["ES256"]) erlaubt nur, was du auflistest. Steht none in der Liste, besteht schon ein unsigniertes Token die Prüfung – lass also nie zu, dass ein Konfigurationswert in dieser Liste landet. HMAC-Schlüssel, die wie öffentliche Schlüssel im PEM-Format aussehen, werden mit This key may not be safe to import abgewiesen, und ES256 weist einen P-384-Schlüssel ab.

Die in 1.9.1 unterstützten Algorithmen umfassen die Familien HS, RS, PS und ES sowie ES256K und EdDSA, nicht aber die Namen Ed25519 und Ed448. ES256-Signaturen bestehen aus 64 Byte rohem r‖s; eine DER-Signatur scheitert mit bad_signature – bei der Diagnose helfen der JWT-Debugger und der Konverter DER ⇄ Raw. Wie die Tokens und Schlüssel eines Identity Providers aussehen, prüfst du mit dem OIDC-Token-Validator und dem JWKS-Checker.

Das Beispiel verwendet eine eingeschränkte Instanz von JsonWebToken und prüft die Claims explizit – genau die zwei Schritte, die die API auf Modulebene auslässt.

Fakten und die Prüfungen dahinter

Nichts im Folgenden ist aus einer Dokumentation abgeschrieben. Das Prüfskript content/libraries/verify/authlib/run.sh hat Authlib (authlib.jose) 1.9.1 unter cryptography 50.0.2 am 20. Oktober 2026 im Container-Image python:3.14.8-slim-trixie ausgeführt; die Seite muss mit seiner Ausgabe übereinstimmen, und jeder Fakt führt die zugehörigen Zeilen auf.

  • Status des JOSE-Moduls

    deprecated

    Der Import von authlib.jose gibt in 1.9.1 authlib.jose module is deprecated, please use joserfc instead. aus.

    Von der Prüfung aufgezeichnet
    fact jose-module-status = deprecated
    evidence jose-module-status: authlib.jose module is deprecated, please use joserfc instead.
  • JWS-Algorithmen

    HS256HS384HS512RS256RS384RS512PS256PS384PS512ES256ES384ES512ES256KEdDSA

    Signieren und Prüfen funktionierten mit HS, RS, PS und ES bei 256/384/512 Bit sowie mit ES256K und EdDSA; Ed25519 und Ed448 lösten UnsupportedAlgorithmError aus.

    Von der Prüfung aufgezeichnet
    fact jws-algorithms = HS256, HS384, HS512, RS256, RS384, RS512, PS256, PS384, PS512, ES256, ES384, ES512, ES256K, EdDSA
    evidence jws-algorithms: Ed25519: UnsupportedAlgorithmError: unsupported_algorithm: 
    evidence jws-algorithms: Ed448: UnsupportedAlgorithmError: unsupported_algorithm: 
    evidence jws-algorithms: algorithms the module-level authlib.jose.jwt accepts: ES256, ES256K, ES384, ES512, EdDSA, HS256, HS384, HS512, PS256, PS384, PS512, RS256, RS384, RS512
  • Kodierung von ES256-Signaturen

    raw

    ES256-Signaturen bestehen aus 64 Byte rohem r‖s.

    Von der Prüfung aufgezeichnet
    fact jws-ecdsa-encoding = raw
  • DER-Signatur in einer JWS

    rejected

    Ein Token mit einer DER-kodierten ES256-Signatur scheitert mit BadSignatureError: bad_signature.

    Von der Prüfung aufgezeichnet
    fact jws-der-signature = rejected
    evidence jws-der-signature: BadSignatureError: bad_signature: 
  • Allowlist der Algorithmen

    from-key

    Das jwt auf Modulebene akzeptiert jeden Algorithmus, den es für den Schlüsseltyp unterstützt: Ein ES256-Token bestand die Prüfung mit einem EC-Schlüssel, während ein RS256-Token gegen denselben EC-Schlüssel mit Invalid data for importing key scheiterte.

    Von der Prüfung aufgezeichnet
    fact jwt-algorithm-allowlist = from-key
    evidence jwt-algorithm-allowlist: authlib.jose.jwt.decode on ES256: verified; RS256 token with an EC key: ValueError: Invalid data for importing key
  • Unsignierte Tokens (alg none)

    opt-in

    Das Standardobjekt jwt löst bei alg: none UnsupportedAlgorithmError aus, mit JsonWebToken(["none"]) besteht dagegen ein unsigniertes Token die Prüfung.

    Von der Prüfung aufgezeichnet
    fact jwt-alg-none = opt-in
    evidence jwt-alg-none: default jwt with an EC key: UnsupportedAlgorithmError: unsupported_algorithm: 
    evidence jwt-alg-none: JsonWebToken(['none']): verified
  • Öffentlicher Schlüssel als HMAC-Secret

    rejected

    Ein öffentlicher Schlüssel im PEM-Format, als HS256-Schlüssel verwendet, löst ValueError: This key may not be safe to import aus – sowohl beim Standardobjekt als auch bei einer eingeschränkten Instanz.

    Von der Prüfung aufgezeichnet
    fact jwt-hmac-public-key = rejected
    evidence jwt-hmac-public-key: JsonWebToken(['HS256']) with PEM text as key: ValueError: This key may not be safe to import
    evidence jwt-hmac-public-key: default jwt with PEM text as key: ValueError: This key may not be safe to import
  • Abgleich der Kurve mit alg

    enforced

    Das Signieren mit ES256 und einem P-384-Schlüssel löst Key for "ES256" not supported, only "P-256" allowed aus.

    Von der Prüfung aufgezeichnet
    fact jwt-ecdsa-curve-check = enforced
    evidence jwt-ecdsa-curve-check: ValueError: Key for "ES256" not supported, only "P-256" allowed
  • Validierung der Claims beim Dekodieren

    no

    decode() gab die Claims eines Tokens zurück, das eine Stunde zuvor abgelaufen war; erst claims.validate() prüft exp, nbf, iss und aud.

    Von der Prüfung aufgezeichnet
    fact jwt-claims-validated-on-decode = no
    evidence jwt-claims-validated-on-decode: decode() of a token expired an hour ago without validate(): returned claims
  • Standardtoleranz für Uhrabweichungen

    0s

    validate() verwendet standardmäßig keine Toleranz (Leeway): Ein Token, das drei Sekunden zuvor abgelaufen war, wurde abgelehnt.

    Von der Prüfung aufgezeichnet
    fact jwt-clock-skew = 0s
  • Ablauf-Claim erforderlich

    no

    Ein Token ohne exp bestand validate(); kennzeichne den Claim in claims_options als erforderlich (essential), um ihn vorzuschreiben.

    Von der Prüfung aufgezeichnet
    fact jwt-exp-required = no

Verwendung

Stelle mit einer auf ES256 beschränkten Instanz ein ES256-Token aus und prüfe es, dann validiere die Claims explizit.
import time

from authlib.jose import JsonWebKey, JsonWebToken

key = JsonWebKey.generate_key("EC", "P-256", is_private=True)
public_jwk = key.as_dict(is_private=False)

# A JsonWebToken instance restricted to ES256 instead of the permissive module-level jwt.
es256 = JsonWebToken(["ES256"])
token = es256.encode({"alg": "ES256"}, {"sub": "user-42", "iss": "https://auth.example.com", "exp": int(time.time()) + 600}, key)

claims = es256.decode(
    token,
    public_jwk,
    claims_options={"iss": {"essential": True, "value": "https://auth.example.com"}, "exp": {"essential": True}},
)
claims.validate(leeway=30)  # decode() checks only the signature; validate() checks the claims
print("sub:", claims["sub"])

Die Snippet-Testumgebung führt jedes Beispiel unverändert im Container-Image python:3.14.8-slim-trixie aus, und der Lauf schlägt fehl, wenn die Ausgabe nicht übereinstimmt.

Einrichtung
pip install --quiet --root-user-action=ignore Authlib==1.9.1 cryptography==50.0.2
Befehl
python usage.py
Ausgabe muss passen (regulärer Ausdruck)
sub: user-42

Bibliotheken