Google Authentication With Laravel 5.8

Google Authentication With Laravel 5.8

Pendahuluan

Otentikasi menjadi gerbang utama sekaligus protector yang biasanya digunakan untuk melindungi data atau membatasi akses pada aplikasi terkait. Ada beragam jenis dan cara otentikasi yang tersedia, salah satunya adalah menggunakan akun google (gmail). Cara ini memudahkan kita untuk melakukan proses sync terhadap akun google yang telah login di-browser sehingga user tidak perlu melakukan otentikasi dengan mengisi form login lagi.

Salah satu package yang telah disediakan oleh Laravel untuk mempermudah proses tersebut adalah dengan menggunakan Socialite, fitur ini memungkinkan pengguna untuk membuat berbagai macam proses otentikasi dengan menggunakan sosial media yang ada seperti Twitter, Facebook, Github dan atau Google+ (Google Account).

Baca Juga: Membuat Repository Pattern Laravel 5.7

Schema Database

Mengikuti perkembangan versi Laravel saat artikel ini dibuat, maka tahap pertama install Laravel 5.8 terlebih dahulu menggunakan command:

composer create-project --prefer-dist laravel/laravel dw-socialite

Sedangkan untuk mempercepat proses pembuatan struktur view dari login page, maka kita akan menggunakan artisan make:auth, dari command line, masuk ke dalam folder project yang baru saja di-install:

# cd dw-socialite

Kemudian jalankan artisan command berikut:

php artisan make:auth

Artisan command diatas akan men-generate seluruh view yang dibutuhkan untuk proses register dan otentikasi, sehingga kita tidak perlu membuatnya secara manual karena tujuan dari artikel ini adalah untuk memahami bagaimana cara membuat fitur otentikasi menggunakan Socialite khususnya fungsi otentikasi menggunakan akun Google.

Adapun schema database yang diperlukan adalah dengan melakukan sedikit modifikasi pada table users yang akan digunakan untuk menyimpan data user yang telah melakukan sync dengan google account mereka. Buka command line, kemudian generate migration berikut untuk menambahkan beberapa field tersebut.

php artisan make:migration add_field_socialite_to_users_table

Buka file migration yang baru saja di-generate, file tersebut berada di dalam folder database/migrations dan modifikasi menjadi:

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class AddFieldSocialiteToUsersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('users', function (Blueprint $table) {
            $table->string('socialite_id')->nullable()->after('id');
            $table->string('socialite_name')->nullable()->after('socialite_id');
            $table->string('photo')->nullable()->after('socialite_name');
            $table->string('password')->nullable()->change();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table('users', function (Blueprint $table) {
            $table->dropColumn('socialite_id');
            $table->dropColumn('socialite_name');
            $table->dropColumn('photo');
        });
    }
}

Penjelasan: Ada 3 field baru yang ditambahkan, pertama socialite_id untuk menyimpan unik ID dari Google, kedua socialite_name untuk menyimpan nama platform yang digunakan dan yang terakhir adalah photo untuk menyimpan uri dari image profile akun yang telah di-sync. Adapun password diubah jadi nullable karena otentikasi menggunakan sosial media tidak membutuhkan password karena akun dari sosial media tersebut sudah melakukan otentikasi pada platform masing-masing.

Jangan lupa untuk memastikan kamu telah menyesuaikan informasi database yang kamu miliki, buat file .env kemudian lengkapi bagian berikut

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=dw_socialite
DB_USERNAME=USERDBANDA
DB_PASSWORD=PASSWORDDBANDA

Sebelum melakukan migrate, dibutuhkan sebuah package agar method change() dapat berjalan, package tersebut adalah doctrine/dbal. Pada command line, install package tersebut

composer require doctrine/dbal

Apabila proses instalasi telah selesai, migrate struktur database yang kamu miliki dengan command:

php artisan migrate

laravel 5.8 socialite

Terakhir, buka file app/User.php kemudian tambahkan socialite_id dan socialite_name pada property hidden dengan alasan security.

//[.. CODE SEBELUMNYA ..]

protected $fillable = [
    'name', 'email', 'password', 'photo'
];

protected $hidden = [
    'password', 'remember_token', 'provider_name', 'provider_id'
];

Install & Konfigurasi Socialite

Tiba saatnya untuk menyelesaikan fitur yang diinginkan menggunakan package Socialite, pada command line, install package tersebut dengan command:

composer require laravel/socialite

Selanjutnya lakukan konfigurasi untuk platform apa saja yang akan digunakan, dalam hal ini adalah Google maka tambahkan konfigurasi untuk Google Account. Buka file config/service.php kemudian tambahkan code berikut:

//[.. CODE SEBELUMNYA ..]
'stripe' => [
    'model' => App\User::class,
    'key' => env('STRIPE_KEY'),
    'secret' => env('STRIPE_SECRET'),
    'webhook' => [
        'secret' => env('STRIPE_WEBHOOK_SECRET'),
        'tolerance' => env('STRIPE_WEBHOOK_TOLERANCE', 300),
    ],
],

//TAMBAHKAN CODE INI
'google' => [
    'client_id' => env('GOOGLE_CLIENT_ID'),
    'client_secret' => env('GOOGLE_CLIENT_SECRET'),
    'redirect' => env('GOOGLE_REDIRECT_CALLBACK'),
],

Perhatikan value dari client_id, client_secret dan redirect semuanya merujuk ke file .env, maka buka file tersebut dan tambahkan code berikut:

GOOGLE_CLIENT_ID=**********SECRETANDA.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=*******SECRETANDA
GOOGLE_REDIRECT_CALLBACK=http://localhost:8000/google/callback

Lalu pertanyaannya, darimana kita mendapatkan CLIENT_ID dan CLIENT_SECRET? Google telah menyediakannya dengan tujuan untuk menggunakan layanan mereka, buka page Google Sign-in dan lakukan beberapa konfigurasi berikut.

Pertama, klik Configure a Project pada halaman Integrating Google Sign-in.

create google sign in laravel

Pastikan kamu telah melakukan otentikasi untuk akun Google, kemudian sebuah modal akan ditampilkan untuk memilih project yang ada atau create new project dan masukkan nama project yang diinginkan.

create new project google sign-in

Kemudian klik Next dan isi setiap permintaan dari form yang disediakan. Hingga pada tahap akhir, kamu akan menemukan halaman yang berisi informasi Client_id dan Client_secret, copy keduanya dan masukkan ke dalam file .env.

Buka halaman API Console, kemudian pilih project yang telah kamu buat dan klik Open.

select project google sign-in

Lalu dari sidebar menu, pilih Credentials, kemudian klik icon pensil untuk mengedit account yang ada.

list account google sign-in

Lakukan konfigurasi berikut dengan memasukkan http://localhost:8000 pada bagian Authorized Javascript Origins. Sedangkan pada bagian Authorized redirect URIs tambahkan http://localhost:8000 dan http://localhost:8000/google/callback

config google sign-in laravel

Authenticate With Google Account

Untuk membuat fungsi authenticate, dibutuhkan beberapa tahap, pertama adalah sebuah method untuk meng-handle redirect ke platform yang dituju, dalam hal ini adalah Google. Buka file Auth/LoginController.php dan tambahkan code berikut:

//[.. CODE SEBELUMNYA ..]

public function redirectToProvider($driver)
{
    return Socialite::driver($driver)->redirect();
}

Jangan lupa untuk menambahkan use statement pada file yang sama.

use Socialite;

Kemudian definisikan route yang tuju untuk proses redirect tersebut, buka file routes/web.php dan tambahkan code berikut:

Route::get('redirect/{driver}', 'Auth\LoginController@redirectToProvider')->name('login.provider');

Langkah selanjutnya adalah meng-handle callback yang membawa data dari proses otentikasi pada platform terkait, buka kembali file Auth/LoginController.php dan tambahkan code:

//[.. CODE SEBELUMNYA ..]

public function handleProviderCallback($driver)
{
    try {
        $user = Socialite::driver($driver)->user();

        $create = User::firstOrCreate([
            'email' => $user->getEmail()
        ], [
            'socialite_name' => $driver,
            'socialite_id' => $user->getId(),
            'name' => $user->getName(),
            'photo' => $user->getAvatar(),
            'email_verified_at' => now()
        ]);

        auth()->login($create, true);
        return redirect($this->redirectPath());
    } catch (\Exception $e) {
        return redirect()->route('login');
    }
}

Penjelasan: Line pertama, mengambil data user menggunakan Socialiate berdasarkan platform (driver) yang digunakan yang dalam hal ini adalah Google. Kemudian line selanjutnya menyimpan data tersebut ke dalam table users dan melakukan proses otentikasi menggunakan helper auth().

Jangan lupa menambahkan use statement untuk me-load model User.

use App/User;

Kembali ke routes/web.php, tambahkan lagi route berikut:

Route::get('{driver}/callback', 'Auth\LoginController@handleProviderCallback')->name('login.callback');

Tiba saatnya untuk membuat sebuah tombol login menggunakan Google account, buka file resources/views/auth/login.blade.php dan modifikasi menjadi:

@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
                <div class="card-header">{{ __('Login') }}</div>

                <div class="card-body">
                    <form method="POST" action="{{ route('login') }}">
                        @csrf

                        <div class="form-group row">
                            <label for="email" class="col-md-4 col-form-label text-md-right">{{ __('E-Mail Address') }}</label>

                            <div class="col-md-6">
                                <input id="email" type="email" class="form-control{{ $errors->has('email') ? ' is-invalid' : '' }}" name="email" value="{{ old('email') }}" required autofocus>

                                @if ($errors->has('email'))
                                    <span class="invalid-feedback" role="alert">
                                        <strong>{{ $errors->first('email') }}</strong>
                                    </span>
                                @endif
                            </div>
                        </div>

                        <div class="form-group row">
                            <label for="password" class="col-md-4 col-form-label text-md-right">{{ __('Password') }}</label>

                            <div class="col-md-6">
                                <input id="password" type="password" class="form-control{{ $errors->has('password') ? ' is-invalid' : '' }}" name="password" required>

                                @if ($errors->has('password'))
                                    <span class="invalid-feedback" role="alert">
                                        <strong>{{ $errors->first('password') }}</strong>
                                    </span>
                                @endif
                            </div>
                        </div>

                        <div class="form-group row">
                            <div class="col-md-6 offset-md-4">
                                <div class="form-check">
                                    <input class="form-check-input" type="checkbox" name="remember" id="remember" {{ old('remember') ? 'checked' : '' }}>

                                    <label class="form-check-label" for="remember">
                                        {{ __('Remember Me') }}
                                    </label>
                                </div>
                            </div>
                        </div>

                        <div class="form-group row mb-0">
                            <div class="col-md-8 offset-md-4">
                                <button type="submit" class="btn btn-primary">
                                    {{ __('Login') }}
                                </button>
                              
                              	<!-- TAMBAHKAN LINE INI -->
                                <a href="{{ route('login.provider', 'google') }}" class="btn btn-danger">{{ __('Google Sign in') }}</a>
                                <!-- TAMBAHKAN LINE INI -->

                                @if (Route::has('password.request'))
                                    <a class="btn btn-link" href="{{ route('password.request') }}">
                                        {{ __('Forgot Your Password?') }}
                                    </a>
                                @endif
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>
@endsection

Apabila kita mengunjungi halaman http://localhost:8000/login maka kita akan mendapatkan tampilan seperti berikut.

google sign-in page

Note: Pastikan kamu menggunakan php artisan serve dengan port 8000 karena uri yang didaftarkan pada API Console adalah localhost dengan port 8000.

Terakhir untuk menampilkan image avatar yang didapatkan dari Google account, modifikasi file resources/views/layouts/app.blade.php, perhatikan pada bagian code berikut:

<!-- CODE SEBELUMNYA -->

<li class="nav-item dropdown">
  
  	<!-- TAMBAHKAN CODE INI -->
    <a id="navbarDropdown" class="nav-link dropdown-toggle" href="#" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" v-pre>
        @if(auth()->user()->photo)
            <img src="{{ auth()->user()->photo }}" alt="photo" width="32" height="32" style="margin-right: 8px;">
        @endif
        {{ auth()->user()->name }} <span class="caret"></span>
    </a>
    <!-- TAMBAHKAN CODE INI -->

    <div class="dropdown-menu dropdown-menu-right" aria-labelledby="navbarDropdown">
        <a class="dropdown-item" href="{{ route('logout') }}"
           onclick="event.preventDefault();
                         document.getElementById('logout-form').submit();">
            {{ __('Logout') }}
        </a>

        <form id="logout-form" action="{{ route('logout') }}" method="POST" style="display: none;">
            @csrf
        </form>
    </div>
</li>

<!-- CODE SETELAHNYA -->

Ketika proses otentikasi berhasil, maka secara otomatis kita akan di-redirect ke halaman dashboard yang telah di-protect dengan middleware auth yang melindungi sebuah page dengan fungsi otentikasi. Maka tampilan yang akan diproleh kurang lebih akan terlihat seperti berikut.

laravel 5.8 socialite

Baca Juga: Membuat Aplikasi Invoice Laravel 5.7 #6: Laporan

Kesimpulan

Beragam fitur yang dimiliki oleh sebuah aplikasi menjadikan user atau pengguna aplikasi tersebut memiliki banyak pilihan untuk digunakan, salah satunya adalah pilihan untuk login menggunakan Google account sehingga user dapat mempercepat proses otentikasinya. Sejatinya cara kerja dari authenticate sama saja yakni dengan mengecek data terkait sesuai atau tidak, kemudian membuat session untuk mengenali user yang melakukan login.

Adapun dokumentasi code dari artikel ini dapat kamu lihat di Github.

Category:
Share:

Comments