Skip to content

feat(auth): enforce supabase jwt authentication#39

Merged
gentamura merged 5 commits intomainfrom
feat/jwt-auth-only
Nov 1, 2025
Merged

feat(auth): enforce supabase jwt authentication#39
gentamura merged 5 commits intomainfrom
feat/jwt-auth-only

Conversation

@gentamura
Copy link
Member

@gentamura gentamura commented Nov 1, 2025

Summary

  • drop the header-based authentication helper and require Supabase-issued JWTs for every request
  • tighten shared types so AuthenticatedToken is always a SupabaseToken
  • align Supabase token fields and guards with the documented JWT claims, updating tests/docs/build artifacts

Testing

  • bun run build
  • bun run lint
  • bun run test

Summary by CodeRabbit

  • Breaking Changes

    • Header-based authentication support removed; public authentication API surface has changed.
  • New Features

    • Stronger Supabase JWT verification with stricter required claims and expanded token metadata.
  • Documentation

    • README updated to reflect the Supabase JWT verification workflow and removed prior header-authentication mention.

@coderabbitai
Copy link

coderabbitai bot commented Nov 1, 2025

Walkthrough

The PR removes header-based authentication and related types/exports, centralizes authentication on Supabase JWT verification, tightens Supabase token shapes and runtime guards, updates tests and docs to use the Supabase-only flow, and adds test helpers and base JWT claim fixtures for tests.

Changes

Cohort / File(s) Summary
Type definitions
packages/types/src/authentication.ts
Removed HeaderToken and HeaderAuthenticationOptions; AuthenticatedToken now equals SupabaseToken; SupabaseAuthenticationOptions no longer extends header options and now includes optional headerName? and scheme?.
Header authentication module deletion
packages/auth/src/authentication/header.ts
Deleted module and exported createHeaderAuthentication (header-based token extraction removed).
Authentication exports (barrels)
packages/auth/src/authentication/index.ts, packages/auth/src/index.ts
Removed re-export and barrel export of createHeaderAuthentication; other exports unchanged.
Supabase authentication logic
packages/auth/src/authentication/supabase.ts
Removed AuthenticatedToken import and isSupabaseToken guard; added stricter validation of iss/aud/exp/iat/role claims; normalized aud handling; build SupabaseToken from payload and allow provisioning to proceed without header-token short-circuit.
Tests — auth & api
packages/auth/src/authentication/supabase.test.ts, packages/api/src/app.test.ts
Added token builder and BASE_* scaffolding; removed tests relying on header/opaque tokens; replaced header helper with a test-only createTestAuthentication that validates Authorization: Bearer <token> and returns a Supabase-based user.
Public API and docs
README.md, packages/auth/README.md
Removed createHeaderAuthentication documentation and updated examples to the Supabase JWT verification API shape (changed option names and invocation pattern).
DB/public token shape
packages/db/src/index.ts
Expanded and tightened SupabaseToken type (made iss/sub/exp/iat/role required, aud as `string
Tests — DB fixtures
packages/db/src/index.test.ts
Added BASE_CLAIMS and updated test helpers to merge base claims into constructed test tokens.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Client as Client (HTTP)
  participant App as App
  participant AuthProv as AuthenticationProvider
  participant Verifier as Supabase Verifier / JWKS

  Client->>App: HTTP request (Authorization: Bearer <token>)
  App->>AuthProv: authentication.authenticate({ request })
  note right of AuthProv #E8F6FF: test helper parses Bearer\nproduction verifies JWT via Supabase flow
  AuthProv->>Verifier: validate token (signature, iss, aud, exp, iat, role)
  Verifier-->>AuthProv: token payload / validation result
  alt valid
    AuthProv-->>App: { user: SupabaseToken }
    App-->>Client: proceed (authenticated)
  else invalid
    AuthProv-->>App: throws AuthenticationError
    App-->>Client: 401 / unauthorized
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Areas likely needing extra attention:
    • packages/auth/src/authentication/supabase.ts — removed guard and changed provisioning control flow and token construction.
    • packages/db/src/index.ts — expanded SupabaseToken shape and runtime guards; ensure downstream compatibility.
    • packages/types/src/authentication.ts — public type changes affecting many consumers.
    • Tests and test helpers (packages/auth/src/authentication/supabase.test.ts, packages/api/src/app.test.ts) — ensure new test-only provider mirrors production behavior sufficiently.

Possibly related PRs

Poem

🐇 I hopped from headers to JWT bright,
Bearer carrot clutched just right.
Claims tucked warm in every nook,
Tests refreshed — a careful look.
Hooray — tokens snug tonight! 🥕

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title "feat(auth): enforce supabase jwt authentication" directly and clearly captures the primary objective of this pull request. The changeset demonstrates a cohesive effort to remove the header-based authentication pathway entirely (deleting createHeaderAuthentication, removing it from exports, updating tests and documentation) while enforcing Supabase JWT verification as the sole authentication mechanism. The title is specific and descriptive—it avoids vague terms and accurately reflects the main technical change across multiple packages. A teammate scanning the repository history would immediately understand that this change replaces header-based auth with Supabase JWT enforcement.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/jwt-auth-only

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b6537af and 0211827.

📒 Files selected for processing (3)
  • packages/api/src/app.test.ts (14 hunks)
  • packages/auth/src/authentication/supabase.test.ts (3 hunks)
  • packages/auth/src/authentication/supabase.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/api/src/app.test.ts
  • packages/auth/src/authentication/supabase.test.ts
🧰 Additional context used
📓 Path-based instructions (3)
packages/*/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

packages/*/src/**/*.{ts,tsx}: Avoid implicit any; TypeScript is run with strict enabled
Prefer type guards or the satisfies operator over as casts where appropriate
Prefer unknown for external inputs
Use PascalCase for types and enums
Use camelCase for variables and functions
Ensure source comments are written in English

Files:

  • packages/auth/src/authentication/supabase.ts
packages/auth/src/authentication/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Place runtime-specific authentication adapters under packages/auth/src/authentication/ (e.g., header.ts, supabase.ts, shared utilities, errors.ts)

Files:

  • packages/auth/src/authentication/supabase.ts
packages/auth/src/authentication/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Extend Supabase JWT verification (createSupabaseAuthentication using .well-known/jwks.json) only via dedicated modules to keep caching and claim validation centralized

Files:

  • packages/auth/src/authentication/supabase.ts
🧠 Learnings (3)
📓 Common learnings
Learnt from: CR
Repo: listee-dev/listee-libs PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-10-02T12:40:33.718Z
Learning: Applies to packages/auth/src/authentication/**/*.ts : Extend Supabase JWT verification (createSupabaseAuthentication using .well-known/jwks.json) only via dedicated modules to keep caching and claim validation centralized
Learnt from: CR
Repo: listee-dev/listee-libs PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-10-02T12:40:33.718Z
Learning: Applies to packages/auth/src/authentication/**/*.{ts,tsx} : Place runtime-specific authentication adapters under packages/auth/src/authentication/ (e.g., header.ts, supabase.ts, shared utilities, errors.ts)
📚 Learning: 2025-10-02T12:40:33.718Z
Learnt from: CR
Repo: listee-dev/listee-libs PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-10-02T12:40:33.718Z
Learning: Applies to packages/auth/src/authentication/**/*.ts : Extend Supabase JWT verification (createSupabaseAuthentication using .well-known/jwks.json) only via dedicated modules to keep caching and claim validation centralized

Applied to files:

  • packages/auth/src/authentication/supabase.ts
📚 Learning: 2025-10-02T12:40:33.718Z
Learnt from: CR
Repo: listee-dev/listee-libs PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-10-02T12:40:33.718Z
Learning: Applies to packages/auth/src/authentication/**/*.{ts,tsx} : Place runtime-specific authentication adapters under packages/auth/src/authentication/ (e.g., header.ts, supabase.ts, shared utilities, errors.ts)

Applied to files:

  • packages/auth/src/authentication/supabase.ts
🧬 Code graph analysis (1)
packages/auth/src/authentication/supabase.ts (3)
packages/auth/src/authentication/shared.ts (1)
  • assertNonEmptyString (16-22)
packages/auth/src/authentication/errors.ts (1)
  • AuthenticationError (1-6)
packages/db/src/index.ts (1)
  • SupabaseToken (157-178)
🔇 Additional comments (4)
packages/auth/src/authentication/supabase.ts (4)

100-120: Excellent claim validation with clear error messages.

The explicit validation of iss, aud, exp, iat, and role ensures all required claims are present and correctly typed. While jose validates token signature and expiration, these manual checks enforce presence of claims that are optional in the JWT spec, providing better error messages and ensuring type safety for downstream usage.


122-126: Correct usage of validated role claim.

Using the validated roleClaim instead of directly accessing payload.role ensures type safety and consistency with the validation logic above.


128-140: Well-structured token construction with correct precedence.

The token construction correctly:

  1. Spreads additionalClaims to capture optional JWT fields (aal, session_id, email, etc.)
  2. Overwrites with explicitly validated claims to ensure type safety and correctness
  3. Normalizes aud from readonly string[] to string[] for compatibility

This pattern ensures validated values take precedence while preserving additional Supabase-specific claims.


165-198: Simplified and type-safe provisioning flow.

The provisioning flow correctly:

  1. Uses extractEmailFromToken helper for safe email extraction with null handling
  2. Removes the runtime type guard (no longer needed since AuthenticatedToken is now always SupabaseToken)
  3. Passes the email (string | null) directly to the provisioner

This aligns with the PR objective to tighten types and enforce Supabase JWT authentication throughout.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gentamura gentamura self-assigned this Nov 1, 2025
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 562056e and 31d19e1.

📒 Files selected for processing (1)
  • packages/db/src/index.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
packages/*/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

packages/*/src/**/*.{ts,tsx}: Avoid implicit any; TypeScript is run with strict enabled
Prefer type guards or the satisfies operator over as casts where appropriate
Prefer unknown for external inputs
Use PascalCase for types and enums
Use camelCase for variables and functions
Ensure source comments are written in English

Files:

  • packages/db/src/index.ts
🧠 Learnings (3)
📓 Common learnings
Learnt from: CR
Repo: listee-dev/listee-libs PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-10-02T12:40:33.718Z
Learning: Applies to packages/auth/src/authentication/**/*.ts : Extend Supabase JWT verification (createSupabaseAuthentication using .well-known/jwks.json) only via dedicated modules to keep caching and claim validation centralized
Learnt from: CR
Repo: listee-dev/listee-libs PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-10-02T12:40:33.718Z
Learning: Applies to packages/auth/src/authentication/**/*.{ts,tsx} : Place runtime-specific authentication adapters under packages/auth/src/authentication/ (e.g., header.ts, supabase.ts, shared utilities, errors.ts)
📚 Learning: 2025-10-02T12:40:33.718Z
Learnt from: CR
Repo: listee-dev/listee-libs PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-10-02T12:40:33.718Z
Learning: Applies to packages/auth/src/authentication/**/*.ts : Extend Supabase JWT verification (createSupabaseAuthentication using .well-known/jwks.json) only via dedicated modules to keep caching and claim validation centralized

Applied to files:

  • packages/db/src/index.ts
📚 Learning: 2025-10-02T12:40:33.718Z
Learnt from: CR
Repo: listee-dev/listee-libs PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-10-02T12:40:33.718Z
Learning: Applies to packages/auth/src/authentication/**/*.{ts,tsx} : Place runtime-specific authentication adapters under packages/auth/src/authentication/ (e.g., header.ts, supabase.ts, shared utilities, errors.ts)

Applied to files:

  • packages/db/src/index.ts
🔇 Additional comments (1)
packages/db/src/index.ts (1)

154-155: LGTM! Clear documentation and appropriate type definition.

The documentation comment with a reference to Supabase's official docs is helpful, and the AuthenticatorAssuranceLevel type correctly models the two-factor authentication levels used in Supabase JWT tokens.

@gentamura gentamura merged commit 94463c7 into main Nov 1, 2025
5 checks passed
@gentamura gentamura deleted the feat/jwt-auth-only branch November 1, 2025 13:20
@coderabbitai coderabbitai bot mentioned this pull request Nov 2, 2025
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