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
Implements Pangolin as an OIDC provider for “Login with Pangolin”, with full OAuth client management for admins and app-consent management for users.
Expected: JSON with fields like issuer, authorization_endpoint, token_endpoint, userinfo_endpoint, jwks_uri, revocation_endpoint,
and end_session_endpoint.
Available scopes and claims
Scope
Claims
openid
sub
profile
name, preferred_username, given_name, family_name
email
email, email_verified
groups
groups (organization/role memberships, formatted like :)
Endpoints
Endpoint
Path
Discovery
/.well-known/openid-configuration
Authorization
/oauth/authorize (browser redirect)
Token
/api/v1/oauth/token
Userinfo
/api/v1/oauth/userinfo
JWKS
/api/v1/oauth/jwks
Revoke
/api/v1/oauth/revoke
Logout
/api/v1/oauth/logout
Demo
TODO
🔄 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/2568
**Author:** [@mallendeo](https://github.com/mallendeo)
**Created:** 3/1/2026
**Status:** 🔄 Open
**Base:** `dev` ← **Head:** `feat/oidc-provider`
---
### 📝 Commits (10+)
- [`8c48803`](https://github.com/fosrl/pangolin/commit/8c488037ed846af975f6230b70d0fbacb800ffb9) feat: implement oidc provider and oauth client management
- [`d915b8e`](https://github.com/fosrl/pangolin/commit/d915b8e1d837d902be8b8ab4543ac50813cf10af) fix: localize oauth oidc ui strings
- [`7c1d5aa`](https://github.com/fosrl/pangolin/commit/7c1d5aa4b3584e6e8bb9712bd4c2f3f1bfaae5ab) feat: refactor oauth clients ui to match pangolin patterns, fix login redirect
- [`cb5be1f`](https://github.com/fosrl/pangolin/commit/cb5be1f3b82dfc0705cf042836b101828773a523) fix: add missing oauth i18n keys to all locales
- [`744ea72`](https://github.com/fosrl/pangolin/commit/744ea721c8023cf62d380b5110f547b3337461e8) fix: patch zod-to-openapi to support ZodCatch type
- [`3888e07`](https://github.com/fosrl/pangolin/commit/3888e078b22921bb961641ee109ed1643d253215) feat: improve oauth consent page ui
- [`3763def`](https://github.com/fosrl/pangolin/commit/3763defa9a51a15a6f8177b31d1a7d1997fc2e14) feat: add connected apps page for managing oauth consents
- [`466b8ed`](https://github.com/fosrl/pangolin/commit/466b8ed45fd5c00f10fa8c7788051a78c8db3e05) feat: add edit profile dialog for name and username
- [`59a93e2`](https://github.com/fosrl/pangolin/commit/59a93e220dbc1336bff0415af5e3620b1e30448a) feat: add given_name and family_name to OIDC claims
- [`4841ef8`](https://github.com/fosrl/pangolin/commit/4841ef8cc025bd031d52e492d73fde5ea6dbea28) fix: add missing i18n keys to all locales
### 📊 Changes
**62 files changed** (+6799 additions, -205 deletions)
<details>
<summary>View changed files</summary>
📝 `install/config/crowdsec/dynamic_config.yml` (+4 -4)
📝 `install/config/traefik/dynamic_config.yml` (+4 -4)
📝 `messages/en-US.json` (+114 -1)
📝 `server/apiServer.ts` (+3 -0)
📝 `server/auth/actions.ts` (+5 -0)
📝 `server/db/pg/schema/schema.ts` (+187 -0)
📝 `server/db/sqlite/schema/schema.ts` (+199 -1)
📝 `server/index.ts` (+2 -0)
📝 `server/lib/cleanupLogs.ts` (+3 -0)
📝 `server/lib/consts.ts` (+1 -1)
➕ `server/lib/oauth/backchannelLogout.ts` (+162 -0)
➕ `server/lib/oauth/backchannelLogoutSecurity.ts` (+328 -0)
➕ `server/lib/oauth/claims.ts` (+111 -0)
➕ `server/lib/oauth/clientAuth.ts` (+145 -0)
➕ `server/lib/oauth/clientMembership.ts` (+22 -0)
➕ `server/lib/oauth/issuer.ts` (+17 -0)
➕ `server/lib/oauth/keys.ts` (+112 -0)
➕ `server/lib/oauth/lifetimes.ts` (+5 -0)
➕ `server/lib/oauth/scopes.ts` (+51 -0)
➕ `server/lib/oauth/tokens.ts` (+61 -0)
_...and 42 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
Implements Pangolin as an OIDC provider for “Login with Pangolin”, with full OAuth client management for admins and app-consent management for users.
See https://github.com/orgs/fosrl/discussions/21
Scaffolding and ongoing development were AI-assisted (Opus 4.6 / Codex 5.3); not all code has been manually reviewed. Contributions welcome.
## What’s included
- OAuth 2.0 Authorization Code flow with PKCE
- OIDC endpoints: discovery, authorize, token, userinfo, JWKS, revoke
- OIDC logout support:
- RP-initiated logout (`end_session_endpoint`)
- back-channel logout dispatch
- Admin OAuth Clients UI: create, edit, delete, rotate secret, advanced settings
- User "Connected Apps" page to revoke grants
- Edit profile dialog (name, username) to support profile claims
- Claims updates, including `given_name`, `family_name`, and org-scoped `groups`
- i18n strings (English only, AI translation removed / out of scope)
- SQLite + PostgreSQL schema/migration updates for v1.17.0
## How to test
If upgrading from a previous install, route `/.well-known` to the API service.
In `config/traefik/dynamic_config.yml`, update the Next.js and API router rules:
```yaml
next-router:
rule: "Host(`yourdomain.com`) && !PathPrefix(`/api/v1`) && !PathPrefix(`/.well-known`)"
# ...
api-router:
rule: "Host(`yourdomain.com`) && (PathPrefix(`/api/v1`) || PathPrefix(`/.well-known`))"
# ...
```
Restart Traefik after changing this.
### Create an OAuth client
1. Go to Org Settings > OAuth Clients
2. Click Create Client
3. Fill in name, redirect URI, and scopes
4. Save the client ID and secret shown in the dialog
### Verify discovery
curl https://yourdomain.com/.well-known/openid-configuration
Expected: JSON with fields like `issuer`, `authorization_endpoint`,
`token_endpoint`, `userinfo_endpoint`, `jwks_uri`, `revocation_endpoint`,
and `end_session_endpoint`.
### Available scopes and claims
| Scope | Claims |
| ------- | --------------------------------------------------------------------------- |
| openid | sub |
| profile | name, preferred_username, given_name, family_name |
| email | email, email_verified |
| groups | groups (organization/role memberships, formatted like <orgName>:<roleName>) |
### Endpoints
| Endpoint | Path |
| ------------- | ----------------------------------- |
| Discovery | /.well-known/openid-configuration |
| Authorization | /oauth/authorize (browser redirect) |
| Token | /api/v1/oauth/token |
| Userinfo | /api/v1/oauth/userinfo |
| JWKS | /api/v1/oauth/jwks |
| Revoke | /api/v1/oauth/revoke |
| Logout | /api/v1/oauth/logout |
## Demo
TODO
---
<sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
📋 Pull Request Information
Original PR: https://github.com/fosrl/pangolin/pull/2568
Author: @mallendeo
Created: 3/1/2026
Status: 🔄 Open
Base:
dev← Head:feat/oidc-provider📝 Commits (10+)
8c48803feat: implement oidc provider and oauth client managementd915b8efix: localize oauth oidc ui strings7c1d5aafeat: refactor oauth clients ui to match pangolin patterns, fix login redirectcb5be1ffix: add missing oauth i18n keys to all locales744ea72fix: patch zod-to-openapi to support ZodCatch type3888e07feat: improve oauth consent page ui3763deffeat: add connected apps page for managing oauth consents466b8edfeat: add edit profile dialog for name and username59a93e2feat: add given_name and family_name to OIDC claims4841ef8fix: add missing i18n keys to all locales📊 Changes
62 files changed (+6799 additions, -205 deletions)
View changed files
📝
install/config/crowdsec/dynamic_config.yml(+4 -4)📝
install/config/traefik/dynamic_config.yml(+4 -4)📝
messages/en-US.json(+114 -1)📝
server/apiServer.ts(+3 -0)📝
server/auth/actions.ts(+5 -0)📝
server/db/pg/schema/schema.ts(+187 -0)📝
server/db/sqlite/schema/schema.ts(+199 -1)📝
server/index.ts(+2 -0)📝
server/lib/cleanupLogs.ts(+3 -0)📝
server/lib/consts.ts(+1 -1)➕
server/lib/oauth/backchannelLogout.ts(+162 -0)➕
server/lib/oauth/backchannelLogoutSecurity.ts(+328 -0)➕
server/lib/oauth/claims.ts(+111 -0)➕
server/lib/oauth/clientAuth.ts(+145 -0)➕
server/lib/oauth/clientMembership.ts(+22 -0)➕
server/lib/oauth/issuer.ts(+17 -0)➕
server/lib/oauth/keys.ts(+112 -0)➕
server/lib/oauth/lifetimes.ts(+5 -0)➕
server/lib/oauth/scopes.ts(+51 -0)➕
server/lib/oauth/tokens.ts(+61 -0)...and 42 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
Implements Pangolin as an OIDC provider for “Login with Pangolin”, with full OAuth client management for admins and app-consent management for users.
See https://github.com/orgs/fosrl/discussions/21
Scaffolding and ongoing development were AI-assisted (Opus 4.6 / Codex 5.3); not all code has been manually reviewed. Contributions welcome.
What’s included
end_session_endpoint)given_name,family_name, and org-scopedgroupsHow to test
If upgrading from a previous install, route
/.well-knownto the API service.In
config/traefik/dynamic_config.yml, update the Next.js and API router rules:Restart Traefik after changing this.
Create an OAuth client
Verify discovery
curl https://yourdomain.com/.well-known/openid-configuration
Expected: JSON with fields like
issuer,authorization_endpoint,token_endpoint,userinfo_endpoint,jwks_uri,revocation_endpoint,and
end_session_endpoint.Available scopes and claims
Endpoints
Demo
TODO
🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.