Laravel là PHP framework được rất nhiều các developer sử dụng trong các dự án web bởi tính vô cùng tiện lợi, gọn gàng, nhanh chóng, lại đi kèm một hệ sinh thái đầy đủ và mạnh mẽ. Không chỉ dừng lại ở một MVC framework đơn thuần, Laravel còn được sử dụng để xây dựng các dự án web service theo chuẩn RESTful vô cùng nhanh chóng.
Một trong những thao tác quan trọng khi xây dựng web service theo chuẩn RESTful chính là cơ chế xác thực API. Biết được điều này nên Laravel đã cho ra đời gói Laravel passport giúp việc xác thực API trở nên đơn giản hơn.
Tuy nhiên mình thấy phần tài liệu của Laravel passport hơi rườm rà khó hiểu, nên mình viết bài viết này nhằm chia sẻ tới các bạn cách tích hợp gói Laravel passport vào dự án Laravel như cách mình vẫn thường làm. Để bạn nào chưa rõ có thể tham khảo, bạn nào biết rồi có thể cho mình góp ý nhé.
Bài viết này mình sẽ sử dụng Laravel 5.5, tuy nhiên với các phiên bản Laravel 5.x khác cũng có cách tích hợp tương tự.
Mục lục
I. Cài đặt project Laravel
1.1 Kiểm tra PHP version
Laravel 5.5 yêu cầu phiên bản tối thiểu của là php 7.0.0. Nên trước khi cài đặt, chúng ta hãy kiểm tra phiên bản PHP trước bằng cách sử dụng command
php -v
Như trên máy của mình, thì sẽ có kết quả là
PHP 7.0.33-0ubuntu0.16.04.6 (cli) ( NTS ) Copyright (c) 1997-2017 The PHP Group Zend Engine v3.0.0, Copyright (c) 1998-2017 Zend Technologies with Zend OPcache v7.0.33-0ubuntu0.16.04.6, Copyright (c) 1999-2017, by Zend Technologies
Vậy là mình đang sử PHP 7.0.33, đủ yêu cầu của Laravel 5.5.
Bạn nào dùng phiên bản PHP nhỏ hơn có thể có cân nhắc giữa việc nâng cấp PHP hoặc sử dụng phiên bản laravel phiên bản thấp hơn nhé
1.2 Cài đặt Laravel 5.5 và tích hợp gói Laravel passport
Cài đặt dự án Laravel bằng cách sử dụng Composer
composer create-project --prefer-dist laravel/laravel blog "5.5.*"
Tích hợp Laravel passport vào dự án Laravel
cd blog composer require paragonie/random_compat:2.* composer require laravel/passport "4.0.*"
Publish các migrations của Laravel passport
php artisan vendor:publish --tag=passport-migration
Tạo database và cấu hình thông tin kết nối trong file .env
DB_CONNECTION=mysql DB_HOST=localhost DB_PORT=3306 DB_DATABASE=laravel_blog DB_USERNAME=root DB_PASSWORD=root
Chạy migrate để tạo các tables cần thiết trong database
php artisan migrate
II. Cấu hình Laravel passport
Tạo một số keys cần thiết cho Laravel passport
php artisan passport:install
Thêm trait Laravel\Passport\HasApiTokens cho model App\User
<?php
// app/User.php
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Laravel\Passport\HasApiTokens;
class User extends Authenticatable
{
use Notifiable, HasApiTokens;
//...
}
Mở class App\Providers\AuthServiceProvider, thêm Passport::routes() vào method boot()
<?php
// app/Providers/AuthServiceProvider.php
namespace App\Providers;
use Laravel\Passport\Passport;
use Illuminate\Support\Facades\Gate;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
class AuthServiceProvider extends ServiceProvider
{
//...
public function boot()
{
//...
Passport::routes();
//...
}
//...
}
Chỉnh driver cho api guard từ token thành passport trong config/auth.php
// config/auth.php 'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'users', ], 'api' => [ 'driver' => 'passport', 'provider' => 'users', ], ], //...
III. Tạo các endpoint cần thiết
Chúng ta sẽ lần lượt tạo các endpoint được tóm tắt trong bảng sau
method | URL | Middleware | Mô tả |
POST | /api/auth/login | Đăng nhập | |
POST | /api/auth/signup | Đăng ký tài khoản | |
DELETE | /api/auth/logout | api:auth | Đăng xuất |
GET | /api/auth/me | api:auth | Lấy thông tin user đang login |
Mở file routes/api.php, xóa hết nội dung và thay thế bằng
<?php
// routes/api.php
use Illuminate\Http\Request;
Route::group([
'prefix' => 'auth'
], function () {
Route::post('login', '[email protected]');
Route::post('signup', '[email protected]');
Route::group([
'middleware' => 'auth:api'
], function() {
Route::delete('logout', '[email protected]');
Route::get('me', '[email protected]');
});
});
Tạo AuthController bằng command sau
php artisan make:controller AuthController
Mở App\Http\Controllers\AuthController vừa tạo, xóa hết nội dung và thay thế bằng
<?php
// app/Http/Controllers/AuthController.php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Carbon\Carbon;
use App\User;
use Validator;
class AuthController extends Controller
{
public function signup(Request $request)
{
$validator = Validator::make($request->all(), [
'name' => 'required|string',
'email' => 'required|string|email|unique:users',
'password' => 'required|string|confirmed'
]);
if ($validator->fails()) {
return response()->json([
'status' => 'fails',
'message' => $validator->errors()->first(),
'errors' => $validator->errors()->toArray(),
]);
}
$user = new User([
'name' => $request->name,
'email' => $request->email,
'password' => bcrypt($request->password)
]);
$user->save();
return response()->json([
'status' => 'success',
]);
}
public function login(Request $request)
{
$validator = Validator::make($request->all(), [
'email' => 'required|string|email',
'password' => 'required|string',
'remember_me' => 'boolean'
]);
if ($validator->fails()) {
return response()->json([
'status' => 'fails',
'message' => $validator->errors()->first(),
'errors' => $validator->errors()->toArray(),
]);
}
$credentials = request(['email', 'password']);
if (!Auth::attempt($credentials)) {
return response()->json([
'status' => 'fails',
'message' => 'Unauthorized'
], 401);
}
$user = $request->user();
$tokenResult = $user->createToken('Personal Access Token');
$token = $tokenResult->token;
if ($request->remember_me) {
$token->expires_at = Carbon::now()->addWeeks(1);
}
$token->save();
return response()->json([
'status' => 'success',
'access_token' => $tokenResult->accessToken,
'token_type' => 'Bearer',
'expires_at' => Carbon::parse(
$tokenResult->token->expires_at
)->toDateTimeString()
]);
}
public function logout(Request $request)
{
$request->user()->token()->revoke();
return response()->json([
'status' => 'success',
]);
}
public function user(Request $request)
{
return response()->json($request->user());
}
}
IV. Thử nghiệm các api
Mình sẽ sử dụng Postman để thử các endpoint đã tạo ra ở phần trên.
Trong ảnh chụp dưới đây, mình deploy Laravel trên local với domain là http://laravel-blog.local, bạn nào không muốn deploy có thể chạy command sau
php artisan serve
Laravel server sẽ truy cập được ở http://localhost:8000 sau khi chạy command trên.
Bạn có thể bấm vào ảnh để xem rõ hơn nhé.
4.1 Endpoint đăng ký

Endpoint này bạn sẽ phải gửi các thông tin của tài khoản, bao gồm:
- name: Họ và tên
- email: Địa chỉ email sử dụng để đăng nhập
- password: Mật khẩu sử dụng để đăng nhập
- password_confirmation: Xác nhận mật khẩu
4.2 Endpoint đăng nhập

Trường email và password chính là hai thông tin mà bạn đã đăng ký ở endpoint trên.
Trong phần response của api này, có hai thông tin bạn cần chú ý là
- access_token: Đây là token sử dụng để xác thực tài khoản, bạn sẽ phải truyền token này trong header đối với các endpoint đi qua middleware api:auth
- token_type: Đây là loại token, mặc định nó sẽ là Bearer, bạn cũng phải truyền thông tin này trong header đối với các endpoint đi qua middleware api:auth
4.3 Endpoint lấy thông tin user đang login

Trong endpoint này, bạn hãy chú ý tới phần Header, mình có truyền lên hai thông tin quan trọng là
- Authorization: Là thông tin để xác thực tài khoản, nó chính là token_type và access_token.
- X-Requested-With: Có giá trị là XMLHttpRequest. Dựa vào thông này Laravel sẽ biết được là bạn đang gửi một XMLHttpRequest và có cách response phù hợp hơn.
Bất kỳ endpoint nào đi qua middleware api:auth đều phải truyền 2 thông tin Header như trên
4.4 Endpoint đăng xuất

Nếu thực hiện thành công api này, thì access_token sẽ bị vô hiệu hóa.
V. Kết luận
Bài viết chủ yếu là code nên các bạn phải đọc kỹ và copy cẩn thận. Để các bạn tiện theo dõi hơn thì toàn bộ source của bài này được mình để trên github tại repo laravel-api-authentication, các bạn có thể tham khảo thêm nếu muốn.
Bài viết được viết dựa trên kinh nghiệm cá nhân, xin nhận mọi gạch đá góp của các bạn.
(*) Request: Là các thông tin được gửi từ client tới server.
(*) Response: Là các thông tin và server trả về client.
(*) Header: Trong phạm vi bài viết này, Header chính là HTTP Header. Nó là một phần của request, hoặc response. Trong header thường chứa các thông tin mô tả về client (trong trường hợp gửi request), và chưa thông tin của server (trong trường hợp trả về response).