Skip to content

feat: OIDC provider for "Login with Pangolin"#2568

Draft
mallendeo wants to merge 91 commits intofosrl:devfrom
mallendeo:feat/oidc-provider
Draft

feat: OIDC provider for "Login with Pangolin"#2568
mallendeo wants to merge 91 commits intofosrl:devfrom
mallendeo:feat/oidc-provider

Conversation

@mallendeo
Copy link
Contributor

@mallendeo mallendeo commented Mar 1, 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

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

Initial scaffolding/discovery was AI-assisted (Opus 4.6 / Codex 5.3); final code was manually reviewed and refactored.

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:

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 :)

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

@mallendeo mallendeo force-pushed the feat/oidc-provider branch from c6dfd3a to 0196b71 Compare March 1, 2026 14:22
@mallendeo mallendeo changed the title feat: OIDC provider feat: OIDC provider for "Login with Pangolin" Mar 1, 2026
@mallendeo mallendeo force-pushed the feat/oidc-provider branch 2 times, most recently from 4e3c4f5 to 9b15e5c Compare March 3, 2026 12:57
@mallendeo mallendeo force-pushed the feat/oidc-provider branch from c932656 to 99d400e Compare March 3, 2026 22:44
@mallendeo mallendeo force-pushed the feat/oidc-provider branch from 99d400e to 3d580bb Compare March 14, 2026 23:52
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