feat: header token authentication to bypass SSO for API access #95

Open
opened 2026-04-05 17:00:54 +02:00 by MrUnknownDE · 0 comments
Owner

Originally created by @crisidev on 3/19/2026

Community Contribution License Agreement

By creating this pull request, I grant the project maintainers an unlimited,
perpetual license to use, modify, and redistribute these contributions under any terms they
choose, including both the AGPLv3 and the Fossorial Commercial license terms. I
represent that I have the right to grant this license for all contributed content.

Description

Adds a new per-resource authentication method that allows clients to bypass SSO by sending a secret token in a custom HTTP header. This is designed for programmatic access: CI/CD pipelines, monitoring tools, webhooks, and other integrations that can't go through browser-based auth.

  • Resources can opt-in by setting a header name (e.g. X-Pangolin-Token) in the authentication settings
  • Tokens are generated with 128-bit entropy, stored as SHA-256 hashes, with optional expiration
  • Badger's verifySession checks the header before falling through to SSO, with a 5-second local cache keyed by hash
    (not raw token)
  • Full CRUD API: generate, list, delete — protected by the same org/resource access middleware as access tokens
  • Refactored verifyAccessTokenAccess and verifyHeaderTokenAccess into a shared verifyTokenResourceAccess
    factory, removing ~140 lines of duplication
  • Expired token cleanup in clearStaleData with proper NULL-safe handling for never-expiring tokens
  • PG + SQLite schema, migrations (1.17.0), OpenAPI registration, i18n keys, and frontend UI with token generation,
    copy-to-clipboard, and delete
Screenshot From 2026-03-19 15-28-14 Screenshot From 2026-03-19 15-28-22 Screenshot From 2026-03-19 15-28-43

How to test?

  • Deploy new version
  • Enable header token on a resource, set header name, generate token
  • Verify token grants access via curl -H "X-Pangolin-Token: <token>"
  • Verify invalid/expired tokens are rejected
  • Verify disabling header token auth blocks token access
  • Verify token deletion removes access
  • Verify audit logs show reason 108 for header token access
  • Test with both SQLite and PostgreSQL
  • Run fresh migration on clean DB (1.17.0 creates table + column)

Notes

This is tested only on my setup with sqlite. I kinda winged the postgresql migrations..

*Originally created by @crisidev on 3/19/2026* ## Community Contribution License Agreement By creating this pull request, I grant the project maintainers an unlimited, perpetual license to use, modify, and redistribute these contributions under any terms they choose, including both the AGPLv3 and the Fossorial Commercial license terms. I represent that I have the right to grant this license for all contributed content. ## Description Adds a new per-resource authentication method that allows clients to bypass SSO by sending a secret token in a custom HTTP header. This is designed for programmatic access: CI/CD pipelines, monitoring tools, webhooks, and other integrations that can't go through browser-based auth. - Resources can opt-in by setting a header name (e.g. `X-Pangolin-Token`) in the authentication settings - Tokens are generated with 128-bit entropy, stored as SHA-256 hashes, with optional expiration - Badger's `verifySession` checks the header before falling through to SSO, with a 5-second local cache keyed by hash (not raw token) - Full CRUD API: generate, list, delete — protected by the same org/resource access middleware as access tokens - Refactored `verifyAccessTokenAccess` and `verifyHeaderTokenAccess` into a shared `verifyTokenResourceAccess` factory, removing ~140 lines of duplication - Expired token cleanup in `clearStaleData` with proper NULL-safe handling for never-expiring tokens - PG + SQLite schema, migrations (1.17.0), OpenAPI registration, i18n keys, and frontend UI with token generation, copy-to-clipboard, and delete <img width="2139" height="400" alt="Screenshot From 2026-03-19 15-28-14" src="https://github.com/user-attachments/assets/7608a61f-ea0d-4c4e-a0ef-ffd3cb3ca32a" /> <img width="2139" height="400" alt="Screenshot From 2026-03-19 15-28-22" src="https://github.com/user-attachments/assets/71901905-8afd-41a2-a595-366ba2256f83" /> <img width="2152" height="660" alt="Screenshot From 2026-03-19 15-28-43" src="https://github.com/user-attachments/assets/b7f21b90-0751-41ce-9677-afd757ef15e3" /> ## How to test? - [ ] Deploy new version - [ ] Enable header token on a resource, set header name, generate token - [ ] Verify token grants access via `curl -H "X-Pangolin-Token: <token>"` - [ ] Verify invalid/expired tokens are rejected - [ ] Verify disabling header token auth blocks token access - [ ] Verify token deletion removes access - [ ] Verify audit logs show reason 108 for header token access - [ ] Test with both SQLite and PostgreSQL - [ ] Run fresh migration on clean DB (1.17.0 creates table + column) ## Notes This is tested only on my setup with sqlite. I kinda winged the postgresql migrations..
Sign in to join this conversation.
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github/pangolin#95