Skip to content

[Refactor][openrouter]: JWT extraction and verification is duplicated between the middleware and _resolve_subject #490

Open
smaramwbc/statewave-openrouter
#1

Description

@jy7lsna

Affected Component

statewave-openrouter — statewave_openrouter.py

Description

The token handling is written out twice, once in the _require_token middleware and once in _resolve_subject:

# lines 134-144 (middleware) and 403-417 (_resolve_subject), near-identical
token = request.headers.get("x-statewave-token", "").strip()
if token[:7].lower() == "bearer ":
    token = token[7:].strip()
if not token:
    return _error(401, "statewave requires a token in X-Statewave-Token", "statewave_auth_required")
try:
    jwt.decode(token, JWT_SECRET, algorithms=["HS256"], options={"require": ["exp"]})
except jwt.InvalidTokenError as exc:
    return _error(401, f"invalid statewave token: {exc}", "statewave_bad_token")

This is security-relevant code, and the two copies have to stay in sync by hand: algorithm list, required claims, header parsing, error types. If someone later adds audience= or leeway= to one and forgets the other, a token could pass the middleware and then fail (or worse, the reverse) in the handler. Every request also verifies the signature twice.

Expected Behavior

One function owns "extract and verify the token".

Suggested fix

Add a helper and use it in both places:

def _verify_token(request: Request) -> tuple[dict | None, JSONResponse | None]:
    """Return (claims, None) or (None, 401 response)."""

Optionally, have the middleware store the claims on request.state.claims, so _resolve_subject reads them instead of decoding again. This is a pure refactor: the existing JWT tests in test_proxy.py should pass unchanged.

Environment

main @ 10ef629.

Severity

Low — maintainability / defense-in-depth refactor, no behavior change.

Activity

  1. MaximGit-tech commented on Oct 6, 2026

    @MaximGit-tech

    Hi! I'd like to work on this.

    I'll extract the token parsing/verification into a shared helper and reuse the claims verified by the middleware in _resolve_subject, so JWT decoding only happens once per request while keeping the existing behavior unchanged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions