mirror of
https://github.com/anikeen-com/id.git
synced 2026-11-04 06:39:32 +00:00
Fix the anikeen API guard and register its user provider
- Register the guard driver and the anikeen user provider with static closures: Laravel binds extend() closures to the AuthManager, so $this->makeGuard() failed. - Look the token's sub up in the user's Anikeen ID column (anikeen_id by default; provider 'column', services.anikeen.user_id_column or useUserIdField()), not in the primary key; works with the anikeen, eloquent and database providers. - JwtParser: key from services.anikeen.public_key(_path) or the bundled key, read once per process; misconfiguration is an error, not a 401. Passport tokens have no client claim, so it is optional now. - Optional revocation check against Anikeen ID (verify_revocation), cached per token. - anikeenTokenCan() without a token, anikeenTokenCanAny(), scope middleware accept JSON responses. - Update the bundled staging public key to the current staging key. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VbpgPaLqhBzo1AXHNs9Cx5
This commit is contained in:
1 parent
b074ec3c0c
commit
dc29eb2844
12 files changed
+554
-163
No files matched your search
+41
-28
@@ -286,30 +286,10 @@ public function boot(): void
|
||||
}
|
||||
```
|
||||
|
||||
### Implementing Auth
|
||||
### Implementing Auth (API tokens)
|
||||
|
||||
This method should typically be called in the `boot` method of your `AppServiceProvider` class:
|
||||
|
||||
```php
|
||||
use Anikeen\Id\AnikeenId;
|
||||
use Anikeen\Id\Providers\AnikeenIdUserProvider;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
public function boot(): void
|
||||
{
|
||||
Auth::provider('anikeen', function ($app, array $config) {
|
||||
return new AnikeenIdUserProvider(
|
||||
$app->make(AnikeenId::class),
|
||||
$app->make(Request::class),
|
||||
$config['model'],
|
||||
$config['fields'] ?? [],
|
||||
);
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
reference the guard in the `guards` configuration of your `auth.php` configuration file:
|
||||
The package registers an `anikeen` guard driver and an `anikeen` user provider. Reference them
|
||||
in `config/auth.php`:
|
||||
|
||||
```php
|
||||
'guards' => [
|
||||
@@ -323,11 +303,7 @@ reference the guard in the `guards` configuration of your `auth.php` configurati
|
||||
'provider' => 'anikeen',
|
||||
],
|
||||
],
|
||||
```
|
||||
|
||||
reference the provider in the `providers` configuration of your `auth.php` configuration file:
|
||||
|
||||
```php
|
||||
'providers' => [
|
||||
'users' => [
|
||||
'driver' => 'eloquent',
|
||||
@@ -337,11 +313,48 @@ reference the provider in the `providers` configuration of your `auth.php` confi
|
||||
'anikeen' => [
|
||||
'driver' => 'anikeen',
|
||||
'model' => App\Models\User::class,
|
||||
'fields' => ['first_name', 'last_name', 'email'],
|
||||
'column' => 'anikeen_id', // optional, see below
|
||||
],
|
||||
],
|
||||
```
|
||||
|
||||
The guard accepts `Authorization: Bearer <access token>` with an access token issued by Anikeen ID
|
||||
(personal access token or OAuth token, a JWT). It verifies the RS256 signature with Anikeen ID's
|
||||
public key and the time claims (`exp`, `nbf`, `iat`, 60 seconds leeway). The token's `sub` (the
|
||||
user's Anikeen ID) is looked up in the column `anikeen_id` of the user model: the provider's
|
||||
`column`, else `services.anikeen.user_id_column`, else `AnikeenId::useUserIdField()`. Tokens of
|
||||
unknown users, client credentials tokens (no `sub`), expired or forged tokens leave the request
|
||||
unauthenticated, so `auth:api` answers `401 {"message": "Unauthenticated."}` to JSON requests.
|
||||
|
||||
The user model uses `Anikeen\Id\HasAnikeenTokens`; the token's scopes are then available:
|
||||
|
||||
```php
|
||||
$request->user()->anikeenTokenCan('user'); // has the scope (or `*`)
|
||||
$request->user()->anikeenTokenCanAny(['user', 'user:read']);
|
||||
```
|
||||
|
||||
or as middleware (`403` without the scope):
|
||||
|
||||
```php
|
||||
use Anikeen\Id\Http\Middleware\CheckForAnyScope;
|
||||
use Anikeen\Id\Http\Middleware\CheckScopes;
|
||||
|
||||
Route::middleware(['auth:api', CheckScopes::using('user')])->post(...); // all scopes
|
||||
Route::middleware(['auth:api', CheckForAnyScope::using('user', 'user:read')])->get(...); // any scope
|
||||
```
|
||||
|
||||
Options in `config/services.php` (`anikeen`):
|
||||
|
||||
| Key | Default | |
|
||||
|-----|---------|-|
|
||||
| `public_key` | – | Anikeen ID's public key (PEM; `\n` escapes allowed) |
|
||||
| `public_key_path` | – | path to that key; without both the key shipped for the `mode` is used |
|
||||
| `user_id_column` | `anikeen_id` | column holding the user's Anikeen ID |
|
||||
| `verify_revocation` | `false` | also ask Anikeen ID (`GET v1/user`) whether the token is still valid, so revoked tokens stop working before they expire; fails closed when Anikeen ID is unreachable |
|
||||
| `revocation_cache_ttl` | `300` | seconds that answer is cached per token |
|
||||
|
||||
The key is read once per process. In tests `AnikeenId::actingAs($user, ['user'])` signs in without a token.
|
||||
|
||||
## General
|
||||
|
||||
#### Setters and Getters
|
||||
|
||||
Reference in new issue
Block a user