Replace JWT Micropub tokens with revocable opaque tokens
Tokens now store a hashed row in micropub_tokens instead of being self-contained signed JWTs, so a leaked or unwanted token can actually be revoked. Since revocation already requires a DB lookup on every request, JWT's stateless-verification benefit was gone anyway, so this also drops the lcobucci/jwt dependency entirely. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014625MfkGZ7GVdbqKme4a8L
This commit is contained in:
parent
f9f2744fad
commit
d5706b5f8f
10 changed files with 124 additions and 181 deletions
|
|
@ -4,18 +4,16 @@ declare(strict_types=1);
|
|||
|
||||
namespace Tests\Feature;
|
||||
|
||||
use App\Models\MicropubToken;
|
||||
use App\Services\TokenService;
|
||||
use DateTimeImmutable;
|
||||
use Lcobucci\JWT\Configuration;
|
||||
use Lcobucci\JWT\Signer\Key\InMemory;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
use Tests\TestCase;
|
||||
|
||||
class TokenServiceTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* Given the token is dependent on a random nonce, the time of creation and
|
||||
* the APP_KEY, to test, we shall create a token, and then verify it.
|
||||
* Given the token is dependent on a random value and stored only as a
|
||||
* hash, to test, we shall create a token, and then verify it.
|
||||
*/
|
||||
#[Test]
|
||||
public function tokenservice_creates_valid_tokens(): void
|
||||
|
|
@ -41,24 +39,29 @@ class TokenServiceTest extends TestCase
|
|||
}
|
||||
|
||||
#[Test]
|
||||
public function tokens_with_different_signing_key_are_not_valid(): void
|
||||
public function unknown_tokens_are_not_valid(): void
|
||||
{
|
||||
$response = $this->get('/api/post', ['HTTP_Authorization' => 'Bearer '.bin2hex(random_bytes(32))]);
|
||||
|
||||
$response->assertJson([
|
||||
'response' => 'error',
|
||||
'error' => 'invalid_token',
|
||||
'error_description' => 'The provided token did not pass validation',
|
||||
]);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function revoked_tokens_are_not_valid(): void
|
||||
{
|
||||
$tokenService = new TokenService;
|
||||
$data = [
|
||||
'me' => 'https://example.org',
|
||||
'client_id' => 'https://quill.p3k.io',
|
||||
'scope' => 'post',
|
||||
];
|
||||
$token = $tokenService->getNewToken($data);
|
||||
|
||||
$config = resolve(Configuration::class);
|
||||
|
||||
$token = $config->builder()
|
||||
->issuedAt(new DateTimeImmutable)
|
||||
->withClaim('client_id', $data['client_id'])
|
||||
->withClaim('me', $data['me'])
|
||||
->withClaim('scope', $data['scope'])
|
||||
->withClaim('nonce', bin2hex(random_bytes(8)))
|
||||
->getToken($config->signer(), InMemory::plainText(random_bytes(32)))
|
||||
->toString();
|
||||
MicropubToken::where('token_hash', hash('sha256', $token))->firstOrFail()->revoke();
|
||||
|
||||
$response = $this->get('/api/post', ['HTTP_Authorization' => 'Bearer '.$token]);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue