Otentikasi Menggunakan Google Two Factor di Laravel

Otentikasi Menggunakan Google Two Factor di Laravel

Laravel adalah Framework yang sangat menakjubkan dimana kita dapat membuat aplikasi dengan sangat menyenangkan. Salah satu fitur yang menarik dari Laravel adalah menyediakan metode untuk membuat proses user otentikasi dengan sangat mudah. Hal ini mencakup proses registrasi bahkan pada tahap reset password sekalipun. Namun, sebagai seorang programmer, imajinasi kita dalam memikirkan sebuah system yang sangat kompleks tentu saja tidak bisa dibatasi hanya pada ruang lingkup yang telah disediakan oleh Framework itu sendiri.

Daya khayal dari imajinasi kita membuat kita memikirkan fitur lainnya untuk menyempurnakan apa yang telah disediakan oleh Framework itu sendiri, terkhusus pada kasus kali ini dalam ruang lingkup otentikasi user. Meski secara default Laravel telah menyediakan fitur tersebut secara kompleks namun kita membutuhkan metode lain untuk melengkapi sistem tersebut, salah satunya adalah dengan menambahkan Google Two Factor Authentication.

Two Factor Authentication (2FA) menjadi pewarna dari proses otentikasi untuk mengamankannya dari berbagai macam hal terkait keamanan, sistem ini menggunakan dua metode (atau sering juga disebut sebagai factor) untuk memverifikasi identitas user. Two factor authentication mengamankan dari serangan berupa phising, social engineering, password brute force dan lain sebagainya.

Pada tutorial kali ini kita akan belajar bersama bagaimana menambahkan method two factor authentication pada sistem otentikasi Laravel. Kita akan menggunakan Google Authenticator dan mengimplementasikan algoritma Time-base One-time Password (TOTP).

Untuk menggunakan metode two factor authentication, user harus menginstall Google Authenticator pada perangkat yang akan digunakan untuk proses verifikasi. Berikut list app yang dapat digunakan:

  1. Authy for iOS, Android, Chrome, OS X

  2. FreeOTP for iOS, Android, dan Pebble

  3. Google Authenticator for iOS

  4. Google Authenticator for Android

  5. Google Authenticator (port) on WIndows Store

  6. Microsoft Authenticator for Windows Phone

  7. LassPass Authenticator for iOS, Android, OS X, Windows

  8. 1Password form iOS, Android, OS X, Windows

Tahap Persiapan

Pada case kali ini kita akan mencoba atau bereksperimen menggunakan Laravel 5.5 fresh install, maka sebelum memulainya install Laravel terlebih dahulu.

composer create-project --prefer-dist laravel/laravel 2fa

Saat ini kita telah memiliki Laravel 5.5 fresh install, langkah selanjutnya adalah melakukan konfigurasi database, maka buka file .envlalu lakukan modifikasi pada bagian informasi database:

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=2fa
DB_USERNAME=root
DB_PASSWORD=toor

Agar lebih serentak kita akan menggunakan server command dari Laravel sehinga URL yang akan kita akses menjadi : localhost:8000

php artisan serve

Jangan lupa untuk melakukan perubahan pada bagian berikut ini dalam file .env

APP_URL=http://localhost:8000

Konfigurasi Otentikasi

Sebagaimana yang telah kita bahas diawal bahwa Laravel hadir dengan fitur yang sangat menarik terkhusus fitur authentication, maka untuk membuat fitur tersebut cukup dengan magic command yang akan meng-generate apa saja yang dibutuhkan untuk proses otentikasi, meliputi routes, controller, views, dll :

php artisan make:auth
​
//buat table yang dibutuhkan dengan command
php artisan migrate

Sampai pada tahap ini kita telah memiliki sistem otentikasi yang dapat anda akses pada URL: http://localhost:8000/register dan http://localhost:8000/login. Akan tetapi ini adalah fitur bawaan dari Laravel itu sendiri, maka tahap selanjutnya kita akan menambahkan fitur two factor authentication dengan cakupan sebagai berikut:

  1. Ketika user melakukan registrasi, kita akan meng-generate user secret untuk authenticator

  2. Pada request selanjutnya, kita akan menggunakan user secret tersebut untuk menampilkan QR Code yang dapat digunakan user untuk melakukan identifikasi pada Google Authenticator.

  3. Ketika user meng-klik "OK", sistem akan mencatat data user beserta Google Authenticator secret mereka.

Dengan menggunakan metode ini, halaman QR Code hanya dapat diakses satu kali. Jika user ingin mengatur two factor authentication lagi, maka mereka harus mengulangi rangkaian prosesnya dari awal dan menghapus user secret yang lama.

Untuk mencapainya, kita akan melakukan pengaturan Google authenticator sebelum mendaftarkan user kedalam database. Untuk mengubah alur registrasi, kita harus mendefinisikan method register pada RegisterController (Dapat anda temukan di app/Http/Controllers/Auth/RegisterController).

Konfigurasi Two Factor Authentication

Sebelum kita melakukan perubahan pada method register, maka yang perlu kita lakukan terlebih dahulu adalah menginstall 2 package berikut:

composer require pragmarx/google2fa-laravel
composer require bacon/bacon-qr-code

Karena kita menggunakan Laravel 5.5, maka tidak perlu untuk mendaftarkan package tersebut karena di Laravel 5.5 telah menggunakan fitur Auto-Discovery. Jika anda menggunakan Laravel versi sebelumnya, maka silahkan definisikan package tersebut pada config/app.php. Selanjutnya, publish file config dengan command:

php artisan vendor:publish --provider=PragmaRX\\Google2FALaravel\\ServiceProvider

Buka file app/Http/Controllers/Auth/RegisterController.php kemudian tambahkan use statement Request :

use Illuminate\Http\Request;

Kemudian buat method register pada file RegisterController

public function register(Request $request)
    {
        //validasi request
        $this->validator($request->all())->validate();
​
        // Initialise the 2FA class
        $google2fa = app('pragmarx.google2fa');
​
        // Menyimpan data registrasi kedalam Array
        $registration_data = $request->all();
​
        // Menambahkan secret key kedalam data registrasi
        $registration_data["google2fa_secret"] = $google2fa->generateSecretKey();
​
        // Menyimpan data registrasi kedalam session user 
        $request->session()->flash('registration_data', $registration_data);
​
        // Generate the QR image. User dapat men-scan QR Code tersebut menggunakan app yang telah di install
        // Untuk mengatur two factor authentication
        $QR_Image = $google2fa->getQRCodeInline(
            config('app.name'),
            $registration_data['email'],
            $registration_data['google2fa_secret']
        );
​
        // Passing the QR barcode image to view
        return view('google2fa.register', ['QR_Image' => $QR_Image, 'secret' => $registration_data['google2fa_secret']]);
    }

Untuk menampilkan QR Code, maka kita harus membuat sebuah view. Pada method register kita telah mendefinisikan sebuah view dengan nama register.blade.php dalam folder google2fa, jadi pada resources/views buat sebuah folder google2fa dan didalamnnya sebuah file register.blade.php

Maka path yang akan kita dapatkan adalah resources/views/google2fa/register.blade.php kemudian tambahkan code berikut kedalam view yang telah kita buat:

@extends('layouts.app')
​
@section('content')
<div class="container">
    <div class="row">
        <div class="col-md-8 col-md-offset-2">
            <div class="panel panel-default">
                <div class="panel-heading">Google Authenticator</div>
​
                <div class="panel-body" style="text-align: center;">
                    <p>Anda dapat menggunakan two factor authentication dengan melakukan scan pada barcode dibawah. Alternatif lainnya, anda dapat menggunakan code berikut: {{ $secret }}</p>
                    <div>
                        <img src="{{ $QR_Image }}">
                    </div>
                    <p>Anda harus mengatur Google Authenticator app sebelum melanjutkan.</p>
                    <div>
                        <a href="/complete-registration"><button class="btn-primary">Selesaikan Pendaftaran</button></a>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
@endsection

Sampai pada tahap ini, seharusnya setelah melakukan registrasi, user akan dibawa pada halaman untuk menampilkan QR Code dan Secret key yang relevan. Tampilan yang akan disuguhkan akan tampak seperti ini:

Kemudian google Google Authenticator untuk scanning barcode agar anda bisa meng-generate OTP yang dapat digunakan untuk proses login.

Registrasi User

Pada tahap diatas kita telah sampai pada proses menampilkan QR Code, namun saat tombol ditekan maka kita akan menemukan error karena URL yang diakses belum didefinisikan pada route untuk meng-handle proses tersebut. Namun, sebelum kita menyelesaikan problem tersebut, kita haru membuat column untuk Google two factor authentication untuk menyimpan secret key kedalam users table. Maka silahkan buat sebuah migration dengan command:

php artisan make:migration add_google2fa_column_to_users --table=users

Kemudian lakukan modifikasi migration tersebut sehingga akan tampak seperti ini:

<?php
​
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
​
class AddGoogle2faColumnToUsers extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('users', function (Blueprint $table) {
            $table->text('google2fa_secret');
        });
    }
​
    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table('users', function (Blueprint $table) {
            $table->dropColumn('google2fa_secret');
        });
    }
}

Migration diatas menginstruksikan untuk menambahkan column baru dengan nama google2fa_secret kedalam table users. Maka jangan lupa untuk menjalankan command migrate:

php artisan migrate

Melanjutkan flow dari proses registrasi, kita akan melakukan perubahan pada file RegisterController pada bagian trait RegistersUsers, lakukan perubahan berikut:

use RegistersUsers;

Menjadi:

use RegistersUsers {
    register as registration;
}

Selanjutnya, definisikan route complete-registration dengan menambahkan route berikut pada routes/web.php

Route::get('/complete-registration', 'Auth\RegisterController@completeRegistration');

Kemudian buat method dengan nama completeRegistration pada controller RegisterController

public function completeRegistration(Request $request)
{        
    $request->merge(session('registration_data'));
    return $this->registration($request);
}

Tentu saja, secara default otentikasi Laravel hanya menyimpan data yang meliputi name, email dan password. Padahal sebelumnya kita telah menambahkan column google2fa_secret, maka lakukan modifikasi pada method create didalam file RegisterController :

protected function create(array $data)
{
    return User::create([
        'name' => $data['name'],
        'email' => $data['email'],
        'password' => bcrypt($data['password']),
        'google2fa_secret' => $data['google2fa_secret'],
    ]);
}

Kita juga harus mengubah model User pada properti fillable dengan menambahkan google2fa_secret sekaligus menyembunyikannya ketika ditampilkan dalam bentuk Array atau JSON.

protected $fillable = [
    'name', 'email', 'password', 'google2fa_secret',
];
​
protected $hidden = [
    'password', 'remember_token', 'google2fa_secret',
];

Sampai pada tahap ini sebenarnya tidak ada masalah dan dapat berjalan sebagaimana mestinya, tapi untuk keamanan tambahan, kita dapat meng-encrypt google2fa_secret dan untuk melakukannya tambahkan method berikut kedalam model User:

public function setGoogle2faSecretAttribute($value)
{
     $this->attributes['google2fa_secret'] = encrypt($value);
}
​
public function getGoogle2faSecretAttribute($value)
{
    return decrypt($value);
}

Note: untuk memahami cara kerja dari kedua method diatas, anda dapat membaca artikel tentang Accessors dan Mutators

Login User

Tahap ini merupakan puncak dari pemabahasan kita dalam artikel ini, sebab jika tahap ini sampai dilewatkan maka apa yang telah kita lakukan sebelumnya tidak ada artinya sebab secara default kita masih dapat login kedalam app menggunakan email dan password sebagaimana mestinya.

Padahal tujuan kita menambahkan fitur ini adalah agar user menggunakan Google Authenticator code sebelum dapat mengakses halaman sepenuhnya. Maka best practice yang dapat digunakan adalah dengan menambahkan middleware. Menariknya, package pragmarx/google2fa-laravel telah menyediakan middleware yang dapat digunakan.

Untuk menggunakannya maka tambahkan code berikut kedalam array routeMiddleware pada file app/Http/Kernel.php

protected $routeMiddleware = [
    ...
    '2fa' => \PragmaRX\Google2FALaravel\Middleware::class,
];

Dengan cara ini, kita dapat menggunakan middleware 2fa kapanpun dibutuhkan, baik didalam file route atau didalam controller. Selanjutnya, kita harus mendefinisikan ke dalam view dimana user harus memasukkan OTP setelah melakukan login. Secara default, kofigurasi tersebut menggunakan view resources/views/google2fa/index.blade.php , maka buat file tersebut dan tambahkan code berikut:

@extends('layouts.app')
​
@section('content')
<div class="container">
    <div class="row">
        <div class="col-md-8 col-md-offset-2">
            <div class="panel panel-default">
                <div class="panel-heading">Registrasi</div>
​
                <div class="panel-body">
                    <form class="form-horizontal" method="POST" action="{{ route('2fa') }}">
                        {{ csrf_field() }}
​
                        <div class="form-group">
                            <label for="one_time_password" class="col-md-4 control-label">One Time Password</label>
​
                            <div class="col-md-6">
                                <input id="one_time_password" type="number" class="form-control" name="one_time_password" required autofocus>
                            </div>
                        </div>
​
                        <div class="form-group">
                            <div class="col-md-6 col-md-offset-4">
                                <button type="submit" class="btn btn-primary">
                                    Login
                                </button>
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>
@endsection

Untuk menangani OTP yang diinput user, kita membuatkan sebuah route yang akan mengerjakan proses tersebut. Dimana flow-nya, middleware melakukan pengecekan pada OTP tersebut, maka kita hanya perlu menggunakan middleware tersebut setelah mendefinisikan route dan melakukan redirect kehalaman sebelumnya. Buka file routes/web.php kemudian tambahkan code berikut:

Route::post('/2fa', function () {
    return redirect(URL()->previous());
})->name('2fa')->middleware('2fa');

Dengan memanfaatkan middleware 2fa kita dapat menverifikasi halaman mana saja yang akan kita lindungi dengan menggunakan two factor authentication dengan memanggil middleware tersebut pada controller yang dituju. Sebagai contoh pada HomeController.php :

public function __construct()
{
    $this->middleware('auth');
}

Menjadi:

public function __construct()
{
   $this->middleware(['auth', '2fa']);
}

Jadi ketika user melakukan login, kemudian di arahkan ke halaman /home maka user harus memasukkan one-time password dari google authenticator. Adapun tampilannya akan tampak seperti ini:

Setelah memasukkan OTP, maka user diizinkan untuk mengakses halaman tersebut.

Re-Authentication User

Kadangkala user akan menemukan case dimana dia merasa OTP seseorang telah mendapatkan akses untuk meng-generate OTP yang dimilikinya, jadi dia ingin membuat yang baru. Maka kita perlu membuat fitur tambahan yakni re-authenticate agar user dapat menggantinya tanpa harus menghubungi kita. Maka untuk melakukannya tambahkan route berikut:

Route::get('/re-authenticate', 'HomeController@reauthenticate');

Lalu pada HomeController.php tambahkan method reauthenticate:

public function reauthenticate(Request $request)
{
    // Cek User Login
    $user = \Auth::user();
​
    // initialise the 2FA class
    $google2fa = app('pragmarx.google2fa');
​
    // generate secret key baru untuk user
    $user->google2fa_secret = $google2fa->generateSecretKey();
​
    // memperbaharui data user
    $user->save();
​
    // generate the QR image
    $QR_Image = $google2fa->getQRCodeInline(
        config('app.name'),
        $user->email,
        $user->google2fa_secret
    );
​
    // Passing the QR barcode image ke view.
    return view('google2fa.register', ['QR_Image' => $QR_Image, 
                                        'secret' => $user->google2fa_secret,
                                        'reauthenticating' => true
                                    ]);
}

Pada method diatas, kita menggunakan view yang telah ada, namun kita membutuhkan beberapa perubahan untuk menambahkan kondisi sesuai yang dilakukan oleh user. Edit file resources/views/google2fa/register.blade.php menjadi seperti berikut:

@extends('layouts.app')
​
@section('content')
<div class="container">
    <div class="row">
        <div class="col-md-8 col-md-offset-2">
            <div class="panel panel-default">
                <div class="panel-heading">Google Authenticator</div>
​
                <div class="panel-body" style="text-align: center;">
                    <p>Anda dapat menggunakan two factor authentication dengan melakukan scan pada barcode dibawah. Alternatif lainnya, anda dapat menggunakan code berikut: {{ $secret }}</p>
                    <div>
                        <img src="{{ $QR_Image }}">
                    </div>
                    @if (!@$reauthenticating)
                    <p>Anda harus mengatur Google Authenticator app sebelum melanjutkan.</p>
                    <div>
                        <a href="/complete-registration"><button class="btn-primary">Selesaikan Pendaftaran</button></a>
                    </div>
                    @endif
                </div>
            </div>
        </div>
    </div>
</div>
@endsection

Untuk mengakses halaman re-authenticate, maka gunakan url http://localhost:8000/re-authenticate dan anda juga dapat menambahkan link pada menu navigasi untuk memudahkan user.

Kesimpulan

Pada case ini kita telah belajar bersama bagaimana menambahkan fitur two factor authentication kedalam proses otentikasi Laravel, mengubah flow registrasi dan login. Dengan keterampilan yang telah kita pelajari bersama ini kita dapat mengembangkan lebih lanjut untuk membuat fitur yang lebih kompleks.

Nah bagi kamu yang ingin mendownload source codenya, silahkan clone repo : github

Category:
Share:

Comments