# Security Guide

Security best practices for AuxCORE integration.

---

## 🔐 API Security

### Protect API Keys
- Store in environment variables
- Never commit to git
- Rotate regularly (create a new key at `/settings/developer/api-keys`, deploy it, then revoke the old one)
- Use different keys per environment (Sandbox `uat.auxcore.net` and Production `app.auxcore.net` keys are separate)
- Only SDK public keys (`lpk_live_…`) may appear in browser code; configure their allowed origins so they are refused from other sites (requests without `Origin` / `X-Merchant-Origin` are then rejected with 403)

### Use HTTPS
- All API calls over HTTPS
- Verify SSL certificates
- No HTTP fallbacks

### Respect Rate Limits
- The gateway answers `429` when a limit is hit; token/checkout endpoints allow 30 requests per 15 minutes per IP, OTP generate/resend 10 per hour
- Read the standard `RateLimit-*` response headers and back off exponentially
- Monitor for anomalies

---

## 💳 Payment Security

### PCI Compliance
- Never store full card numbers
- Collect cards with the PCI SDK (`https://vault.auxcore.net/sdk/auxVault.js`) and send only `pci_tok_…` tokens — raw `CardNumber` is rejected with `400 PCI_SCOPE_VIOLATION`
- Server-side `POST /api/v1/public/tokenize-card` accepts raw card data and requires a secret key; using it puts your servers in PCI scope
- Don't log sensitive data
- Follow PCI DSS guidelines

### Verify Webhooks
Every delivery carries `X-Webhook-Signature: t=<unix>,v1=<hex>`. Recompute HMAC-SHA256 over `"<t>.<raw body>"` with the endpoint's signing secret, compare in constant time, and reject timestamps more than 5 minutes away from the current time, including future timestamps.

Copy the complete `verifySignature()` helper from the [Node.js webhook example](../examples/nodejs.md#webhook-handler-express) into your server code and reuse it across handlers. It validates header types, a positive safe-integer timestamp and a 64-character hexadecimal signature before comparing equal-length buffers. Missing or malformed input returns `false`.

```javascript
// Inside a route mounted with express.raw({ type: 'application/json' }).
const rawBody = req.body.toString('utf8');
if (!verifySignature(rawBody, req.headers['x-webhook-signature'], secret)) {
  return res.status(401).send('Invalid signature');
}
```

Register the raw-body route before `express.json()` and validate your signing-secret configuration at startup. Parse JSON only after verification. Deduplicate `event.id` using an atomic insert into a durable inbox with a unique constraint; return `2xx` only after the event is stored for processing, including duplicate deliveries. Storage failures must return `5xx` so the sender can retry. Make worker side effects idempotent as well. See the [integration guide](./integration-guide.md#phase-4-webhooks) for the receiver pattern.

---

## 🛡️ Fraud Prevention

- Enable AVS/CVV filters
- Set transaction limits
- Monitor for suspicious patterns
- Use risk scoring

---

**Need help?** Contact support@auxcore.net
