Laravel 13 + Filament 5 admin panel and REST API for a non-profit developer collective, backed by the Pireon OAuth identity server. The public site is a separate, server-rendered application consuming /api/public/v1. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
82 lines
1.9 KiB
PHP
82 lines
1.9 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Services\Pireon;
|
|
|
|
use Illuminate\Contracts\Session\Session;
|
|
|
|
/**
|
|
* Keeps the signed-in panel user's token set in the session and transparently
|
|
* refreshes it when it ages out.
|
|
*
|
|
* Tokens live in the session rather than the database on purpose: they are
|
|
* per-session credentials, and logging out or the session expiring should take
|
|
* them with it.
|
|
*/
|
|
class TokenStore
|
|
{
|
|
protected const KEY = 'pireon.token';
|
|
|
|
public function __construct(
|
|
protected Session $session,
|
|
protected PireonClient $client,
|
|
) {}
|
|
|
|
public function put(AccessToken $token): void
|
|
{
|
|
$this->session->put(self::KEY, $token->toArray());
|
|
}
|
|
|
|
public function get(): ?AccessToken
|
|
{
|
|
$state = $this->session->get(self::KEY);
|
|
|
|
return is_array($state) ? AccessToken::fromArray($state) : null;
|
|
}
|
|
|
|
public function forget(): void
|
|
{
|
|
$this->session->forget(self::KEY);
|
|
}
|
|
|
|
/**
|
|
* The current access token, refreshed first if it has expired.
|
|
*
|
|
* Returns null when there is no token, or when the refresh failed — the
|
|
* caller should treat that as "this session is no longer authenticated"
|
|
* and send the user back through the login flow.
|
|
*/
|
|
public function accessToken(): ?string
|
|
{
|
|
$token = $this->get();
|
|
|
|
if ($token === null) {
|
|
return null;
|
|
}
|
|
|
|
if (! $token->hasExpired()) {
|
|
return $token->accessToken;
|
|
}
|
|
|
|
if (! $token->isRefreshable()) {
|
|
$this->forget();
|
|
|
|
return null;
|
|
}
|
|
|
|
try {
|
|
$refreshed = $this->client->refresh($token->refreshToken);
|
|
} catch (PireonException) {
|
|
// The refresh token was revoked or expired upstream.
|
|
$this->forget();
|
|
|
|
return null;
|
|
}
|
|
|
|
$this->put($refreshed);
|
|
|
|
return $refreshed->accessToken;
|
|
}
|
|
}
|