Skip to content

Teknis — OPA Auth

Service forward-auth middleware RAGA yang dibangun di atas Bun + Express 5. Dipanggil oleh reverse proxy (Traefik) untuk setiap request masuk — bertugas memvalidasi token JWT via Redis, lalu meminta keputusan otorisasi ke OPA (Open Policy Agent). Jika diizinkan, service ini meneruskan informasi user (role, nama, grant, ID) ke service downstream via response header.

Repository

KeyValue
Git Remotehttps://git.tlab.co.id/tarantula/tarantula-v2/opa-bun/opa-auth.git
Branch Aktifmain
bash
git clone https://git.tlab.co.id/tarantula/tarantula-v2/opa-bun/opa-auth.git
cd opa-auth

Tech Stack

LayerTeknologi
RuntimeBun 1
FrameworkExpress 5 (TypeScript)
CacheRedis DB 1 (ioredis) — validasi whitelist token
Policy EngineOPA (Open Policy Agent) — keputusan allow/deny
Secret ManagementInfisical SDK v5
LoggingMorgan (HTTP request log)
Buildbun build --compile → binary tunggal

Environment Variables

Tidak ada file .env — semua variabel diinjeksikan sebagai env var container. Hanya variabel bootstrap Infisical yang perlu diset; sisanya diambil dari Infisical saat startup.

Bootstrap (env var container)

VariableDefaultKeterangan
NODE_PORT3000Port server Express
INFISICAL_SITE_URLhttps://app.infisical.comURL Infisical server
INFISICAL_CLIENT_IDClient ID Universal Auth
INFISICAL_CLIENT_SECRETClient Secret Universal Auth
INFISICAL_ENVIRONMENTEnvironment target (dev / staging / prod)
INFISICAL_PROJECT_IDID project Infisical
INFISICAL_PATHPath secrets di Infisical

Secrets via Infisical

VariableKeterangan
URL_OPABase URL OPA server; digunakan sebagai {URL_OPA}/v1/data/verify_access
REDIS_HOSTHost Redis/Dragonfly untuk validasi whitelist token
REDIS_PORTPort Redis (default 6379)

Endpoints

MethodPathKeterangan
GET/Forward-auth handler utama; dipanggil Traefik untuk setiap request
GET/healthHealth check → { status: "UP" }

Alur Autentikasi

Logika Detail

  1. Header parsing — Traefik mengirim headers:
    • x-forwarded-method → HTTP method request asli
    • x-forwarded-uri → URI request asli (termasuk query string)
    • x-forwarded-prefix → prefix routing, digunakan untuk mengekstrak nama service (/api/tarantula/...tarantula)
    • Authorization → Bearer token JWT
  2. Konstruksi path — Path yang dikirim ke OPA dikonstruksi sebagai /{service}{cleanPath} (tanpa query string).
  3. Redis check — Token dicek di Redis DB 1 dengan key whitelist_access_token:{token}. Check ini di-skip untuk path yang mengandung /notifications.
  4. OPA decision — OPA memverifikasi JWT, memeriksa policy (lihat Teknis OPA Config), dan mengembalikan allow, user_roles, user_is_granted, user_cases, dan token.payload (decoded JWT: sub, username).
  5. Response headers — Jika diizinkan, opa-auth menyetel headers yang dibaca oleh service downstream untuk mengetahui identitas user tanpa perlu decode JWT ulang.
  6. Bypass header untuk login/logout/OPTIONS — Jika cleanPath persis /auth/login atau /auth/logout, atau method request adalah OPTIONS (preflight CORS), dan OPA mengizinkan (allow === true), opa-auth membalas 200 OK kosong tanpa menyetel header X-Auth-User-* — endpoint-endpoint ini tidak butuh identitas user diteruskan ke downstream.
  7. Fallback error — Semua exception yang tidak tertangani secara eksplisit (mis. OPA/Redis tidak terjangkau, timeout, response tidak terduga) ditangkap oleh catch di level handler dan selalu dibalas sebagai 401 Your token is expired — bukan 500 — sehingga error infrastruktur di sisi opa-auth tidak dibedakan dari token kedaluwarsa di sisi klien.

Response Header yang Disetel

HeaderIsiContoh
X-Auth-User-RolesJSON array role["admin"]
X-Auth-User-NameUsername dari JWT payload"john_doe"
X-Auth-User-GrantArray resource yang diizinkan["/workspace/read"]
X-Auth-User-CasesArray kasus khusus[]
X-Auth-User-IDUUID user dari JWT sub"abc-123"

Build & Run

bash
# Install dependencies
bun install

# Jalankan development
bun run index.ts

# Build binary tunggal (digunakan di Docker)
bun build --compile --minify --sourcemap --target=bun-linux-x64 ./index.ts --outfile opa-auth

# Jalankan binary
./opa-auth

Docker

bash
docker build -t opa-auth .
docker run -p 3000:3000 \
  -e INFISICAL_SITE_URL=http://... \
  -e INFISICAL_CLIENT_ID=... \
  -e INFISICAL_CLIENT_SECRET=... \
  -e INFISICAL_ENVIRONMENT=dev \
  -e INFISICAL_PROJECT_ID=... \
  -e INFISICAL_PATH=... \
  opa-auth