Urutan cara kerja refresh token dalam sistem otentikasi berbasis token

A
IQBAL FARHAN SYUHADA
20 Jun 2024

1. Pengguna Login

Pengguna melakukan login dengan memberikan kredensial (seperti username dan password) ke aplikasi klien.

2. Aplikasi Klien Mengirim Permintaan Login ke Server Otentikasi

Aplikasi klien mengirim permintaan login ke server otentikasi, biasanya ke endpoint tertentu (misalnya, /login atau /auth/token).

Permintaan:

POST /login
Content-Type: application/json

{
  "username": "user",
  "password": "password"
}

3. Server Otentikasi Memverifikasi Kredensial

Server otentikasi memverifikasi kredensial pengguna. Jika valid, server menghasilkan dua token:

  • Access Token: Token ini memiliki masa berlaku yang pendek (misalnya, 1 jam).
  • Refresh Token: Token ini memiliki masa berlaku yang lebih panjang (misalnya, beberapa hari atau minggu).

Respons:

{
  "access_token": "ACCESS_TOKEN",
  "expires_in": 3600,  // 1 hour
  "refresh_token": "REFRESH_TOKEN"
}

4. Aplikasi Klien Menyimpan Token

Aplikasi klien menyimpan access token dan refresh token. Access token digunakan untuk permintaan API yang memerlukan otentikasi.

5. Pengguna Membuat Permintaan ke API

Pengguna membuat permintaan ke API yang dilindungi dengan menyertakan access token dalam header permintaan.

Permintaan:

GET /protected-resource
Authorization: Bearer ACCESS_TOKEN

6. Server API Memverifikasi Access Token

Server API memverifikasi access token. Jika valid dan belum kedaluwarsa, server API memproses permintaan dan mengirimkan respons.

7. Access Token Kedaluwarsa

Jika access token kedaluwarsa, pengguna tidak bisa lagi mengakses sumber daya yang dilindungi. Aplikasi klien perlu mendapatkan access token baru.

8. Aplikasi Klien Menggunakan Refresh Token

Aplikasi klien mengirim permintaan ke server otentikasi untuk mendapatkan access token baru menggunakan refresh token.

Permintaan:

POST /token
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token&refresh_token=REFRESH_TOKEN&client_id=CLIENT_ID&client_secret=CLIENT_SECRET

9. Server Otentikasi Memverifikasi Refresh Token

Server otentikasi memverifikasi refresh token. Jika valid, server mengeluarkan access token baru (dan kadang-kadang refresh token baru juga).

Respons:

{
  "access_token": "NEW_ACCESS_TOKEN",
  "expires_in": 3600,  // 1 hour
  "refresh_token": "NEW_REFRESH_TOKEN"  // Optional
}

10. Aplikasi Klien Menyimpan Token Baru

Aplikasi klien menyimpan access token baru dan, jika ada, refresh token baru. Access token baru digunakan untuk permintaan API berikutnya.

11. Ulangi Proses

Proses ini diulangi setiap kali access token kedaluwarsa. Refresh token memungkinkan aplikasi klien untuk terus mendapatkan access token baru tanpa memaksa pengguna untuk login kembali.

Contoh Implementasi

Berikut adalah contoh sederhana implementasi dalam kode menggunakan Express.js untuk server otentikasi dan frontend aplikasi klien.

Backend Server (Express.js)

const express = require('express');
const jwt = require('jsonwebtoken');
const bodyParser = require('body-parser');

const app = express();
app.use(bodyParser.json());

const users = [{ username: 'user', password: 'password' }];
const refreshTokens = [];

app.post('/login', (req, res) => {
  const { username, password } = req.body;
  const user = users.find(u => u.username === username && u.password === password);
  if (user) {
    const accessToken = jwt.sign({ username }, 'ACCESS_TOKEN_SECRET', { expiresIn: '1h' });
    const refreshToken = jwt.sign({ username }, 'REFRESH_TOKEN_SECRET');
    refreshTokens.push(refreshToken);
    res.json({ accessToken, refreshToken });
  } else {
    res.sendStatus(401);
  }
});

app.post('/token', (req, res) => {
  const { refreshToken } = req.body;
  if (!refreshToken || !refreshTokens.includes(refreshToken)) {
    return res.sendStatus(403);
  }
  jwt.verify(refreshToken, 'REFRESH_TOKEN_SECRET', (err, user) => {
    if (err) return res.sendStatus(403);
    const accessToken = jwt.sign({ username: user.username }, 'ACCESS_TOKEN_SECRET', { expiresIn: '1h' });
    res.json({ accessToken });
  });
});

app.listen(3000);

Frontend Aplikasi

async function login(username, password) {
  const response = await fetch('/login', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ username, password }),
  });
  const data = await response.json();
  localStorage.setItem('accessToken', data.accessToken);
  localStorage.setItem('refreshToken', data.refreshToken);
}

async function fetchWithToken(url, options) {
  let accessToken = localStorage.getItem('accessToken');
  let response = await fetch(url, {
    ...options,
    headers: { ...options.headers, 'Authorization': `Bearer ${accessToken}` },
  });

  if (response.status === 401) {
    // Access token kedaluwarsa, gunakan refresh token
    const refreshToken = localStorage.getItem('refreshToken');
    const tokenResponse = await fetch('/token', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ refreshToken }),
    });

    if (tokenResponse.ok) {
      const { accessToken: newAccessToken } = await tokenResponse.json();
      localStorage.setItem('accessToken', newAccessToken);
      // Ulangi permintaan dengan access token baru
      response = await fetch(url, {
        ...options,
        headers: { ...options.headers, 'Authorization': `Bearer ${newAccessToken}` },
      });
    } else {
      // Handle refresh token invalid atau kedaluwarsa
      // Misalnya, redirect ke halaman login
    }
  }

  return response;
}

Dengan mengikuti urutan cara kerja ini, Anda dapat mengimplementasikan sistem otentikasi yang aman dan efisien menggunakan access token dan refresh token.