> ## Documentation Index
> Fetch the complete documentation index at: https://docs.csku.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Autentikasi Webhook

> Amankan endpoint webhook Anda

## Pengenalan

Saat CSKU AI mengirim webhook ke endpoint Anda, request akan menyertakan header `Authorization` yang berisi secret key yang telah Anda konfigurasi di dashboard.

<Callout type="warning">
  <strong>Tanggung Jawab Pengguna:</strong> Validasi webhook sepenuhnya menjadi tanggung jawab Anda. CSKU AI hanya mengirimkan header `Authorization` - Anda yang harus memvalidasi di sisi server Anda untuk memastikan request benar-benar berasal dari CSKU AI.
</Callout>

<Callout type="info">
  Tanpa validasi yang tepat, endpoint webhook Anda bisa menerima request palsu dari pihak yang tidak berwenang.
</Callout>

## Cara Kerja

1. Anda mengatur secret key di dashboard CSKU AI ([app.csku.ai/settings/webhook-settings](https://app.csku.ai/settings/webhook-settings))
2. Setiap kali CSKU AI mengirim webhook, secret key tersebut disertakan di header `Authorization`
3. **Anda bertanggung jawab** untuk memvalidasi header ini di server Anda

## Header Autentikasi

```http theme={null}
Authorization: {your_secret_key}
```

## Validasi (Tanggung Jawab Anda)

Anda **wajib** memvalidasi header `Authorization` di server Anda. CSKU AI tidak melakukan validasi - kami hanya mengirim webhook dengan header yang berisi secret key Anda.

<Steps>
  <Step title="Ekstrak Header">
    Baca header `Authorization` dari request yang masuk
  </Step>

  <Step title="Bandingkan">
    Bandingkan nilai header dengan secret key yang Anda simpan
  </Step>

  <Step title="Respons">
    Kembalikan 401 jika tidak cocok, lanjutkan jika cocok
  </Step>
</Steps>

## Contoh Implementasi

### Node.js/Express

```javascript theme={null}
const SECRET_KEY = 'your_secret_key';

app.post('/webhook', (req, res) => {
  const authHeader = req.headers.authorization;
  
  if (authHeader !== SECRET_KEY) {
    console.error('Secret webhook tidak valid');
    return res.status(401).json({ error: 'Unauthorized' });
  }
  
  // Proses webhook...
  res.status(200).send('OK');
});
```

### Python/Flask

```python theme={null}
from flask import Flask, request, jsonify

app = Flask(__name__)
SECRET_KEY = 'your_secret_key'

@app.route('/webhook', methods=['POST'])
def webhook():
    # Validasi autentikasi
    auth_header = request.headers.get('Authorization')
    if auth_header != SECRET_KEY:
        print('Secret webhook tidak valid')
        return jsonify({'error': 'Unauthorized'}), 401
    
    # Proses webhook...
    return 'OK', 200
```

### PHP

```php theme={null}
<?php
$SECRET_KEY = 'your_secret_key';

function webhookHandler() {
    global $SECRET_KEY;
    
    // Validasi autentikasi
    $authHeader = $_SERVER['HTTP_AUTHORIZATION'] ?? '';
    if ($authHeader !== $SECRET_KEY) {
        error_log('Secret webhook tidak valid');
        http_response_code(401);
        echo json_encode(['error' => 'Unauthorized']);
        return;
    }
    
    // Proses webhook...
    http_response_code(200);
    echo 'OK';
}

webhookHandler();
?>
```

## Kesalahan Umum

<AccordionGroup>
  <Accordion title="Case Sensitivity">
    Perbandingan secret key bersifat case-sensitive. Pastikan Anda membandingkan nilai yang tepat tanpa modifikasi apapun.
  </Accordion>

  <Accordion title="Whitespace">
    Perhatikan whitespace di awal atau akhir secret key Anda. Gunakan `.trim()` atau yang setara untuk membersihkan input.
  </Accordion>

  <Accordion title="Nama Header">
    Pastikan Anda memeriksa header `Authorization`, bukan header kustom seperti `X-Authorization`.
  </Accordion>

  <Accordion title="Environment Variables">
    Jangan hardcode secret key Anda. Gunakan environment variables atau secrets management.
  </Accordion>
</AccordionGroup>

## Praktik Terbaik

<Callout type="info">
  Ikuti praktik terbaik ini untuk memastikan penanganan webhook yang aman.
</Callout>

### 1. Gunakan Environment Variables

```javascript theme={null}
// ❌ Buruk - Secret di-hardcode
const SECRET_KEY = 'secret_123456';

// ✅ Bagus - Environment variable
const SECRET_KEY = process.env.WEBHOOK_SECRET_KEY;
```

### 2. Implementasikan Rate Limiting

```javascript theme={null}
const rateLimit = require('express-rate-limit');

const webhookRateLimit = rateLimit({
  windowMs: 60 * 1000, // 1 menit
  max: 100, // Batasi setiap IP ke 100 request per windowMs
  message: 'Terlalu banyak request dari IP ini'
});

app.use('/webhook', webhookRateLimit);
```

### 3. Log Percobaan Autentikasi

```javascript theme={null}
app.post('/webhook', (req, res) => {
  const authHeader = req.headers.authorization;
  const clientIP = req.ip;
  
  if (authHeader !== SECRET_KEY) {
    console.error(`Percobaan webhook tidak sah dari IP: ${clientIP}`);
    return res.status(401).json({ error: 'Unauthorized' });
  }
  
  console.log(`Webhook diterima dari IP: ${clientIP}`);
  // Proses webhook...
  res.status(200).send('OK');
});
```

### 4. Gunakan HTTPS di Produksi

<Note>
  Selalu gunakan HTTPS untuk endpoint webhook Anda di lingkungan produksi.
</Note>

* Mengenkripsi data dalam transit
* Mencegah serangan man-in-the-middle
* Standar industri untuk keamanan API

### 5. Rotasi Secret Key Secara Berkala

```javascript theme={null}
// Dukung beberapa secret aktif untuk rotasi
const SECRET_KEYS = [
  process.env.WEBHOOK_SECRET_KEY,
  process.env.WEBHOOK_SECRET_KEY_OLD
];

app.post('/webhook', (req, res) => {
  const authHeader = req.headers.authorization;
  
  if (!SECRET_KEYS.includes(authHeader)) {
    return res.status(401).json({ error: 'Unauthorized' });
  }
  
  // Proses webhook...
  res.status(200).send('OK');
});
```

## Troubleshooting

### Kegagalan Autentikasi

**Gejala:** Selalu menerima error 401

<AccordionGroup>
  <Accordion title="Periksa Secret Key">
    Verifikasi secret key Anda cocok persis dengan yang dikonfigurasi di dashboard CSKU AI.
  </Accordion>

  <Accordion title="Verifikasi Nama Header">
    Pastikan Anda memeriksa header yang benar: `Authorization` (bukan `authorization` dengan huruf kecil).
  </Accordion>

  <Accordion title="Cari Whitespace">
    Trim whitespace dari secret yang disimpan dan header yang diterima.
  </Accordion>

  <Accordion title="Case Sensitivity">
    Secret key bersifat case-sensitive. Periksa perbedaan huruf besar/kecil yang tidak disengaja.
  </Accordion>
</AccordionGroup>

### Mode Debug

```javascript theme={null}
app.post('/webhook', (req, res) => {
  const authHeader = req.headers.authorization;
  
  // Debug logging (nonaktifkan di produksi!)
  console.log('Auth header diterima:', authHeader);
  console.log('Secret yang diharapkan:', SECRET_KEY);
  console.log('Cocok:', authHeader === SECRET_KEY);
  
  if (authHeader !== SECRET_KEY) {
    return res.status(401).json({ error: 'Unauthorized' });
  }
  
  // Proses webhook...
  res.status(200).send('OK');
});
```

<Callout type="error">
  <strong>Penting:</strong> Hapus debug logging sebelum deploy ke produksi untuk menghindari eksposur data sensitif.
</Callout>

## Langkah Keamanan Tambahan

<AccordionGroup>
  <Accordion title="IP Whitelisting">
    Pertimbangkan untuk whitelist alamat IP CSKU AI (hubungi support untuk daftarnya).
  </Accordion>

  <Accordion title="Request Timeout">
    Atur timeout yang wajar untuk mencegah serangan slow HTTP.
  </Accordion>

  <Accordion title="Validasi Payload">
    Validasi struktur dan tipe data dari payload yang masuk.
  </Accordion>

  <Accordion title="Rate Limiting">
    Implementasikan rate limiting per IP untuk mencegah penyalahgunaan.
  </Accordion>
</AccordionGroup>

## Langkah Selanjutnya

<CardGroup cols={2}>
  <Card title="Konfigurasi" icon="settings" href="/webhooks/configuration">
    Siapkan endpoint webhook Anda
  </Card>

  <Card title="Praktik Terbaik" icon="check-circle" href="/webhooks/best-practices">
    Pastikan penanganan webhook yang andal
  </Card>
</CardGroup>

## Dukungan

Butuh bantuan dengan autentikasi webhook?

* Email: [support@csku.ai](mailto:support@csku.ai)
* Dokumentasi: [https://docs.csku.ai](https://docs.csku.ai)
