Authlib es un kit completo de OAuth 2.0 y OpenID Connect para Flask, Django, Starlette y httpx, y authlib.jose es la capa de JWS, JWE, JWK y JWT sobre la que se construyó. Importarlo en la 1.9.1 emite authlib.jose module is deprecated, please use joserfc instead.; los mantenedores trasladaron el código JOSE al paquete independiente joserfc, y el módulo antiguo se conserva por compatibilidad hasta la 2.0. El código existente sigue funcionando, pero el código nuevo debería usar joserfc.
El detalle que más problemas causa es que decode() solo comprueba la firma. Un token que había caducado una hora antes salió de decode() sin ninguna queja; la caducidad, el emisor y la audiencia solo se comprueban cuando llamas a claims.validate(), con un claims_options que marque exp e iss como esenciales, porque, si no, un token sin ellos también pasa. La tolerancia de reloj es cero salvo que pases una a validate().
El tratamiento de los algoritmos depende del objeto que uses. El jwt de nivel de módulo acepta todos los algoritmos que conoce y elige según el tipo de clave, así que un token RS256 presentado con una clave EC falló al importar la clave; una instancia JsonWebToken(["ES256"]) solo admite los que incluyas en la lista. Basta con incluir none en la lista para que un token sin firmar se verifique, así que nunca dejes que un valor de configuración acabe en esa lista. Las claves HMAC que parecen claves públicas PEM se rechazan con This key may not be safe to import, y ES256 rechaza una clave P-384.
Los algoritmos admitidos en la 1.9.1 abarcan las familias HS, RS, PS y ES, ES256K y EdDSA, pero no los nombres Ed25519 ni Ed448. Las firmas ES256 son 64 bytes de r‖s en bruto; una firma DER falla con bad_signature, algo que ayudan a diagnosticar el decodificador de JWT y el conversor DER ⇄ en bruto. Para comprobar cómo son los tokens y las claves de un proveedor de identidad, usa el validador de tokens OIDC y el comprobador de JWKS.
El ejemplo usa una instancia restringida de JsonWebToken y valida los claims de forma explícita: los dos pasos que la API de nivel de módulo omite.