Basic Auth

Basic Auth #

HTTP Basic Authentication adalah mekanisme autentikasi paling sederhana dalam ekosistem HTTP — browser menampilkan dialog login bawaan, user memasukkan username dan password, dan browser mengirimkan credentials dalam setiap request sebagai header Authorization: Basic base64(username:password).

Meski sederhana, basicauth sangat berguna untuk melindungi area tertentu dari aplikasi yang tidak memerlukan user management yang kompleks: admin panel internal, staging environment, directory listing, atau API yang hanya diakses oleh beberapa orang.

Cara Kerja HTTP Basic Auth #

1. Browser request ke URL yang dilindungi basicauth
   GET /admin/ HTTP/1.1
   Host: example.com

2. Caddy merespons dengan 401 Unauthorized
   HTTP/1.1 401 Unauthorized
   WWW-Authenticate: Basic realm="Restricted Area"
   
3. Browser menampilkan dialog login
   ┌─────────────────────────────┐
   │ Sign in                     │
   │ example.com                 │
   │ Username: [            ]    │
   │ Password: [            ]    │
   │          [Cancel] [Sign in] │
   └─────────────────────────────┘

4. User masukkan username "alice" dan password "secret123"
   Browser encode: base64("alice:secret123") = "YWxpY2U6c2VjcmV0MTIz"
   
   GET /admin/ HTTP/1.1
   Authorization: Basic YWxpY2U6c2VjcmV0MTIz

5. Caddy decode header, verifikasi username dan bcrypt hash password
   → Cocok → Request diteruskan
   → Tidak cocok → 401 Unauthorized lagi

Membuat Password Hash #

Caddy menggunakan bcrypt untuk menyimpan password hash — jauh lebih aman dari plaintext atau MD5. Kamu tidak pernah menyimpan password asli di Caddyfile, hanya hash-nya.

# Generate bcrypt hash untuk password
caddy hash-password --plaintext "password-kamu"

# Output contoh:
# $2a$14$8lGvWLMR9jGg2.bSZlAHOeYuI1FjTPExECWQpkLPMH1y0LkJnbEKy

# Dengan cost factor berbeda (default 14, range 4-31)
# Cost lebih tinggi = lebih aman tapi lebih lambat
caddy hash-password --plaintext "password-kamu" --cost 12

# Interaktif (tidak menampilkan password di terminal/history)
caddy hash-password
# Enter password: [ketik tanpa echo]
# Confirm password: [ketik lagi]
# Output: $2a$14$...
Bcrypt dengan cost 14 membutuhkan sekitar 1-2 detik per hash verification di hardware modern. Ini disengaja — membuat brute force attack jauh lebih lambat. Jangan khawatir tentang “overhead” ini untuk normal login, tapi perhatikan jika endpoint basicauth mendapat traffic sangat tinggi.

Konfigurasi Dasar #

example.com {
    basicauth {
        # Format: username bcrypt_hash
        alice $2a$14$8lGvWLMR9jGg2.bSZlAHOeYuI1FjTPExECWQpkLPMH1y0LkJnbEKy
        bob   $2a$14$7kFuXLMR9jGg2.bSZlAHOeYuI1FjTPExECWQpkLPMH1y0LkJnbEKy
    }
    
    root * /var/www/protected
    file_server
}

Proteksi Hanya Sebagian Path #

example.com {
    # Hanya proteksi path /admin/*
    basicauth /admin/* {
        admin $2a$14$adminHashHere
        devops $2a$14$devopsHashHere
    }
    
    # Path lain bisa diakses tanpa auth
    root * /var/www/html
    file_server
}

Menggunakan Matcher #

example.com {
    @protected {
        path /admin/*
        path /internal/*
        path /metrics
    }
    
    basicauth @protected {
        alice $2a$14$aliceHashHere
        bob   $2a$14$bobHashHere
    }
    
    root * /var/www/html
    file_server
}

Custom Realm #

Realm adalah teks yang muncul di dialog login browser:

example.com {
    basicauth * {
        # Ubah teks yang muncul di dialog login browser
        realm "Portal Admin Example.com"
        
        alice $2a$14$aliceHashHere
        bob   $2a$14$bobHashHere
    }
    
    reverse_proxy localhost:3000
}

Bypass Auth untuk IP Internal #

Skenario umum: basicauth untuk akses dari internet, tapi IP internal tidak perlu auth:

example.com {
    @internal remote_ip 10.0.0.0/8 192.168.0.0/16 172.16.0.0/12
    @external not remote_ip 10.0.0.0/8 192.168.0.0/16 172.16.0.0/12
    
    # Hanya request dari luar yang perlu auth
    basicauth @external {
        alice $2a$14$aliceHashHere
    }
    
    root * /var/www/html
    file_server
}

Basicauth + Reverse Proxy #

Ketika Caddy digunakan sebagai reverse proxy dengan basicauth, backend menerima informasi user via header:

admin.example.com {
    basicauth {
        alice $2a$14$aliceHashHere
        bob   $2a$14$bobHashHere
    }
    
    reverse_proxy localhost:9000 {
        # Teruskan username ke backend
        # Setelah basicauth berhasil, {http.auth.user.id} berisi username
        header_up X-Authenticated-User {http.auth.user.id}
        
        # Hapus Authorization header dari backend
        # (backend tidak perlu validasi lagi)
        header_up -Authorization
    }
}
// Di backend Node.js — ambil username dari header
app.get('/admin/dashboard', (req, res) => {
    const user = req.headers['x-authenticated-user'];
    console.log(`User ${user} accessed dashboard`);
    res.json({ user, data: getDashboardData(user) });
});

Menyimpan Hash dengan Aman — Environment Variables #

Menaruh password hash langsung di Caddyfile yang masuk ke version control tidak ideal meski hash aman:

{
    # Konfigurasi dari environment variable
}

example.com {
    basicauth {
        # Hash bisa di-load dari environment variable
        alice {env.ALICE_PASSWORD_HASH}
        bob   {env.BOB_PASSWORD_HASH}
    }
    
    reverse_proxy localhost:3000
}
# Set env vars sebelum jalankan Caddy
export ALICE_PASSWORD_HASH='$2a$14$aliceHashHere'
export BOB_PASSWORD_HASH='$2a$14$bobHashHere'

# Atau di systemd override
sudo systemctl edit caddy
# [Service]
# EnvironmentFile=/etc/caddy/caddy.env

# /etc/caddy/caddy.env (mode 600)
# ALICE_PASSWORD_HASH=$2a$14$...
# BOB_PASSWORD_HASH=$2a$14$...

Mengelola Banyak User #

Untuk banyak user, gunakan script untuk generate Caddyfile snippet:

#!/bin/bash
# generate-basicauth.sh
# Usage: ./generate-basicauth.sh users.txt > basicauth-snippet.txt

# users.txt format: username:password (satu per baris)
while IFS=':' read -r username password; do
    hash=$(caddy hash-password --plaintext "$password")
    echo "    $username $hash"
done < "$1"
# users.txt
alice:secret123
bob:another-password
charlie:yet-another
# Generate snippet
./generate-basicauth.sh users.txt > /etc/caddy/basicauth-users.txt

# Lihat hasilnya
cat /etc/caddy/basicauth-users.txt
# alice $2a$14$...
# bob   $2a$14$...
# charlie $2a$14$...

# Import ke Caddyfile dengan import directive
# basicauth {
#     import /etc/caddy/basicauth-users.txt
# }

Keterbatasan Basic Auth dan Alternatifnya #

Basic Auth cocok untuk:
  ✓ Melindungi area internal dari akses tidak sah
  ✓ Staging environment (agar tidak terindeks Google)
  ✓ Admin panel dengan pengguna terbatas
  ✓ File server yang perlu proteksi sederhana
  ✓ Quick protection sementara

Basic Auth TIDAK cocok untuk:
  ✗ Aplikasi consumer (user experience buruk)
  ✗ Butuh logout yang proper (browser cache credentials)
  ✗ Remember me / session management
  ✗ OAuth, SSO, LDAP integration
  ✗ Audit log yang detail
  ✗ Password reset self-service
  ✗ Multi-factor authentication

Alternatif yang lebih lengkap:
  → caddy-security plugin (LDAP, OAuth, JWT)
  → Authelia (self-hosted, bisa dikombinasikan dengan Caddy)
  → Authentik (self-hosted identity provider)
  → Cloudflare Access (jika pakai Cloudflare)

Security Considerations #

# Basic Auth WAJIB digunakan dengan HTTPS
# HTTP Basic Auth mengirim credentials dalam Base64 — mudah didecode!
# Selalu pastikan HTTPS aktif (Caddy otomatis melakukan ini)

# Cek apakah HTTPS aktif
curl -I https://example.com/admin/
# Harus HTTPS, bukan HTTP

# Rate limiting untuk mencegah brute force
# (Caddy sendiri tidak punya rate limiting bawaan untuk basicauth)
# Gunakan fail2ban atau rate limit plugin untuk produksi yang kritis

Melindungi Staging Environment dari Google #

Basic auth adalah cara paling mudah mencegah search engine mengindeks staging environment:

staging.example.com {
    # Google dan crawler lain tidak bisa melewati basicauth
    # Staging tidak akan muncul di hasil pencarian
    basicauth {
        deploy $2a$14$deployHashHere
        qa     $2a$14$qaHashHere
    }
    
    # Tambahkan header anti-indexing sebagai lapisan kedua
    header X-Robots-Tag "noindex, nofollow"
    
    reverse_proxy staging-backend:3000
}

Ini jauh lebih andal dibanding hanya mengandalkan robots.txt yang bisa diabaikan oleh crawler nakal.


Ringkasan #

  • Caddy menggunakan bcrypt untuk password hash — gunakan caddy hash-password --plaintext "password" untuk generate hash dan simpan hasilnya di Caddyfile.
  • Jangan pernah simpan password plaintext di Caddyfile — selalu gunakan bcrypt hash.
  • Gunakan matcher untuk melindungi hanya path tertentu (basicauth /admin/* { ... }), bukan seluruh site.
  • Setelah autentikasi berhasil, {http.auth.user.id} berisi username yang bisa diteruskan ke backend via header_up.
  • Basic auth wajib menggunakan HTTPS — tanpa TLS, credentials bisa dicuri dari network traffic.
  • Untuk aplikasi dengan kebutuhan auth yang lebih kompleks (OAuth, SSO, MFA), gunakan plugin seperti caddy-security atau solusi terpisah seperti Authelia.

← Sebelumnya: Caddy JSON   Berikutnya: Rate Limiting →

About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact