Laravel Sanctum - Sanctum merupakan Laravel official package yang menyediakan featherweight authentication system untuk SPA (Single Page applications), mobile applications dan API berbasis token sederhana. Sanctum memungkinkan setiap user aplikasi menghasilkan beberapa token API untuk akun mereka. Nah, token tersebut dapat diberikan kemampuan atau scope yang menentukan tindakan atau actions mana yang diizinkan untuk dilakukan oleh token tersebut.
Source: Laravel Sanctum
Di artikel ini, saya akan membagikan tutorial tentang penggunaan sanctum package untuk membuat Rest API Authentication di laravel 9. Tidak hanya itu, saya juga akan menjelaskan tentang bagaimana mengintegrasikan dengan Gmail dan Twilio, sehingga saat user register, maka otomatis juga akan mengirimkan welcome message ke email dan whatsapp user tersebut.
Note: Saya menggunakan Laragon, PHP v 8.1.3 dan Laravel v 9.3.1
Baiklah, mari langsung saja kita ke langkah-langkahnya π
Step 1: Install Laravel
//via Laravel Installer
composer global require laravel/installer
laravel new laravel-sanctum
//via Composer
composer create-project laravel/laravel laravel-sanctum
Langkah pertama yang harus kita lakukan tentu saja adalah menginstall laravel. Ada beberapa cara yang bisa dilakukan untuk menginstall laravel, diantaranya adalah dengan menggunakan composer atau laravel installer. Jika kamu sudah menginstall laravel installer, kamu bisa langsung saja menjalankan perintah laravel new laravel-sanctum. Dan jika kamu tidak menggunakan laravel installer atau terbiasa menggunakan composer, kamu bisa menjalankan perintah composer create-project laravel/laravel laravel-sanctum.
Setelah berhasil menginstall laravel, sekarang kita bisa menjalankan perintah php artisan serve, lalu buka pada browser dengan URL 127.0.0.1:{port} atau laravel-sanctum.test. Gambar di atas merupakan tampilan dari laravel starter.
Step 2: Set up Database
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel_sanctum
DB_USERNAME=root
DB_PASSWORD=
Oke, setelah menyelesaikan step pertama, lanjutkan dengan membuat database baru dan jangan lupa untuk menyesuaikan DB_DATABASE pada file .env.
Step 3: Install Laravel Sanctum
By default, versi terbaru Laravel sudah menyertakan Laravel Sanctum. Namun, jika pada file composer.json kamu tidak menyertakan laravel/sanctum, kamu dapat mengikuti petunjuk penginstalan di bawah ini.
composer require laravel/sanctum
Jalankan perintah seperti di atas untuk menginstall sanctum package pada laravel project.
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
Selanjutnya, kita bisa mempublikasikan Sanctum configuration dan migration file menggunakan perintah artisan vendor:publish. File sanctum config akan ditempatkan di direktori config.
Step 4: Set up Model & Migration
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('photo')->nullable();
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('phone_number');
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
}
Oke, selanjutnya kita perlu melakukan set up pada file users migration. Disini kita hanya perlu menambahkan dua column yaitu photo dan phone_number, dari beberapa column yang telah ada sebelumnya. Kenapa kita perlu menambahkan kedua column tersebut? Karena seperti yang telah saya jelaskan sebelumnya, pada artikel ini kita tidak hanya mengimplementasikan Sanctum authentication pada laravel 9, namun kita juga akan belajar bagaimana melakukan upload file dan mengirimkan welcome message dengan Gmail dan Twilio di Rest API Laravel 9.
php artisan migrate
Jika sudah menambahkan dua column tersebut, sekarang kita bisa menjalankan perintah artisan migrate untuk memigrasi file-file migration menjadi table-table di database yang telah kita buat sebelumnya.
protected $fillable = [
'photo',
'name',
'email',
'phone_number',
'password',
];
Karena kita mengubah file default users migration dari laravel, maka kita juga perlu menyesuaikannya pada file User model. Silahkan buka file models/User.php, tambahkan photo dan phone_number pada method $fillable.
Step 5: Set up Twilio
Pada step kelima ini, kita akan melakukan set up Twilio pada laravel project kita. Jika kamu belum mendaftar akun Twilio, silahkan melakukan pendaftaran terlebih dahulu di situs resmi Twilio.com atau silahkan klik link disini. Isi data pada beberapa input fields yang tersedia seperti First Name, Last Name, Email dan Password.
Karena akun Twilio yang saya gunakan merupakan akun trial, jadi disini saya akan menggunakan Twilio Testing Sandbox untuk mencoba mengirimkan welcome message ke whatsapp. Jika kamu sudah masuk ke halaman console Twilio, silahkan masuk ke menu Messaging > Try it out > Send a Whatsapp message. Kirim pesan whatsapp seperti yang telah dijelaskan pada halaman tersebut atau klik link pada text "click here".
Twilio Sandbox: β You are all set! The sandbox can now send/receive messages from whatsapp:+14155238xxx. Reply stop to leave the sandbox any time.
Jika kamu sudah mengirimkan pesan whatsapp ke nomor trial whatsapp Twilio dan menerima pesan dari Twilio seperti di atas, itu artinya kita sudah dapat menggunakan Twilio Testing Sandbox.
composer require twilio/sdk
Nah, sebelum mengimplementasi Twilio pada laravel project kita, ada hal yang harus kita lakukan yaitu menginstall Twilio SDK. Silahkan install Twilio SDK menggunakan perintah composer seperti di atas.
TWILIO_AUTH_SID="AC045b168ea3fad122bb8206dcbxxxxxxxx"
TWILIO_AUTH_TOKEN="cb6f96cd2e744f9b0811252053xxxxxxxx"
TWILIO_WHATSAPP_FROM="whatsapp:+141552388882"
Selanjutnya, kita perlu menambahkan beberapa record baru pada file .env kita. Tambahkan record seperti di atas pada file .env dan sesuaikan valuenya dengan data dari akun Twilio kamu.
Step 6: Set up Laravel Notification
Selain mengirimkan welcome message via whatsapp menggunakan layanan dari Twilio, di artikel ini saya juga akan menjelaskan bagaimana cara mengirimkan welcome message tersebut via email. Untuk email sendernya, disini saya akan menggunakan Gmail. Sebelum menggunakan Gmail sebagai email sender, pastikan pengaturan keamanan pada akun google kamu sudah dalam kondisi on untuk mengakses aplikasi yang kurang aman seperti gambar di atas.
MAIL_MAILER=smtp
MAIL_HOST=smtp.googlemail.com
MAIL_PORT=587
MAIL_USERNAME=mail@gmail.com
MAIL_PASSWORD=password
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=mail@gmail.com
MAIL_FROM_NAME="Divisidev"
Kemudian, sesuaikan Mail record pada file .env menjadi seperti contoh di atas. *Ganti valuenya dengan alamat dan password email kamu.
php artisan make:notification WelcomeEmailNotification
Kita lanjutkan untuk membuat notification class di laravel. Silahkan jalankan perintah artisan seperti di atas pada terminal. Perintah tersebut akan menempatkan notification class baru di direktori app/Notifications kita. Setiap notification class berisi method via dan sejumlah variabel method pembuatan pesan, seperti toMail atau toDatabase , yang mengubah notification menjadi pesan yang disesuaikan untuk chanel tertentu.
<?php
namespace App\Notifications;
use App\Models\User;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
class WelcomeEmailNotification extends Notification
{
use Queueable;
/**
* Create a new notification instance.
*
* @return void
*/
public function __construct(User $user)
{
$this->user = $user;
}
/**
* Get the notification's delivery channels.
*
* @param mixed $notifiable
* @return array
*/
public function via($notifiable)
{
return ['mail'];
}
/**
* Get the mail representation of the notification.
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage)
->greeting('Hello, '.$this->user->name)
->line('Welcome to Divisidev')
->action('Explore', url('/'))
->line('Thank you for using our application!');
}
/**
* Get the array representation of the notification.
*
* @param mixed $notifiable
* @return array
*/
public function toArray($notifiable)
{
return [
//
];
}
}
Selanjutnya, buka file app/Notifications/WelcomeEmailNotification.php dan sesuaikan kode yang ada menjadi seperti di atas. Disini kita menambahkan construct dan mendefinisikan teks pesan email pada method toMail.
Step 7: Set up Controller
php artisan make:controller API/AuthController
Oke, pada step ketujuh kita akan membuat file Controller baru yang nantinya akan kita gunakan untuk membuat logic-logic. Silahkan jalankan perintah artisan seperti di atas. Perintah tersebut akan membuatkan kita file AuthController.php yang terletak di direktori app/Http/Controllers/API.
<?php
namespace App\Http\Controllers\API;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Auth;
use Validator;
use App\Models\User;
use App\Notifications\WelcomeEmailNotification;
use Illuminate\Support\Facades\Storage;
use Twilio\Rest\Client;
class AuthController extends Controller
{
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'
]);
if($validator->fails()){
return response()->json($validator->errors());
}
$photo = $request->file('photo');
if ($photo) {
$fileName = time().'_'.$photo->getClientOriginalName();
$filePath = $photo->storeAs('images/users', $fileName, 'public');
}
$phone_number = $request['phone_number'];
if ($request['phone_number'][0] == "0") {
$phone_number = substr($phone_number, 1);
}
if ($phone_number[0] == "8") {
$phone_number = "62" . $phone_number;
}
$user = User::create([
'photo' => $filePath ?? null,
'name' => $request->name,
'email' => $request->email,
'phone_number' => $phone_number,
'password' => Hash::make($request->password)
]);
$this->whatsappNotification($user->phone_number, $user->name);
$user->notify(new WelcomeEmailNotification($user));
$token = $user->createToken('auth_token')->plainTextToken;
return response()
->json(['data' => $user,'access_token' => $token, 'token_type' => 'Bearer',]);
}
private function whatsappNotification($recipient, $userName)
{
$sid = env("TWILIO_AUTH_SID");
$token = env("TWILIO_AUTH_TOKEN");
$wa_from = env("TWILIO_WHATSAPP_FROM");
$twilio = new Client($sid, $token);
$body = 'Hello '.$userName.', welcome to Divisidev.';
return $twilio->messages->create("whatsapp:+$recipient",[
"from" => "$wa_from",
"body" => $body
]);
}
// method for login
public function login(Request $request)
{
if (!Auth::attempt($request->only('email', 'password')))
{
return response()
->json(['message' => 'Unauthorized'], 401);
}
$user = User::where('email', $request['email'])->firstOrFail();
$token = $user->createToken('auth_token')->plainTextToken;
return response()
->json(['message' => 'Hi '.$user->name.', welcome to home','access_token' => $token, 'token_type' => 'Bearer',]);
}
public function profile()
{
return response()->json(['message' => 'Your Profile','data' => Auth::user()]);
}
// method for profile update
public function update(Request $request)
{
$user = Auth::user();
$validator = Validator::make($request->all(),[
'name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users,email,'.$user->id,
'password' => 'nullable|string|min:8'
]);
if($validator->fails()){
return response()->json($validator->errors());
}
$photo = $request->file('photo');
if ($photo) {
Storage::delete('public/'.$user->photo);
$fileName = time().'_'.$photo->getClientOriginalName();
$filePath = $photo->storeAs('images/users', $fileName, 'public');
}
$phone_number = $request['phone_number'];
if ($request['phone_number'][0] == "0") {
$phone_number = substr($phone_number, 1);
}
if ($phone_number[0] == "8") {
$phone_number = "62" . $phone_number;
}
$user->update([
'photo' => $filePath ?? $user->photo,
'name' => $request->name,
'email' => $request->email,
'phone_number' => $phone_number,
'password' => $request->password ? Hash::make($request->password) : $user->password
]);
return response()->json(['message' => 'Data Updated Successfully','data' => $user]);
}
// method for user logout and delete token
public function logout()
{
auth()->user()->tokens()->delete();
return response()->json(['message' => 'You have logged out']);
}
}
Kemudian, buka file AuthController.php yang baru saja kita generate tersebut dan sesuaikan codenya menjadi seperti di atas. Pada AuthController ini kita mempunyai beberapa method diantaranya; register, whatsappNotification, profile, update, login dan logout. Method-method tersebut akan dijelaskan di bawah ini.
Register
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'
]);
if($validator->fails()){
return response()->json($validator->errors());
}
$photo = $request->file('photo');
if ($photo) {
$fileName = time().'_'.$photo->getClientOriginalName();
$filePath = $photo->storeAs('images/users', $fileName, 'public');
}
$phone_number = $request['phone_number'];
if ($request['phone_number'][0] == "0") {
$phone_number = substr($phone_number, 1);
}
if ($phone_number[0] == "8") {
$phone_number = "62" . $phone_number;
}
$user = User::create([
'photo' => $filePath ?? null,
'name' => $request->name,
'email' => $request->email,
'phone_number' => $phone_number,
'password' => Hash::make($request->password)
]);
$this->whatsappNotification($user->phone_number, $user->name);
$user->notify(new WelcomeEmailNotification($user));
$token = $user->createToken('auth_token')->plainTextToken;
return response()
->json(['data' => $user,'access_token' => $token, 'token_type' => 'Bearer',]);
}
Jadi, ketika method register ini dipanggil, maka yang pertama dilakukan adalah melakukan validasi dan memastikan bahwa name, email dan password sudah terisi. Jika request gagal divalidasi, maka akan mengirimkan response dengan data validasi error. Kemudian, method ini juga akan memeriksa apakah ada request photo, dan jika ada maka file tersebut akan ditempat di direktori storage/app/public/images/users dengan nama {time}_nama_asli_file. Selanjutnya, method ini masih juga melakukan pemeriksaan untuk request phone_number. Jika value awal dari request phone_numer 0 maka 0 akan dihapus dan diganti dengan 62. Jadi, misalnya ada request phone_number dengan value 082143232322, maka value yang akan dimasukkan ke database adalah 6282143232322.
Nah, selanjutnya semua request tersebut akan dimasukkan ke table users dan akan memanggil method whatsappNotification untuk mengirimkan whatsapp ke nomor telephone (phone_number) dan notify untuk mengirimkan welcome message via email ke user tersebut. Dan pada method register ini, saya juga akan sekalian melakukan generate token untuk akun user tersebut, begitu user tersebut berhasil melakukan register.
whatsappMessage
private function whatsappNotification($recipient, $userName)
{
$sid = env("TWILIO_AUTH_SID");
$token = env("TWILIO_AUTH_TOKEN");
$wa_from = env("TWILIO_WHATSAPP_FROM");
$twilio = new Client($sid, $token);
$body = 'Hello '.$userName.', welcome to Divisidev.';
return $twilio->messages->create("whatsapp:+$recipient",[
"from" => "$wa_from",
"body" => $body
]);
}
method ini berfungsi untuk mengirimkan whatsapp ke user dengan menggunakan layanan dari Twilio. Disini kita membutuhkan value dari variable recipient dan userName yang bisa kita dapatkan dari method register. Tidak lupa, disini kita juga menggunakan ID dari Twilio yang telah ke set up pada file .env.
Logout
public function logout()
{
auth()->user()->tokens()->delete();
return response()->json(['message' => 'You have logged out']);
}
Saat method ini dipanggil, maka akan menghapus token milik user tersebut dari database. Sehingga, jika user tersebut ingin mengakses halaman yang telah diproteksi dengan middleware auth:sanctum, dia harus login terlebih dahulu untuk mendapatkan access token lagi.
Step 8: Set up Route
<?php
use App\Http\Controllers\API\AuthController;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
Route::controller(AuthController::class)->group(function () {
Route::post('/register', 'register');
Route::post('/login', 'login');
Route::middleware('auth:sanctum')->group(function () {
Route::prefix('/profile')->group(function () {
Route::get('/', 'profile');
Route::post('/', 'update');
});
Route::post('/logout', 'logout');
});
});
Setelah selesai melakukan set up Controller, langkah selanjutnya atau pada langkah ke delapan ini, kita akan melakukan set up route. Silahkan buka file routes/api.php dan sesuaikan code yang ada menjadi seperti di atas. Disini saya menggunakan fitur terbaru di laravel 9 yaitu route group berdasarkan controller (AuthController).
Note: Jika beberapa route menggunakan controller yang sama, kita dapan menggunakan controller method untuk menentukan controller untuk semua route dalam group.
Selain itu, kita juga akan mengelompokkan route dalam group middleware auth:sanctum untuk route-route yang perlu diproteksi seperti get profile, update profile dan logout.
Step 8: Testing
Oke, setelah menyelesaikan langkah-langkah di atas, sekarang waktunya untuk pengujian. Untuk menguji Rest API authentication yang telah kita buat dengan Sanctum di laravel 9 ini, kita bisa menggunakan Postman.
Register
Pengujian yang pertama adalah menguji fitur register. Silahkan buka Postman, buat request baru dengan method Post, isi URL dengan 127.0.0.1:{port}/api/register atau laravel-sanctum.test/api/register. Kemudian pada tab Body, pilih type form-data dan tambahkan Key dan Value seperti gambar di atas, lalu klik Send. Jika request yang kamu kirimkan berhasil divalidasi, maka response yang akan diberikan akan seperti di bawah ini.
response
{
"data": {
"photo": "images/users/1646482837_divisidev-logo.png",
"name": "Hilmi",
"email": "hilmi@gmail.com",
"phone_number": "628214325xxxxx",
"updated_at": "2022-03-05T12:20:37.000000Z",
"created_at": "2022-03-05T12:20:37.000000Z",
"id": 1
},
"access_token": "1|gAjCy41db6fqIbyAtXKGhkZzEYNIp0QQ0Ebx0BjE",
"token_type": "Bearer"
}
Nah, seperti yang telah saya sebutkan pada step ketujuh. Jika user berhasil melakukan register, maka akan langsung digenerate access token. Kita akan membutuhkan token tersebut untuk mengakses route yang telah diproteksi dengan middleware auth:sanctum.
Token
1|gAjCy41db6fqIbyAtXKGhkZzEYNIp0QQ0Ebx0BjE
Token seperti diataslah yang akan dibutuhkan. Simpan token dari response yang kamu dapat.
Kemudian, cek email yang kamu gunakan saat melakukan register atau saat mengirimkan request-request register tadi. Seharusnya, kamu akan mendapatkan welcome message seperti gambar di atas.
Selain welcome message dalam bentuk email, kamu juga akan mendapatkan welcome message dalam bentuk pesan whatsapp. Jika kamu tidak mendapatkannya, pastikan value dari request phone_number yang kamu kirimkan bernilai nomor telephone yang sama dengan yang kamu daftarkan di Twilio.
Get Profile
Pengujian yang selanjutnya adalah melihat data profile user yang dibuat untuk authentication. Seperti yang telah saya jelaskan sebelumya, untuk route get profile ini telah kita proteksi menggunakan middleware auth:sanctum, sehingga untuk mengaksesnya, kita perlu menambahkan token yang telah kita dapatkan saat melakukan register atau login.
Silahkan buat request baru dengan method GET, isi URL dengan 127.0.0.1:{port}/api/profile atau laravel-sanctum.test/api/profile. Pada tab Authorization, pilih type Bearer Token dan isi tokennya dengan token yang telah didapatkan saat melakukan register atau login. Jika token sudah benar, klik Send, maka akan menampilkan response berupa data dari user tersebut seperti pada gambar di atas.
Update Profile
OK, Next. Kita akan melakukan pengujian pada endpoint update profile. Sama seperti pada endpoint get profile, pada update profile ini kita juga memerlukan token untuk mengaksesnya. Silahkan buat request baru dengan method POST, isi URL dengan 127.0.0.1:{port}/api/profile atau laravel-sanctum.test/api/profile. Pada tab Authorization, pilih type Bearer Token dan isi tokennya dengan token yang telah didapatkan saat melakukan register atau login.
Kemudian, buka tab Body dan pilih type form-data. Isi key dan value sesuai dengan apa yang ingin kamu ubah dari data profile tersebut, lalu klik Send. Jika request berhasil divalidasi maka data dari profile kamu akan berubah dan jika ada request photo baru, maka file lama yang ada storage juga akan dihapus dan akan digantikan dengan file baru.
Logout
Selanjutnya Kita akan melakukan pengujian pada endpoint logout. Sama seperti pada endpoint get profile dan update profile, pada endpoint logout ini kita juga memerlukan token untuk mengaksesnya. Silahkan buat request baru dengan method POST, isi URL dengan 127.0.0.1:{port}/api/logout atau laravel-sanctum.test/api/logout. Pada tab Authorization, pilih type Bearer Token dan isi tokennya dengan token yang telah didapatkan saat melakukan register atau login. Jika kita klik send, maka semua token yang dimiliki user tersebut pada table personal_access_tokens akan terhapus. Dan jika kita ingin mengakses get profile, update profile dan logout, kita perlu login kembali untuk mendapatkan token.
Login
Dan yang terakhir, kita akan melakukan pengujian pada endpoint login. Silahkan buat request baru dengan method POST, isi URL dengan 127.0.0.1:{port}/api/login atau laravel-sanctum.test/api/login. Kemudian, klik tab body dan isi key email dan password lalu klik Send. Jika request yang kamu kirimkan berhasil divalidasi, maka akan menampilkan response berisikan message dan bearer token seperti pada gambar di atas.
Kesimpulan
Kita telah sama-sama belajar bagaimana cara implementasi Sanctum package untuk membuat Rest API Authentication di Laravel 9. Tidak hanya itu, di artikel ini juga telah kita bahas bagaimana membuat welcome message dengan Gmail dan Twilio Whatsapp Service di Laravel 9. Pada dasarnya, penggunaan Sanctum package ini akan sangat dibutuhkan dan membantu saat kita bekerja dengan divisi Front End Developer dalam membangun suatu sistem yang terintegrasi atau saat kita membangun suatu sistem dengan Back End menggunakan Laravel sebagai framework dan Front End menggunakan stack seperti Next.js, Vue, Flutter dan lain-lain.
Cukup sekian artikel kali ini, semoga artikel ini dapat membantu teman-teman. Jika kalian punya cara lain, kritik, saran atau apapun itu yang ingin disampaikan, silahkan tulis pada form komentar di bawah ini. Sampai jumpa di artikel berikutnya.
Happy Coding Dev π¨βπ» π
π Full Documentation: Laravel Sanctum
Credit: Data illustrations by Storyset
Top comments (0)