Files
landing-api/config/pireon.php
Josep Piguillem d10ce1ca57
Some checks failed
Tests / lint (push) Has been cancelled
Tests / test (push) Has been cancelled
Tests / test-postgres (push) Has been cancelled
Tests / mcp (push) Has been cancelled
Take Pireon's webhooks: a deactivation or a revocation counts at once
Until now, an account switched off or a token revoked at the identity
server kept working here: bearer tokens until the introspection cache
ran out, panel sessions until they ended, and machine tokens for good,
as they only look at the local account.

POST /api/v1/webhooks/pireon takes user.deactivated (the account goes
inactive, which stops its machine tokens and the panel; its sessions
end and its cached tokens are forgotten) and token.revoked (sessions
and cached tokens go). Pireon signs each delivery with the secret of
the client that registered the webhook, so either PIREON_WEBHOOK_SECRET
(password client) or PIREON_REDIRECT_WEBHOOK_SECRET («Entrar con
Pireon») verifies it; with neither, the endpoint refuses everything.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 17:01:57 +02:00

139 lines
5.3 KiB
PHP

<?php
declare(strict_types=1);
return [
/*
|--------------------------------------------------------------------------
| Pireon OAuth2 identity server
|--------------------------------------------------------------------------
|
| This application is an OAuth2 *client* of the Pireon identity server
| (Laravel Passport). The server owns identity only: it tells us who the
| user is. Authorisation (roles and permissions) is resolved locally by
| spatie/laravel-permission — see config/permission.php.
|
*/
'server' => rtrim((string) env('PIREON_SERVER', 'https://oauth.pireon.dev'), '/'),
/*
| Base path of the server's REST API, as declared in its OpenAPI document
| ("servers": [{"url": "/api"}]).
*/
'api_prefix' => '/api',
'client_id' => env('PIREON_CLIENT_ID'),
'client_secret' => env('PIREON_CLIENT_SECRET'),
/*
| Where the identity server sends the user back after they authorise us.
| Must match one of the redirect URIs registered for the client.
*/
'redirect_uri' => env('PIREON_REDIRECT_URI', env('APP_URL', 'http://localhost').'/auth/callback'),
/*
| The redirect flow («Entrar con Pireon», Authorization Code + PKCE) can
| use a client of its own. A Pireon client allows one grant type, so when
| the one above is a password client, register another for
| authorization_code (redirect URI as above) and put it here. Left empty,
| the client above is used for both.
*/
'redirect_client_id' => env('PIREON_REDIRECT_CLIENT_ID'),
'redirect_client_secret' => env('PIREON_REDIRECT_CLIENT_SECRET'),
/*
| Offer «Entrar con Pireon» under the e-mail and password form. By default
| only once a redirect client is set: the main one is usually a password
| client, and the button would fail with it. Set it to true when the main
| client allows authorization_code too.
*/
'redirect_login' => (bool) (env('PIREON_REDIRECT_LOGIN') ?? filled(env('PIREON_REDIRECT_CLIENT_ID'))),
/*
| Scopes requested for panel sessions. We only ever need to read the
| identity of the person logging in, so we stay minimal by default.
| Add "users:read"/"users:write" if you surface remote user management.
*/
'scopes' => array_values(array_filter(
explode(',', (string) env('PIREON_SCOPES', 'account:read'))
)),
'endpoints' => [
'authorize' => '/oauth/authorize',
'token' => '/oauth/token',
'user' => '/user',
],
/*
|--------------------------------------------------------------------------
| Grants
|--------------------------------------------------------------------------
|
| "authorization_code" (with PKCE) is the interactive flow used by the
| Filament panel. "password" is kept available for automated tests and
| first-party mobile clients that cannot open a browser; disable it in
| production if you do not need it.
|
*/
'password_grant_enabled' => (bool) env('PIREON_PASSWORD_GRANT', true),
/*
|--------------------------------------------------------------------------
| Token introspection cache
|--------------------------------------------------------------------------
|
| The identity server exposes no introspection or JWKS endpoint, so an API
| bearer token is validated by calling GET /api/user upstream with it. That
| result is cached (keyed by a hash of the token, never the token itself)
| to keep per-request latency down. Keep this short: it bounds how long a
| token revoked upstream still works here.
|
*/
'introspection_ttl' => (int) env('PIREON_INTROSPECTION_TTL', 60),
/*
|--------------------------------------------------------------------------
| Webhooks (POST /api/v1/webhooks/pireon)
|--------------------------------------------------------------------------
|
| `user.deactivated` and `token.revoked` take effect at once instead of
| when the cache above runs out. Pireon signs each delivery with the secret
| of the client that registered the webhook, and only the client that
| issued a token tells when it is revoked: register the webhook on both
| clients (password and redirect) and put each secret here. With none, the
| endpoint refuses everything.
|
*/
'webhook_secrets' => array_values(array_filter([
env('PIREON_WEBHOOK_SECRET'),
env('PIREON_REDIRECT_WEBHOOK_SECRET'),
])),
'http_timeout' => (int) env('PIREON_HTTP_TIMEOUT', 10),
/*
|--------------------------------------------------------------------------
| Provisioning
|--------------------------------------------------------------------------
|
| Role granted to a user the first time they sign in. Because authorisation
| is local-only, a brand new identity gets the least-privileged role and an
| administrator promotes them from the panel.
|
*/
'default_role' => env('PIREON_DEFAULT_ROLE', 'viewer'),
/*
| Refuse the session when the identity server reports the account as
| inactive or still awaiting approval (approved_at === null).
*/
'require_active_account' => (bool) env('PIREON_REQUIRE_ACTIVE', true),
'require_approved_account' => (bool) env('PIREON_REQUIRE_APPROVED', true),
];