laravel,

Laravel | JWT Authentication REST API

trannguyenhan trannguyenhan Follow Aug 10, 2022 · 7 mins read
Laravel | JWT Authentication REST API
Share this

Để xác thực người dùng qua API trong Laravel chúng ta sẽ sử dụng một thư viện của bên thú 3 là tymondesigns/jwt-auth.

Cài đặt

Trước hết, tạo một project và kết nối nó tới database. Sau đó cài đặt thư viện jwt-auth bằng composer:

composer require tymon/jwt-auth

Thêm các config mới vào config/app.php:

'providers' => [
    ....
    ....
    Tymon\JWTAuth\Providers\LaravelServiceProvider::class,
],
'aliases' => [
    ....
    'JWTAuth' => Tymon\JWTAuth\Facades\JWTAuth::class,
    'JWTFactory' => Tymon\JWTAuth\Facades\JWTFactory::class,
    ....
],

Chạy lệnh artisan để xuất bản các tệp cấu hình của thư viện:

php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\LaravelServiceProvider"

Sau khi chạy xong lệnh trên, quay lại thư mục config/ sẽ có thêm một file mới là jwt.php, là nơi đặt các file cấu hình của thư viện jwt-auth. Chúng ta không cần sửa bất cứ gì ở file này cả.

Tạo khóa bí mật bằng cách thực hiện lệnh sau:

php artisan jwt:secret

Sau khi chạy xong, quay lại file .env một biến môi trường mới được thêm vào file dạng JWT_SECRET={STRING}.

Cấu hình

Cập nhật Model User

Model user đã được tạo sẵn trong mỗi project Laravel. Giờ cần cập nhật để nó implement lại Tymon\JWTAuth\Contracts\JWTSubject và thêm vào 2 phương thức getJWTIdentifier()getJWTCustomClaims():

<?php

namespace App\Models;

use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
use Tymon\JWTAuth\Contracts\JWTSubject;

class User extends Authenticatable implements JWTSubject
{
    use HasApiTokens, HasFactory, Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var array<int, string>
     */
    protected $fillable = [
        'name',
        'email',
        'password',
    ];

    /**
     * The attributes that should be hidden for serialization.
     *
     * @var array<int, string>
     */
    protected $hidden = [
        'password',
        'remember_token',
    ];

    /**
     * The attributes that should be cast.
     *
     * @var array<string, string>
     */
    protected $casts = [
        'email_verified_at' => 'datetime',
    ];

    public function getJWTIdentifier()
    {
        return $this->getKey();
    }

    public function getJWTCustomClaims()
    {
        return [];
    }
}

Cấu hình Auth guard

Trong file config/auth.php, thực hiện một số thay đổi để Laravel sử dụng jwt xác thực cho ứng dụng và đặt default guard là api:

'defaults' => [
    'guard' => 'api',
    'passwords' => 'users',
],

...

'guards' => [
    'api' => [
        'driver' => 'jwt',
        'provider' => 'users',
    ],
],

Bây giờ chúng ta có thể sử dụng hệ thống Auth tích hợp sẵn của Laravel với jwt-auth.

Tạo route và AuthController

Thêm một số route vào routes/api.php như sau:

Route::group([
    'middleware' => 'api',
    'prefix' => 'auth'
], function () {
    Route::group(['middleware' => 'auth:api'], function(){
        Route::post('logout', [AuthController::class, 'logout']);
        Route::post('refresh', [AuthController::class, 'refresh']);
        Route::post('me', [AuthController::class, 'me']);
    });

    Route::post('login', [AuthController::class, 'login']);
    Route::post('register', [AuthController::class, 'register']);
});

Tạo AuthController bằng artisan command:

php artisan make:controller AuthController

Đặt đoạn mã sau vào trong Controller vừa tạo:

<?php

namespace App\Http\Controllers;

use App\Helper;
use App\Http\Requests\Auth\LoginRequest;
use App\Http\Requests\Auth\RegisterRequest;
use App\Models\User;
use Illuminate\Http\JsonResponse;

class AuthController extends Controller
{
    /**
     * Get a JWT via given credentials.
     *
     * @param LoginRequest $request
     * @return JsonResponse
     */
    public function login(LoginRequest $request): JsonResponse
    {
        $credentials = $request->only(['email', 'password']);

        if (! $token = auth()->attempt($credentials)) {
            return response()->json(['error' => 'Unauthorized'], 401);
        }

        return Helper::successResponseWithToken($token);
    }

    /**
     * Get the authenticated User.
     *
     * @return JsonResponse
     */
    public function me(): JsonResponse
    {
        return Helper::successResponse(auth()->user());
    }

    /**
     * Log the user out (Invalidate the token).
     *
     * @return JsonResponse
     */
    public function logout(): JsonResponse
    {
        auth()->logout();
        return Helper::successResponse();
    }

    /**
     * Refresh a token.
     *
     * @return JsonResponse
     */
    public function refresh(): JsonResponse
    {
        $newToken = auth()->refresh();
        return Helper::successResponseWithToken($newToken);
    }

    /**
     * Register new account
     * @param RegisterRequest $request
     * @return JsonResponse
     */
    public function register(RegisterRequest $request): JsonResponse
    {
        $data = $request->all();
        $data['password'] = bcrypt($data['password']);

        $user = new User();
        $user->fill($data);
        $user->save();

        return Helper::successResponse(true);
    }
}

Trong Controller sử dụng một số lớp bên ngoài như Helper, RegisterRequest, LoginRequest,… để xem đầy đủ bạn có thể xem trực tiếp project qua GITHUB: https://github.com/hacerweb/laravel-jwt-auth

Kiểm tra

Sau khi xong giờ mở Postman lên để kiểm tra API, với môi request hãy thêm 2 tham số như sau vào trong header:

{
    "Accept": "application/json",
    "Content-Type": "application/json"
}

Trong Postman chúng ta chỉ cần thêm vào như sau:

API đăng kí

API đăng nhập

API get-me

Với API này chỉ những người đã đăng nhập mới có thể sử dụng, vì vậy trước khi gọi, hãy bỏ token mà bạn vừa đăng nhập xong vào mục Auth->Bearer Token:

Sau đó gọi API để lấy kết quả:

Nếu không có token (hay gọi là chưa đăng nhập) thì kết quả trả về sẽ không thể lấy được thông tin người dùng:

Tham khảo: https://jwt-auth.readthedocs.io, https://www.positronx.io, https://github.com/hacerweb/

Join Newsletter
Get the latest news right in your inbox. We never spam!
trannguyenhan
Written by trannguyenhan Follow
Hi, i'm trannguyenhan