You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
4.3 KiB
4.3 KiB
Refresh Token
Tujuan
Memperbarui JWT yang akan habis masa berlakunya tanpa harus login ulang dengan username/password LDAP. Digunakan oleh FE PWA untuk menjaga sesi tetap aktif.
Business Rule
- Token lama harus masih valid (belum expired) untuk bisa di-refresh
- Token baru diterbitkan dengan TTL penuh (
expires_indari awal lagi) - Token lama tidak di-invalidate (stateless JWT — tidak ada blacklist)
- Groups dan is_admin diambil dari payload token lama, bukan re-query ke LDAP
- Rate limit: 30 request / menit per IP
Kapan Harus Refresh?
Strategi yang direkomendasikan untuk PWA:
Token diterima saat login → expires_in: 3600 (1 jam)
↓
Simpan: access_token, expires_at = Date.now() + (expires_in * 1000)
↓
Sebelum setiap request API:
if (Date.now() > expires_at - 5 * 60 * 1000) // 5 menit sebelum expire
→ POST /auth/refresh
→ Simpan token baru
↓
Jika refresh gagal (401) → redirect ke halaman login
URL
POST https://console.gisportal.id/api/v1/auth/refresh
HTTP Method
POST
Authentication
Token lama (yang akan di-refresh) dikirim di header:
Authorization: Bearer <jwt_lama_yang_masih_valid>
Request Body
Tidak diperlukan (kosong).
Response Success
HTTP 200
{
"data": {
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJqb2huLmRvZSIsImlzX2FkbWluIjp0cnVlLCJleHAiOjE3MTk1MDM2MDB9.new_signature",
"token_type": "Bearer",
"expires_in": 3600,
"auth_type": "ldap_jwt"
}
}
Response Error
HTTP 401 — Token tidak ada:
{
"error": {
"code": "missing_token",
"message": "No token provided."
}
}
HTTP 401 — Token expired atau invalid:
{
"error": {
"code": "invalid_token",
"message": "Token invalid or expired."
}
}
Status Code
| Code | Kondisi |
|---|---|
| 200 | Token berhasil di-refresh |
| 401 | Token tidak ada / expired / invalid |
| 429 | Rate limit (30x/menit) |
Contoh Request
curl -s -X POST https://console.gisportal.id/api/v1/auth/refresh \
-H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."
Contoh Implementasi PWA (JavaScript)
const TOKEN_KEY = 'geonet_token';
const EXPIRES_KEY = 'geonet_expires_at';
async function getValidToken() {
const expiresAt = parseInt(localStorage.getItem(EXPIRES_KEY) || '0');
const token = localStorage.getItem(TOKEN_KEY);
// Refresh jika kurang dari 5 menit lagi expire
if (Date.now() > expiresAt - 5 * 60 * 1000) {
const res = await fetch('https://console.gisportal.id/api/v1/auth/refresh', {
method: 'POST',
headers: { 'Authorization': `Bearer ${token}` }
});
if (!res.ok) {
// Token expired total → login ulang
window.location.href = '/login';
return null;
}
const data = await res.json();
localStorage.setItem(TOKEN_KEY, data.data.access_token);
localStorage.setItem(EXPIRES_KEY, Date.now() + data.data.expires_in * 1000);
return data.data.access_token;
}
return token;
}
// Gunakan sebelum setiap API call
const token = await getValidToken();
const res = await fetch('https://console.gisportal.id/api/v1/databases', {
headers: { 'Authorization': `Bearer ${token}` }
});
Sequence Flow
sequenceDiagram
PWA->>API: POST /auth/refresh (Bearer token_lama)
API->>API: Validasi JWT signature & exp
alt Token masih valid
API->>API: Issue JWT baru (TTL penuh)
API->>AuditLog: log api.v1.auth.refresh
API-->>PWA: 200 {access_token baru, expires_in: 3600}
else Token expired/invalid
API-->>PWA: 401 invalid_token
PWA->>PWA: Redirect ke /login
end
Database yang Diakses
- Tidak ada (JWT stateless)
databaselist_audit— write audit log
Audit Log
Event: api.v1.auth.refresh
Rate Limit
30 request / menit per IP.
Idempotent
Tidak — setiap call menghasilkan token baru dengan exp baru.
Security
- Token lama tidak di-blacklist (stateless JWT)
- Jika token bocor, revoke dengan cara: admin bisa rotate
APP_KEY(invalidate semua JWT) - Selalu gunakan HTTPS
Changelog
| Tanggal | Perubahan |
|---|---|
| 2026-06-23 | Endpoint dibuat untuk mendukung FE PWA my.gisportal.id |