---
title: "Menguasai Seni Keamanan Progressive Web App"
---

# Menguasai Seni Keamanan Progressive Web App

Progressive Web Apps (PWAs) telah menjadi standar de‑facto untuk memberikan pengalaman mirip aplikasi di web terbuka. Kekuatan inti mereka—kemampuan offline, notifikasi push, dan kemampuan di‑instal—juga memperkenalkan permukaan serangan baru yang jarang ditemui situs web tradisional. Artikel ini menyelami **siklus hidup keamanan PWA**, menggabungkan penguatan pada tingkat jaringan, perlindungan runtime, dan praktik operasional terbaik. Pada akhirnya, Anda akan memiliki daftar periksa yang dapat diterapkan pada proyek apa pun, baik itu pembaca berita sederhana atau platform e‑commerce yang kompleks.

> **TL;DR**: Amankan PWA Anda dengan HTTPS, terapkan CSP ketat, sandbank service worker, validasi semua masukan, dan adopsi rutinitas pemantauan berkelanjutan.

---

## 1. Lapisan Transport – Garis Pertahanan Pertama

### 1.1 Terapkan HTTPS di Seluruh Tempat

Semua browser modern memaksa **HTTPS** untuk pendaftaran service worker. Namun, beberapa aset (misalnya analitik pihak ketiga) masih dapat dimuat lewat HTTP, menimbulkan peringatan mixed‑content dan membuka celah serangan man‑in‑the‑middle (MITM).

**Langkah‑langkah kunci:**

1. Dapatkan sertifikat TLS tepercaya (Let’s Encrypt, Cloudflare, dll.).
2. Alihkan semua permintaan `http://` ke `https://` melalui konfigurasi server.
3. Aktifkan **HSTS** (HTTP Strict Transport Security) untuk memaksa browser menggunakan HTTPS selama periode yang ditentukan.

```nginx
# Contoh potongan NGINX
server {
    listen 80;
    server_name example.com www.example.com;
    return 301 https://$host$request_uri;
}
server {
    listen 443 ssl http2;
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    # Pengaturan TLS ...
}
```

> **Catatan**: HSTS menghilangkan serangan penurunan, tetapi memerlukan perencanaan matang karena setelah diatur, browser akan menolak koneksi HTTP selama periode yang ditetapkan.

### 1.2 Certificate Pinning (Opsional)

Untuk PWA yang sangat sensitif—perbankan, catatan kesehatan—pertimbangkan **certificate pinning** melalui **Public Key Pinning Extension for HTTP (HPKP)**. Meskipun HPKP sedang dihentikan karena risiko penyebarannya, Anda dapat memperoleh keamanan serupa dengan header **Expect‑CT** yang memaksa Certificate Transparency.

```http
Expect-CT: max-age=86400, enforce, report-uri="https://example.com/report"
```

---

## 2. Penguatan Service Worker

Service worker merupakan inti kemampuan offline PWA. Mereka berjalan di thread latar dengan privilese tinggi, menjadikannya target utama eksploitasi.

### 2.1 Pembatasan Scope

Tentukan `scope` sekecil mungkin saat mendaftarkan service worker. Ini mencegah worker menangkap permintaan di luar area yang dimaksud.

```javascript
navigator.serviceWorker.register('/sw.js', { scope: '/app/' })
  .then(reg => console.log('SW terdaftar dengan scope:', reg.scope));
```

### 2.2 Verifikasi Integritas dengan Subresource Integrity (SRI)

Jika Anda memuat skrip service worker dari CDN, lindungi dengan **SRI** agar kode yang diambil cocok dengan hash yang diharapkan.

```html
<script src="https://cdn.example.com/sw.js"
        integrity="sha384-abc123..."
        crossorigin="anonymous"></script>
```

### 2.3 Content Security Policy untuk Service Worker

**CSP** yang ketat dapat mencegah worker memuat skrip berbahaya atau terhubung ke origin yang tidak diinginkan.

```http
Content-Security-Policy: script-src 'self' https://trusted.cdn.com; 
                         connect-src 'self' https://api.example.com;
```

> **Tip**: Gunakan direktif `worker-src` (didukung di browser terbaru) untuk secara eksplisit mengizinkan origin skrip worker.

### 2.4 Manajemen State dan Validasi Cache

Jangan pernah mempercayai entri cache secara membabi buta. Selalu validasi kesegaran respons yang di‑cache, terutama untuk token autentikasi atau data pribadi.

```javascript
self.addEventListener('fetch', event => {
  const url = new URL(event.request.url);
  if (url.pathname.startsWith('/api/')) {
    // Lewati cache untuk data dinamis
    event.respondWith(fetch(event.request));
    return;
  }
  // Strategi default cache‑first untuk aset statis
  event.respondWith(
    caches.match(event.request).then(cached => cached || fetch(event.request))
  );
});
```

---

## 3. Perlindungan Runtime – CSP, Permissions, dan Sandbox

### 3.1 CSP Lengkap

CSP yang dirancang dengan baik mengurangi risiko **Cross‑Site Scripting (XSS)** dan **Data Injection**. Berikut contoh kebijakan yang disesuaikan untuk PWA tipikal:

```http
Content-Security-Policy:
  default-src 'self';
  script-src 'self' 'sha256-XYZ' https://analytics.example.com;
  style-src 'self' 'unsafe-inline';
  img-src 'self' data:;
  font-src 'self' https://fonts.gstatic.com;
  connect-src 'self' https://api.example.com wss://socket.example.com;
  frame-ancestors 'none';
  base-uri 'self';
  form-action 'self';
```

- `script-src` menyertakan hash untuk skrip inline agar tidak perlu `unsafe-inline`.
- `frame-ancestors 'none'` menonaktifkan clickjacking.
- `connect-src` mengizinkan API dan endpoint WebSocket yang sah.

### 3.2 Permissions Policy (Feature‑Policy Sebelumnya)

Batasi fitur browser yang kuat yang mungkin secara tidak sengaja diwarisi oleh PWA.

```http
Permissions-Policy: geolocation=(), microphone=(), camera=(), payment=()
```

### 3.3 Atribut Sandbox untuk Konten Tersemat

Jika PWA Anda menyematkan iframe pihak ketiga, sandbank mereka untuk mencegah eksekusi skrip dan navigasi.

```html
<iframe src="https://maps.example.com"
        sandbox="allow-scripts allow-same-origin"
        loading="lazy"></iframe>
```

---

## 4. Autentikasi & Otorisasi

### 4.1 Autentikasi Berbasis Token dengan JWT

Gunakan **JSON Web Tokens (JWT)** untuk autentikasi tanpa status, tetapi jangan pernah menyimpannya di `localStorage`—gunakan **cookie Secure, HttpOnly** untuk mengurangi pencurian lewat XSS.

```http
Set-Cookie: token=eyJhbGciOi...; HttpOnly; Secure; SameSite=Strict; Path=/; Max-Age=3600
```

### 4.2 Rotasi Refresh Token

Implementasikan rotasi refresh token untuk membatasi dampak token yang dikompromikan.

1. Klien mengirim refresh token.
2. Server memvalidasi dan mengeluarkan token akses **baru** serta refresh token **baru**.
3. Refresh token lama dinonaktifkan di basis data.

### 4.3 Mitigasi CSRF

Meskipun menggunakan cookie same‑site, gunakan **token anti‑CSRF** untuk permintaan POST yang mengubah status.

```html
<input type="hidden" name="csrf_token" value="{{ .CSRFToken }}">
```

Di server, verifikasi bahwa token cocok dengan sesi.

---

## 5. Penyimpanan Data yang Aman

PWA dapat menyimpan data melalui **IndexedDB**, **Cache API**, dan **Web Storage**. Masing‑masing mempunyai pertimbangan keamanannya.

| Penyimpanan | Kesesuaian | Tips Keamanan |
|-------------|------------|----------------|
| **Cache API** | Aset statis, fallback offline | Cache hanya sumber yang tidak berubah. Gunakan nama cache versi untuk membersihkan data usang. |
| **IndexedDB** | Data terstruktur, preferensi pengguna | Enkripsi field sensitif di sisi klien dengan Web Crypto API. |
| **LocalStorage / SessionStorage** | Data kecil yang tidak sensitif | Hindari menyimpan rahasia. Data dapat diakses oleh skrip apapun pada halaman. |

### 5.1 Contoh: Enkripsi Data di IndexedDB

```javascript
async function encryptAndStore(key, value) {
  const cryptoKey = await crypto.subtle.generateKey(
    { name: "AES-GCM", length: 256 },
    true,
    ["encrypt", "decrypt"]
  );
  const iv = crypto.getRandomValues(new Uint8Array(12));
  const encoded = new TextEncoder().encode(value);
  const ciphertext = await crypto.subtle.encrypt(
    { name: "AES-GCM", iv },
    cryptoKey,
    encoded
  );
  const db = await openDB('secure-store', 1, {
    upgrade(db) { db.createObjectStore('secrets'); }
  });
  await db.put('secrets', { iv, ciphertext }, key);
}
```

---

## 6. Pemantauan, Audit, dan Respons Insiden

Keamanan bukan konfigurasi sekali saja; ia merupakan siklus berkelanjutan.

### 6.1 Pemindaian Otomatis

- Gunakan **OWASP ZAP** atau **Burp Suite** untuk memindai XSS, CSRF, dan header yang tidak aman.
- Integrasikan audit **Lighthouse** ke dalam pipeline CI/CD untuk menegakkan kepatuhan PWA.

### 6.2 Logging pada Runtime

Tangkap error service‑worker dan kirim ke endpoint aman untuk analisis.

```javascript
self.addEventListener('error', event => {
  fetch('https://logs.example.com/collect', {
    method: 'POST',
    body: JSON.stringify({ message: event.message, stack: event.error.stack })
  });
});
```

### 6.3 Playbook Insiden

1. **Deteksi**: Peringatan dari trafik abnormal atau laporan pelanggaran CSP.
2. **Karantina**: Cabut JWT yang terkompromi, putar kembali API key.
3. **Eradikasi**: Perbaiki kode yang rentan, perbarui cache service‑worker.
4. **Pemulihan**: Deploy versi baru, pantau agar tidak kembali.
5. **Pasca‑mortem**: Dokumentasikan akar penyebab, perbarui daftar periksa keamanan.

---

## 7. Gambaran Visual – Lapisan Keamanan dalam PWA

```mermaid
flowchart TB
    subgraph "Lapisan Transport"
        H["\"HTTPS\""]
        S["\"HSTS\""]
    end
    subgraph "Service Worker"
        SW["\"Pembatasan Scope\""]
        CS["\"Validasi Cache\""]
    end
    subgraph "Runtime"
        CSP["\"Content Security Policy\""]
        PP["\"Permissions Policy\""]
        SAN["\"Sandboxed iFrames\""]
    end
    subgraph "Auth & Data"
        JWT["\"Secure Cookies\""]
        REF["\"Rotasi Refresh\""]
        ENC["\"Enkripsi IndexedDB\""]
    end
    subgraph "Monitoring"
        SCAN["\"OWASP ZAP\""]
        LOG["\"Runtime Logging\""]
    end

    H --> SW --> CSP --> JWT --> SCAN
    S --> SW
    CS --> PP
    PP --> ENC
    LOG --> SCAN
```

Diagram di atas menggambarkan bagaimana setiap kontrol keamanan membangun di atas yang sebelumnya, membentuk arsitektur defense‑in‑depth.

---

## 8. Daftar Periksa – Referensi Cepat untuk PWA yang Aman

- [ ] Layani semua konten lewat HTTPS dengan HSTS diaktifkan.  
- [ ] Daftarkan service worker dengan scope sekecil mungkin.  
- [ ] Terapkan Subresource Integrity untuk skrip yang dimuat dari CDN.  
- [ ] Pakai CSP ketat, termasuk `worker-src` dan hash skrip.  
- [ ] Gunakan Permissions‑Policy untuk menonaktifkan fitur browser yang tidak dipakai.  
- [ ] Simpan token autentikasi dalam cookie Secure, HttpOnly; jangan di `localStorage`.  
- [ ] Rotasi refresh token dan validasi token CSRF pada permintaan yang mengubah status.  
- [ ] Enkripsi data sensitif di IndexedDB.  
- [ ] Jalankan pemindaian OWASP ZAP otomatis pada setiap PR.  
- [ ] Siapkan logging real‑time untuk error service‑worker.  
- [ ] Pertahankan playbook respons insiden.

---

## 9. Pertanyaan yang Sering Diajukan

**T1: Apakah PWA memerlukan Service Worker untuk keamanan?**  
Tidak. Langkah keamanan seperti HTTPS, CSP, dan cookie aman berfungsi secara independen. Namun, Service Worker adalah tempat sebagian besar serangan runtime muncul, sehingga memerlukan penguatan ekstra.

**T2: Bisakah saya memakai `unsafe-inline` di CSP untuk styling?**  
Sebaiknya hindari. Sebagai gantinya, gunakan hash atau nonce pada style inline, atau pindahkan ke file CSS eksternal.

**T3: Seberapa sering saya harus mengganti sertifikat TLS?**  
Let’s Encrypt mengeluarkan sertifikat 90‑hari; otomatisasikan perpanjangannya. Untuk sertifikat self‑signed atau komersial, targetkan masa berlaku maksimal 1 tahun.

---

## 10. Kesimpulan

Progressive Web Apps mengaburkan batas antara pengalaman native dan web, memberi kemampuan kuat sekaligus memperluas permukaan serangan. Dengan memadukan keamanan transport, memperketat scope service‑worker, menegakkan Content Security Policy yang disiplin, serta menerapkan praktik autentikasi yang kuat, Anda dapat melindungi PWA tanpa mengorbankan performa.

Ingat: keamanan adalah perjalanan, bukan tujuan akhir. Tetap perbarui dependensi, audit kode secara rutin, dan ikuti perkembangan ancaman terbaru. Dengan menerapkan praktik yang dijabarkan di sini, PWA Anda akan tetap kuat melawan serangan web paling umum.

---

## <span class='highlight-content'>Lihat</span> Juga

- [MDN Web Docs – Service Workers](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API)
- [OWASP Top Ten Project](https://owasp.org/www-project-top-ten/)
- [Mozilla – Content Security Policy (CSP)](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP)
- [Web.dev – HTTPS and HSTS](https://web.dev/transport-layer-security/)
- [RFC 6797 – HTTP Strict Transport Security (HSTS)](https://tools.ietf.org/html/rfc6797)