Skip to content

feat: require bearer token for facilitator endpoints#36

Merged
ponderingdemocritus merged 2 commits intomainfrom
ponderingdemocritus/pushcommit
Feb 8, 2026
Merged

feat: require bearer token for facilitator endpoints#36
ponderingdemocritus merged 2 commits intomainfrom
ponderingdemocritus/pushcommit

Conversation

@ponderingdemocritus
Copy link
Contributor

@ponderingdemocritus ponderingdemocritus commented Feb 8, 2026

Summary

Adds mandatory bearer token authentication to protect the /verify and /settle endpoints. The facilitator now requires either a BEARER_TOKEN or BEARER_TOKENS environment variable to start, ensuring secure access to payment processing endpoints.

Changes

  • New bearer token module with configurable protected paths and token validation
  • CI improvements: stabilized Docker startup smoke test with retry logic and better error handling
  • App now supports loading modules dynamically for middleware composition
  • Comprehensive tests for bearer token authentication

This is a breaking change requiring BEARER_TOKEN to be set in production deployments.

Summary by CodeRabbit

  • New Features

    • Added bearer token authentication to secure API endpoints
    • Implemented modular app configuration supporting flexible authentication integration
  • Tests

    • Added comprehensive test coverage for bearer token authentication module and integration scenarios

@coderabbitai
Copy link

coderabbitai bot commented Feb 8, 2026

📝 Walkthrough

Walkthrough

The PR implements Bearer token authentication for the facilitator server by introducing a reusable Elysia module system, adding a bearer token middleware module, and enhancing CI workflows with improved container readiness checks and token-based configuration.

Changes

Cohort / File(s) Summary
CI Infrastructure
.github/workflows/ci.yml
Adds robust container readiness verification with a 30-second polling loop checking the /supported endpoint, trap-cleanup mechanism, BEARER_TOKEN environment variable, and strict shell options (set -euo pipefail). Replaces fixed 5-second sleep with persistent health checks and log dumps on failure.
Module System
examples/facilitator-server/src/app.ts
Introduces AppModule type and extends AppConfig with optional modules array. Implements module registration loop that applies modules to the base Elysia app after OTEL setup but before route definitions.
Bearer Token Authentication
examples/facilitator-server/src/index.ts, examples/facilitator-server/src/modules/bearer-token.ts
Implements bearer token authentication module with configuration validation, path normalization, and onBeforeHandle interceptor. Adds BEARER_TOKEN environment handling in index.ts and integrates the module to protect /verify and /settle endpoints with proper 401 responses and WWW-Authenticate headers.
Tests
examples/facilitator-server/tests/app.test.ts, examples/facilitator-server/tests/bearer-token-module.test.ts
Adds integration test for bearer token module with app and comprehensive unit tests validating protected/unprotected route access, token validation, and proper authentication failure responses.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐰 ✨ A module hops into place,

Bearer tokens guard the space,

CI waits with patient care,

Auth checks float through the air,

Security blooms with developer's grace! 🌟

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ 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%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ 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 clearly and accurately summarizes the main change: adding bearer token authentication to facilitator endpoints, which aligns with the primary objective of the PR.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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 ponderingdemocritus/pushcommit

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.

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

🤖 Fix all issues with AI agents
In `@examples/facilitator-server/src/modules/bearer-token.ts`:
- Around line 44-46: The escapeRealm function currently only escapes double
quotes and misses backslashes; update escapeRealm(realm: string) to first
replace backslashes with double-backslashes and then escape double quotes (i.e.,
realm.replace(/\\/g, '\\\\').replace(/"/g, '\\"')) so both '\' and '"' are
properly escaped per RFC 7230 quoted-string rules; ensure you modify the
escapeRealm function accordingly.
🧹 Nitpick comments (4)
.github/workflows/ci.yml (1)

111-126: Redundant final curl; if it fails, no logs are dumped.

Line 126 re-runs the same health check that already succeeded inside the loop. It's mostly harmless, but if the container happens to crash between the loop exit and this call, the script fails without dumping logs (unlike the ready != "true" branch). Consider removing it or, if you want to keep a final assertion, wrapping it in similar error-reporting logic.

Suggested simplification
          if [ "$ready" != "true" ]; then
            echo "Container did not become ready. Dumping logs:"
            docker logs test-facilitator || true
            exit 1
          fi
-
-          curl -fsS http://localhost:8090/supported >/dev/null
examples/facilitator-server/src/app.ts (1)

103-103: AppModule = unknown discards type safety.

This forces as any on line 152 and allows callers to pass anything (numbers, strings, etc.) in the modules array without compile-time feedback. Consider a minimal function signature that matches the Elysia plugin contract.

Suggested improvement
-export type AppModule = unknown;
+export type AppModule = (app: Elysia) => Elysia;

This would also let you drop the as any cast on line 152.

examples/facilitator-server/src/modules/bearer-token.ts (1)

48-50: Return type unknown loses the Elysia plugin contract.

Same as AppModule in app.ts — returning unknown hides the actual (app: Elysia) => Elysia signature. Typing it properly would give callers and app.use() better compile-time checks.

examples/facilitator-server/src/index.ts (1)

30-44: Token loading logic is sound.

The precedence (BEARER_TOKENSBEARER_TOKEN → error) is clear, and the fail-fast throw on missing tokens prevents starting without auth. This is a good security posture.

One minor nit: the error message reads awkwardly — "to require bearer auth for facilitator startup" suggests the purpose is to require auth, rather than conveying that auth is required for startup.

Suggested wording
   throw new Error(
-    "Set BEARER_TOKEN or BEARER_TOKENS to require bearer auth for facilitator startup."
+    "BEARER_TOKEN or BEARER_TOKENS environment variable is required."
   );

Comment on lines +44 to +46
function escapeRealm(realm: string): string {
return realm.replace(/"/g, '\\"');
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

escapeRealm doesn't escape backslashes.

Per RFC 7230's quoted-string grammar, both " and \ must be escaped in a quoted string value. A realm containing a backslash would produce a malformed WWW-Authenticate header.

Suggested fix
 function escapeRealm(realm: string): string {
-  return realm.replace(/"/g, '\\"');
+  return realm.replace(/[\\"]/g, '\\$&');
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function escapeRealm(realm: string): string {
return realm.replace(/"/g, '\\"');
}
function escapeRealm(realm: string): string {
return realm.replace(/[\\"]/g, '\\$&');
}
🤖 Prompt for AI Agents
In `@examples/facilitator-server/src/modules/bearer-token.ts` around lines 44 -
46, The escapeRealm function currently only escapes double quotes and misses
backslashes; update escapeRealm(realm: string) to first replace backslashes with
double-backslashes and then escape double quotes (i.e., realm.replace(/\\/g,
'\\\\').replace(/"/g, '\\"')) so both '\' and '"' are properly escaped per RFC
7230 quoted-string rules; ensure you modify the escapeRealm function
accordingly.

@ponderingdemocritus ponderingdemocritus merged commit e7d22c5 into main Feb 8, 2026
3 checks passed
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