Security hardening.
TokenIssuervalidates secret/private_key presence and HMAC key length at construction, so misconfiguration fails at startup instead of on the first token issuance (CWE-665).- JWT
jtinow usessecrets.token_hexinstead ofuuid4(CWE-330). - A warning is emitted when
audienceis unset (audience verification disabled) and the first time an in-memory revoked token is recorded (it does not propagate across worker processes). verify_passwordonly treats credential mismatch / invalid-hash as a failed check; unexpected errors are logged instead of silently returningFalse(CWE-755).
Security hardening.
- 401 responses now return a generic
"Invalid or expired token"detail; the underlying PyJWT message is logged at DEBUG instead of leaked to clients (CWE-201). TokenIssuerrejects HMAC secrets shorter than 32 bytes per RFC 7518 §3.2 (CWE-1022).requires_scopesuses explicitscope→scopesprecedence so an explicit emptyscopeno longer silently falls back (CWE-840).requires_scopes()with no arguments raisesValueErrorat construction rather than producing a permissive dependency (CWE-284).- Reserved JWT claims (
exp,iat,jti,type,sub,iss,aud,nbf) supplied viaextra_claimsare dropped with a warning instead of overwriting issuer-controlled values. PasswordHashernow uses explicit OWASP-aligned argon2id parameters (time_cost=3,memory_cost=65536,parallelism=4).- The active-issuer registry uses
WeakKeyDictionaryto avoid theid(app)ABA hazard.
Initial release.
- JWT access + refresh tokens (HS256/384/512, RS*, ES*).
- argon2id password hashing with
needs_rehash. - DI guards:
requires_user,requires_claims,requires_scopes. - In-memory
RevocationListwith lazy expiry sweep. init_auth(app, config=...)plugin entry point.