#38-Laravel API Autentikasi menggunakan JWT

Persiapan

  1. Install Laravel & Buat Proyek
  2. Buat Database laravel_api (MySQL)
  3. Setting Konfigurasi Laravel

Install & Setting JWT Package

composer require tymon/jwt-auth:dev-develop --prefer-source

Lalu buka config/app.php

Di bagian Provider tambahkan baris kode seperti di bawah ini :

Tymon\JWTAuth\Providers\LaravelServiceProvider::class;

Di Bagian Aliases tambahkan 2 baris kode seperti di bawah ini :

'JWTAuth' => Tymon\JWTAuth\Facades\JWTAuth::class, 
'JWTFactory' => Tymon\JWTAuth\Facades\JWTFactory::class,

Setelah itu publish JWT Packagenya dengan mengetik perintah :

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

Lalu buat jwt-auth secretnya dengan mengetik perintah

php artisan jwt:secret

Buat Model User

buka file Model User, lokasi filenya ada di app/User.php buatlah seperti di bawah ini :

<?php

namespace App;

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

class User extends Authenticatable implements JWTSubject
{
    use Notifiable;

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

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'password', 'remember_token',
    ];

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

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

Pada Laravel table user secara otomatis sudah ada dalam database migrate, kita langsung jalankan migrate, maka table users akan otomatis tercreate di database.

php artisan migrate

Buat User Controller

Ubah isi app/Http/Controllers/UserController.php

php artisan make:controller UserController
<?php

namespace App\Http\Controllers;

use App\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use JWTAuth;
use Tymon\JWTAuth\Exceptions\JWTException;

class UserController extends Controller
{
    public function login(Request $request)
    {
        $credentials = $request->only('email', 'password');
        try {
            if (! $token = JWTAuth::attempt($credentials)) {
                return response()->json(['error' => 'invalid_credentials'], 400);
            }
        } catch (JWTException $e) {
            return response()->json(['error' => 'could_not_create_token'], 500);
        }
        return response()->json(compact('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:6|confirmed',
        ]);

        if($validator->fails()){
            return response()->json($validator->errors()->toJson(), 400);
        }

        $user = User::create([
            'name' => $request->get('name'),
            'email' => $request->get('email'),
            'password' => Hash::make($request->get('password')),
        ]);
        $token = JWTAuth::fromUser($user);
        return response()->json(compact('user','token'),201);
    }

    public function getAuthenticatedUser()
    {
        try {
            if (! $user = JWTAuth::parseToken()->authenticate()) {
                return response()->json(['user_not_found'], 404);
            }
        } catch (Tymon\JWTAuth\Exceptions\TokenExpiredException $e) {
            return response()->json(['token_expired'], $e->getStatusCode());
        } catch (Tymon\JWTAuth\Exceptions\TokenInvalidException $e) {
            return response()->json(['token_invalid'], $e->getStatusCode());
        } catch (Tymon\JWTAuth\Exceptions\JWTException $e) {
            return response()->json(['token_absent'], $e->getStatusCode());
        }
        return response()->json(compact('user'));
    }
}

Buat Middleware

php artisan make:middleware JwtMiddleware

Ubah isi app/Http/Middleware/JwtMiddleware.php

<?php

namespace App\Http\Middleware;

use Closure;
use JWTAuth;
use Exception;
use Tymon\JWTAuth\Http\Middleware\BaseMiddleware;

class JwtMiddleware extends BaseMiddleware
{

    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        try {
            $user = JWTAuth::parseToken()->authenticate();
        } catch (Exception $e) {
            if ($e instanceof \Tymon\JWTAuth\Exceptions\TokenInvalidException){
                return response()->json(['status' => 'Token is Invalid']);
            }else if ($e instanceof \Tymon\JWTAuth\Exceptions\TokenExpiredException){
                return response()->json(['status' => 'Token is Expired']);
            }else{
                return response()->json(['status' => 'Authorization Token not found']);
            }
        }
        return $next($request);
    }
}

Tambahkan Konfigurasi Kernel

Setelah itu edit Kernel.php di app/http/Kernel.php di bagian $routeMiddleware tambahkan sebaris code berikut :

'jwt.verify' => \App\Http\Middleware\JwtMiddleware::class,

Route API

Tambahkan baris berikut pada routes/api.php

Route::post('register', 'UserController@register');
Route::post('login', 'UserController@login');
Route::get('book', 'BookController@book');

Route::get('bookall', 'BookController@bookAuth')->middleware('jwt.verify');
Route::get('user', 'UserController@getAuthenticatedUser')->middleware('jwt.verify');

Buat Book Controller

Book merupakan sebuah Page, yang berisi method book dan bookall, dimana book tidak memerlukan Autentikasi sementara bookall memerlukan autentikasi.

php artisan make:controller BookController

Berikut isi app/Http/Controllers/BookController.php

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Auth;

class BookController extends Controller
{
    public function book() {
        $data = "Data All Book";
        return response()->json($data, 200);
    }

    public function bookAuth() {
        $data = "Welcome " . Auth::user()->name;
        return response()->json($data, 200);
    }
}

Implementasi

Sekarang kita akan mencoba API yang telah kita buat :

Jalankan proyek laravel

php artisan serve

Buka API Tools dari Chrome, disini saya menggunakan Advanced REST client. Buka kedua url di bawah tanpa melakukan login

Request URL : http://localhost:8000/api/book

/book no-login Allow

Request URL : http://localhost:8000/api/bookall

/bookall no-login Not Allow

Lalu lakukan registrasi dan login untuk mencoba akses localhost:8000/api/bookall dengan link registrasi localhost:8000/api/register

POST register

Setelah registrasi coba melakukan login dengan email dan password yang sudah di daftarkan dengan link localhost:8000/api/login, setelah itu kita akan mendapat token, token tersebut akan kita gunakan untuk mengakses localhost:8000/api/bookall

Login

Setelah itu coba akses localhost:8000/api/bookall dengan menambahkan Bearer dan token di dalam header. Copy token yang di dapat saat melakukan login

bookall with Authorization

Coba juga untuk mengakses localhost:8000/api/user untuk mendapatkan informasi data user yang sedang login

User with Authorization

Catatan :

Untuk mengakses API dari proyek lain kita perlu untuk mengenable CORS protection menggunakan https://github.com/barryvdh/laravel-cors


Buat CRUD ToDos API

Buat Model + Migrate

php artisan make:model Todo -m

Ubah schema table todos

Schema::create('todos', function (Blueprint $table) {
    $table->bigIncrements('id');
    $table->integer('user_id');
    $table->char('title');
    $table->boolean('isCompleted');
    $table->timestamps();
});
php artisan migrate

Edit Model

protected $fillable= ['user_id','title','isCompleted'];

Membuat Routes

Sebelum mengatur method pada controller, kita tambahkan route resource pada routes/api.php

Route::resource('todo', 'TodoController')->middleware('jwt.verify');

Buat Controller CRUD

php artisan make:controller TodoController --resource

app/Http/Controllers/TodoController.php

<?php

namespace App\Http\Controllers;

use App\Todo;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use JWTAuth;
use Tymon\JWTAuth\Exceptions\JWTException;

class TodoController extends Controller
{
    public function index()
    {
        try {
            if (! $user = JWTAuth::parseToken()->authenticate()) {
                return response()->json(['user_not_found'], 404);
            }
        } catch (Tymon\JWTAuth\Exceptions\TokenExpiredException $e) {
            return response()->json(['token_expired'], $e->getStatusCode());
        } catch (Tymon\JWTAuth\Exceptions\TokenInvalidException $e) {
            return response()->json(['token_invalid'], $e->getStatusCode());
        } catch (Tymon\JWTAuth\Exceptions\JWTException $e) {
            return response()->json(['token_absent'], $e->getStatusCode());
        }
        $data=Todo::all();
        return response()->json($data);
    }

    public function create()
    {
        //
    }

    public function store(Request $request)
    {
        try {
            if (! $user = JWTAuth::parseToken()->authenticate()) {
                return response()->json(['user_not_found'], 404);
            }
        } catch (Tymon\JWTAuth\Exceptions\TokenExpiredException $e) {
            return response()->json(['token_expired'], $e->getStatusCode());
        } catch (Tymon\JWTAuth\Exceptions\TokenInvalidException $e) {
            return response()->json(['token_invalid'], $e->getStatusCode());
        } catch (Tymon\JWTAuth\Exceptions\JWTException $e) {
            return response()->json(['token_absent'], $e->getStatusCode());
        }
        
        $this->validate($request,[
            'user_id' => 'required',
            'title' => 'required',
        ]);
  
        Todo::create([
            'user_id' => $request->user_id,
            'title' => $request->title,
            'isCompleted' => 0
        ]);
        
        return response()->json(array('message'=>'Input Success'));
    }

    public function show($id)
    {
        //
    }

    public function edit($id)
    {
        //
    }

    public function update(Request $request, $id)
    {
        try {
            if (! $user = JWTAuth::parseToken()->authenticate()) {
                return response()->json(['user_not_found'], 404);
            }
        } catch (Tymon\JWTAuth\Exceptions\TokenExpiredException $e) {
            return response()->json(['token_expired'], $e->getStatusCode());
        } catch (Tymon\JWTAuth\Exceptions\TokenInvalidException $e) {
            return response()->json(['token_invalid'], $e->getStatusCode());
        } catch (Tymon\JWTAuth\Exceptions\JWTException $e) {
            return response()->json(['token_absent'], $e->getStatusCode());
        }
        
        $this->validate($request,[
            'user_id' => 'required',
            'title' => 'required',
        ]);
        
        $row=Todo::find($id);
        $row->user_id = $request->user_id;
        $row->title = $request->title;
        $row->isCompleted = $request->isCompleted==1?1:0;
        $row->save();
        
        return response()->json(array('message'=>'Update Success'));
    }

    public function destroy($id)
    {
        try {
            if (! $user = JWTAuth::parseToken()->authenticate()) {
                return response()->json(['user_not_found'], 404);
            }
        } catch (Tymon\JWTAuth\Exceptions\TokenExpiredException $e) {
            return response()->json(['token_expired'], $e->getStatusCode());
        } catch (Tymon\JWTAuth\Exceptions\TokenInvalidException $e) {
            return response()->json(['token_invalid'], $e->getStatusCode());
        } catch (Tymon\JWTAuth\Exceptions\JWTException $e) {
            return response()->json(['token_absent'], $e->getStatusCode());
        }
        
        $row=Todo::find($id);
        $row->delete();
        
        return response()->json(array('message'=>'Delete Success'));
    }
}

Sumber :

  1. https://medium.com/@newrey9227/belajar-autentikasi-api-di-laravel-menggunakan-jwt-c8c52d82e9d4

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>