Claude
Skills
Sign in
Back

api-security

Included with Lifetime
$97 forever

Comprehensive API security guidance covering authentication methods, rate limiting, input validation, CORS, security headers, and protection against OWASP API Top 10 vulnerabilities. Use when designing API authentication, implementing rate limiting, configuring CORS, setting security headers, or reviewing API security.

Backend & APIs

What this skill does


# API Security

Comprehensive guidance for securing APIs, covering authentication, authorization, rate limiting, validation, and protection against common API attacks.

## When to Use This Skill

Use this skill when:

- Choosing API authentication methods
- Implementing rate limiting
- Configuring CORS policies
- Setting security headers
- Validating API inputs
- Preventing data exposure
- Protecting against BOLA/IDOR attacks
- Implementing request signing
- Securing API gateways

## OWASP API Security Top 10 (2023)

| Rank | Vulnerability | Description | Mitigation |
|------|--------------|-------------|------------|
| API1 | Broken Object Level Authorization | Access to unauthorized objects | Object-level authorization checks |
| API2 | Broken Authentication | Authentication flaws | Strong authentication, MFA |
| API3 | Broken Object Property Level Authorization | Excessive data exposure, mass assignment | Response filtering, allowlists |
| API4 | Unrestricted Resource Consumption | DoS via resource exhaustion | Rate limiting, pagination |
| API5 | Broken Function Level Authorization | Access to unauthorized functions | Function-level authz checks |
| API6 | Unrestricted Access to Sensitive Business Flows | Abuse of business logic | Rate limiting, fraud detection |
| API7 | Server Side Request Forgery (SSRF) | Server makes malicious requests | URL validation, allowlists |
| API8 | Security Misconfiguration | Improper configuration | Security hardening, automation |
| API9 | Improper Inventory Management | Unknown/unmanaged APIs | API inventory, versioning |
| API10 | Unsafe Consumption of APIs | Trusting third-party APIs | Validate external responses |

## API Authentication Methods

### Method Comparison

| Method | Use Case | Pros | Cons |
|--------|----------|------|------|
| API Keys | Simple services, internal APIs | Easy to implement | No user context, hard to rotate |
| OAuth 2.0 Bearer Tokens | User-delegated access | Standard, scoped | Token management complexity |
| JWT | Stateless authentication | Self-contained, scalable | Size, revocation challenges |
| mTLS | Service-to-service | Strong identity, encryption | Certificate management |
| HMAC Signatures | Request integrity | Tamper-proof | Implementation complexity |

### API Key Security

```csharp
using System.Security.Cryptography;
using Microsoft.AspNetCore.Http;

/// <summary>
/// API key authentication handler using ASP.NET Core middleware.
/// Uses CryptographicOperations.FixedTimeEquals for timing-safe comparison.
/// </summary>
public sealed class ApiKeyAuthenticationHandler(
    IApiKeyValidator validator,
    ILogger<ApiKeyAuthenticationHandler> logger)
{
    private const string ApiKeyHeader = "X-API-Key";
    private const string ClientIdHeader = "X-Client-ID";

    public async Task<bool> ValidateAsync(HttpContext context, CancellationToken ct = default)
    {
        if (!context.Request.Headers.TryGetValue(ApiKeyHeader, out var apiKeyHeader))
        {
            logger.LogWarning("API key required but not provided");
            return false;
        }

        var apiKey = apiKeyHeader.ToString();
        var clientId = context.Request.Headers[ClientIdHeader].ToString();

        // Hash the provided key
        var providedHash = SHA256.HashData(System.Text.Encoding.UTF8.GetBytes(apiKey));

        // Retrieve stored hash for this client
        var storedHash = await validator.GetKeyHashAsync(clientId, ct);
        if (storedHash is null)
        {
            logger.LogWarning("No stored key found for client {ClientId}", clientId);
            return false;
        }

        // Timing-safe comparison to prevent timing attacks
        if (!CryptographicOperations.FixedTimeEquals(providedHash, storedHash))
        {
            logger.LogWarning("Invalid API key for client {ClientId}", clientId);
            return false;
        }

        return true;
    }
}

public interface IApiKeyValidator
{
    Task<byte[]?> GetKeyHashAsync(string clientId, CancellationToken ct = default);
}

// Best practices for API keys:
// 1. Use sufficiently long, random keys (32+ bytes)
// 2. Transmit only over HTTPS
// 3. Store hashed, not plaintext
// 4. Implement key rotation
// 5. Scope keys to specific operations
// 6. Rate limit per key
```

### Request Signing (HMAC)

```csharp
using System.Security.Cryptography;
using System.Text;

/// <summary>
/// HMAC-SHA256 request signer for API authentication.
/// Generates and verifies request signatures for tamper-proof requests.
/// </summary>
public sealed class RequestSigner
{
    private readonly string _apiKey;
    private readonly byte[] _secretKey;

    public RequestSigner(string apiKey, string secretKey)
    {
        _apiKey = apiKey;
        _secretKey = Encoding.UTF8.GetBytes(secretKey);
    }

    /// <summary>
    /// Generate signature headers for a request.
    /// </summary>
    public Dictionary<string, string> SignRequest(string method, string path, string body = "")
    {
        var timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString();
        var stringToSign = $"{method}\n{path}\n{timestamp}\n{body}";

        using var hmac = new HMACSHA256(_secretKey);
        var signature = hmac.ComputeHash(Encoding.UTF8.GetBytes(stringToSign));

        return new Dictionary<string, string>
        {
            ["X-API-Key"] = _apiKey,
            ["X-Timestamp"] = timestamp,
            ["X-Signature"] = Convert.ToBase64String(signature)
        };
    }
}

/// <summary>
/// Verifies HMAC-SHA256 request signatures.
/// </summary>
public sealed class SignatureVerifier(ISecretKeyProvider secretProvider)
{
    private static readonly TimeSpan MaxClockSkew = TimeSpan.FromMinutes(5);

    /// <summary>
    /// Verify request signature with timing-safe comparison.
    /// </summary>
    public async Task<bool> VerifyAsync(
        string apiKey,
        string timestamp,
        string signature,
        string method,
        string path,
        string body = "",
        CancellationToken ct = default)
    {
        // Check timestamp freshness (5-minute window)
        if (!long.TryParse(timestamp, out var requestTime))
            return false;

        var requestDateTime = DateTimeOffset.FromUnixTimeSeconds(requestTime);
        if (Math.Abs((DateTimeOffset.UtcNow - requestDateTime).TotalSeconds) > MaxClockSkew.TotalSeconds)
            return false;

        // Retrieve secret key for this API key
        var secretKey = await secretProvider.GetSecretAsync(apiKey, ct);
        if (secretKey is null)
            return false;

        // Regenerate expected signature
        var stringToSign = $"{method}\n{path}\n{timestamp}\n{body}";
        using var hmac = new HMACSHA256(secretKey);
        var expected = hmac.ComputeHash(Encoding.UTF8.GetBytes(stringToSign));

        // Timing-safe comparison to prevent timing attacks
        var provided = Convert.FromBase64String(signature);
        return CryptographicOperations.FixedTimeEquals(expected, provided);
    }
}

public interface ISecretKeyProvider
{
    Task<byte[]?> GetSecretAsync(string apiKey, CancellationToken ct = default);
}
```

## Rate Limiting

### Rate Limiting Strategies

| Strategy | Description | Use Case |
|----------|-------------|----------|
| Fixed Window | Count requests in fixed time windows | Simple, predictable |
| Sliding Window | Rolling window of requests | Smoother limits |
| Token Bucket | Tokens replenish over time | Allow bursts |
| Leaky Bucket | Requests processed at fixed rate | Smooth traffic |

### Implementation (Token Bucket with ASP.NET Core)

```csharp
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.RateLimiting;
using StackExchange.Redis;
using System.Threading.RateLimiting;

/// <summary>
/// Token bucket rate limiting result.
/// </summary>
public sealed record RateLimitResult(
    bool IsAllowed,
    int Remaining,
    long ResetTimeUnix,
    int RetryAfterSeconds = 0);

/// <summary>
/// Token bucket rat

Related in Backend & APIs