You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于项目创建Laravel Passport令牌及项目权限校验方案咨询

Got it, let's work through this problem where users need separate Laravel Passport tokens for each of their projects, and we need to validate their access to the specific project on every API request. Here's a practical, step-by-step solution:

First, we need to connect Passport's access tokens to projects. The default oauth_access_tokens table doesn't track project associations, so let's add that with a migration:

php artisan make:migration add_project_id_to_oauth_access_tokens_table

Open the generated migration file and add the project foreign key:

public function up()
{
    Schema::table('oauth_access_tokens', function (Blueprint $table) {
        $table->unsignedBigInteger('project_id')->nullable();
        $table->foreign('project_id')->references('id')->on('projects')->onDelete('cascade');
    });
}

public function down()
{
    Schema::table('oauth_access_tokens', function (Blueprint $table) {
        $table->dropForeign(['project_id']);
        $table->dropColumn('project_id');
    });
}

Run the migration with php artisan migrate once you're done. Also, make sure your projects table already exists with a user_id field linking to the project owner.

Step 2: Customize Passport's Access Token Model

Next, we need to extend Passport's token model to support the project_id field and add relationship checks. First, publish Passport's models:

php artisan vendor:publish --tag=passport-models

Open app/Models/Passport/AccessToken.php and update it like this:

use App\Models\Project;

class AccessToken extends \Laravel\Passport\Token
{
    protected $fillable = [
        'name',
        'scopes',
        'revoked',
        'project_id', // Add this to allow filling
    ];

    // Link token to its associated project
    public function project()
    {
        return $this->belongsTo(Project::class);
    }

    // Check if the token's owner has access to the linked project
    public function userHasAccess()
    {
        // Adjust this if you have project members (not just owners)
        return $this->project->user_id === $this->user_id;
    }
}

Don't forget to update your config/passport.php to use this custom model:

'models' => [
    'access_token' => App\Models\Passport\AccessToken::class,
],
Step 3: Generate Tokens Tied to Specific Projects

Now let's create an endpoint to generate project-specific tokens. Add this method to an API controller (e.g., AuthController):

use App\Models\Project;
use Illuminate\Http\Request;
use Laravel\Passport\Client;

public function generateProjectToken(Request $request)
{
    $request->validate([
        'project_id' => 'required|exists:projects,id',
        'name' => 'required|string', // e.g., "My Project - Mobile App"
    ]);

    // First, confirm the user owns the requested project
    $project = Project::where('id', $request->project_id)
        ->where('user_id', auth()->id())
        ->firstOrFail();

    // Grab your password grant client (create one via `php artisan passport:client --password` if missing)
    $client = Client::where('password_client', true)->first();

    // Create the token and attach the project ID
    $token = auth()->user()->createToken(
        $request->name,
        [], // Add scopes here if you need granular permissions
        $project->id
    );

    return response()->json([
        'access_token' => $token->accessToken,
        'token_type' => 'Bearer',
        'expires_at' => $token->token->expires_at,
        'project_id' => $project->id,
    ]);
}
Step 4: Build a Middleware to Validate Project Access

This is the core part—we need to check that the token used for the request is tied to the project being accessed. Create the middleware:

php artisan make:middleware ValidateProjectAccess

Open app/Http/Middleware/ValidateProjectAccess.php and add the validation logic:

use Closure;
use Illuminate\Http\Request;
use Laravel\Passport\TokenRepository;

class ValidateProjectAccess
{
    protected $tokenRepository;

    public function __construct(TokenRepository $tokenRepository)
    {
        $this->tokenRepository = $tokenRepository;
    }

    public function handle(Request $request, Closure $next)
    {
        // Get the project ID from the route (adjust this if you get it from request body instead)
        $projectId = $request->route('project');

        if (!$projectId) {
            return response()->json(['message' => 'Project ID is required'], 400);
        }

        // Retrieve the token from the request
        $token = $this->tokenRepository->findById($request->bearerToken());

        if (!$token) {
            return response()->json(['message' => 'Unauthenticated'], 401);
        }

        // Check if the token's project matches the requested project AND the user has access
        if ($token->project_id != $projectId || !$token->userHasAccess()) {
            return response()->json(['message' => 'You do not have access to this project'], 403);
        }

        // Attach the project instance to the request for easy use in controllers
        $request->merge(['project' => $token->project]);

        return $next($request);
    }
}

Register the middleware in app/Http/Kernel.php under $routeMiddleware:

protected $routeMiddleware = [
    // ... other middleware
    'project.access' => \App\Http\Middleware\ValidateProjectAccess::class,
];
Step 5: Apply the Middleware to Protected Routes

Finally, wrap your project-specific API routes with both auth:api and project.access middleware:

use Illuminate\Support\Facades\Route;

Route::middleware(['auth:api', 'project.access'])->group(function () {
    // Example routes
    Route::get('/projects/{project}/tasks', [TaskController::class, 'index']);
    Route::post('/projects/{project}/tasks', [TaskController::class, 'store']);
    Route::put('/projects/{project}', [ProjectController::class, 'update']);
});
Extra Notes
  • If your project has multiple roles (like members, editors, admins), replace the userHasAccess method with a check against a project_user pivot table that tracks roles.
  • Add scopes to tokens (e.g., ['project:read', 'project:write']) and extend the middleware to validate scopes for specific actions if you need finer-grained control.

内容的提问来源于stack exchange,提问作者Kalyanakannan padivasu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:45:04