[PR #2676] [CLOSED] feat: header token authentication to bypass SSO for API access #34413

Closed
opened 2026-06-17 03:59:08 -05:00 by GiteaMirror · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/fosrl/pangolin/pull/2676
Author: @crisidev
Created: 3/19/2026
Status: Closed

Base: mainHead: main


📝 Commits (3)

  • fb7847f add header token auth to bypass SSO for API access
  • df27ee0 Merge branch 'fosrl:main' into main
  • 78cfc2a Fix indentation bug

📊 Changes

26 files changed (+1378 additions, -152 deletions)

View changed files

📝 messages/en-US.json (+30 -0)
📝 server/auth/actions.ts (+3 -0)
server/auth/verifyHeaderToken.ts (+48 -0)
📝 server/db/pg/schema/schema.ts (+17 -1)
📝 server/db/sqlite/schema/schema.ts (+17 -1)
📝 server/middlewares/index.ts (+1 -0)
📝 server/middlewares/verifyAccessTokenAccess.ts (+5 -141)
server/middlewares/verifyHeaderTokenAccess.ts (+6 -0)
server/middlewares/verifyTokenResourceAccess.ts (+159 -0)
📝 server/openApi.ts (+1 -0)
📝 server/routers/badger/logRequestAudit.ts (+1 -0)
📝 server/routers/badger/verifySession.ts (+45 -3)
📝 server/routers/external.ts (+27 -0)
server/routers/headerToken/deleteHeaderToken.ts (+72 -0)
server/routers/headerToken/generateHeaderToken.ts (+148 -0)
server/routers/headerToken/index.ts (+3 -0)
server/routers/headerToken/listHeaderTokens.ts (+89 -0)
📝 server/routers/resource/getResourceAuthInfo.ts (+4 -1)
📝 server/routers/resource/updateResource.ts (+11 -1)
📝 server/setup/clearStaleData.ts (+15 -1)

...and 6 more files

📄 Description

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..


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/fosrl/pangolin/pull/2676 **Author:** [@crisidev](https://github.com/crisidev) **Created:** 3/19/2026 **Status:** ❌ Closed **Base:** `main` ← **Head:** `main` --- ### 📝 Commits (3) - [`fb7847f`](https://github.com/fosrl/pangolin/commit/fb7847ff2b4cd1818bc54e880ea3d755f8af7d43) add header token auth to bypass SSO for API access - [`df27ee0`](https://github.com/fosrl/pangolin/commit/df27ee0952929e05be537066834017097657e1f8) Merge branch 'fosrl:main' into main - [`78cfc2a`](https://github.com/fosrl/pangolin/commit/78cfc2a47447f3aefe3d9a36ba811b39b6a3beda) Fix indentation bug ### 📊 Changes **26 files changed** (+1378 additions, -152 deletions) <details> <summary>View changed files</summary> 📝 `messages/en-US.json` (+30 -0) 📝 `server/auth/actions.ts` (+3 -0) ➕ `server/auth/verifyHeaderToken.ts` (+48 -0) 📝 `server/db/pg/schema/schema.ts` (+17 -1) 📝 `server/db/sqlite/schema/schema.ts` (+17 -1) 📝 `server/middlewares/index.ts` (+1 -0) 📝 `server/middlewares/verifyAccessTokenAccess.ts` (+5 -141) ➕ `server/middlewares/verifyHeaderTokenAccess.ts` (+6 -0) ➕ `server/middlewares/verifyTokenResourceAccess.ts` (+159 -0) 📝 `server/openApi.ts` (+1 -0) 📝 `server/routers/badger/logRequestAudit.ts` (+1 -0) 📝 `server/routers/badger/verifySession.ts` (+45 -3) 📝 `server/routers/external.ts` (+27 -0) ➕ `server/routers/headerToken/deleteHeaderToken.ts` (+72 -0) ➕ `server/routers/headerToken/generateHeaderToken.ts` (+148 -0) ➕ `server/routers/headerToken/index.ts` (+3 -0) ➕ `server/routers/headerToken/listHeaderTokens.ts` (+89 -0) 📝 `server/routers/resource/getResourceAuthInfo.ts` (+4 -1) 📝 `server/routers/resource/updateResource.ts` (+11 -1) 📝 `server/setup/clearStaleData.ts` (+15 -1) _...and 6 more files_ </details> ### 📄 Description ## 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.. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
GiteaMirror added the pull-request label 2026-06-17 03:59:08 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/pangolin#34413