Skip to content

feat(session): add require_user_session and warn about short JWT HMAC keys - #275

Merged
allen0099 merged 1 commit into
masterfrom
feat/session-user-jwt-key-114-116
Sep 26, 2026
Merged

allen0099 merged 1 commit into
masterfrom
feat/session-user-jwt-key-114-116

Conversation

@allen0099

Copy link
Copy Markdown
Owner

Summary

Closes #114. Closes #116.

#114: require_user_session

get_session, RequiredSession and UserSessionDep only check that a session exists. Under FastAPICacheXSessionMiddleware, any visitor who reaches a route that writes to request.session (a cart, a CSRF value) gets an anonymous session with user=None, and that session passes all three.

  • New require_user_session dependency. It builds on get_session, so the SessionBearer OpenAPI scheme still appears.
  • It answers 401 Authentication required with WWW-Authenticate: Bearer when there is no session or session.user is None.
  • Annotated alias AuthenticatedSession.
  • Exported from fastapi_cachex.session and fastapi_cachex.
  • UserSessionDep is unchanged. A comment and the docs say it still accepts anonymous sessions until 0.4.0.

#116: short JWT HMAC keys

SessionConfig requires 32 characters, but HS384 and HS512 need 48 and 64 bytes (RFC 7518 §3.2).

  • JWTTokenSerializer.__init__ now emits one UserWarning when the key is shorter than the hash output.
    • The key is measured in UTF-8 bytes, the same way PyJWT measures it.
    • stacklevel points at the code that constructed the serializer.
    • The message names secret_key and jwt_algorithm and suggests a fix.
  • Category: UserWarning. It matches the existing cookie_same_site misconfiguration warning and is the base class of PyJWT's InsecureKeyLengthWarning. It cannot be InsecureKeyLengthWarning itself, because jwt_module may be a non-PyJWT implementation.
  • PyJWT's own per-call warning is not suppressed. The only way to do that is warnings.catch_warnings() around every encode/decode, which mutates process-global warning state on each request. The docs mention the PyJWT warning instead.
  • Raising instead of warning stays with 0.4.0.

Docs

  • SESSION.md (EN and zh-TW):
    • get_session vs require_user_session, with an example;
    • the dependency list gains require_user_session, UserSessionDep and AuthenticatedSession;
    • the JWT section and "Secret Key" best practice give the per-algorithm key lengths.
  • CLAUDE.md session notes updated.

Tests

  • test_require_user_session_rejects_anonymous_sessions runs end to end through FastAPICacheXSessionMiddleware. With no session it gets 401. After an anonymous cart write, RequiredSession passes but AuthenticatedSession gets 401 with WWW-Authenticate: Bearer. With a user session, it succeeds.
  • test_jwt_serializer_warns_once_about_a_short_hmac_key covers these cases, using the stub JWT module, so no PyJWT import:
    • HS256 with 32 characters;
    • HS384 and HS512 on either side of the limit;
    • 32 é characters (64 bytes) under HS512.
  • Mutation-checked, each against the full suite:
    • dropping the user check fails only the middleware test;
    • dropping the warning call fails only the two "warns" cases;
    • counting characters instead of bytes fails only the é case;
    • stacklevel=2 fails only the two "warns" cases, via the filename assertion.
  • Local runs:
    • uv run pytest: 807 passed, 190 skipped. The live Redis/Memcached tests were skipped because no test servers were configured for this run; CI runs them.
    • pre-commit run --all-files (with SKIP=uv-lock): clean.
    • Both strict docs builds: clean.

CHANGELOG

Added:

- **`require_user_session` / `AuthenticatedSession` require a logged-in
  user.** `get_session`, `RequiredSession` and `UserSessionDep` accept the
  anonymous session any visitor gets by writing to `request.session`; the
  new dependency also answers `401` when `session.user` is `None`.
  `UserSessionDep` keeps its behaviour until 0.4.0.
  ([#114](https://github.com/allen0099/FastAPI-CacheX/issues/114))

Security:

- **The JWT serializer warns about an HMAC key shorter than RFC 7518
  requires.** `secret_key` needs only 32 characters, but `HS384` and `HS512`
  need 48 and 64 bytes. `JWTTokenSerializer` now emits one `UserWarning`
  when it is built with a shorter key, instead of relying on PyJWT's
  per-token `InsecureKeyLengthWarning`.
  ([#116](https://github.com/allen0099/FastAPI-CacheX/issues/116))

… keys

get_session, RequiredSession and UserSessionDep only check that a session
exists, so an anonymous session created by a cart or CSRF write passes
them. require_user_session (AuthenticatedSession) also answers 401 when
session.user is None. UserSessionDep keeps its behaviour until 0.4.0.

JWTTokenSerializer now emits one UserWarning when it is built with a
secret_key shorter, in UTF-8 bytes, than the HMAC hash output that
RFC 7518 section 3.2 requires (48 bytes for HS384, 64 for HS512).

Closes #114
Closes #116
@allen0099 allen0099 added this to the 0.3.8 milestone Sep 26, 2026
@allen0099 allen0099 added enhancement New feature or request session Session management subsystem security Security vulnerability or hardening labels Sep 26, 2026
@allen0099
allen0099 merged commit 163086b into master Sep 26, 2026
11 checks passed
@allen0099
allen0099 deleted the feat/session-user-jwt-key-114-116 branch September 26, 2026 23:14
allen0099 added a commit that referenced this pull request Sep 27, 2026
Copies the CHANGELOG sections of #207, #208, #209, #211, #212, #272,
#273, #274, #275, #276, #279 and #284 into Unreleased. The #273 entry
drops expire_if_equals from its list of methods that changed, since that
primitive is new in 0.3.8.
allen0099 added a commit that referenced this pull request Sep 27, 2026
Copies the CHANGELOG sections of #207, #208, #209, #211, #212, #272,
#273, #274, #275, #276, #279 and #284 into Unreleased. The #273 entry
drops expire_if_equals from its list of methods that changed, since that
primitive is new in 0.3.8.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request security Security vulnerability or hardening session Session management subsystem

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Warn when the JWT HMAC secret is shorter than the hash output Add a dependency that requires a session with a user

1 participant