Scopes allow your API clients to request a specific set of permissions when requesting authorization to access an account. For example, if you are building an e-commerce application, not all API consumers will need the ability to place orders. Instead, you may allow the consumers to only request authorization to access order shipment statuses. In other words, scopes allow your application’s users to limit the actions a third-party application can perform on their behalf.
Defining Scopes
You may define your API’s scopes using the Passport::tokensCan method in the boot method of your AuthServiceProvider. The tokensCan method accepts an array of scope names and scope descriptions. The scope description may be anything you wish and will be displayed to users on the authorization approval screen:
use Laravel\Passport\Passport; Passport::tokensCan([ 'place-orders' => 'Place orders', 'check-status' => 'Check order status', ]);
Assigning Scopes To Tokens
When Requesting Authorization Codes
When requesting an access token using the authorization code grant, consumers should specify their desired scopes as the scope query string parameter. The scope parameter should be a space-delimited list of scopes:
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://your-app.com/oauth/authorize?'.$query); });
Checking Scopes
Passport includes two middleware that may be used to verify that an incoming request is authenticated with a token that has been granted a given scope. To get started, add the following middleware to the $routeMiddleware property of your app/Http/Kernel.php file:
‘scopes’ => \Laravel\Passport\Http\Middleware\CheckScopes::class,
‘scope’ => \Laravel\Passport\Http\Middleware\CheckForAnyScope::class,
Check For All Scopes
The scopes middleware may be assigned to a route to verify that the incoming request’s access token has all of the listed scopes:
Route::get(‘/orders’, function () {
// Access token has both “check-status” and “place-orders” scopes…
})->middleware(‘scopes:check-status,place-orders’);
Check For Any Scopes
The scope middleware may be assigned to a route to verify that the incoming request’s access token has at least one of the listed scopes:
Route::get(‘/orders’, function () {
// Access token has either “check-status” or “place-orders” scope…
})->middleware(‘scope:check-status,place-orders’);
Checking Scopes On A Token Instance
Once an access token authenticated request has entered your application, you may still check if the token has a given scope using the tokenCan method on the authenticated User instance:
use Illuminate\Http\Request;
Route::get(‘/orders’, function (Request $request) {
if ($request->user()->tokenCan(‘place-orders’)) {
//
}
});
Additional Scope Methods
The scopeIds method will be return an array of all defined IDs / names:
Laravel\Passport\Passport::scopeIds();
The scopes method will return an array of all defined scopes as instances of Laravel\Passport\Scope:
Laravel\Passport\Passport::scopes();
The scopesFor method will return an array of Laravel\Passport\Scope instances matching the given IDs / names:
Laravel\Passport\Passport::scopesFor([‘place-orders’, ‘check-status’]);
You may determine if a given scope has been defined using the hasScope method:
Laravel\Passport\Passport::hasScope(‘place-orders’);
Consuming Your API With JavaScript
When building an API, it can be extremely useful to be able to consume your own API from your JavaScript application. This approach to API development allows your own application to consume the same API that you are sharing with the world. The same API may be consumed by your web application, mobile applications, third-party applications, and any SDKs that you may publish on various package managers.
Typically, if you want to consume your API from your JavaScript application, you would need to manually send an access token to the application and pass it with each request to your application. However, Passport includes a middleware that can handle this for you. All you need to do is add the CreateFreshApiToken middleware to your web middleware group in your app/Http/Kernel.php file:
‘web’ => [
// Other middleware…
\Laravel\Passport\Http\Middleware\CreateFreshApiToken::class,
],
Note: You should ensure that the EncryptCookies middleware is listed prior to the CreateFreshApiToken middleware in your middleware stack.
This Passport middleware will attach a laravel_token cookie to your outgoing responses. This cookie contains an encrypted JWT that Passport will use to authenticate API requests from your JavaScript application. Now, you may make requests to your application’s API without explicitly passing an access token:
axios.get(‘/api/user’)
.then(response => {
console.log(response.data);
});
Customizing The Cookie Name
If needed, you can customize the laravel_token cookie’s name using the Passport::cookie method. Typically, this method should be called from the boot method of your AuthServiceProvider:
/**
* Register any authentication / authorization services.
*
* @return void
*/
public function boot()
{
$this->registerPolicies();
Passport::routes();
Passport::cookie(‘custom_name’);
}
CSRF Protection
When using this method of authentication, the default Laravel JavaScript scaffolding instructs Axios to always send the X-CSRF-TOKEN and X-Requested-With headers. However, you should be sure to include your CSRF token in a HTML meta tag:
window.axios.defaults.headers.common = {
‘X-Requested-With’: ‘XMLHttpRequest’,
};
Events
Passport raises events when issuing access tokens and refresh tokens. You may use these events to prune or revoke other access tokens in your database. You may attach listeners to these events in your application’s EventServiceProvider:
/**
* The event listener mappings for the application.
*
* @var array
*/
protected $listen = [
‘Laravel\Passport\Events\AccessTokenCreated’ => [
‘App\Listeners\RevokeOldTokens’,
],
‘Laravel\Passport\Events\RefreshTokenCreated’ => [
‘App\Listeners\PruneOldTokens’,
],
];
Testing
Passport’s actingAs method may be used to specify the currently authenticated user as well as its scopes. The first argument given to the actingAs method is the user instance and the second is an array of scopes that should be granted to the user’s token:
use App\User;
use Laravel\Passport\Passport;
public function testServerCreation()
{
Passport::actingAs(
factory(User::class)->create(),
[‘create-servers’]
);
$response = $this->post(‘/api/create-server’);
$response->assertStatus(201);
}
ぬお、なんか今日は無償に疲れた。