Laravel ทำ JWT Authentication มีโค๊ดตัวอย่าง (Laravel 7.x) EP7

Sharing is caring!

JWT คืออะไร บทความนี้ไม่ขอกล่าว แต่แนะนำบทความนี้ อธิบายได้ละเอียดเลย “JSON Web Token มาตรฐานใหม่ ในการทำ Authentication” บทความที่ผมจะเขียนนี้จะพาทำ workshop ง่ายๆ แทบเหมือนว่า copy code จาก web “JSON Web Token Authentication for Laravel & Lumen” นี้มาเลยก็ว่าได้

ติดตั้ง Dependencies และ Config Project

  1. ต้องทำการติดตั้ง dependency ที่ชื่อว่า tymon/jwt-auth ด้วยคำสั่ง
$composer require tymon/jwt-auth

Using version ^1.0 for tymon/jwt-auth
./composer.json has been updated
Running composer update tymon/jwt-auth
Loading composer repositories with package information
Updating dependencies
...
[32mPackage manifest generated successfully.[39m
2 packages you are using are looking for funding.
Use the `composer fund` command to find out more!

2. รันคำสั่ง Publish the config เพื่อสร้างไฟล์ jwt.php config ไฟล์ ที่ config/jwt.php ให้อัตโนมัติเองหลังจากรันคำสั่ง

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

Copied File [\vendor\tymon\jwt-auth\config\config.php] To [\config\jwt.php]
Publishing complete.

3. รันคำสั่ง Generate secret key เพื่อ generate jwt key ในไฟล์ .env JWT_SECRET=? เพื่อเป็น key ตั้งต้นให้การ Generate Token ทำ authenticate token หลังรันคำสั่งตรวจสอบ secret key ที่ .env

$php artisan jwt:secret

jwt-auth secret [Wwt4F********************************************UNvQ14f] set successfully.

4. แก้ไข class User.php เพิ่ม implement JWTSubject

<?php

namespace App;

use Tymon\JWTAuth\Contracts\JWTSubject;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable implements JWTSubject
{
    use Notifiable;

    // Rest omitted for brevity

    /**
     * Get the identifier that will be stored in the subject claim of the JWT.
     *
     * @return mixed
     */
    public function getJWTIdentifier()
    {
        return $this->getKey();
    }

    /**
     * Return a key value array, containing any custom claims to be added to the JWT.
     *
     * @return array
     */
    public function getJWTCustomClaims()
    {
        return [];
    }
}

5. แก้ไข gaurds driver ของ api จากเดิม passport ไปเป็น jwt
– driver => jwt (jwt auth)
– provider => users (model auth user)

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

...

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

...
 'providers' => [
    'users' => [
      'driver' => 'eloquent',
      'model' => App\Models\User::class,
    ],

6. create table users

CREATE TABLE `users` (
  `id` bigint unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
  `email` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
  `email_verified_at` timestamp NULL DEFAULT NULL,
  `password` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
  `remember_token` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `created_at` timestamp NULL DEFAULT NULL,
  `updated_at` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `users_email_unique` (`email`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci

7. เพิ่ม basic authenticate route ที่ไฟล์ routes/api.php
– ‘middleware’ => ‘api’ (ประตูดัก request , response ของ route ที่มี pattern: /api/*)
– ‘prefix’ => ‘auth’ (prefix url ex: /api/auth/login )

Route::group([

    'middleware' => 'api',
    'prefix' => 'auth'

], function ($router) {


    Route::post('register', 'App\Http\Controllers\AuthController@register');
    Route::post('login', 'App\Http\Controllers\AuthController@login');
    Route::post('logout', 'App\Http\Controllers\AuthController@logout');
    Route::post('refresh', 'App\Http\Controllers\AuthController@refresh');
    Route::post('me', 'App\Http\Controllers\AuthController@me');

});

8. สร้าง AuthController สำหรับใส่ Auth Logic (login , logout , register , info)

$php artisan make:controller AuthController
<?php

namespace App\Http\Controllers;

use App\Models\User;
use Illuminate\Http\Request;

class AuthController extends Controller
{
  /**
   * Create a new AuthController instance.
   *
   * @return void
   */
  public function __construct()
  {
    $this->middleware('auth:api', ['except' => ['login', 'register']]);
  }

  public function register(Request $request)
  {
    $user = User::create([
      'name' => $request->name,
      'email' => $request->email,
      'password' => bcrypt($request->password),
    ]);

    $token = auth()->login($user);

    return $this->respondWithToken($token);
  }

  /**
   * Get a JWT via given credentials.
   *
   * @return \Illuminate\Http\JsonResponse
   */
  public function login()
  {
    $credentials = request(['email', 'password']);
    //return response()->json($credentials);
    if (!$token = auth()->attempt($credentials)) {
      return response()->json(['error' => 'Unauthorized'], 401);
    }

    return $this->respondWithToken($token);
  }

  /**
   * Get the authenticated User.
   *
   * @return \Illuminate\Http\JsonResponse
   */
  public function me()
  {
    return response()->json(auth()->user());
  }

  /**
   * Log the user out (Invalidate the token).
   *
   * @return \Illuminate\Http\JsonResponse
   */
  public function logout()
  {
    auth()->logout();

    return response()->json(['message' => 'Successfully logged out']);
  }

  /**
   * Refresh a token.
   *
   * @return \Illuminate\Http\JsonResponse
   */
  public function refresh()
  {
    return $this->respondWithToken(auth()->refresh());
  }

  /**
   * Get the token array structure.
   *
   * @param  string $token
   *
   * @return \Illuminate\Http\JsonResponse
   */
  protected function respondWithToken($token)
  {
    return response()->json([
      'access_token' => $token,
      'token_type' => 'bearer',
      'expires_in' => auth()->factory()->getTTL() * 60
    ]);
  }
}

9. ทดสอบระบบ
– [POST] http://127.0.0.1:8000/api/auth/register (ระบบจะสร้าง user ใน table users )
– [POST] http://127.0.0.1:8000/api/auth/login (ระบบเช็ค user ใน table users)
– [POST] http://127.0.0.1:8000/api/auth/me (ระบบแสดง user จาก bearer token )
– [POST] http://127.0.0.1:8000/api/auth/logout (ระบบ expired token ออกจากระบบ)

http://127.0.0.1:8000/api/auth/register
http://127.0.0.1:8000/api/auth/login
http://127.0.0.1:8000/api/auth/me (Bearer Token ด้วย)
http://127.0.0.1:8000/api/auth/logout (Bearer Token ด้วย)

สรุปท้ายบทความ

JWT เป็นเพียงการ Encode Data ที่จะกอบไปด้วย 3 ส่วนหลัก ๆ คือ Headers (เข้ารหัสแบบไหนอยู่ (เช่น SHA256, RSA)) ,Payload เป็นข้อมูลจริง ,Signature เอาไว้เช็คกับ Payload เป็นเพียงมาตรฐานเปิด (RFC 7519) ที่ช่วยเข้ามาแก้ไขโดยมีข้อดีหลัก ๆ 2 ข้อ คือขนาดไม่ใหญ่มาก ,ลักษณะการเก็บข้อมูลในตัวเอง

หากผู้อ่านท่านใดสงสัยหรืออยากที่จะแนะนำบทความ สามารถคอมเม้นทิ้งท้ายไว้ได้เลยครับ ^^

ใส่ความเห็น

อีเมลของคุณจะไม่แสดงให้คนอื่นเห็น ช่องข้อมูลจำเป็นถูกทำเครื่องหมาย *