Passport란
Laravel Passport는 Laravel 애플리케이션을 OAuth2 인가 서버로 동작시키기 위한 공식 패키지입니다.
서드파티 앱 연동이나 엄격한 OAuth2 플로우가 필요한 API에서 사용합니다.
Passport vs Sanctum
OAuth2가 필수라면 Passport를 선택합니다.
단순한 API 토큰 인증이나 SPA / 모바일 인증이 목적이라면 Sanctum을 선택합니다.
| 관점 | Passport | Sanctum |
|---|
| 목적 | OAuth2 서버 구현 | 단순한 API 인증 |
| 적합한 사례 | 외부 앱 연동, OAuth2 표준 준수 | 자사 SPA, 모바일, 개인용 토큰 |
| 복잡도 | 높음 | 낮음 |
Laravel 13의 공식 권장은 install:api --passport입니다.
php artisan install:api --passport
기존 프로젝트에서 수동 도입하는 경우, 다음 명령으로도 설정할 수 있습니다.
composer require laravel/passport
php artisan passport:install
첫 배포 시에는 키 생성만 실행하고 싶은 경우도 있습니다.
php artisan passport:keys
User 모델
User 모델에 HasApiTokens 트레이트와 OAuthenticatable 인터페이스를 추가합니다.
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 드라이버를 사용합니다.
'guards' => [
'api' => [
'driver' => 'passport',
'provider' => 'users',
],
],
서비스 프로바이더 설정
AppServiceProvider의 boot()에서 스코프 정의와 토큰 유효 기간을 설정할 수 있습니다.
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));
}
클라이언트 관리
인가 코드 그랜트용 클라이언트
php artisan passport:client
이 클라이언트는 사용자 동의 화면을 동반하는 OAuth2 표준 플로우에서 사용합니다.
클라이언트 크리덴셜 그랜트용 클라이언트
php artisan passport:client --client
머신 간 통신 엔드포인트에서는 EnsureClientIsResourceOwner 미들웨어를 사용합니다.
use Laravel\Passport\Http\Middleware\EnsureClientIsResourceOwner;
Route::get('/orders', function () {
// ...
})->middleware(EnsureClientIsResourceOwner::using('orders:read'));
토큰 관리
스코프 부여
$accessToken = $user->createToken(
'dashboard-token',
['orders:read', 'orders:create']
)->accessToken;
스코프 체크
use Laravel\Passport\Http\Middleware\CheckToken;
Route::get('/orders', function () {
// ...
})->middleware(['auth:api', CheckToken::using('orders:read')]);
use Laravel\Passport\Passport;
$token = Passport::token()->find($tokenId);
$token?->revoke();
API 라우트 보호
사용자 액세스 토큰으로 보호하는 API에는 auth:api를 붙입니다.
Route::middleware('auth:api')->group(function () {
Route::get('/user', fn (Request $request) => $request->user());
Route::get('/orders', [OrderController::class, 'index']);
});
클라이언트 크리덴셜 그랜트 라우트는 auth:api가 아닌 EnsureClientIsResourceOwner를 사용해 주세요.
Personal Access Token
OAuth2의 완전 플로우를 사용하지 않고, 사용자 자신이 API 토큰을 발행하는 용도에 적합합니다.
php artisan passport:client --personal
$token = $request->user()->createToken('cli-token', ['orders:read'])->accessToken;
Personal Access Token이 주요 용도라면, Laravel 공식에서도 Sanctum을 검토할 것을 권장하고 있습니다.
관련 링크