Aller au contenu
ecdsa.com
Python

Authlib (authlib.jose)

Le module JOSE d’Authlib, la couche de jetons sur laquelle reposent les clients et serveurs OAuth et OpenID Connect d’Authlib : déclaré obsolète dans la 1.9 au profit de joserfc, il décode sans valider les claims et accepte alg: none dès que vous le listez.
Licence
BSD-3-Clause
Version vérifiée
1.9.1 ·
Code source
github.com/authlib/authlib
Documentation
docs.authlib.org/en/latest/

Compatibilité en un coup d’œil

JOSE et JWT

Algorithmes JWS
HS256HS384HS512RS256RS384RS512PS256PS384PS512ES256ES384ES512ES256KEdDSA

Authlib est une boîte à outils OAuth 2.0 et OpenID Connect complète pour Flask, Django, Starlette et httpx, et authlib.jose est la couche JWS, JWE, JWK et JWT sur laquelle elle a été bâtie. Dans la 1.9.1, son import émet authlib.jose module is deprecated, please use joserfc instead. ; les mainteneurs ont déplacé le code JOSE dans le paquet distinct joserfc, et l’ancien module est conservé pour compatibilité jusqu’à la 2.0. Le code existant continue de fonctionner, mais le nouveau code devrait cibler joserfc.

Le piège le plus fréquent est que decode() ne vérifie que la signature. Un jeton expiré depuis une heure est ressorti de decode() sans la moindre objection ; l’expiration, l’émetteur et l’audience ne sont vérifiés que lorsque vous appelez claims.validate(), avec des claims_options qui marquent exp et iss comme essentiels, car sinon un jeton qui ne les contient pas passe aussi. La marge de tolérance est nulle, sauf si vous en passez une à validate().

La gestion des algorithmes dépend de l’objet utilisé. Le jwt de niveau module accepte tous les algorithmes qu’il connaît et choisit selon le type de clé, si bien qu’un jeton RS256 présenté avec une clé EC a échoué à l’import de la clé ; une instance JsonWebToken(["ES256"]) n’autorise que ce que vous listez. Lister none suffit pour qu’un jeton non signé passe la vérification : ne laissez donc jamais une valeur de configuration se retrouver dans cette liste. Les clés HMAC qui ressemblent à des clés publiques PEM sont refusées avec This key may not be safe to import, et ES256 refuse une clé P-384.

Dans la 1.9.1, les algorithmes pris en charge couvrent les familles HS, RS, PS et ES, ES256K et EdDSA, mais pas les noms Ed25519 ni Ed448. Les signatures ES256 font 64 octets de r‖s brut ; une signature DER échoue avec bad_signature, ce que le débogueur JWT et le convertisseur DER ⇄ brut aident à diagnostiquer. Pour voir à quoi ressemblent les jetons et les clés d’un fournisseur d’identité, utilisez le validateur de jetons OIDC et le vérificateur JWKS.

L’exemple utilise une instance JsonWebToken restreinte et valide explicitement les claims : les deux étapes que l’API de niveau module laisse de côté.

Les faits et les vérifications qui les fondent

Rien de ce qui suit n’est copié d’une documentation. La vérification content/libraries/verify/authlib/run.sh a exécuté Authlib (authlib.jose) 1.9.1 sur cryptography 50.0.2 dans l’image de conteneur python:3.14.8-slim-trixie le 20 octobre 2026 ; la page doit correspondre à ce que la vérification a affiché, et chaque fait cite les lignes en question.

  • État du module JOSE

    deprecated

    Dans la 1.9.1, l’import de authlib.jose émet authlib.jose module is deprecated, please use joserfc instead.

    Relevé par la vérification
    fact jose-module-status = deprecated
    evidence jose-module-status: authlib.jose module is deprecated, please use joserfc instead.
  • Algorithmes JWS

    HS256HS384HS512RS256RS384RS512PS256PS384PS512ES256ES384ES512ES256KEdDSA

    Signature et vérification réussies avec HS, RS, PS et ES en 256/384/512 bits, ES256K et EdDSA ; Ed25519 et Ed448 ont levé UnsupportedAlgorithmError.

    Relevé par la vérification
    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
  • Encodage des signatures ES256

    raw

    Les signatures ES256 font 64 octets, en r‖s brut.

    Relevé par la vérification
    fact jws-ecdsa-encoding = raw
  • Signature DER dans un JWS

    rejected

    Un jeton avec une signature ES256 encodée en DER échoue avec BadSignatureError: bad_signature.

    Relevé par la vérification
    fact jws-der-signature = rejected
    evidence jws-der-signature: BadSignatureError: bad_signature: 
  • Liste d’algorithmes autorisés

    from-key

    Le jwt de niveau module accepte tout algorithme qu’il prend en charge pour le type de clé : un jeton ES256 a été vérifié avec une clé EC, tandis qu’un jeton RS256 présenté à la clé EC a échoué avec Invalid data for importing key.

    Relevé par la vérification
    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
  • Jetons non signés (alg none)

    opt-in

    Le jwt par défaut lève UnsupportedAlgorithmError pour alg: none, mais JsonWebToken(["none"]) vérifie un jeton non signé.

    Relevé par la vérification
    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
  • Clé publique utilisée comme secret HMAC

    rejected

    Une clé publique PEM utilisée comme clé HS256 lève ValueError: This key may not be safe to import, avec l’objet par défaut comme avec une instance restreinte.

    Relevé par la vérification
    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
  • Courbe vérifiée par rapport à alg

    enforced

    Signer en ES256 avec une clé P-384 lève Key for "ES256" not supported, only "P-256" allowed.

    Relevé par la vérification
    fact jwt-ecdsa-curve-check = enforced
    evidence jwt-ecdsa-curve-check: ValueError: Key for "ES256" not supported, only "P-256" allowed
  • Claims validés au décodage

    no

    decode() a renvoyé les claims d’un jeton expiré depuis une heure ; seul claims.validate() vérifie exp, nbf, iss et aud.

    Relevé par la vérification
    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
  • Décalage d’horloge toléré par défaut

    0s

    validate() n’applique aucune marge de tolérance par défaut : un jeton expiré depuis trois secondes a été rejeté.

    Relevé par la vérification
    fact jwt-clock-skew = 0s
  • Claim d’expiration obligatoire

    no

    Un jeton sans exp a passé validate() ; marquez ce claim comme essentiel dans claims_options pour l’exiger.

    Relevé par la vérification
    fact jwt-exp-required = no

Utilisation

Émettre et vérifier un jeton ES256 avec une instance limitée à ES256, puis valider explicitement les claims.
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"])

Le banc de test des extraits de code exécute chaque exemple tel quel dans l’image de conteneur python:3.14.8-slim-trixie, et l’exécution échoue si la sortie ne correspond pas.

Mise en place
pip install --quiet --root-user-action=ignore Authlib==1.9.1 cryptography==50.0.2
Commande
python usage.py
La sortie doit correspondre à cette expression régulière
sub: user-42

Bibliothèques