Initial commit: Pireon Admin — headless admin panel and public API
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>
This commit is contained in:
81
app/Services/Pireon/TokenStore.php
Normal file
81
app/Services/Pireon/TokenStore.php
Normal file
@@ -0,0 +1,81 @@
|
||||
<?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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user