Authenticate against any OIDC provider, for on-premises installs
CI / verify (push) Successful in 2m55s
CI / verify (push) Successful in 2m55s
The seam existed with only a Supabase implementation, so an on-prem deployment had no way to authenticate. A customer running PIG inside their own network already has Okta, Entra, Keycloak, Auth0 or Google Workspace; asking them to stand up a second identity system is a serious adoption tax and in a regulated environment usually refused outright. Setting PIG_OIDC_ISSUER is normally the whole configuration — the JWKS is discovered from the issuer's well-known document. PIG_OIDC_JWKS_URI skips discovery entirely for an air-gapped network. OIDC takes precedence over Supabase so an on-prem install can leave the hosted values in its environment file without them quietly taking over. Three decisions worth stating: Discovery is resolved lazily and the FAILURE is not cached. Doing it per request would put the customer's identity provider on the critical path of every API call; doing it eagerly at boot would mean their IdP rebooting takes the CRM down with it. So it happens on first use and retries on the next request. The audience check is optional but warned about loudly. Without it, a token the provider issued for ANY other application in the same tenant verifies here — a token minted for an unrelated internal tool would be accepted as a PIG session. It cannot be mandatory because some providers legitimately issue single-audience tokens. Email falls back through email, preferred_username and upn, because providers disagree, but a preferred_username without an "@" is ignored — PIG keys membership on the address, and a bare username must never become an account identity. Also fixed a warning that claimed "authentication is DISABLED" on a correctly configured OIDC deployment. That is worse than silence: an operator who reads it on a secure install learns to ignore the warnings. The dev bypass itself was already correct — it keys on the resolved provider rather than on Supabase. 18 new tests, most of them about what the provider must REFUSE: a foreign signing key, a foreign issuer, a token for a different application, an expired token, a token with no subject, and a discovery outage that must not become permanent. Keys are generated per test and the JWKS is served locally, so they run offline. Verified: production refuses to start with neither provider, starts with OIDC alone, enforces 401 on an unauthenticated request, and warns only about the genuinely missing admin list. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -91,6 +91,11 @@ in the service layer or in the agent. The API signals the agent by *writing a
|
||||
row to `agent_tasks`*, never by calling it — so the queue survives the agent
|
||||
being down and no request thread ever blocks on a model.
|
||||
|
||||
**There are two auth providers, behind one interface.** Supabase for the
|
||||
hosted deployment, OIDC for on-premises — see `apps/api/src/lib/auth-provider.ts`.
|
||||
Both reduce to "verify a bearer token, return a subject and an email", because
|
||||
that is all PIG needs. Never reach for a provider SDK outside that file.
|
||||
|
||||
**Authentication is not authorization.** A verified JWT proves someone has an
|
||||
account in an identity provider that PIG *shares with another application*. It
|
||||
does not prove they belong here. Access requires a row in PIG's own `users`
|
||||
|
||||
Reference in New Issue
Block a user