如何为手动创建的Laravel Passport访问令牌添加自定义声明
Great question! Since you're manually issuing tokens by extending Passport's AccessTokenController, and your previous package worked for non-refresh-token scenarios, here are two reliable ways to add custom claims that work with refresh tokens too, tailored to your existing code:
Method 1: Override the Password Grant Class (Most Flexible)
This approach lets you directly control the claims added when tokens are generated, including both access and refresh tokens.
Create a custom Password Grant class
Make a new class that extends Passport's defaultPasswordGrantand overrides thegetClaimsmethod to inject your custom data:<?php namespace App\Passport; use Laravel\Passport\Bridge\PasswordGrant; use League\OAuth2\Server\Entities\UserEntityInterface; class CustomPasswordGrant extends PasswordGrant { protected function getClaims(UserEntityInterface $userEntity) { // Start with Passport's default claims $claims = parent::getClaims($userEntity); // Fetch your user model to get custom data $user = \App\Models\User::find($userEntity->getIdentifier()); // Add your custom claims here $claims['user_id'] = $user->id; $claims['nickname'] = $user->nickname; $claims['role'] = $user->role; return $claims; } }Replace the default grant in your AuthServiceProvider
Update thebootmethod ofAuthServiceProviderto use your custom grant instead of the default one:use App\Passport\CustomPasswordGrant; use Laravel\Passport\Passport; use League\OAuth2\Server\AuthorizationServer; public function boot() { $this->registerPolicies(); Passport::routes(); // Swap the default password grant with our custom one $this->app->extend(AuthorizationServer::class, function ($server, $app) { $grant = new CustomPasswordGrant( $app->make(\Laravel\Passport\Bridge\UserRepository::class), $app->make(\Laravel\Passport\Bridge\RefreshTokenRepository::class) ); $grant->setRefreshTokenTTL(Passport::refreshTokensExpireIn()); $server->enableGrantType( $grant, Passport::tokensExpireIn() ); return $server; }); }Update your AccessTokenController (optional)
Your existing controller code can stay mostly the same, but if you want to surface the custom claims in your API response (not just the JWT payload), you can add them before returning:// Inside your issueToken method, after decoding the token response $user = User::where('email', $username)->first(); $data['custom_claims'] = [ 'user_id' => $user->id, 'nickname' => $user->nickname, 'role' => $user->role ]; return Response::json($data);
Method 2: Use Passport's TokenCreated Event (Simpler)
If you prefer a more event-driven approach, you can hook into Passport's TokenCreated event to add claims after the token is generated.
Create an event listener
Make a listener that modifies the token's claims when the event fires:<?php namespace App\Listeners; use Laravel\Passport\Events\TokenCreated; class AddCustomClaimsToToken { public function handle(TokenCreated $event) { $user = $event->user; // Add custom claims to the access token $event->token->claims = array_merge( $event->token->claims, [ 'user_id' => $user->id, 'nickname' => $user->nickname, 'role' => $user->role ] ); // Optional: Add claims to the refresh token too if ($event->refreshToken) { $event->refreshToken->claims = array_merge( $event->refreshToken->claims, ['user_id' => $user->id] ); } } }Register the listener
Add the listener to yourEventServiceProviderso it triggers when tokens are created:protected $listen = [ \Laravel\Passport\Events\TokenCreated::class => [ \App\Listeners\AddCustomClaimsToToken::class, ], ];No changes needed to your AccessTokenController
Your existing controller code will work as-is— the event listener automatically adds the claims when the token is issued.
Bonus: Verifying the Claims
To confirm your custom claims are included, you can decode the access token anywhere in your app using:
use Laravel\Passport\Passport; $decodedToken = Passport::decode($accessToken); // Access custom claims like: $decodedToken['nickname']
内容的提问来源于stack exchange,提问作者eljulio

