> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# Laravel Passport（OAuth2 服务器实现）

> 介绍如何使用 Laravel Passport 实现 OAuth2 服务器。涵盖与 Sanctum 的选型、安装、客户端管理、作用域及令牌运维等内容。

## 什么是 Passport

Laravel Passport 是让 Laravel 应用作为 OAuth2 授权服务器运行的官方包。
用于第三方应用集成，或需要严格遵循 OAuth2 流程的 API。

```mermaid theme={null}
sequenceDiagram
    participant User as 用户
    participant Client as OAuth 客户端
    participant App as Laravel 应用<br>(Passport)
    participant API as 受保护的 API

    User->>Client: 发起授权
    Client->>App: 授权请求
    App->>User: 显示同意页面
    User->>App: 允许
    App-->>Client: 授权码
    Client->>App: 用授权码换取访问令牌
    App-->>Client: 访问令牌
    Client->>API: 携带 Bearer 令牌调用 API
    API-->>Client: 响应
```

## Passport 与 Sanctum 的对比

如果必须支持 OAuth2，请选择 Passport。
如果只是单纯的 API 令牌认证，或用于 SPA / 移动端认证，请选择 Sanctum。

| 维度   | Passport             | Sanctum          |
| ---- | -------------------- | ---------------- |
| 目标   | 实现 OAuth2 服务器        | 简单的 API 认证       |
| 适用场景 | 第三方应用集成、遵循 OAuth2 标准 | 自家 SPA、移动端、个人用令牌 |
| 复杂度  | 高                    | 低                |

## 安装

Laravel 13 官方推荐使用 `install:api --passport`。

```shell theme={null}
php artisan install:api --passport
```

如果要在已有项目中手动引入，也可以通过下面的命令进行配置。

```shell theme={null}
composer require laravel/passport
php artisan passport:install
```

首次部署时，可能只想生成密钥。

```shell theme={null}
php artisan passport:keys
```

## 配置

### User 模型

在 `User` 模型上添加 `HasApiTokens` trait 和 `OAuthenticatable` 接口。

```php theme={null}
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Passport\Contracts\OAuthenticatable;
use Laravel\Passport\HasApiTokens;

class User extends Authenticatable implements OAuthenticatable
{
    use HasApiTokens, HasFactory, Notifiable;
}
```

### auth 守卫

在 `config/auth.php` 中，让 `api` 守卫使用 `passport` 驱动。

```php theme={null}
'guards' => [
    'api' => [
        'driver' => 'passport',
        'provider' => 'users',
    ],
],
```

### 服务提供者配置

在 `AppServiceProvider` 的 `boot()` 中可以定义作用域并设置令牌有效期。

```php theme={null}
use Carbon\CarbonInterval;
use Laravel\Passport\Passport;

public function boot(): void
{
    Passport::tokensCan([
        'orders:read' => '查看订单',
        'orders:create' => '创建订单',
    ]);

    Passport::defaultScopes(['orders:read']);

    Passport::tokensExpireIn(CarbonInterval::days(15));
    Passport::refreshTokensExpireIn(CarbonInterval::days(30));
    Passport::personalAccessTokensExpireIn(CarbonInterval::months(6));
}
```

## 客户端管理

### 授权码授权（Authorization Code）客户端

```shell theme={null}
php artisan passport:client
```

这种客户端用于伴有用户同意页面的 OAuth2 标准流程。

### 客户端凭证授权（Client Credentials）客户端

```shell theme={null}
php artisan passport:client --client
```

对于机器间通信的接口，请使用 `EnsureClientIsResourceOwner` 中间件。

```php theme={null}
use Laravel\Passport\Http\Middleware\EnsureClientIsResourceOwner;

Route::get('/orders', function () {
    // ...
})->middleware(EnsureClientIsResourceOwner::using('orders:read'));
```

## 令牌管理

### 附加作用域

```php theme={null}
$accessToken = $user->createToken(
    'dashboard-token',
    ['orders:read', 'orders:create']
)->accessToken;
```

### 校验作用域

```php theme={null}
use Laravel\Passport\Http\Middleware\CheckToken;

Route::get('/orders', function () {
    // ...
})->middleware(['auth:api', CheckToken::using('orders:read')]);
```

### 吊销

```php theme={null}
use Laravel\Passport\Passport;

$token = Passport::token()->find($tokenId);
$token?->revoke();
```

## 保护 API 路由

为使用用户访问令牌进行保护的 API 添加 `auth:api`。

```php theme={null}
Route::middleware('auth:api')->group(function () {
    Route::get('/user', fn (Request $request) => $request->user());
    Route::get('/orders', [OrderController::class, 'index']);
});
```

<Warning>
  对于使用客户端凭证授权的路由，请使用 `EnsureClientIsResourceOwner` 而不是 `auth:api`。
</Warning>

## Personal Access Token

适合不使用完整 OAuth2 流程，让用户自己签发 API 令牌的场景。

```shell theme={null}
php artisan passport:client --personal
```

```php theme={null}
$token = $request->user()->createToken('cli-token', ['orders:read'])->accessToken;
```

<Info>
  如果 Personal Access Token 是主要用途，Laravel 官方也建议考虑使用 Sanctum。
</Info>

## 相关链接

* [Laravel 官方文档：Passport](https://laravel.com/docs/13.x/passport)
* [Laravel 官方文档：Sanctum](https://laravel.com/docs/13.x/sanctum)


## Related topics

- [Laravel Sanctum（API 令牌认证）](/zh/sanctum.md)
- [Socialite for Discord](/zh/packages/socialite-discord.md)
- [用 Laravel 构建 MCP 服务器](/zh/advanced/mcp-server.md)
- [Laravel Passkeys 初步调查(passkeys-server + @laravel/passkeys)](/zh/blog/passkeys-introduction.md)
- [Socialite（LINE Login）- LINE SDK for Laravel](/zh/packages/laravel-line-sdk/socialite.md)
