# Security Recommendations

> **Tip:**
>
> **Using [ALTCHA Sentinel](/docs/sentinel/) or [ALTCHA Cloud](/docs/cloud/)?** Replay protection, challenge expiration, and rate limiting are already handled for you. The recommendations below mainly apply if you're running a **custom integration** — generating and verifying challenges on your own server without Sentinel or Cloud.

## Replay Attacks

To defend against replay attacks—where a client resubmits a previously valid solution—your server must ensure that each challenge is single-use.

Maintain a registry (e.g., in-memory store or database) of solved challenges, and reject any attempt to reuse a challenge that has already been accepted.

Use a short [challenge expiration](#challenge-expiration) to limit how long a challenge remains valid. In combination with expiration, your registry can automatically discard entries after the same duration.

As a general guideline, set the expiration time between 20 minutes and 1 hour.

### Replay Attacks with Server Signatures

This applies if you verify Sentinel/Cloud payloads yourself using `verifyServerSignature` from a [library](/docs/integration/server/), rather than the verification endpoint below.

When using Sentinel or Cloud, your backend receives a *server signature* instead of a proof-of-work solution. This signature must be verified cryptographically.

To prevent reuse, maintain a registry of processed payloads. Use the unique `id` field from the payload, along with the signed `verificationData` object, as the key in this registry.

By default, Sentinel and Cloud set a challenge expiration of 20 minutes, which can be adjusted using the `expires` parameter in the Security Group settings.
Your registry should retain entries for at least the same duration as the configured expiration time.

> **Note:**
>
> If you instead call the [`POST /v1/verify/signature`](/sentinel-api-docs-v1.html#tag/verify/post/v1/verify/signature) endpoint (recommended), replay protection is built in and you don't need to maintain your own registry.

## Challenge Expiration

Challenge expiration (via the `expiresAt` parameter) ensures that challenges cannot be reused after a defined period. This reduces the window of opportunity for attackers.

For custom integrations, set this when generating the challenge on your server. Sentinel and Cloud set a default expiration of 20 minutes, configurable via the `expires` parameter in the Security Group settings.

## Rate Limiting

Implement rate limiting to mitigate brute-force and denial-of-service (DoS) attacks. This helps prevent malicious clients from overwhelming your system with excessive requests.

This applies to custom challenge-generation and verification endpoints. Sentinel and Cloud include built-in rate limiting, configurable via the Security Group settings.
