Skip to content

Add OAuth 2.0 / JWT Bearer token authentication - #664

Draft
jakeichikawasalesforce wants to merge 8 commits into
masterfrom
jwt-auth-integration
Draft

Add OAuth 2.0 / JWT Bearer token authentication#664
jakeichikawasalesforce wants to merge 8 commits into
masterfrom
jwt-auth-integration

Conversation

@jakeichikawasalesforce

Copy link
Copy Markdown
Collaborator

Summary

Adds OAuth 2.0 / JWT Bearer token authentication as an alternative (or
complement) to TabPy's existing password-file basic auth. This lets
per-user credentials issued by an external identity provider (IdP) be
used instead of, or alongside, a single shared password-file credential.

  • Validates incoming JWTs against a configured IdP: signature (via JWKS),
    issuer, audience, expiry/nbf, and optionally required scopes.
  • New config settings: TABPY_OAUTH_ENABLED, TABPY_OAUTH_ISSUER,
    TABPY_OAUTH_JWKS_URI, TABPY_OAUTH_AUDIENCE,
    TABPY_OAUTH_REQUIRED_SCOPES (optional), TABPY_OAUTH_LOG_USER
    (optional, default true).
  • Basic auth and OAuth can be enabled at the same time; the method used
    is selected per-request based on the Authorization header scheme
    (Basic vs Bearer), so both can coexist on the same server.
  • TABPY_OAUTH_ISSUER and TABPY_OAUTH_JWKS_URI are required to use
    https:// — the JWKS response is the trust anchor for verifying JWT
    signatures, so fetching it over plain HTTP would let an on-path
    attacker substitute their own keys.
  • The JWT signing algorithm is always pinned to the JWKS-resolved key's
    algorithm, never trusted from the token header, to prevent
    algorithm-confusion attacks (e.g. RS256→HS256 substitution, alg=none).
  • JWKS fetches are cached and reused per-IdP; a forced refresh (triggered
    by an unrecognized kid) is rate-limited so repeated bogus kids from
    an unauthenticated caller can't force unbounded blocking network fetches
    on TabPy's single IO-loop thread.
  • Docs updated in docs/server-config.md.

Testing

  • Added unit tests covering JWT validation (test_jwt_auth.py), OAuth
    request handling end-to-end (test_oauth_handler.py), and OAuth config
    validation (test_config.py).
  • Full unit test suite passes locally.
  • Manually verified against a local self-signed-HTTPS JWKS endpoint:
    valid token accepted, expired/wrong-issuer/wrong-audience tokens
    rejected with 401, and the request-context log line correctly includes
    the authenticated TabPy user when TABPY_LOG_DETAILS and
    TABPY_OAUTH_LOG_USER are enabled.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant