Add IndieAuth token revocation endpoint (RFC 7009)
Implements the current IndieAuth spec's dedicated /revocation endpoint so clients can self-revoke a token (e.g. on user sign-out), rather than only supporting revocation via the admin side. Always responds 200 per spec, whether the token was found or not, so callers can't use it to probe token validity. Skips the legacy action=revoke-on-/token fallback the spec mentions for older clients, since the only real client here is already being updated to use the current endpoint. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014625MfkGZ7GVdbqKme4a8L
This commit is contained in:
parent
d5706b5f8f
commit
9c9a6392c8
5 changed files with 54 additions and 2 deletions
|
|
@ -19,7 +19,8 @@ class HeaderLinkTest extends TestCase
|
|||
$this->assertSame('<'.config('app.url').'/.well-known/indieauth-server>; rel="indieauth-metadata"', $linkHeaders[0]);
|
||||
$this->assertSame('<'.config('app.url').'/auth>; rel="authorization_endpoint"', $linkHeaders[1]);
|
||||
$this->assertSame('<'.config('app.url').'/token>; rel="token_endpoint"', $linkHeaders[2]);
|
||||
$this->assertSame('<'.config('app.url').'/api/post>; rel="micropub"', $linkHeaders[3]);
|
||||
$this->assertSame('<'.config('app.url').'/webmention>; rel="webmention"', $linkHeaders[4]);
|
||||
$this->assertSame('<'.config('app.url').'/revocation>; rel="revocation_endpoint"', $linkHeaders[3]);
|
||||
$this->assertSame('<'.config('app.url').'/api/post>; rel="micropub"', $linkHeaders[4]);
|
||||
$this->assertSame('<'.config('app.url').'/webmention>; rel="webmention"', $linkHeaders[5]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,9 @@ declare(strict_types=1);
|
|||
|
||||
namespace Tests\Feature;
|
||||
|
||||
use App\Models\MicropubToken;
|
||||
use App\Models\User;
|
||||
use App\Services\TokenService;
|
||||
use GuzzleHttp\Psr7\Uri;
|
||||
use GuzzleHttp\Psr7\UriResolver;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
|
|
@ -692,4 +694,29 @@ class IndieAuthTest extends TestCase
|
|||
'me' => config('app.url'),
|
||||
]);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function it_should_revoke_a_known_token(): void
|
||||
{
|
||||
$token = resolve(TokenService::class)->getNewToken([
|
||||
'me' => config('app.url'),
|
||||
'client_id' => 'https://app.example.com',
|
||||
'scope' => 'create',
|
||||
]);
|
||||
|
||||
$response = $this->post('/revocation', ['token' => $token]);
|
||||
$response->assertStatus(200);
|
||||
|
||||
$this->assertTrue(
|
||||
MicropubToken::where('token_hash', hash('sha256', $token))->firstOrFail()->isRevoked
|
||||
);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function it_should_return200_for_an_unknown_token(): void
|
||||
{
|
||||
$response = $this->post('/revocation', ['token' => bin2hex(random_bytes(32))]);
|
||||
|
||||
$response->assertStatus(200);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue