NUXT: Autentikasi dan Session

Fitur umum yang hampir ada di setiap aplikasi adalah fitur login, fungsi paling sederhana dari fitur ini salah satunya untuk mengatur hak akses dari seorang pengguna. Misalkan ada halaman atau aksi yang hanya bisa diakses oleh pengguna yang sudah terautentikasi, sedangkan jika belum, aksi atau halaman tersebut tidak bisa dilakukan atau dikunjungi.

Pada bahasa pemograman lain seperti PHP misalnya, memiliki fitur session yang berfungsi menyimpan sementara data pengguna yang login, selama data pengguna tersebut tercatat di session berarti pengguna tersebut masih login.

Lalu bagaimana untuk frontend? Frontend yang menggunakan javascript framework seperti nuxt? Pada tema tulisan kali ini saya mencoba membaginya pada tiga tulisan:
1. Membuat Autentikasi dan Cek Session dengan bantuan API ‘login/status’
2. Membuat Autentikasi dan Session dengan bantuan express.js
3. Membandingkan dua alur login 1 dan 2

Di sini saya tidak akan membahas di sisi server, saya berasumsi API tujuan sudah dibuat sebelumnya. Pada tulisan pertama ini saya memiliki 2 tujuan API: oauth/token untuk login dan login/status untuk mengecek kondisi user terkait.

Saya menggunakan Laravel dan Passport untuk membuat sistem login dalam contoh saat ini

Contoh respon API oauth/token:

{
    "token_type": "Bearer",
    "expires_in": 1577923199,
    "access_token": "bla-bla-bla-random-token",
    "refresh_token": "bla-bla-bla-random-token",
    "user": {
        "id": 2,
        "email": "user@email.com",
        "name": "user",
    }
}

Contoh respon API login/status:

{
    "status": true,
}

Install NUXT

Untuk memasang nuxt kita bisa gunakan perintah dari vue-cli

vue init nuxt-community/starter-template login-nuxt

Perintah di atas akan mengunduh struktur nuxt ke dalam folder ‘login-nuxt’.

Untuk menjalankannya, cukup masuk ke dalam folder yang telah dibuat tadi, lalu jalankan perintah install.

cd login-nuxt
npm install

Setelah selesai untuk menjalankannya kita cukup jalankan perintah berikut:

npm run dev

Asalinya nuxt akan berjalan di port 3000, atau pada alamat localhost:3000

Sebelum memulai, kita membutuhkan beberapa paket tambahan, antara lain:
1. @nuxtjs/axios: Paket ini untuk http request bisa sih pake axios standar, tapi saya memilih ini karena sudah diset untuk nuxt
2. js-cookie: Paket ini untuk bisa menulis cookie di client side
3. cookie: Paket ini agar cookie bisa dibaca di server side nuxt

Jalankan perintah berikut untuk memasangnya:

npm i js-cookie cookie @nuxtjs/axios --save

Khusus @nuxtjs/axios kita perlu daftarkan di nuxt.config.js seperti berikut:

module.exports = {
.... konfigurasi bawaan
  modules: [
    '@nuxtjs/axios',
  ],

.... konfigurasi lainnya
}

Komponen Login

Pertama saya akan ubah isi dari pages/index.vue menjadi seperti berikut


  

Sehingga saat diakses akan muncul

Di bagian ‘script’ kita tambahkan paket js-cookie, dan pada method login() kita akan mengakses oauth/token sebagai login:

import cookie from 'js-cookie'
export default {
... script di sini
}

Bagian Login

login() {
        let payload = {
          username: "user@email.com",
          password: "qweqwe",
          grant_type: "password",
          client_id: 1,
          client_secret:'ZtppjuOEWcHlJOAqqWlV9ep4D5klbkknBERUcqkc'
        }
        // body content untuk login tentu disesuaikan dengan API yang tersedia
        // http request dengan axios
        this.$axios.$post('http://localhost:8000/oauth/token/',payload)
            .then( (response) => {
                let access_token = response.access_token
                let expired = 0.5
                cookie.set('token', access_token, { expires: expired })
            })
            .catch(function (error) {
                console.log(error)
            })
    }

Script di atas itu saat menekan tombol ‘login’ maka akan memicu methods login yang melakukan request http ke API tujuan, respon yang didapat terutama access_token akan disimpan di cookie dengan bantuan paket js-cookie.

Lalu bagaimana untuk kondisi “sedang login” agar tombol ‘login’ otomatis berubah menjadi tombol ‘logout’, maka selanjutnya yang saya buat adalah vuex.

Di nuxt untuk memasang state management vuex sangat mudah, cukup buat index.js di folder store.
Di dalam vuex ini saya akan membuat 1 state yaitu ‘isLogin’ yang nilainya boolean dan satu buah mutation untuk mengubah nilai ‘isLogin’

import Vuex from "vuex"

export const state = () => ({
  isLogin: false
})

export const mutations = {
  SET_LOGIN(state, data) {
    state.isLogin = data
  }
}

Lalu halaman ‘index.vue’saya ubah seperti berikut


  

Di sana saya membuat satu buah computed dengan nama ‘isLogin’ yang mengambil nilai dari state vuex. Lalu di body tepatnya di button saya tambahkan v-if, dan pada bagian setelah login saya tambahkan perintah commit untuk mengubah nilai state menjadi true.

Hasilnya :

Sudah selesai? Belum. Sekarang kalau halaman di-reload maka tombol akan berubah jadi login padahal kita baru saja login, maka dari situ API ‘login/status’ digunakan.

Di nuxt ada tepatnya di vuex ada action bawaan dengan nama nuxtServerInit, action ini akan terus dieksekusi sebelum halaman berhasil di-render yang terjadi di aplikasi nuxt, dengan pola tersebut saya akan memanfaatkan untuk selalu ngecek status user. Di vuex yang telah dibuat mari tambahkan action sehinggal lengkapnya seperti berikut.

import Vuex from "vuex"
import cookie from "cookie"

export const state = () => ({
  isLogin: false
})

export const mutations = {
  SET_LOGIN(state, data) {
    state.isLogin = data
  }
}

export const actions = {
  // nuxtServerInit  dijalankan oleh Nuxt.js sebelum server-rendering setiap page
  async nuxtServerInit({ commit }, context) {
    const cookies = cookie.parse(context.req.headers.cookie || "");
    let token = cookies.token
    context.$axios.setToken(token, "Bearer")
    await context.$axios.$get('http://localhost:8000/login/status/')
            .then( (response) => {
              if (response) {
                commit('SET_LOGIN', true)
              }
            })
            .catch(function (error) {
                commit("SET_LOGIN", false)
            })
  }
};

Di atas saya tambahkan paket ‘cookie’ fugnsinya agar bisa membaca cookie yang tersedia ( yang tadi sempat dibuat saat login ), lalu cookie tadi disertakan di header request, lalu hasil dari request digunakan untuk mengecek jika respon dari login status sama dengan ‘true’ ya tinggal ubah state isLogin dengan mutation SET_LOGIN

Sekarang coba reload harusnya sih tetap yang nongol logout.

Untuk fungsi logout juga mudah sekali, karena ini tergantung kepada token yang kita perlu lakukan cukup hapus token

logout() {
        cookie.remove('token')
                this.$store.commit('SET_LOGIN',false)
    }

Set status login sudah selesai, sekarang bagaimana untuk mengetes bahwa ada halaman yang hanya bisa diakses oleh yang login. Maka kita akan memanfaatkan fungsi middleware.

Sebelumnya mari buat dulu satu halaman yang hanya diakses orang login, di dalam folder pages saya buat secret.vue


  

Hanya untuk yang login

Sekarang kunjungi localhost:3000/secret kalau bisa logout dulu, hasilnya pasti masih bisa diakses, nah sekarang baru buat middleware yang tadi sempat disinggung, buat berkas auth.js di dalam folder middleware

export default function ({ store, error }) {
    if (!store.state.isLogin) {
        error({ statusCode: 403, message: '403 Forbidden' })
    }
}

Pada perintah di atas, fungsi akan mengecek ke state isLogin, jika bernilai tidak sama dengan true maka akan diarahkan ke halaman galat forbidden

Lalu di secret.vue kita panggil fungsi middleware

export default {
   middleware: "auth",
}

Sekarang coba akses kembali localhost:3000/secret lalu bandingkan dalam kondisi login dan logout.

Saat tak login

Saat login

Referensi :
https://codeburst.io/nuxt-authentication-from-scratch-a7a024c7201b