---
type: how-to
title: Resep reverse proxy dan kontrak callback
summary: Sambungkan gerbang proxy di Traefik atau Caddy, hosting callback yang mengubah pass terpecahkan menjadi cookie, dan gerbangi Authelia tanpa menyentuhnya.
---

Tiap reverse proxy butuh dua bagian yang sama: sebuah pemeriksaan **otorisator** yang bertanya ke Caputchin apakah sebuah permintaan membawa pass sah, dan sebuah **callback** pada origin-mu yang mengubah pass terpecahkan menjadi cookie `cpt_gate`. [Penelusuran nginx](/docs/proxy-page-gate/set-up) menunjukkan bentuknya ujung ke ujung; halaman ini memberi proxy lain, kontrak callback yang tepat, dan contoh Authelia lengkap. Ganti `YOUR_SITE_KEY` dengan kunci publikmu di mana-mana.

Endpoint-nya sama di mana-mana:

- **Otorisator**: `GET https://verify.caputchin.com/v1/gate/authz?site=YOUR_SITE_KEY`, dengan header `Cookie` pengunjung diteruskan. `204` berarti izinkan, `401` berarti tantangan.
- **Tantangan**: alihkan peramban ke `https://verify.caputchin.com/v1/gate/challenge?site=YOUR_SITE_KEY&return=<URL asli>`.

## Traefik

Pakai middleware `forwardAuth` untuk otorisator. Traefik meneruskan header `Cookie` yang masuk secara default. Pada `401` dari middleware, alihkan peramban ke tantangan (sebuah middleware halaman-galat yang menunjuk rute kecil yang mengeluarkan `302`, atau tangani `401` di edge-mu).

```yaml
http:
  middlewares:
    cpt-gate:
      forwardAuth:
        address: "https://verify.caputchin.com/v1/gate/authz?site=YOUR_SITE_KEY"
        # The 401 from forwardAuth is your signal to send the browser to:
        #   https://verify.caputchin.com/v1/gate/challenge?site=YOUR_SITE_KEY&return=<original-url>
  routers:
    portal:
      rule: "Host(`auth.example.com`)"
      middlewares: ["cpt-gate"]
      service: your-app
```

## Caddy

Pakai `forward_auth` untuk otorisator dan `handle_errors` untuk mengubah `401` menjadi pengalihan. Ini titik awal; sesuaikan sintaks direktif untuk versi Caddy-mu.

```caddy
auth.example.com {
  forward_auth https://verify.caputchin.com {
    uri /v1/gate/authz?site=YOUR_SITE_KEY
    copy_headers Cookie
  }
  handle_errors {
    @challenge expression {http.error.status_code} == 401
    redir @challenge https://verify.caputchin.com/v1/gate/challenge?site=YOUR_SITE_KEY&return={scheme}://{host}{uri} 302
  }
  reverse_proxy your-app:8080
}
```

## Callback

Halaman tantangan terhosting menyelesaikan dengan auto-mengirim sebuah formulir `POST` ke `https://<origin-mu>/__cpt/callback` dengan dua field di **body**: `cpt_gate` (pass) dan `to` (ke mana mengirim pengunjung). Tambahkan satu rute ini ke origin-mu (atau sebagai location khusus pada proxy). Ia harus:

1. Membaca `cpt_gate` dan `to` dari **body** POST, tak pernah dari URL (pass di URL bocor ke log dan perujuk).
2. Memastikan `to` ada di origin-mu sendiri, dan menolak apa pun selainnya, agar callback tak bisa diubah menjadi open redirect.
3. Men-set cookie dengan atribut di bawah.
4. Mengalihkan (`303`) ke `to`.

```js
// Any tiny handler on your origin works. Express shown; ~15 lines.
app.post("/__cpt/callback", express.urlencoded({ extended: false }), (req, res) => {
  const pass = String(req.body.cpt_gate || "");
  const to = String(req.body.to || "/");
  const target = new URL(to, `https://${req.headers.host}`);
  if (target.host !== req.headers.host) return res.status(400).end(); // same-origin only
  res.setHeader(
    "Set-Cookie",
    `cpt_gate=${pass}; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=1800`
  );
  res.redirect(303, target.pathname + target.search);
});
```

Atribut cookie adalah keseluruhan model keamanan. Karena pass tak terikat ke perangkat, `HttpOnly` (memblokir pencurian oleh skrip), `Secure` (hanya HTTPS), `SameSite=Lax`, dan `Max-Age` pendek (cocokkan dengan TTL izin lewat-mu) adalah yang melindunginya. Juga: jangan catat nilai `cpt_gate` di access log-mu, dan pertahankan `Referrer-Policy: no-referrer` pada callback agar pass tak pernah ikut menumpang di header perujuk.

## Contoh terpecahkan: Authelia

Portal login Authelia adalah app mono-halaman terkompilasi tanpa tempat untuk menyisipkan widget dan tanpa hook plugin, jadi gerbang adalah cara melindunginya. Authelia sudah duduk di balik sebuah reverse proxy (begitulah ForwardAuth-nya sendiri bekerja), dan proxy itulah tempat gerbang berada. Authelia sendiri dibiarkan sepenuhnya tanpa modifikasi.

Pasang gerbang pada vhost portal (misalnya `auth.example.com`):

- **Gerbangi** HTML portal dan endpoint login faktor-pertama (`/api/firstfactor`).
- **Kecualikan** endpoint verify milik ForwardAuth Authelia sendiri (`/api/verify`), yang proxy panggil untuk tiap permintaan upstream terlindungi. Menggerbanginya akan merusak tiap app terlindungi di balik Authelia.
- **Kecualikan** health check dan aset statis yang halaman tantangan itu sendiri butuhkan.
- **Tambahkan** rute `/__cpt/callback` seperti di atas.

Gerbang menjauhkan bot dari portal; Regulation bawaan Authelia (batas percobaan ulang dan ban) tetap membatasi percobaan ulang kredensial bagi siapa pun yang lolos, jadi kedua lapisan bertumpuk. Gerbang melindungi hanya portal interaktif (UI login dan persetujuan); ia tak menggerbangi, dan tak seharusnya, endpoint token non-interaktif.

## Lihat juga

- [Siapkan gerbang proxy](/docs/proxy-page-gate/set-up): penelusuran nginx dan rollout mode-pratinjau-dulu.
- [Ikhtisar](/docs/proxy-page-gate/overview): konsepnya dan cookie izin lewat.
- [Statistik](/docs/proxy-page-gate/statistics): pastikan penyambungan dengan mengamati tantangan lawan lolos langsung.
