Introduction to Laravel Passport
Laravel Passport is a comprehensive library that makes API authentication a breeze in Laravel applications. Developed and maintained by the Laravel community, Passport integrates seamlessly with Laravel's built-in features to provide a complete OAuth2 server implementation out-of-the-box. With Laravel Passport, you can issue tokens, authenticate users, and protect your API routes, making it an essential tool for modern web application development.
API Authentication is a critical aspect of web development, particularly when you're building a secure, scalable, and user-friendly application. Laravel Passport takes care of this by providing robust and standards-compliant OAuth2 functionalities. With it, you can:
- Secure your API endpoints
- Issue various types of tokens, including Personal Access Tokens and OAuth2 tokens
- Implement Single Sign-On (SSO) capabilities
- Perform role-based access control
- Easily manage OAuth clients and tokens
In this article, we'll delve into the various aspects of Laravel Passport to understand how to effectively implement API authentication in a Laravel application. From installation to advanced features, we've got you covered. So let's get started!
Installation and Configuration
Installing and configuring Laravel Passport is a straightforward process. This section provides a step-by-step guide on how to set up Passport in your Laravel application, ensuring you can start building secure APIs quickly.
re working on Laravel Passport, you'll need to have Laravel Installed.
- PHP >= 7.3
- Composer
- Laravel CLI
- A database (MySQL, SQLite, etc.)
I have already provided an extensive detailed tutorial on complete Laravel Installation and Environment Setup. You can follow the same if you are new to Laravel.
Install Laravel Passport using Composer:Â First, you need to require the Passport package in your Laravel project. Navigate to your Laravel project root directory in your terminal or command prompt and run the following command:
composer require laravel/passport
Composer will download and install the Laravel Passport package and its dependencies.
Check if the Installation is Successful: After running the command, you should see Laravel Passport listed in your project's composer.json
file under the require
section.
$ ls -l composer.json -rwxr-xr-x 1 deepak www-data 1919 Aug 28 23:20 composer.json
Run migrations: Laravel Passport comes with migration files that create the necessary database tables for OAuth clients, access tokens, and related data. Run the following command to execute the migrations:
php artisan migrate
Once the migration is successful, you'll see new tables related to Passport in your database. These tables will store OAuth2 clients and token data.
Install Passport: This command will install Passport's encryption keys as well as create "personal access" and "password grant" clients which will be used for generating access tokens:
php artisan passport:install
Output:
Encryption keys generated successfully. Personal access client created successfully. Client ID: 1 Client secret: mLEeN9Jdq9sf5n0cHQVcTMmz0M3aCHpEXICjMoAQ Password grant client created successfully. Client ID: 2 Client secret: gfPZ1qnTYCGzkFoEQOX0uJRK0fCJUHG1Daxv3zxz
Register Passport Service Provider: If you are using Laravel version less than 5.5, you'll need to manually add the Passport service provider in your config/app.php
file in the providers
array:
// config/app.php
'providers' => [
// ... Other providers
Laravel\Passport\PassportServiceProvider::class,
],
For Laravel 5.5 and above, service provider registration is automatic.
Configure the User Model: You'll need to update your User
model to use Passport's HasApiTokens
trait:
// app/Models/User.php
use Laravel\Passport\HasApiTokens;
class User extends Authenticatable
{
use HasApiTokens, Notifiable;
// ...
}
Configure AuthServiceProvider
: Open your AuthServiceProvider
and register the routes and tokens within the boot
method:
// app/Providers/AuthServiceProvider.php
use Laravel\Passport\Passport;
public function boot()
{
$this->registerPolicies();
Passport::routes();
}
Configure API Authentication Driver: Modify your config/auth.php
to use Passport as the driver for API authentication:
// config/auth.php
'guards' => [
'api' => [
'driver' => 'passport',
'provider' => 'users',
],
],
Configuration File and Environment Settings
- Configuration File: After running
passport:install
, apassport.php
file will be placed in yourconfig
folder. You can adjust settings like token lifetime in this file. - Environment Settings: Passport's keys are typically stored in the
storage
directory but you can specify a different location by setting thePASSPORT_PRIVATE_KEY
andPASSPORT_PUBLIC_KEY
environment variables in your.env
file. - Client IDs and Secret: When you run
passport:install
, it will generate client IDs and client secrets. Keep these confidential. You can also create new clients manually by running:
php artisan passport:client
This will interactively guide you through creating a new client and will display the client ID and secret upon completion.
Generating Tokens
1. Personal Access Tokens
Creating Personal Access Client: After you have run php artisan passport:install
, you can create a Personal Access Client. You can also create one manually by running:
php artisan passport:client --personal
Issuing Tokens: Inside your application, you can issue tokens using the createToken
method on a User
model instance:
$token = $user->createToken('Token Name')->accessToken;
This will return an access token string that you can return as a response from an API endpoint, for example.
2. Client Credentials Grant Tokens
Creating Client: You can create a new client by running:
php artisan passport:client
Note down the Client ID
and Client Secret
.
Requesting Token: To request a token using client credentials, you can use a request like the following:
curl -X POST "http://your-app.com/oauth/token" \
-d "grant_type=client_credentials" \
-d "client_id=CLIENT_ID_HERE" \
-d "client_secret=CLIENT_SECRET_HERE" \
-d "scope=SCOPE_HERE_IF_ANY"
This will return a JSON object containing the token.
3. Authorization Code Grant Tokens
Creating Client: Use the following command to create a client that can handle authorization codes.
php artisan passport:client
When prompted to, say "yes" for authorization codes.
Redirect to Authorization Page: Redirect your user to the /oauth/authorize
route, along with the client_id
and redirect_uri
.
$query = http_build_query([
'client_id' => 'CLIENT_ID',
'redirect_uri' => 'REDIRECT_URI',
'response_type' => 'code',
'scope' => 'SCOPE_IF_ANY',
]);
return redirect("http://your-app.com/oauth/authorize?$query");
Handle Callback: After authorization, the user will be redirected back to your redirect_uri
. You can capture the code
parameter from the URL and exchange it for an access token:
$http = new GuzzleHttp\Client;
$response = $http->post('http://your-app.com/oauth/token', [
'form_params' => [
'grant_type' => 'authorization_code',
'client_id' => 'CLIENT_ID',
'client_secret' => 'CLIENT_SECRET',
'redirect_uri' => 'REDIRECT_URI',
'code' => $code,
],
]);
return json_decode((string) $response->getBody(), true);
This will return a JSON object containing the access token and refresh token.
User Authentication
Before diving into token generation, it's important to set up a basic authentication system for your users if you haven't already done so. Laravel makes this very simple with the php artisan make:auth
command, although starting with Laravel 6, the UI scaffolding is separated into a package called laravel/ui
. You can follow the Laravel documentation for setting up basic user registration and authentication.
1. Implementing Authentication Routes
Login Route: Create a login route that takes an email and password, then generates a token.
use Illuminate\Http\Request;
Route::post('/login', function (Request $request) {
$credentials = $request->only('email', 'password');
if (Auth::attempt($credentials)) {
$user = Auth::user();
$token = $user->createToken('MyApp')->accessToken;
return response()->json(['token' => $token], 200);
} else {
return response()->json(['error' => 'Unauthorized'], 401);
}
});
Register Route: You can create a register route similarly. Validate the user input, create a new user, and then issue a token.
Route::post('/register', function (Request $request) {
$request->validate([
'name' => 'required',
'email' => 'required|email|unique:users',
'password' => 'required|min:6',
]);
$user = User::create([
'name' => $request->name,
'email' => $request->email,
'password' => bcrypt($request->password),
]);
$token = $user->createToken('MyApp')->accessToken;
return response()->json(['token' => $token], 200);
});
Logout Route: For logging out, you can revoke the user's tokens.
Route::middleware('auth:api')->post('/logout', function (Request $request) {
$request->user()->token()->revoke();
return response()->json(['message' => 'Successfully logged out']);
});
2. Creating User Tokens
Personal Access Tokens: After logging in, you can issue a token for the authenticated user.
$token = $user->createToken('Token Name')->accessToken;
Token with Scopes: Scopes allow you to limit what a token can do. You can issue a token with scopes like this:
$token = $user->createToken('My Token', ['view-posts', 'create-posts'])->accessToken;
Revoking Tokens: You can revoke tokens by calling the revoke
method.
$user->token()->revoke();
Refreshing Tokens: For grant types that support refresh tokens (like Authorization Code Grant), you can refresh a token by issuing a new request to the /oauth/token
endpoint with grant_type
set to refresh_token
.
Secure API Endpoints
Securing your API endpoints is crucial when you're developing a web application. Laravel Passport provides several ways to help you secure your API routes.
1. Using Middleware
Auth Middleware: The auth:api
middleware ensures that the user is authenticated before they can access the route.
Route::middleware('auth:api')->get('/user', function (Request $request) {
return $request->user();
});
Scope Middleware: You can define middlewares to check the token's scopes.
Route::middleware(['auth:api', 'scopes:admin'])->get('/admin', function () {
// Accessible only to tokens that have the admin scope
});
Rate Limiting Middleware: Laravel also provides a throttle
middleware that you can use to limit how many requests a user can make in a given period.
Route::middleware('auth:api', 'throttle:60,1')->group(function () {
Route::get('/profile', function () {
// API logic here
});
});
2. Protecting Routes
Grouping Routes: You can group your API routes that need authentication.
Route::middleware('auth:api')->group(function () {
Route::get('/dashboard', 'DashboardController@index');
Route::get('/profile', 'ProfileController@index');
});
Individual Routes: Or you can protect individual routes by directly adding the middleware to them.
Route::get('/dashboard', 'DashboardController@index')->middleware('auth:api');
Resource Controllers: If you're using resource controllers, you can specify middleware like this:
Route::apiResource('posts', 'PostController')->middleware('auth:api');
Conditional Middleware: You can conditionally apply middleware using the when
method.
Route::get('/data', function () {
// Your logic
})->middleware(function ($request, $next) {
return $request->user()->isAdmin() ? $next($request) : abort(403);
});
Token Issuance and Revocation
Token issuance, revocation, and management are fundamental aspects of API security, and Laravel Passport provides a comprehensive set of features to manage tokens easily.
1. Generating Access Tokens
Personal Access Tokens: If you're using personal access tokens, you can issue a new token using the createToken
method on a User
model instance. This is suitable for "first-party" clients that you control:
$token = $user->createToken('My Personal Token')->accessToken;
OAuth2 Authorization Code Grant: If you're using an OAuth2 authorization code grant (often used for third-party clients), then you'll guide users through the OAuth2 flow, ultimately receiving an access token in return.
Password Grant: If you want to issue a token based on user credentials directly, you can use the "password grant":
curl -X POST "http://your-app.com/oauth/token" \
-d "grant_type=password" \
-d "client_id=CLIENT_ID" \
-d "client_secret=CLIENT_SECRET" \
-d "username=USER_EMAIL" \
-d "password=USER_PASSWORD" \
-d "scope=*"
2. Refreshing Tokens
OAuth2 Grants: For OAuth2 authorization code grants, Passport will issue a refresh token alongside the access token. You can use this refresh token to get a new access token:
curl -X POST "http://your-app.com/oauth/token" \
-d "grant_type=refresh_token" \
-d "refresh_token=YOUR_REFRESH_TOKEN_HERE" \
-d "client_id=CLIENT_ID" \
-d "client_secret=CLIENT_SECRET" \
-d "scope=*"
Personal Access Tokens: Personal access tokens don't need to be refreshed. If you need a new one, simply issue a new token.
3. Revoking Tokens
Revoke Single Token: You can revoke a specific token by calling the revoke
method on it:
$user->token()->revoke();
Revoke All Tokens for User: You can also revoke all tokens for a user:
$user->tokens->each(function ($token, $key) {
$token->revoke();
});
Prune Tokens: It's also good to periodically prune revoked and expired tokens. You can set up a scheduled job for that:
use Laravel\Passport\Token;
Token::where('expires_at', '<', now())->orWhere('revoked', true)->delete();
Role-based Access Control
Role-based Access Control (RBAC) is a security paradigm wherein different users are granted access to different parts of the system based on their roles. Laravel doesn't include RBAC features out-of-the-box, but it's very flexible and allows you to build on top of its existing facilities to create a role-based access system. Libraries like spatie/laravel-permission
can also make implementing RBAC easier.
1. Assigning Roles and Permissions
Database Schema: You'll typically need tables for roles, permissions, and pivot tables like role_user, role_permissions, etc.
Eloquent Models: Create Eloquent models for Role
and Permission
and establish the relationships.
class Role extends Model
{
public function permissions()
{
return $this->belongsToMany(Permission::class);
}
}
class Permission extends Model
{
public function roles()
{
return $this->belongsToMany(Role::class);
}
}
class User extends Authenticatable
{
public function roles()
{
return $this->belongsToMany(Role::class);
}
}
Assigning Roles: Assign roles to users. This could be done during user registration or from an admin interface.
$user->roles()->attach($roleId);
Assigning Permissions to Roles: Assign permissions to roles in a similar manner.
$role->permissions()->attach($permissionId);
2. Middleware for Role-based Access
1. Creating Middleware: You can create middleware to handle role-based checks.
php artisan make:middleware CheckRole
Modify the handle
method:
public function handle(Request $request, Closure $next, $role)
{
if (!$request->user() || !$request->user()->hasRole($role)) {
return abort(403, 'Unauthorized');
}
return $next($request);
}
Add a hasRole
method in your User
model to check roles:
public function hasRole($role)
{
return $this->roles->pluck('name')->contains($role);
}
2. Register Middleware: Register your middleware in Kernel.php
.
protected $routeMiddleware = [
// ...
'role' => \App\Http\Middleware\CheckRole::class,
];
3. Using Middleware in Routes: Apply the middleware to your routes.
Route::middleware(['auth:api', 'role:admin'])->group(function () {
Route::get('/admin', 'AdminController@index');
});
Or use it in the controller constructor:
public function __construct()
{
$this->middleware(['auth:api', 'role:admin']);
}
Managing OAuth Clients
Managing OAuth clients is a critical aspect of an OAuth2-based authentication system like Laravel Passport. This allows you to issue access tokens for different clients like mobile apps, web apps, and third-party services. Here's how to manage OAuth clients in Laravel Passport.
1. Creating OAuth Clients via Passport's Command
Laravel Passport provides an Artisan command that makes it easy to create new clients. After installing Passport, you can use the passport:client
command to create a new client.
php artisan passport:client
When you run this command, Passport will prompt you to provide the client name and whether you would like to allow the client to access the user's personal access tokens. The command will generate a client ID and secret for you.
You can specify options to generate clients tailored for different OAuth2 grant types:
Password Grant Client
php artisan passport:client --password
Personal Access Client
php artisan passport:client --personal
Client Credentials Grant Client
php artisan passport:client --client
2. Updating OAuth Clients
OAuth clients are stored in your database, and you can update them like any other Eloquent model. However, changing the client's secret or ID manually is not advised as it may break existing applications that use that client. If you must change them, make sure to update them in all places where they are used.
Here's how you could update a client:
use Laravel\Passport\Client;
$client = Client::find(1); // Find client by ID
$client->name = 'New Client Name';
$client->redirect = 'https://new-redirect-uri.com/callback';
$client->save();
3. Deleting OAuth Clients
Deleting an OAuth client will revoke all tokens issued for that client and can be disruptive for end-users. But if you need to do it, it can be done via Eloquent:
use Laravel\Passport\Client;
$client = Client::find(1); // Find client by ID
$client->delete();
Alternatively, you could set up an admin interface to manage OAuth clients more conveniently.
Rate Limiting
Rate limiting is an essential feature for controlling the amount of incoming requests to your API. This helps to maintain the quality of your service and to protect it from abuse or attacks. Laravel, in combination with Laravel Passport, provides built-in mechanisms for API rate limiting.
1. How to Implement Rate Limiting
Laravel provides a throttle
middleware that handles rate limiting. You can specify the rate limits as middleware parameters in your routes.
Here's an example where users are allowed 60 requests per minute:
Route::middleware('auth:api', 'throttle:60,1')->group(function () {
Route::get('/user', function (Request $request) {
return $request->user();
});
});
In the above example, throttle:60,1
specifies that a user can make up to 60 requests per minute (1
minute).
2. Customizing Rate Limits per User
You can customize rate limits dynamically based on the authenticated user or other aspects of the incoming request by defining a rate limiter in the boot
method of your RouteServiceProvider
.
Here's how to define a rate limiter that allows a different number of requests per minute based on the user's role:
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Support\Facades\RateLimiter;
public function boot()
{
RateLimiter::for('api', function (Request $request) {
if ($request->user() && $request->user()->role === 'admin') {
return Limit::perMinute(1000);
}
return Limit::perMinute(60);
});
}
After defining the rate limiter, you can apply it to routes using the throttle
middleware, specifying the name of the rate limiter as an argument:
Route::middleware(['auth:api', 'throttle:api'])->group(function () {
Route::get('/user', function (Request $request) {
return $request->user();
});
});
This allows you to implement more complex and dynamic rate limiting logic, adapting to the needs of your application and your users.
Frontend Considerations
When using Laravel Passport for building an API that will be consumed by a frontend, there are a number of security and architectural considerations to keep in mind.
1. Handling Tokens on the Frontend
Storing Tokens: Once you obtain an access token, you have to decide where to store it. The common places are:
- LocalStorage: Easy to use but not recommended for sensitive data like tokens due to cross-site scripting (XSS) risks.
- SessionStorage: Similar to LocalStorage but limited to a session. It has the same XSS risks.
- HttpOnly Cookies: More secure, but you'll need to ensure cross-origin requests are properly handled and may need to account for CSRF attacks.
- In-Memory: Store it in a JavaScript variable. This is the most secure client-side option but you'll lose the token if the page is refreshed.
Sending Tokens: Typically, tokens are added to the headers of your HTTP requests.
axios.get('/api/resource', {
headers: { 'Authorization': `Bearer ${token}` }
})
2. CORS and CSRF Concerns
1. CORS (Cross-Origin Resource Sharing): When making requests from a domain other than the one where your Laravel API resides, you'll need to configure CORS. Laravel includes a CORS package by default. Configure it in the cors.php
config file.
'paths' => ['api/*', 'sanctum/csrf-cookie', 'login', 'logout'],
'allowed_methods' => ['*'],
'allowed_origins' => ['https://your-frontend-domain.com'],
'allowed_origins_patterns' => [],
'allowed_headers' => ['*'],
Remember to only allow origins that you control to interact with your API.
2. CSRF (Cross-Site Request Forgery): CSRF tokens are usually not needed for stateless APIs (like ones using OAuth2 tokens for each request). However, if you're using session authentication in some parts of your app, Laravel makes it easy to include CSRF tokens. These tokens should be attached to POST
, PUT
, PATCH
, and DELETE
requests.
If you opt to use cookies to store tokens, make sure to also secure against CSRF by ensuring a CSRF cookie is set and attached to requests. Laravel automatically includes a CSRF token in a cookie named XSRF-TOKEN
. In your frontend, you can include this token in the headers of mutating requests.
axios.defaults.headers.common['X-XSRF-TOKEN'] = readCookie('XSRF-TOKEN');
Where readCookie
is a function that reads cookies to get the XSRF-TOKEN
.
Advanced Features
Laravel Passport offers a variety of advanced features to make your API more flexible and secure. Here's a closer look at some of these:
1. Scopes and Scope Restrictions
Scopes allow your API clients to request a specific set of permissions when requesting authorization. For example, you might define read
, write
, and delete
scopes for more fine-grained control over what actions a client can perform.
To define scopes, add them to the boot
method of your AuthServiceProvider
using the Passport::tokensCan
method:
use Laravel\Passport\Passport;
public function boot()
{
Passport::tokensCan([
'read' => 'Read your data',
'write' => 'Modify your data',
'delete' => 'Delete your data',
]);
}
To restrict routes to certain scopes, use the scope
or scopes
middleware:
Route::get('/post', function () {
// Accessible only with "read" scope
})->middleware(['auth:api', 'scope:read']);
Route::get('/edit', function () {
// Accessible with either "read" or "write" scope
})->middleware(['auth:api', 'scopes:read,write']);
2. Multiple Authentication Guards
Laravel allows you to define multiple authentication guards. This is useful when your application has different types of users that need to authenticate in different ways. For example, you might have an admin
guard and a user
guard.
In config/auth.php
, you can define multiple guards like so:
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'admin' => [
'driver' => 'passport',
'provider' => 'admins',
],
'user' => [
'driver' => 'passport',
'provider' => 'users',
],
],
To specify which guard to use in your routes, you can use the guard
method on the Auth
facade or specify it directly in the middleware:
Route::middleware('auth:admin')->group(function () {
// Your routes here
});
// OR
use Illuminate\Support\Facades\Auth;
Auth::guard('admin')->user();
3. Token Lifetimes
By default, Passport issues long-lived access tokens that expire after one year. However, you can modify these defaults by using the tokensExpireIn
and refreshTokensExpireIn
methods. This can be set in the boot
method of the AuthServiceProvider
:
use Carbon\Carbon;
public function boot()
{
Passport::routes();
// Access tokens will expire after 1 day.
Passport::tokensExpireIn(Carbon::now()->addDays(1));
// Refresh tokens will expire after 30 days.
Passport::refreshTokensExpireIn(Carbon::now()->addDays(30));
}
Common Errors and Troubleshooting
Troubleshooting is a common task when working with any authentication mechanism, and Laravel Passport is no exception. Here are some common errors and solutions when working with Laravel Passport.
Invalid Token Errors
1. Token Not Provided: Make sure that the token is correctly passed in the header of the request with the prefix Bearer
.
Authorization: Bearer YOUR_ACCESS_TOKEN_HERE
2. Token Signature Could Not Be Verified: This generally means that the token has been tampered with or that it was created with a different secret. Make sure the correct APP_KEY
is set in your .env
file and that it matches the key used when the token was created.
3. Token Blacklisted: If using JWT tokens, a "blacklisted" error can happen if the token was manually invalidated.
Expired Tokens
1. Token Has Expired: OAuth2 tokens have a built-in expiry. Once a token is expired, you need to either refresh the token (if you are using a refresh token) or request a new one.
Refreshing an Expired Token: If you have a refresh token, you can obtain a new access token by making a POST request to the /oauth/token
endpoint with the refresh_token
grant type.
POST /oauth/token
{
"grant_type": "refresh_token",
"refresh_token": "YOUR_REFRESH_TOKEN_HERE",
"client_id": "CLIENT_ID",
"client_secret": "CLIENT_SECRET"
}
Requesting a New Token: If you can't refresh the token, the client must go through the authorization process again to obtain a new access token.
Other Common Issues
- Unauthorized Error After Logging In: This might happen if the token is not correctly stored on the client or not correctly sent in subsequent requests.
- CORS Errors: If you see CORS (Cross-Origin Resource Sharing) errors, make sure you have set up CORS correctly on your server. Laravel provides options to do so in its
cors.php
config file. - 500 Server Errors: Check your Laravel logs to get more details. Common reasons include permissions problems on the storage directories, or issues with the Passport package itself that may require you to run
composer update
. - Client Errors (like Client ID not found): Make sure you've run the
passport:install
command and that theoauth_clients
table contains your client IDs. - Mismatching Redirect URI: Make sure that the redirect URI you specify during the OAuth authorization process exactly matches one of the redirect URIs registered for the client.
- Sessions Not Working as Expected: If you're using stateful sessions in conjunction with tokens, make sure that both the web and API guard configurations are set up correctly.
- Key path "file://[...]" does not exist or is not readable: This usually happens when the keys for the tokens are not generated or not accessible. You can regenerate them using the command
php artisan passport:keys
.
Summary
Laravel Passport offers a complete, full-featured OAuth2 server implementation for your Laravel application. It simplifies various aspects of API authentication, from basic token issuance to more advanced features like scopes and multiple guards. We've touched upon:
- Installation & Configuration: Setting up Laravel Passport is straightforward, and you have options to configure various aspects through environment variables and dedicated configuration files.
- Token Management: Passport supports various OAuth2 grant types, allowing you to issue tokens in different ways, such as Personal Access Tokens, Client Credentials Grant Tokens, and Authorization Code Grant Tokens.
- User Authentication: The package offers utilities for implementing your authentication routes and generating user-specific tokens easily.
- Security: Security features like rate-limiting and middleware options can protect your API endpoints from abuse.
- Advanced Features: Scopes, multiple authentication guards, and custom token lifetimes offer granular control over your API's authentication behavior.
- Troubleshooting: While the package is designed to be as straightforward as possible, like any software, it has its quirks. Being aware of common errors and knowing how to debug them can save a lot of time.
- Frontend Considerations: Handling tokens securely on the frontend and dealing with CORS and CSRF are crucial for the security and functionality of your application.
Additional Resources
- Official Laravel Passport Documentation: The most authoritative resource on Laravel Passport. It’s comprehensive and includes code samples.
- OAuth 2.0 Simplified: A book by Aaron Parecki that explains the OAuth 2.0 protocol in depth.
- Laravel News: A great resource for staying updated on Laravel features, including Passport.
- Laracasts: Features numerous video tutorials on Laravel and related tools, including Passport.
- Stack Overflow: If you encounter issues, someone has probably faced them before. Stack Overflow can be a great resource for solutions.