Laravel Passport
- 소개
- 설치
- 구성
- 액세스 토큰 발급
- PKCE를 사용한 권한 부여 코드 부여
- 비밀번호 부여 토큰
- 암시적 부여 토큰
- 클라이언트 자격 증명 부여 토큰
- 개인 액세스 토큰
- 라우트 보호
- 토큰 스코프
- JavaScript로 API 사용
- 이벤트
- 테스트
소개
Laravel Passport는 몇 분 안에 Laravel 애플리케이션을 위한 완전한 OAuth2 서버 구현을 제공합니다. Passport는 Andy Millington과 Simon Hamp가 관리하는 League OAuth2 server를 기반으로 구축되었습니다.
이 문서는 이미 OAuth2에 익숙하다고 가정합니다. OAuth2에 대해 아무것도 모르는 경우, 계속하기 전에 OAuth2의 일반적인 용어 및 기능에 익숙해지는 것을 고려하십시오.
Passport 또는 Sanctum?
시작하기 전에 Laravel Passport 또는 Laravel Sanctum 중 어느 것이 애플리케이션에 더 적합한지 결정하는 것이 좋습니다. 애플리케이션이 OAuth2를 반드시 지원해야 하는 경우 Laravel Passport를 사용해야 합니다.
그러나 싱글 페이지 애플리케이션, 모바일 애플리케이션을 인증하거나 API 토큰을 발행하려는 경우 Laravel Sanctum을 사용해야 합니다. Laravel Sanctum은 OAuth2를 지원하지 않지만 훨씬 간단한 API 인증 개발 경험을 제공합니다.
설치
install:api Artisan 명령어를 통해 Laravel Passport를 설치할 수 있습니다.
php artisan install:api --passport
이 명령어는 OAuth2 클라이언트와 액세스 토큰을 저장하는 데 필요한 테이블을 생성하기 위한 데이터베이스 마이그레이션을 게시하고 실행합니다. 또한 이 명령어는 보안 액세스 토큰을 생성하는 데 필요한 암호화 키를 생성합니다.
추가적으로, 이 명령어는 Passport Client 모델의 기본 키 값으로 자동 증가 정수 대신 UUID를 사용할지 여부를 묻습니다.
install:api 명령어를 실행한 후에는 Laravel\Passport\HasApiTokens 트레이트를 App\Models\User 모델에 추가하세요. 이 트레이트는 인증된 사용자의 토큰과 스코프를 검사할 수 있는 몇 가지 헬퍼 메서드를 모델에 제공합니다.
<?phpnamespace App\Models;use Illuminate\Database\Eloquent\Factories\HasFactory;use Illuminate\Foundation\Auth\User as Authenticatable;use Illuminate\Notifications\Notifiable;use Laravel\Passport\HasApiTokens;class User extends Authenticatable{ use HasApiTokens, HasFactory, Notifiable;}
마지막으로, 애플리케이션의 config/auth.php 설정 파일에서 api 인증 가드를 정의하고 driver 옵션을 passport로 설정해야 합니다. 이렇게 하면 들어오는 API 요청을 인증할 때 Passport의 TokenGuard를 사용하도록 애플리케이션에 지시합니다.
'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'users', ], 'api' => [ 'driver' => 'passport', 'provider' => 'users', ],],
Passport 배포
Passport를 애플리케이션 서버에 처음 배포할 때는 passport:keys 명령어를 실행해야 할 가능성이 높습니다. 이 명령어는 액세스 토큰을 생성하기 위해 Passport가 필요로 하는 암호화 키를 생성합니다. 생성된 키는 일반적으로 소스 제어에 보관되지 않습니다.
php artisan passport:keys
필요한 경우, Passport의 키가 로드되어야 하는 경로를 정의할 수 있습니다. 이를 위해 Passport::loadKeysFrom 메서드를 사용할 수 있습니다. 일반적으로 이 메서드는 애플리케이션의 App\Providers\AppServiceProvider 클래스의 boot 메서드에서 호출해야 합니다.
/** * Bootstrap any application services. */public function boot(): void{ Passport::loadKeysFrom(__DIR__.'/../secrets/oauth');}
환경 변수에서 키 로드하기
또는, vendor:publish Artisan 명령어를 사용하여 Passport의 구성 파일을 게시할 수 있습니다:
php artisan vendor:publish --tag=passport-config
구성 파일이 게시된 후, 환경 변수로 정의하여 애플리케이션의 암호화 키를 로드할 수 있습니다:
PASSPORT_PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----<private key here>-----END RSA PRIVATE KEY-----"PASSPORT_PUBLIC_KEY="-----BEGIN PUBLIC KEY-----<public key here>-----END PUBLIC KEY-----"
Passport 업그레이드
Passport의 새 주요 버전으로 업그레이드할 때는 업그레이드 가이드를 주의 깊게 검토하는 것이 중요합니다.
구성
클라이언트 시크릿 해싱
클라이언트의 시크릿을 데이터베이스에 저장할 때 해시 처리하고 싶다면 App\Providers\AppServiceProvider 클래스의 boot 메서드에서 Passport::hashClientSecrets 메서드를 호출해야 합니다.
use Laravel\Passport\Passport;Passport::hashClientSecrets();
활성화되면 모든 클라이언트 시크릿은 생성 직후에만 사용자에게 표시될 수 있습니다. 일반 텍스트 클라이언트 시크릿 값은 데이터베이스에 저장되지 않으므로, 시크릿 값을 잃어버린 경우 복구할 수 없습니다.
토큰 수명
기본적으로 Passport는 1년 후에 만료되는 장기 액세스 토큰을 발급합니다. 더 길거나 짧은 토큰 수명을 구성하려면 tokensExpireIn, refreshTokensExpireIn 및 personalAccessTokensExpireIn 메서드를 사용할 수 있습니다. 이러한 메서드는 애플리케이션의 App\Providers\AppServiceProvider 클래스의 boot 메서드에서 호출해야 합니다.
/** * 애플리케이션 서비스 부트스트랩. */public function boot(): void{ Passport::tokensExpireIn(now()->addDays(15)); Passport::refreshTokensExpireIn(now()->addDays(30)); Passport::personalAccessTokensExpireIn(now()->addMonths(6));}
Passport의 데이터베이스 테이블에 있는 expires_at 열은 읽기 전용이며 표시 목적으로만 사용됩니다. 토큰을 발급할 때 Passport는 서명 및 암호화된 토큰 내에 만료 정보를 저장합니다. 토큰을 무효화해야 하는 경우 토큰을 취소해야 합니다.
기본 모델 재정의
자체 모델을 정의하고 해당 Passport 모델을 확장하여 Passport에서 내부적으로 사용하는 모델을 자유롭게 확장할 수 있습니다.
use Laravel\Passport\Client as PassportClient;class Client extends PassportClient{ // ...}
모델을 정의한 후에는 Laravel\Passport\Passport 클래스를 통해 사용자 지정 모델을 사용하도록 Passport에 지시할 수 있습니다. 일반적으로 애플리케이션의 App\Providers\AppServiceProvider 클래스의 boot 메서드에서 사용자 지정 모델에 대해 Passport에 알려야 합니다.
use App\Models\Passport\AuthCode;use App\Models\Passport\Client;use App\Models\Passport\PersonalAccessClient;use App\Models\Passport\RefreshToken;use App\Models\Passport\Token;/** * 애플리케이션 서비스 부트스트랩. */public function boot(): void{ Passport::useTokenModel(Token::class); Passport::useRefreshTokenModel(RefreshToken::class); Passport::useAuthCodeModel(AuthCode::class); Passport::useClientModel(Client::class); Passport::usePersonalAccessClientModel(PersonalAccessClient::class);}
라우트 재정의
경우에 따라 Passport에서 정의한 라우트를 사용자 지정하고 싶을 수 있습니다. 이를 위해서는 먼저 애플리케이션의 AppServiceProvider의 register 메서드에 Passport::ignoreRoutes를 추가하여 Passport에서 등록한 라우트를 무시해야 합니다.
use Laravel\Passport\Passport;/** * 모든 애플리케이션 서비스를 등록. */public function register(): void{ Passport::ignoreRoutes();}
그런 다음 라우트 파일에 정의된 Passport의 라우트를 애플리케이션의 routes/web.php 파일로 복사하여 원하는 대로 수정할 수 있습니다.
Route::group([ 'as' => 'passport.', 'prefix' => config('passport.path', 'oauth'), 'namespace' => '\Laravel\Passport\Http\Controllers',], function () { // Passport 라우트...});
액세스 토큰 발급
OAuth2를 권한 부여 코드를 통해 사용하는 것은 대부분의 개발자에게 OAuth2에서 익숙한 방법입니다. 권한 부여 코드를 사용할 때 클라이언트 애플리케이션은 사용자를 서버로 리디렉션하며, 여기에서 사용자는 클라이언트에 액세스 토큰을 발급하기 위한 요청을 승인하거나 거부합니다.
클라이언트 관리
먼저, 애플리케이션의 API와 상호 작용해야 하는 애플리케이션을 빌드하는 개발자는 "클라이언트"를 만들어 애플리케이션을 등록해야 합니다. 일반적으로 이는 애플리케이션의 이름과 사용자가 권한 부여 요청을 승인한 후 애플리케이션이 리디렉션할 수 있는 URL을 제공하는 것으로 구성됩니다.
passport:client 명령어
클라이언트를 만드는 가장 간단한 방법은 passport:client Artisan 명령어를 사용하는 것입니다. 이 명령어는 OAuth2 기능을 테스트하기 위해 자신만의 클라이언트를 만드는 데 사용할 수 있습니다. client 명령어를 실행하면 Passport에서 클라이언트에 대한 추가 정보를 묻고 클라이언트 ID와 시크릿을 제공합니다.
php artisan passport:client
리디렉션 URL
클라이언트에 여러 개의 리디렉션 URL을 허용하려면, passport:client 명령에서 URL을 묻는 메시지가 나타날 때 쉼표로 구분된 목록을 사용하여 지정할 수 있습니다. 쉼표를 포함하는 모든 URL은 URL 인코딩해야 합니다.
http://example.com/callback,http://examplefoo.com/callback
JSON API
애플리케이션 사용자는 client 명령을 사용할 수 없으므로, Passport는 클라이언트를 생성하는 데 사용할 수 있는 JSON API를 제공합니다. 이렇게 하면 클라이언트 생성, 업데이트 및 삭제를 위한 컨트롤러를 수동으로 코딩해야 하는 번거로움을 덜 수 있습니다.
그러나 사용자가 클라이언트를 관리할 수 있도록 대시보드를 제공하려면 Passport의 JSON API를 자체 프런트엔드와 페어링해야 합니다. 아래에서 클라이언트 관리를 위한 모든 API 엔드포인트를 검토합니다. 편의를 위해 Axios를 사용하여 엔드포인트에 대한 HTTP 요청을 만드는 방법을 보여드리겠습니다.
JSON API는 web 및 auth 미들웨어로 보호되므로 자체 애플리케이션에서만 호출할 수 있습니다. 외부 소스에서 호출할 수 없습니다.
GET /oauth/clients
이 경로는 인증된 사용자의 모든 클라이언트를 반환합니다. 이는 주로 사용자가 클라이언트를 편집하거나 삭제할 수 있도록 모든 클라이언트를 나열하는 데 유용합니다.
axios.get('/oauth/clients') .then(response => { console.log(response.data); });
POST /oauth/clients
이 경로는 새로운 클라이언트를 생성하는 데 사용됩니다. 클라이언트의 name과 redirect URL 두 가지 데이터가 필요합니다. redirect URL은 사용자가 권한 요청을 승인하거나 거부한 후 리디렉션될 URL입니다.
클라이언트가 생성되면 클라이언트 ID와 클라이언트 비밀이 발급됩니다. 이러한 값은 애플리케이션에서 액세스 토큰을 요청할 때 사용됩니다. 클라이언트 생성 경로는 새로운 클라이언트 인스턴스를 반환합니다.
const data = { name: 'Client Name', redirect: 'http://example.com/callback'};axios.post('/oauth/clients', data) .then(response => { console.log(response.data); }) .catch (response => { // List errors on response... });
PUT /oauth/clients/{client-id}
이 경로는 클라이언트를 업데이트하는 데 사용됩니다. 클라이언트의 name과 redirect URL 두 가지 데이터가 필요합니다. redirect URL은 사용자가 권한 요청을 승인하거나 거부한 후 리디렉션될 URL입니다. 이 경로는 업데이트된 클라이언트 인스턴스를 반환합니다.
const data = { name: 'New Client Name', redirect: 'http://example.com/callback'};axios.put('/oauth/clients/' + clientId, data) .then(response => { console.log(response.data); }) .catch (response => { // List errors on response... });
DELETE /oauth/clients/{client-id}
이 경로는 클라이언트를 삭제하는 데 사용됩니다.
axios.delete('/oauth/clients/' + clientId) .then(response => { // ... });
토큰 요청하기
권한 부여를 위한 리디렉션
클라이언트가 생성되면 개발자는 클라이언트 ID와 비밀키를 사용하여 애플리케이션에서 권한 부여 코드 및 액세스 토큰을 요청할 수 있습니다. 먼저, 소비 애플리케이션은 다음과 같이 애플리케이션의 /oauth/authorize 경로로 리디렉션 요청을 해야 합니다.
use Illuminate\Http\Request;use Illuminate\Support\Str;Route::get('/redirect', function (Request $request) { $request->session()->put('state', $state = Str::random(40)); $query = http_build_query([ 'client_id' => 'client-id', 'redirect_uri' => 'http://third-party-app.com/callback', 'response_type' => 'code', 'scope' => '', 'state' => $state, // 'prompt' => '', // "none", "consent", 또는 "login" ]); return redirect('http://passport-app.test/oauth/authorize?'.$query);});
prompt 매개변수를 사용하여 Passport 애플리케이션의 인증 동작을 지정할 수 있습니다.
prompt 값이 none이면 사용자가 Passport 애플리케이션에 이미 인증되지 않은 경우 Passport는 항상 인증 오류를 발생시킵니다. 값이 consent이면 소비 애플리케이션에 이전에 모든 스코프가 부여되었더라도 Passport는 항상 권한 부여 승인 화면을 표시합니다. 값이 login이면 사용자가 이미 세션을 가지고 있더라도 Passport 애플리케이션은 항상 사용자에게 애플리케이션에 다시 로그인하라는 메시지를 표시합니다.
prompt 값이 제공되지 않으면 사용자는 요청된 스코프에 대해 소비 애플리케이션에 대한 액세스 권한을 이전에 부여하지 않은 경우에만 권한 부여를 요청받게 됩니다.
/oauth/authorize 경로는 Passport에 의해 이미 정의되어 있음을 기억하십시오. 이 경로를 수동으로 정의할 필요가 없습니다.
요청 승인하기
권한 부여 요청을 수신할 때 Passport는 prompt 매개변수(있는 경우) 값에 따라 자동으로 응답하며 사용자에게 권한 부여 요청을 승인하거나 거부할 수 있는 템플릿을 표시할 수 있습니다. 요청을 승인하면 소비 애플리케이션에서 지정한 redirect_uri로 다시 리디렉션됩니다. redirect_uri는 클라이언트가 생성될 때 지정된 redirect URL과 일치해야 합니다.
권한 부여 승인 화면을 사용자 지정하려면 vendor:publish Artisan 명령을 사용하여 Passport의 뷰를 게시할 수 있습니다. 게시된 뷰는 resources/views/vendor/passport 디렉터리에 배치됩니다.
php artisan vendor:publish --tag=passport-views
php artisan vendor:publish --tag=passport-views
은(는) Passport 뷰를 게시하는 명령어입니다.
때로는 퍼스트 파티 클라이언트를 인증할 때와 같이 인증 프롬프트를 건너뛰고 싶을 수 있습니다. Client 모델을 확장하고 skipsAuthorization 메서드를 정의하여 이를 수행할 수 있습니다. skipsAuthorization이 true를 반환하면 클라이언트가 승인되고 사용자가 즉시 redirect_uri로 다시 리디렉션됩니다. 단, 소비 애플리케이션이 인증을 위해 리디렉션할 때 prompt 매개변수를 명시적으로 설정한 경우는 예외입니다.
<?phpnamespace App\Models\Passport;use Laravel\Passport\Client as BaseClient;class Client extends BaseClient{ /** * 클라이언트가 인증 프롬프트를 건너뛸지 여부를 결정합니다. */ public function skipsAuthorization(): bool { return $this->firstParty(); }}
권한 부여 코드를 액세스 토큰으로 변환
사용자가 권한 부여 요청을 승인하면 소비 애플리케이션으로 다시 리디렉션됩니다. 소비자는 먼저 리디렉션 전에 저장된 값과 비교하여 state 매개변수를 확인해야 합니다. 상태 매개변수가 일치하면 소비자는 액세스 토큰을 요청하기 위해 애플리케이션에 POST 요청을 발행해야 합니다. 이 요청에는 사용자가 권한 부여 요청을 승인할 때 애플리케이션에서 발행한 권한 부여 코드가 포함되어야 합니다.
use Illuminate\Http\Request;use Illuminate\Support\Facades\Http;Route::get('/callback', function (Request $request) { $state = $request->session()->pull('state'); throw_unless( strlen($state) > 0 && $state === $request->state, InvalidArgumentException::class, 'Invalid state value.' ); $response = Http::asForm()->post('http://passport-app.test/oauth/token', [ 'grant_type' => 'authorization_code', 'client_id' => 'client-id', 'client_secret' => 'client-secret', 'redirect_uri' => 'http://third-party-app.com/callback', 'code' => $request->code, ]); return $response->json();});
이 /oauth/token 경로는 access_token, refresh_token 및 expires_in 속성이 포함된 JSON 응답을 반환합니다. expires_in 속성에는 액세스 토큰이 만료될 때까지의 시간(초)이 포함됩니다.
/oauth/authorize 경로와 마찬가지로 /oauth/token 경로는 Passport에서 정의합니다. 이 경로를 수동으로 정의할 필요가 없습니다.
JSON API
Passport에는 권한이 부여된 액세스 토큰을 관리하기 위한 JSON API도 포함되어 있습니다. 이를 사용자 고유의 프런트엔드와 결합하여 사용자가 액세스 토큰을 관리할 수 있는 대시보드를 제공할 수 있습니다. 편의를 위해 Axios를 사용하여 엔드포인트에 대한 HTTP 요청을 만드는 방법을 보여드리겠습니다. JSON API는 web 및 auth 미들웨어로 보호되므로 자체 애플리케이션에서만 호출할 수 있습니다.
GET /oauth/tokens
이 경로는 인증된 사용자가 생성한 모든 권한이 부여된 액세스 토큰을 반환합니다. 이는 주로 사용자의 모든 토큰을 나열하여 취소할 수 있도록 하는 데 유용합니다.
axios.get('/oauth/tokens') .then(response => { console.log(response.data); });
DELETE /oauth/tokens/{token-id}
이 경로는 권한이 부여된 액세스 토큰과 관련된 갱신 토큰을 취소하는 데 사용할 수 있습니다.
axios.delete('/oauth/tokens/' + tokenId);
토큰 갱신
애플리케이션에서 수명이 짧은 액세스 토큰을 발급하는 경우, 사용자는 액세스 토큰이 발급될 때 제공된 갱신 토큰을 통해 액세스 토큰을 갱신해야 합니다.
use Illuminate\Support\Facades\Http;$response = Http::asForm()->post('http://passport-app.test/oauth/token', [ 'grant_type' => 'refresh_token', 'refresh_token' => 'the-refresh-token', 'client_id' => 'client-id', 'client_secret' => 'client-secret', 'scope' => '',]);return $response->json();
이 /oauth/token 경로는 access_token, refresh_token 및 expires_in 속성을 포함하는 JSON 응답을 반환합니다. expires_in 속성은 액세스 토큰이 만료될 때까지 남은 시간(초)을 나타냅니다.
토큰 폐기
Laravel\Passport\TokenRepository의 revokeAccessToken 메서드를 사용하여 토큰을 폐기할 수 있습니다. Laravel\Passport\RefreshTokenRepository의 revokeRefreshTokensByAccessTokenId 메서드를 사용하여 토큰의 갱신 토큰을 폐기할 수 있습니다. 이러한 클래스는 Laravel의 서비스 컨테이너를 사용하여 해결할 수 있습니다.
use Laravel\Passport\TokenRepository;use Laravel\Passport\RefreshTokenRepository;$tokenRepository = app(TokenRepository::class);$refreshTokenRepository = app(RefreshTokenRepository::class);// 액세스 토큰 폐기...$tokenRepository->revokeAccessToken($tokenId);// 토큰의 모든 갱신 토큰 폐기...$refreshTokenRepository->revokeRefreshTokensByAccessTokenId($tokenId);
토큰 제거
토큰이 폐기되거나 만료된 경우 데이터베이스에서 해당 토큰을 제거할 수 있습니다. Passport에 포함된 passport:purge Artisan 명령어를 사용하여 이 작업을 수행할 수 있습니다.
# 폐기된 토큰 및 만료된 토큰과 인증 코드를 제거합니다...php artisan passport:purge# 6시간 이상 만료된 토큰만 제거합니다...php artisan passport:purge --hours=6# 폐기된 토큰과 인증 코드만 제거합니다...php artisan passport:purge --revoked# 만료된 토큰과 인증 코드만 제거합니다...php artisan passport:purge --expired
애플리케이션의 routes/console.php 파일에서 예약된 작업을 구성하여 토큰을 정기적으로 자동 정리할 수도 있습니다.
use Illuminate\Support\Facades\Schedule;Schedule::command('passport:purge')->hourly();
PKCE를 사용한 Authorization Code Grant
"Proof Key for Code Exchange"(PKCE)를 사용한 Authorization Code grant는 싱글 페이지 애플리케이션이나 네이티브 애플리케이션이 API에 액세스하기 위해 인증하는 안전한 방법입니다. 이 grant는 클라이언트 시크릿이 기밀로 저장될 것을 보장할 수 없거나 공격자가 권한 부여 코드를 가로채는 위협을 완화하기 위해 사용해야 합니다. "code verifier"와 "code challenge"의 조합은 액세스 토큰을 위해 권한 부여 코드를 교환할 때 클라이언트 시크릿을 대체합니다.
클라이언트 생성
애플리케이션이 PKCE를 사용한 권한 부여 코드 grant를 통해 토큰을 발급하기 전에 PKCE를 활성화한 클라이언트를 만들어야 합니다. --public 옵션과 함께 passport:client Artisan 명령을 사용하여 이 작업을 수행할 수 있습니다.
php artisan passport:client --public
토큰 요청
코드 검증자 및 코드 챌린지
이 권한 부여 방식은 클라이언트 비밀을 제공하지 않으므로, 개발자는 토큰을 요청하기 위해 코드 검증자와 코드 챌린지 조합을 생성해야 합니다.
코드 검증자는 RFC 7636 사양에 정의된 대로 문자, 숫자 및 "-", ".", "_", "~" 문자를 포함하는 43자에서 128자 사이의 임의의 문자열이어야 합니다.
코드 챌린지는 URL 및 파일 이름에 안전한 문자로 Base64 인코딩된 문자열이어야 합니다. 후행 '=' 문자는 제거해야 하며, 줄 바꿈, 공백 또는 다른 추가 문자는 없어야 합니다.
$encoded = base64_encode(hash('sha256', $code_verifier, true));$codeChallenge = strtr(rtrim($encoded, '='), '+/', '-_');
권한 부여를 위한 리디렉션
클라이언트가 생성되면 클라이언트 ID와 생성된 코드 검증자 및 코드 챌린지를 사용하여 애플리케이션에서 권한 부여 코드와 액세스 토큰을 요청할 수 있습니다. 먼저, 소비 애플리케이션은 애플리케이션의 /oauth/authorize 경로로 리디렉션 요청을 보내야 합니다.
use Illuminate\Http\Request;use Illuminate\Support\Str;Route::get('/redirect', function (Request $request) { $request->session()->put('state', $state = Str::random(40)); $request->session()->put( 'code_verifier', $code_verifier = Str::random(128) ); $codeChallenge = strtr(rtrim( base64_encode(hash('sha256', $code_verifier, true)) , '='), '+/', '-_'); $query = http_build_query([ 'client_id' => 'client-id', 'redirect_uri' => 'http://third-party-app.com/callback', 'response_type' => 'code', 'scope' => '', 'state' => $state, 'code_challenge' => $codeChallenge, 'code_challenge_method' => 'S256', // 'prompt' => '', // "none", "consent", or "login" ]); return redirect('http://passport-app.test/oauth/authorize?'.$query);});
권한 부여 코드를 액세스 토큰으로 변환
사용자가 권한 부여 요청을 승인하면 소비 애플리케이션으로 다시 리디렉션됩니다. 소비자는 표준 권한 부여 코드 부여와 마찬가지로 리디렉션 전에 저장된 값에 대해 state 매개변수를 확인해야 합니다.
state 매개변수가 일치하면 소비자는 액세스 토큰을 요청하기 위해 애플리케이션에 POST 요청을 발행해야 합니다. 요청에는 사용자가 권한 부여 요청을 승인했을 때 애플리케이션에서 발행한 권한 부여 코드와 원래 생성된 코드 검증자가 포함되어야 합니다.
use Illuminate\Http\Request;use Illuminate\Support\Facades\Http;Route::get('/callback', function (Request $request) { $state = $request->session()->pull('state'); $codeVerifier = $request->session()->pull('code_verifier'); throw_unless( strlen($state) > 0 && $state === $request->state, InvalidArgumentException::class ); $response = Http::asForm()->post('http://passport-app.test/oauth/token', [ 'grant_type' => 'authorization_code', 'client_id' => 'client-id', 'redirect_uri' => 'http://third-party-app.com/callback', 'code_verifier' => $codeVerifier, 'code' => $request->code, ]); return $response->json();});
비밀번호 부여 토큰
더 이상 비밀번호 부여 토큰을 사용하는 것을 권장하지 않습니다. 대신 OAuth2 서버에서 현재 권장하는 부여 유형을 선택해야 합니다.
OAuth2 비밀번호 부여를 통해 모바일 애플리케이션과 같은 다른 자사 클라이언트는 이메일 주소/사용자 이름과 비밀번호를 사용하여 액세스 토큰을 얻을 수 있습니다. 이렇게 하면 사용자가 전체 OAuth2 권한 부여 코드 리디렉션 흐름을 거치지 않고도 자사 클라이언트에 액세스 토큰을 안전하게 발행할 수 있습니다.
비밀번호 부여를 활성화하려면 애플리케이션의 App\Providers\AppServiceProvider 클래스의 boot 메서드에서 enablePasswordGrant 메서드를 호출하세요.
/** * Bootstrap any application services. */public function boot(): void{ Passport::enablePasswordGrant();}
비밀번호 부여 클라이언트 생성
애플리케이션이 비밀번호 부여를 통해 토큰을 발행하기 전에 비밀번호 부여 클라이언트를 생성해야 합니다. --password 옵션과 함께 passport:client Artisan 명령을 사용하여 이 작업을 수행할 수 있습니다. passport:install 명령을 이미 실행한 경우 이 명령을 실행할 필요가 없습니다.
php artisan passport:client --password
토큰 요청하기
패스워드 권한 클라이언트를 생성했으면, 사용자의 이메일 주소와 패스워드를 사용하여 /oauth/token 경로로 POST 요청을 보내 액세스 토큰을 요청할 수 있습니다. 이 경로는 Passport에 의해 이미 등록되어 있으므로 수동으로 정의할 필요가 없습니다. 요청이 성공하면 서버에서 JSON 응답으로 access_token과 refresh_token을 받게 됩니다.
use Illuminate\Support\Facades\Http;$response = Http::asForm()->post('http://passport-app.test/oauth/token', [ 'grant_type' => 'password', 'client_id' => 'client-id', 'client_secret' => 'client-secret', 'username' => '[email protected]', 'password' => 'my-password', 'scope' => '',]);return $response->json();
기본적으로 액세스 토큰은 수명이 깁니다. 그러나 필요한 경우 최대 액세스 토큰 수명을 구성할 수 있습니다.
모든 스코프 요청하기
패스워드 권한 또는 클라이언트 자격 증명 권한을 사용할 때, 애플리케이션에서 지원하는 모든 스코프에 대해 토큰을 승인하고 싶을 수 있습니다. * 스코프를 요청하여 이를 수행할 수 있습니다. * 스코프를 요청하면 토큰 인스턴스의 can 메서드는 항상 true를 반환합니다. 이 스코프는 password 또는 client_credentials 권한을 사용하여 발급된 토큰에만 할당할 수 있습니다.
use Illuminate\Support\Facades\Http;$response = Http::asForm()->post('http://passport-app.test/oauth/token', [ 'grant_type' => 'password', 'client_id' => 'client-id', 'client_secret' => 'client-secret', 'username' => '[email protected]', 'password' => 'my-password', 'scope' => '*',]);
사용자 프로바이더 사용자 정의하기
애플리케이션에서 둘 이상의 인증 사용자 프로바이더를 사용하는 경우, artisan passport:client --password 명령을 통해 클라이언트를 생성할 때 --provider 옵션을 제공하여 패스워드 권한 클라이언트가 사용할 사용자 프로바이더를 지정할 수 있습니다. 주어진 프로바이더 이름은 애플리케이션의 config/auth.php 구성 파일에 정의된 유효한 프로바이더와 일치해야 합니다. 그런 다음 미들웨어를 사용하여 경로를 보호하여 해당 가드의 지정된 프로바이더의 사용자만 권한을 부여받도록 할 수 있습니다.
사용자 이름 필드 사용자 정의하기
패스워드 권한을 사용하여 인증할 때, Passport는 인증 가능한 모델의 email 속성을 "사용자 이름"으로 사용합니다. 그러나 모델에 findForPassport 메서드를 정의하여 이 동작을 사용자 정의할 수 있습니다.
<?phpnamespace App\Models;use Illuminate\Foundation\Auth\User as Authenticatable;use Illuminate\Notifications\Notifiable;use Laravel\Passport\HasApiTokens;class User extends Authenticatable{ use HasApiTokens, Notifiable; /** * 주어진 사용자 이름에 대한 사용자 인스턴스를 찾습니다. */ public function findForPassport(string $username): User { return $this->where('username', $username)->first(); }}
패스워드 유효성 검사 사용자 정의하기
패스워드 권한을 사용하여 인증할 때, Passport는 모델의 password 속성을 사용하여 주어진 패스워드를 검증합니다. 모델에 password 속성이 없거나 패스워드 유효성 검사 로직을 사용자 정의하려는 경우, 모델에 validateForPassportPasswordGrant 메서드를 정의할 수 있습니다.
<?phpnamespace App\Models;use Illuminate\Foundation\Auth\User as Authenticatable;use Illuminate\Notifications\Notifiable;use Illuminate\Support\Facades\Hash;use Laravel\Passport\HasApiTokens;class User extends Authenticatable{ use HasApiTokens, Notifiable; /** * Passport 패스워드 권한에 대한 사용자의 패스워드를 검증합니다. */ public function validateForPassportPasswordGrant(string $password): bool { return Hash::check($password, $this->password); }}
암시적 권한 토큰
더 이상 암시적 권한 토큰을 사용하는 것을 권장하지 않습니다. 대신, 현재 OAuth2 서버에서 권장하는 권한 유형을 선택해야 합니다.
암시적 권한은 권한 부여 코드 권한과 유사하지만, 토큰은 권한 부여 코드를 교환하지 않고 클라이언트에 반환됩니다. 이 권한은 클라이언트 자격 증명을 안전하게 저장할 수 없는 JavaScript 또는 모바일 애플리케이션에서 가장 일반적으로 사용됩니다. 권한을 활성화하려면 애플리케이션의 App\Providers\AppServiceProvider 클래스의 boot 메서드에서 enableImplicitGrant 메서드를 호출합니다.
/** * 애플리케이션 서비스를 부트스트랩합니다. */public function boot(): void{ Passport::enableImplicitGrant();}
권한이 활성화되면 개발자는 클라이언트 ID를 사용하여 애플리케이션에서 액세스 토큰을 요청할 수 있습니다. 사용하는 애플리케이션은 다음과 같이 애플리케이션의 /oauth/authorize 경로로 리디렉션 요청을 해야 합니다.
use Illuminate\Http\Request;Route::get('/redirect', function (Request $request) { $request->session()->put('state', $state = Str::random(40)); $query = http_build_query([ 'client_id' => 'client-id', 'redirect_uri' => 'http://third-party-app.com/callback', 'response_type' => 'token', 'scope' => '', 'state' => $state, // 'prompt' => '', // "none", "consent", 또는 "login" ]); return redirect('http://passport-app.test/oauth/authorize?'.$query);});
/oauth/authorize 경로는 Passport에 의해 이미 정의되어 있습니다. 이 경로를 수동으로 정의할 필요는 없습니다.
클라이언트 자격 증명 권한 토큰
클라이언트 자격 증명 권한은 머신 간 인증에 적합합니다. 예를 들어 API를 통해 유지 관리 작업을 수행하는 예약된 작업에서 이 권한을 사용할 수 있습니다.
애플리케이션이 클라이언트 자격 증명 권한을 통해 토큰을 발급하기 전에 클라이언트 자격 증명 권한 클라이언트를 생성해야 합니다. passport:client Artisan 명령의 --client 옵션을 사용하여 이를 수행할 수 있습니다.
php artisan passport:client --client
다음으로, 이 권한 부여 유형을 사용하려면 CheckClientCredentials 미들웨어에 대한 미들웨어 별칭을 등록하십시오. 애플리케이션의 bootstrap/app.php 파일에서 미들웨어 별칭을 정의할 수 있습니다:
use Laravel\Passport\Http\Middleware\CheckClientCredentials;->withMiddleware(function (Middleware $middleware) { $middleware->alias([ 'client' => CheckClientCredentials::class ]);})
그런 다음, 미들웨어를 라우트에 연결합니다:
Route::get('/orders', function (Request $request) { ...})->middleware('client');
특정 스코프로 라우트에 대한 액세스를 제한하려면 client 미들웨어를 라우트에 연결할 때 필요한 스코프를 쉼표로 구분된 목록으로 제공할 수 있습니다:
Route::get('/orders', function (Request $request) { ...})->middleware('client:check-status,your-scope');
토큰 검색
이 권한 부여 유형을 사용하여 토큰을 검색하려면 oauth/token 엔드포인트에 요청을 합니다:
use Illuminate\Support\Facades\Http;$response = Http::asForm()->post('http://passport-app.test/oauth/token', [ 'grant_type' => 'client_credentials', 'client_id' => 'client-id', 'client_secret' => 'client-secret', 'scope' => 'your-scope',]);return $response->json()['access_token'];
개인 접근 토큰
경우에 따라 사용자는 일반적인 권한 부여 코드 리디렉션 흐름을 거치지 않고도 스스로 접근 토큰을 발급하고 싶어할 수 있습니다. 사용자가 애플리케이션의 UI를 통해 자신에게 토큰을 발급하도록 허용하는 것은 사용자가 API를 실험하도록 허용하거나 일반적으로 접근 토큰을 발급하는 더 간단한 접근 방식으로 유용할 수 있습니다.
애플리케이션이 주로 Passport를 사용하여 개인 접근 토큰을 발급하는 경우, API 접근 토큰 발급을 위한 Laravel의 가벼운 첫 번째 파티 라이브러리인 Laravel Sanctum을 사용하는 것을 고려해 보십시오.
개인 접근 클라이언트 생성
애플리케이션이 개인 접근 토큰을 발급하기 전에 개인 접근 클라이언트를 생성해야 합니다. --personal 옵션을 사용하여 passport:client Artisan 명령을 실행하여 이를 수행할 수 있습니다. passport:install 명령을 이미 실행한 경우 이 명령을 실행할 필요가 없습니다.
php artisan passport:client --personal
개인 액세스 클라이언트를 생성한 후 클라이언트의 ID와 일반 텍스트 비밀 값을 애플리케이션의 .env 파일에 넣으세요:
PASSPORT_PERSONAL_ACCESS_CLIENT_ID="client-id-value"PASSPORT_PERSONAL_ACCESS_CLIENT_SECRET="unhashed-client-secret-value"
개인 액세스 토큰 관리
개인 액세스 클라이언트를 생성했다면 App\Models\User 모델 인스턴스에서 createToken 메서드를 사용하여 주어진 사용자에 대한 토큰을 발급할 수 있습니다. createToken 메서드는 토큰의 이름을 첫 번째 인수로, 선택적 범위 배열을 두 번째 인수로 받습니다:
use App\Models\User;$user = User::find(1);// 범위 없이 토큰 생성...$token = $user->createToken('Token Name')->accessToken;// 범위를 사용하여 토큰 생성...$token = $user->createToken('My Token', ['place-orders'])->accessToken;
JSON API
Passport는 개인 액세스 토큰을 관리하기 위한 JSON API도 포함합니다. 이 API를 자체 프론트엔드와 결합하여 사용자가 개인 액세스 토큰을 관리할 수 있는 대시보드를 제공할 수 있습니다. 아래에서는 개인 액세스 토큰을 관리하기 위한 모든 API 엔드포인트를 검토합니다. 편의를 위해 Axios를 사용하여 엔드포인트에 HTTP 요청을 보내는 방법을 보여드리겠습니다.
JSON API는 web 및 auth 미들웨어로 보호되므로 자체 애플리케이션에서만 호출할 수 있습니다. 외부 소스에서 호출할 수 없습니다.
GET /oauth/scopes
이 경로는 애플리케이션에 대해 정의된 모든 범위를 반환합니다. 이 경로를 사용하여 사용자가 개인 액세스 토큰에 할당할 수 있는 범위를 나열할 수 있습니다:
axios.get('/oauth/scopes') .then(response => { console.log(response.data); });
GET /oauth/personal-access-tokens
이 경로는 인증된 사용자가 생성한 모든 개인 액세스 토큰을 반환합니다. 이는 사용자가 토큰을 편집하거나 취소할 수 있도록 사용자의 모든 토큰을 나열하는 데 주로 유용합니다.
axios.get('/oauth/personal-access-tokens') .then(response => { console.log(response.data); });
POST /oauth/personal-access-tokens
이 경로는 새로운 개인 액세스 토큰을 생성합니다. 토큰의 name과 토큰에 할당해야 하는 scopes 두 가지 데이터가 필요합니다.
const data = { name: '토큰 이름', scopes: []};axios.post('/oauth/personal-access-tokens', data) .then(response => { console.log(response.data.accessToken); }) .catch (response => { // 응답에 대한 오류 목록 ... });
DELETE /oauth/personal-access-tokens/{token-id}
이 경로는 개인 액세스 토큰을 취소하는 데 사용할 수 있습니다.
axios.delete('/oauth/personal-access-tokens/' + tokenId);
경로 보호
미들웨어를 통해
Passport는 들어오는 요청에서 액세스 토큰의 유효성을 검사하는 인증 가드를 포함합니다. api 가드가 passport 드라이버를 사용하도록 구성한 후에는 유효한 액세스 토큰이 필요한 모든 경로에 auth:api 미들웨어를 지정하기만 하면 됩니다.
Route::get('/user', function () { // ...})->middleware('auth:api');
클라이언트 자격 증명 부여를 사용하는 경우, auth:api 미들웨어 대신 the client 미들웨어를 사용하여 경로를 보호해야 합니다.
다중 인증 가드
애플리케이션에서 완전히 다른 Eloquent 모델을 사용할 수 있는 여러 유형의 사용자를 인증하는 경우, 애플리케이션에서 각 사용자 제공자 유형에 대한 가드 구성을 정의해야 할 가능성이 높습니다. 이렇게 하면 특정 사용자 제공자를 위한 요청을 보호할 수 있습니다. 예를 들어, 다음 가드 구성이 config/auth.php 구성 파일에 주어졌을 때:
'api' => [ 'driver' => 'passport', 'provider' => 'users',],'api-customers' => [ 'driver' => 'passport', 'provider' => 'customers',],
다음 경로는 들어오는 요청을 인증하기 위해 customers 사용자 제공자를 사용하는 api-customers 가드를 활용합니다.
Route::get('/customer', function () { // ...})->middleware('auth:api-customers');
Passport와 함께 여러 사용자 제공자를 사용하는 방법에 대한 자세한 내용은 비밀번호 부여 문서를 참조하십시오.
액세스 토큰 전달하기
Passport로 보호되는 경로를 호출할 때 애플리케이션의 API 소비자는 요청의 Authorization 헤더에 액세스 토큰을 Bearer 토큰으로 지정해야 합니다. 예를 들어, Guzzle HTTP 라이브러리를 사용하는 경우:
use Illuminate\Support\Facades\Http;$response = Http::withHeaders([ 'Accept' => 'application/json', 'Authorization' => 'Bearer '.$accessToken,])->get('https://passport-app.test/api/user');return $response->json();
토큰 범위
범위를 통해 API 클라이언트는 계정에 액세스할 수 있는 권한을 요청할 때 특정 권한 집합을 요청할 수 있습니다. 예를 들어 전자 상거래 애플리케이션을 구축하는 경우 모든 API 소비자에게 주문을 할 수 있는 기능이 필요한 것은 아닙니다. 대신 소비자가 주문 배송 상태에 액세스할 수 있는 권한만 요청하도록 허용할 수 있습니다. 즉, 범위를 통해 애플리케이션 사용자는 제3자 애플리케이션이 자신을 대신하여 수행할 수 있는 작업을 제한할 수 있습니다.
범위 정의
애플리케이션의 App\Providers\AppServiceProvider 클래스의 boot 메서드에서 Passport::tokensCan 메서드를 사용하여 API 범위를 정의할 수 있습니다. tokensCan 메서드는 범위 이름과 범위 설명의 배열을 허용합니다. 범위 설명은 원하는 대로 무엇이든 될 수 있으며 권한 승인 화면에서 사용자에게 표시됩니다.
/** * Bootstrap any application services. */public function boot(): void{ Passport::tokensCan([ 'place-orders' => '주문하기', 'check-status' => '주문 상태 확인', ]);}
기본 범위
클라이언트가 특정 범위를 요청하지 않으면 setDefaultScope 메서드를 사용하여 토큰에 기본 범위를 연결하도록 Passport 서버를 구성할 수 있습니다. 일반적으로 애플리케이션의 App\Providers\AppServiceProvider 클래스의 boot 메서드에서 이 메서드를 호출해야 합니다.
use Laravel\Passport\Passport;Passport::tokensCan([ 'place-orders' => '주문하기', 'check-status' => '주문 상태 확인',]);Passport::setDefaultScope([ 'check-status', 'place-orders',]);
Passport의 기본 범위는 사용자가 생성한 개인 액세스 토큰에는 적용되지 않습니다.
토큰에 범위 할당하기
권한 부여 코드를 요청할 때
권한 부여 코드 부여를 사용하여 액세스 토큰을 요청할 때 소비자는 원하는 범위를 scope 쿼리 문자열 매개변수로 지정해야 합니다. scope 매개변수는 공백으로 구분된 범위 목록이어야 합니다.
Route::get('/redirect', function () { $query = http_build_query([ 'client_id' => 'client-id', 'redirect_uri' => 'http://example.com/callback', 'response_type' => 'code', 'scope' => 'place-orders check-status', ]); return redirect('http://passport-app.test/oauth/authorize?'.$query);});
개인 액세스 토큰을 발급할 때
App\Models\User 모델의 createToken 메서드를 사용하여 개인 액세스 토큰을 발급하는 경우 원하는 범위의 배열을 메서드의 두 번째 인수로 전달할 수 있습니다.
$token = $user->createToken('My Token', ['place-orders'])->accessToken;
범위 확인
Passport에는 주어진 범위를 부여받은 토큰으로 들어오는 요청이 인증되었는지 확인하는 데 사용할 수 있는 두 개의 미들웨어가 포함되어 있습니다. 시작하려면 애플리케이션의 bootstrap/app.php 파일에 다음 미들웨어 별칭을 정의합니다.
use Laravel\Passport\Http\Middleware\CheckForAnyScope;use Laravel\Passport\Http\Middleware\CheckScopes;->withMiddleware(function (Middleware $middleware) { $middleware->alias([ 'scopes' => CheckScopes::class, 'scope' => CheckForAnyScope::class, ]);})
모든 범위 확인
scopes 미들웨어를 경로에 할당하여 들어오는 요청의 액세스 토큰에 나열된 모든 범위가 있는지 확인할 수 있습니다.
Route::get('/orders', function () { // 액세스 토큰에 "check-status" 및 "place-orders" 범위가 모두 있습니다...})->middleware(['auth:api', 'scopes:check-status,place-orders']);
모든 범위 확인
scope 미들웨어를 경로에 할당하여 들어오는 요청의 액세스 토큰에 나열된 범위 중 최소 하나가 있는지 확인할 수 있습니다.
Route::get('/orders', function () { // 액세스 토큰에 "check-status" 또는 "place-orders" 범위가 있습니다...})->middleware(['auth:api', 'scope:check-status,place-orders']);
토큰 인스턴스에서 범위 확인
액세스 토큰 인증 요청이 애플리케이션에 들어온 후에도 인증된 App\Models\User 인스턴스에서 tokenCan 메서드를 사용하여 토큰에 지정된 범위가 있는지 확인할 수 있습니다.
use Illuminate\Http\Request;Route::get('/orders', function (Request $request) { if ($request->user()->tokenCan('place-orders')) { // ... }});
추가 범위 메서드
scopeIds 메서드는 정의된 모든 ID/이름의 배열을 반환합니다.
use Laravel\Passport\Passport;Passport::scopeIds();
scopes 메서드는 정의된 모든 범위를 Laravel\Passport\Scope 인스턴스로 반환합니다.
Passport::scopes();
scopesFor 메서드는 지정된 ID/이름과 일치하는 Laravel\Passport\Scope 인스턴스 배열을 반환합니다.
Passport::scopesFor(['place-orders', 'check-status']);
hasScope 메서드를 사용하여 주어진 범위가 정의되었는지 확인할 수 있습니다.
Passport::hasScope('place-orders');
JavaScript로 API 소비하기
API를 구축할 때 JavaScript 애플리케이션에서 자신의 API를 사용할 수 있는 것이 매우 유용할 수 있습니다. 이러한 API 개발 접근 방식을 사용하면 자신의 애플리케이션이 세계와 공유하는 것과 동일한 API를 사용할 수 있습니다. 동일한 API는 웹 애플리케이션, 모바일 애플리케이션, 타사 애플리케이션 및 다양한 패키지 관리자에서 게시할 수 있는 모든 SDK에서 사용할 수 있습니다.
일반적으로 JavaScript 애플리케이션에서 API를 사용하려면 액세스 토큰을 애플리케이션에 수동으로 보내고 애플리케이션에 대한 각 요청과 함께 전달해야 합니다. 그러나 Passport에는 이를 처리할 수 있는 미들웨어가 포함되어 있습니다. 애플리케이션의 bootstrap/app.php 파일에서 web 미들웨어 그룹에 CreateFreshApiToken 미들웨어를 추가하기만 하면 됩니다.
use Laravel\Passport\Http\Middleware\CreateFreshApiToken;->withMiddleware(function (Middleware $middleware) { $middleware->web(append: [ CreateFreshApiToken::class, ]);})
CreateFreshApiToken 미들웨어가 미들웨어 스택에 나열된 마지막 미들웨어인지 확인해야 합니다.
이 미들웨어는 나가는 응답에 laravel_token 쿠키를 첨부합니다. 이 쿠키에는 Passport가 JavaScript 애플리케이션의 API 요청을 인증하는 데 사용할 암호화된 JWT가 포함되어 있습니다. JWT의 수명은 session.lifetime 구성 값과 같습니다. 이제 브라우저가 모든 후속 요청과 함께 쿠키를 자동으로 보내므로 액세스 토큰을 명시적으로 전달하지 않고도 애플리케이션의 API에 요청할 수 있습니다.
axios.get('/api/user') .then(response => { console.log(response.data); });
쿠키 이름 사용자 정의
필요한 경우 Passport::cookie 메서드를 사용하여 laravel_token 쿠키의 이름을 사용자 정의할 수 있습니다. 일반적으로 이 메서드는 애플리케이션의 App\Providers\AppServiceProvider 클래스의 boot 메서드에서 호출해야 합니다.
/** * Bootstrap any application services. */public function boot(): void{ Passport::cookie('custom_name');}
CSRF 보호
이 인증 방법을 사용할 때는 유효한 CSRF 토큰 헤더가 요청에 포함되어 있는지 확인해야 합니다. 기본 Laravel JavaScript 스캐폴딩에는 암호화된 XSRF-TOKEN 쿠키 값을 사용하여 동일 출처 요청에 X-XSRF-TOKEN 헤더를 자동으로 보내는 Axios 인스턴스가 포함되어 있습니다.
X-XSRF-TOKEN 대신 X-CSRF-TOKEN 헤더를 보내도록 선택하는 경우 csrf_token()에서 제공하는 암호화되지 않은 토큰을 사용해야 합니다.
이벤트
Passport는 액세스 토큰과 새로 고침 토큰을 발급할 때 이벤트를 발생시킵니다. 이러한 이벤트를 수신하여 데이터베이스의 다른 액세스 토큰을 정리하거나 취소할 수 있습니다.
| 이벤트 이름 |
|---|
Laravel\Passport\Events\AccessTokenCreated |
Laravel\Passport\Events\RefreshTokenCreated |
테스트
Passport의 actingAs 메서드를 사용하여 현재 인증된 사용자와 해당 범위를 지정할 수 있습니다. actingAs 메서드에 주어진 첫 번째 인수는 사용자 인스턴스이고 두 번째 인수는 사용자 토큰에 부여해야 하는 범위 배열입니다.
use App\Models\User;use Laravel\Passport\Passport;test('서버를 생성할 수 있습니다', function () { Passport::actingAs( User::factory()->create(), ['create-servers'] ); $response = $this->post('/api/create-server'); $response->assertStatus(201);});
use App\Models\User;use Laravel\Passport\Passport;public function test_servers_can_be_created(): void{ Passport::actingAs( User::factory()->create(), ['create-servers'] ); $response = $this->post('/api/create-server'); $response->assertStatus(201);}
Passport의 actingAsClient 메서드는 현재 인증된 클라이언트와 해당 범위(scopes)를 지정하는 데 사용될 수 있습니다. actingAsClient 메서드에 전달되는 첫 번째 인자는 클라이언트 인스턴스이고 두 번째 인자는 클라이언트 토큰에 부여되어야 하는 범위 배열입니다.
use Laravel\Passport\Client;use Laravel\Passport\Passport;test('주문을 검색할 수 있습니다', function () { Passport::actingAsClient( Client::factory()->create(), ['check-status'] ); $response = $this->get('/api/orders'); $response->assertStatus(200);});
use Laravel\Passport\Client;use Laravel\Passport\Passport;public function test_orders_can_be_retrieved(): void{ Passport::actingAsClient( Client::factory()->create(), ['check-status'] ); $response = $this->get('/api/orders'); $response->assertStatus(200);}