Introduction: Why OAuth2 Matters
In today’s connected world, APIs are essential for modern applications. Whether you’re building a mobile app, a single-page application, or connecting to third-party services, you need a secure way to authenticate users and protect your API endpoints.
That’s where OAuth2 comes in. It is the industry-standard protocol for authorization. When implementing OAuth2 in Laravel applications, Laravel Passport is the tool you need.
In this guide, we’ll cover everything you need to know about Laravel Passport, from the basics to building a complete OAuth2 authentication system.
What is OAuth2?
Before discussing Laravel Passport, let’s clarify what OAuth2 is.
OAuth2 is an authorization framework that allows applications to gain limited access to user accounts on an HTTP service. It enables applications to access your resources without needing to share your password.
The Real-World Analogy
Imagine you’re at a hotel:
- Your room key is like an access token; it gives you access to specific resources (your room).
- The front desk acts as the authorization server, issuing and validating keys.
- Your room represents the protected resource; only people with the right key can enter.
- When you check out, your key stops working; this is similar to token revocation.
Why Not Just Use Basic Authentication?
You might ask, “Why not just send username and password with every API request?”
Here are the reasons OAuth2 is better:
- Security: Tokens can be revoked without changing passwords.
- Scope: Different tokens can have different permissions.
- Expiration: Tokens automatically expire, which limits damage from theft.
- Third-party access: You can give access to other apps without sharing credentials.
- Stateless: Ideal for distributed systems and microservices.
Laravel Passport
Laravel Passport is a complete OAuth2 server implementation for Laravel applications. It simplifies the process of adding OAuth2 authentication and requires only a few Artisan commands.
What Passport Gives You
Out of the box, Passport offers:
- OAuth2 Server Implementation – Full OAuth2 protocol support
- Multiple Grant Types – Including Password, Authorization Code, and Client Credentials
- Token Management – Ability to issue, refresh, and revoke tokens
- Scope System – To define detailed permissions
- Personal Access Tokens – Easy tokens for first-party applications
- Ready-to-use Routes – Authentication routes set up automatically
Setting Up Your First Passport Application
Let’s create a simple API using Passport authentication.
Step 1: Installation
First, install Passport via Composer.
composer require laravel/passport
Step 2: Run Migrations
The passport requires several database tables to store clients and tokens.
php artisan migrate
This creates:
- oauth_access_tokens – Stores access tokens
- oauth_refresh_tokens – Stores refresh tokens
- oauth_clients – Stores OAuth clients
- oauth_personal_access_clients – Configuration for personal access clients
- oauth_auth_codes – Temporary authorization codes
Step 3: Install Passport
Generate encryption keys and create “Password Grant” and “Personal Access” clients.
php artisan passport:install
You’ll see output like this:
Personal access client created successfully.
Password grant client created successfully.
Client ID: 1
Client secret: abc123...
Important: Save these credentials! You’ll need them for certain grant types
Step 4: Configure Your User Model
Add the HasApiTokens trait to your User model.
<?php
namespace App\Models;
use Laravel\Passport\HasApiTokens;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use HasApiTokens;
// ... rest of your model
}
This trait provides methods for:
- Creating tokens: $user->createToken(‘token-name’)
- Checking tokens: $user->token()
- Revoking tokens: $user->token()->revoke()
Step 5: Configure Authentication Guard
In config/auth.php, set Passport as your API driver.
'guards' => [
'api' => [
'driver' => 'passport',
'provider' => 'users',
],
],
Step 6: Register Passport Routes
In your AuthServiceProvider, set up Passport.
<?php
namespace App\Providers;
use Laravel\Passport\Passport;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
class AuthServiceProvider extends ServiceProvider
{
public function boot()
{
$this->registerPolicies();
// Token lifetimes
Passport::tokensExpireIn(now()->addDays(15));
Passport::refreshTokensExpireIn(now()->addDays(30));
Passport::personalAccessTokensExpireIn(now()->addMonths(6));
}
}
Building Your Authentication API
Now let’s create a complete authentication system with registration, login, and logout.
The Authentication Controller
Here’s a full controller that manages all authentication operations.
<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
class AuthController extends Controller
{
/**
* Register a new user and return access token
*/
public function register(Request $request)
{
$validator = Validator::make($request->all(), [
'name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users',
'password' => 'required|string|min:8|confirmed',
]);
if ($validator->fails()) {
return response()->json([
'message' => 'Validation failed',
'errors' => $validator->errors(),
], 422);
}
// Create the user
$user = User::create([
'name' => $request->name,
'email' => $request->email,
'password' => Hash::make($request->password),
]);
// Generate access token
$token = $user->createToken('auth_token')->accessToken;
return response()->json([
'message' => 'Registration successful',
'access_token' => $token,
'token_type' => 'Bearer',
'user' => $user,
], 201);
}
/**
* Login user and return access token
*/
public function login(Request $request)
{
// Validate input
$credentials = $request->only('email', 'password');
if (!Auth::attempt($credentials)) {
return response()->json([
'message' => 'Invalid credentials',
], 401);
}
// Get authenticated user
$user = User::where('email', $request->email)->firstOrFail();
// Generate token
$token = $user->createToken('auth_token')->accessToken;
return response()->json([
'message' => 'Login successful',
'access_token' => $token,
'token_type' => 'Bearer',
'user' => $user,
]);
}
/**
* Get authenticated user details
*/
public function user(Request $request)
{
return response()->json([
'user' => $request->user(),
]);
}
/**
* Logout user (revoke token)
*/
public function logout(Request $request)
{
$request->user()->token()->revoke();
return response()->json([
'message' => 'Successfully logged out',
]);
}
}
The Key Concepts Explained
- Creating Tokens:
$token = $user->createToken('auth_token')->accessToken;
This generates a new access token for the user. The string ‘auth_token’ is just a label for this token.
2. Returning Tokens:
return response()->json([
'access_token' => $token,
'token_type' => 'Bearer',
]);
We return the token to the client, who will use it for future requests.
3. Protecting Routes:
Route::middleware('auth:api')->group(function () {
Route::get('/user', [AuthController::class, 'user']);
});
The auth:api middleware checks the token with every request.
4. Revoking Tokens:
$request->user()->token()->revoke();
This invalidates the token, effectively logging the user out.
Defining API Routes:
In routes/api.php, create your authentication routes.
<?php
use App\Http\Controllers\Api\AuthController;
use Illuminate\Support\Facades\Route;
// Public routes (no authentication required)
Route::post('/register', [AuthController::class, 'register']);
Route::post('/login', [AuthController::class, 'login']);
// Protected routes (require authentication)
Route::middleware('auth:api')->group(function () {
Route::get('/user', [AuthController::class, 'user']);
Route::post('/logout', [AuthController::class, 'logout']);
// Add more protected routes here
Route::get('/posts', [PostController::class, 'index']);
Route::post('/posts', [PostController::class, 'store']);
});
Using Your API – The Client Side:
Now that your API is set up, let’s discuss how clients will use it.
Step 1: Register or Login
# Register a new user
curl -X POST http://your-api.com/api/register \
-H "Content-Type: application/json" \
-d '{
"name": "John Doe",
"email": "john@example.com",
"password": "secretpass123",
"password_confirmation": "secretpass123"
}'
Response:
{
"message": "Registration successful",
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGc...",
"token_type": "Bearer",
"user": {
"id": 1,
"name": "John Doe",
"email": "john@example.com"
}
}
Step 2: Store the Token
The client application should keep this token safe. Options include:
- Mobile apps: Secure storage (Keychain on iOS, Keystore on Android)
- Web apps: HttpOnly cookies or localStorage (use caution)
- Desktop apps: Encrypted local storage
Step 3: Use the Token
For each following request, include the token in the Authorization header.
curl -X GET http://your-api.com/api/user \
-H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGc..."
Response:
{
"user": {
"id": 1,
"name": "John Doe",
"email": "john@example.com"
}
}
Step 4: Logout
When the user logs out, revoke the token.
curl -X POST http://your-api.com/api/logout \
-H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGc..."
Advanced Passport Features
- Token Scopes:
Scopes help define detailed permissions.
// Define scopes
Passport::tokensCan([
'read-posts' => 'Read blog posts',
'write-posts' => 'Create and edit posts',
'delete-posts' => 'Delete posts',
]);
// Create token with specific scopes
$token = $user->createToken('Limited Token', ['read-posts'])->accessToken;
// Protect routes with scope middleware
Route::middleware(['auth:api', 'scope:write-posts'])->post('/posts', …);
2. Token Refresh:
Allow users to get new tokens without needing to log in again.
// In your controller
public function refresh(Request $request)
{
$request->user()->token()->revoke();
$token = $request->user()->createToken('auth_token')->accessToken;
return response()->json([
'access_token' => $token,
]);
}
3. Personal Access Tokens:
Use personal access tokens for simpler needs.
// Create a personal access token
$token = $user->createToken('My Token')->accessToken;
// These don't require client credentials
// Perfect for CLI tools or internal services
Conclusion
Laravel Passport makes adding OAuth2 authentication easy and secure. In this guide, we discussed:
- Understanding OAuth2 and its grant types
- Installing and configuring Passport
- Building a complete authentication API
- Implementing registration, login, and logout
- Protecting routes with middleware
- Testing your API
- Best security practices
- Real-world examples

Leave a comment