From 37d32c2226e76f5e5a9ec81abf92e029a1706d97 Mon Sep 17 00:00:00 2001 From: Matt Williams Date: Fri, 22 Aug 2025 14:12:04 -0500 Subject: [PATCH 01/27] Add security learning center card and API design-first security guide - Created new Security learning center card in cards.ts - Added learn/security/ directory with proper structure - Added comprehensive API design-first security guide article covering TLS, input validation, rate limiting, and access control - Fixed TOC navigation by removing bold formatting from headings - Removed confusing Mermaid diagrams per feedback - Added proper anchor links for deep navigation - Updated sidebars.yaml and created security index page --- .../api-design-first-security-guide.md | 889 ++++++++++++++++++ learn/security/index.md | 13 + learn/security/sidebars.yaml | 2 + .../testing/tools-for-api-testing-in-2025.md | 369 ++++++++ pages/learning-center/cards.ts | 29 +- 5 files changed, 1286 insertions(+), 16 deletions(-) create mode 100644 learn/security/api-design-first-security-guide.md create mode 100644 learn/security/index.md create mode 100644 learn/security/sidebars.yaml create mode 100644 learn/testing/tools-for-api-testing-in-2025.md diff --git a/learn/security/api-design-first-security-guide.md b/learn/security/api-design-first-security-guide.md new file mode 100644 index 00000000..f13ad9b0 --- /dev/null +++ b/learn/security/api-design-first-security-guide.md @@ -0,0 +1,889 @@ +# Secure APIs by Design: A Guide to TLS, Validation & Rate Limiting with OpenAPI + +_Build secure APIs from the ground up using OpenAPI security contracts and automated governance._ + +--- + + +## Key Takeaways + +Many teams discover security vulnerabilities after they're already in production, but it doesn't have to be that way! + +In this guide, we'll walk though how to turn your OpenAPI specification into a security contract that actually gets enforced. We'll give some tips and tricks on setting up TLS encryption, implementing input validation, defining rate limiting policies, and configuring access control. By the time you're done, you'll know how to catch some security issues during the design phase instead of scrambling to fix them once they're in production. + +**We'll cover how to:** +- Transform your OpenAPI specs into executable security policies +- Automate security enforcement in your CI/CD pipeline +- Reduce vulnerability discovery time (from months to minutes in some cases) +- Build APIs that are secure by design upfront + +--- + + +## From Reactive Patching to Proactive API Security + +High-profile data breaches frequently trace back to insecure APIs, exposing a fundamental flaw in traditional security approaches. The conventional method — identifying and patching vulnerabilities in production — is reactive, costly, and ultimately inadequate. In it's typical (and more common then we'd like) form, this paradigm treats security as more of an afterthought. + +### OpenAPI as Your Security Contract + +The core of this strategy is treating your OpenAPI specification not as only documentation, but also as an executable security contract. This contract declaratively defines the complete set of security requirements, constraints, and policies before any application code is written. It becomes the single source of truth that dictates how an API must behave to be considered secure. + +However, a contract, much like a law, is only as strong as its enforcement. This is where [Redocly CLI](https://redocly.com/docs/cli/) governance and linting capabilities can provide value by making your contract into dynamic, automated guardrails that validate security requirements at every stage of development. + +*OpenAPI specifications are validated by Redocly governance engine in CI/CD pipeline, failing builds for security violations and requiring fixes before deployment.* + + +## Building Secure API Infrastructure: The Technical Foundation + +Building secure APIs doesn't have to feel like playing whack-a-mole with vulnerabilities. Once you shift from reactive patching to proactive design, you'll wonder why you ever did it any other way. Let's explore how to make security an automatic part of your API development process. + +Let's look at 4 key areas: + +1. **TLS Encryption** - Protecting data in transit with enforced HTTPS +2. **Input Validation** - Rejecting malicious data through schema contracts +3. **Rate Limiting** - Preventing abuse with documented policies +4. **Access Control** - Defining authentication and authorization schemes + +Where these areas are codified in your OpenAPI specification and enforced through automated governance, they provide a foundation for APIs that are secure by design - something we very much endorse! + +```mermaid +graph TD + A["🏛️ Secure API Foundation"] --> B["🔐 TLS Encryption
Data in Transit"] + A --> C["✅ Input Validation
Schema Contracts"] + A --> D["⚡ Rate Limiting
Abuse Prevention"] + A --> E["🔑 Access Control
Auth & Authorization"] + + B --> F["• HTTPS Enforcement
• Certificate Management
• Strong Cipher Suites"] + C --> G["• JSON Schema Rules
• Type Validation
• Length Constraints"] + D --> H["• x-rate-limit Extensions
• 429 Response Headers
• Multi-tier Limits"] + E --> I["• Security Schemes
• JWT/OAuth2
• Scope Management"] + + J["📄 OpenAPI 3.1
Specification"] --> A + K["⚙️ Redocly
Governance"] --> A + + style A fill:#e8f5e8 + style B fill:#e3f2fd + style C fill:#fff3e0 + style D fill:#fce4ec + style E fill:#f1f8e9 + style J fill:#e1f5fe + style K fill:#f3e5f5 +``` + +*Architecture diagram showing the four essential areas of API security (TLS encryption, input validation, rate limiting, access control) supported by OpenAPI specifications and Redocly governance automation.* + + +## TLS Encryption: Protecting Data in Transit with OpenAPI + +When a client and an API exchange information, that data travels across the internet, a public network. Without protection, this data gets intercepted and read by malicious actors. This is where encryption comes in. + +> **The Banking Vault Principle**: When banks transfer large sums between branches, they don't send cash in regular envelopes. They use armored vehicles with multiple security layers. TLS encryption works similarly — it creates a secure transport layer that protects your API data during transit, even across untrusted networks. + +**Encryption in transit** works similarly, creating a secure, private tunnel for API data as it moves between the client and the server. + +### TLS 1.3: The Modern Standard + +This secure tunnel is primarily established using Transport Layer Security (TLS) version 1.3, as specified in IETF RFC 8446. Any modern API security guidance must unequivocally mandate TLS 1.3, as older protocols—including all versions of SSL, TLS 1.0, and TLS 1.1—are deprecated and considered insecure due to known vulnerabilities. + +When a client connects to an API over `https://`, it initiates a "TLS handshake." During this handshake, the client and server perform crucial steps: + +1. **Authentication:** The server presents its TLS certificate to the client to prove its identity, ensuring the client is talking to the legitimate server and not an impostor. +2. **Agreement on Encryption:** They agree on a set of cryptographic algorithms (a "cipher suite") to use for the session. +3. **Key Exchange:** They securely generate and exchange unique session keys that will be used to encrypt and decrypt all data for the remainder of the conversation. + +We're not going to get all the way into it in this article, but here is what the handshake looks like: + +### TLS Handshake Process + +```mermaid +sequenceDiagram + participant C as Client + participant S as Server + + Note over C,S: TLS Handshake Process + + C->>S: 1. Client Hello (Supported cipher suites) + + S->>C: 2. Server Hello + Certificate + Note right of S: Server presents TLS certificate to prove identity + + C->>C: 3. Certificate Validation + Note left of C: Client verifies server certificate is trusted + + C->>S: 4. Cipher Suite Selection + Note over C,S: Both agree on cryptographic algorithms + + C->>S: 5. Key Exchange + S->>C: 6. Key Exchange Complete + Note over C,S: Generate and exchange unique session keys + + Note over C,S: 🔒 Secure Communication Begins + + C->>S: Encrypted API Request + S->>C: Encrypted API Response + +``` + +*Sequence diagram illustrating the TLS handshake process between client and server, showing certificate validation, cipher suite selection, and secure key exchange that ensures encrypted API communication.* + +### TLS Security Guarantees + +TLS, when done right, provides three essential security guarantees: + +* **Confidentiality:** It encrypts the data, preventing eavesdroppers from reading it. +* **Integrity:** It ensures that the data has not been altered or tampered with during transit. +* **Authentication:** It verifies the identity of the server, protecting against man-in-the-middle attacks. + +This is why secure APIs always use URLs that start with `https://` instead of `http://`. The 's' stands for 'secure' and indicates that the connection is protected by TLS encryption. + +### TLS Implementation Best Practices + +In our production environments, we've learned that telling teams to "use HTTPS" without specifics sometimes leads to misconfigured TLS and a false sense of security. Proper TLS implementation requires: + +* **Enforcing Strong Cipher Suites**: Configure servers to only negotiate cryptographic algorithms that are considered secure, disabling weak or obsolete ciphers +* **Proper Certificate Management**: Use certificates from trusted Certificate Authorities (CAs), ensure they are not expired, and implement robust processes for certificate issuance, renewal, and revocation +* **Protection Against Man-in-the-Middle (MiTM) Attacks**: Implement HTTP Strict Transport Security (HSTS) to instruct browsers to only communicate over HTTPS, preventing protocol downgrade attacks + +#### Common TLS misconfigurations + +* Weak or legacy protocols enabled (SSL, TLS 1.0/1.1) — disable them explicitly +* Missing HSTS header — add Strict-Transport-Security with long max-age +* Mixed content or accidental HTTP endpoints — redirect to HTTPS at the edge +* Expiring certificates — monitor expiry and automate renewal + +Quick checks: + +```bash +# Verify protocol and cipher suites +openssl s_client -connect api.example.com:443 -tls1_3 -cipher 'TLS_AES_256_GCM_SHA384' < /dev/null | grep -E 'Protocol|Cipher' + +# Scan for common TLS issues +testssl.sh --fast https://api.example.com +``` + +> Expert insight: "Treat TLS as a product with owners and SLAs. We track TLS health on dashboards the same way we track latency and errors." + +### Enforcing HTTPS in Your API Specification + +The security contract for encrypted transit begins within the `servers` object of your OpenAPI specification. Every URL defined here must use the `https://` scheme—this isn't just documentation, it's a formal declaration of your API's secure endpoints. + +**OpenAPI Servers Declaration:** +```yaml +# openapi.yaml +servers: + - url: https://api.production.com/v1 + description: Production Server + - url: https://api.staging.com/v1 + description: Staging Server +``` + +**Redocly Governance Enforcement:** + +For complete configuration options, see the [Redocly CLI configuration guide](https://redocly.com/docs/cli/configuration/). + +```yaml +# redocly.yaml - Advanced TLS enforcement +extends: + - recommended + +rules: + # Built-in rule: Ensure HTTPS usage + no-http-verbs-in-paths: error + + # Custom rule: Enforce production domain patterns + rule/enforce-production-tls: + subject: + type: Server + property: url + assertions: + pattern: "^https://api\\.(production|staging)\\.com" + message: "Server URLs must use https:// and point to approved domains." + severity: error +``` + +When integrated into your CI/CD pipeline, this configuration creates an automated security gate. If a developer attempts to commit an OpenAPI file with `http://api.production.com` or `https://api.dev.internal`, the pipeline fails with a clear error message, preventing insecure configurations from ever reaching production. + +*Redocly governance fails a CI/CD build if an OpenAPI spec uses HTTP instead of HTTPS, requiring developers to fix security violations before deployment.* + +### TLS Configuration Examples + +**Nginx Configuration:** +```nginx +server { + listen 443 ssl http2; + server_name api.example.com; + + # TLS 1.3 only + ssl_protocols TLSv1.3; + + # Strong cipher suites + ssl_ciphers TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256; + + # HSTS header + add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; + + # Certificate files + ssl_certificate /path/to/certificate.crt; + ssl_certificate_key /path/to/private.key; +} +``` + +**Express.js Configuration:** +```javascript +const https = require('https'); +const fs = require('fs'); +const express = require('express'); + +const app = express(); + +// HSTS middleware +app.use((req, res, next) => { + res.setHeader('Strict-Transport-Security', 'max-age=31536000; includeSubDomains'); + next(); +}); + +const options = { + key: fs.readFileSync('private.key'), + cert: fs.readFileSync('certificate.crt'), + // Force TLS 1.3 + secureProtocol: 'TLSv1_3_method' +}; + +https.createServer(options, app).listen(443); +``` + +### Attack Example: Heartbleed (TLS library vulnerability, 2014) + +These attacks are both real and can be problematic. Heartbleed (CVE-2014-0160) allowed attackers to read server memory via malformed TLS heartbeat messages. Real incidents, including the Canada Revenue Agency breach, demonstrated how secrets (keys, cookies) could be exfiltrated. + +```mermaid +sequenceDiagram + participant A as Attacker + participant S as Vulnerable Server (OpenSSL) + + A->>S: TLS handshake + A->>S: Malformed Heartbeat Request (len >> data) + S-->>A: Memory contents leak (keys, session cookies) + A->>S: Follow-on requests using stolen secrets +``` + +*Sequence diagram showing the Heartbleed attack: malformed TLS heartbeat requests cause vulnerable OpenSSL servers to leak memory contents including encryption keys and session data.* + +Why this matters: TLS is only as strong as its implementation. Monitoring and rapid patching for library CVEs are part of infrastructure security. + +--- + + +## Input Validation: Preventing Injection Attacks with Schema-Based Security + +APIs are designed to accept data as input. However, an API should never blindly trust the data it receives from a client. The process of rigorously checking all incoming data is called data validation. NIST defines data validation as "The process of determining that data...is acceptable according to a predefined set of tests and the results of those tests." + +### The Restaurant Waiter Analogy + +> **The Restaurant Waiter**: The API is the waiter, and its documentation (or schema) is the menu. The menu explicitly states what can be ordered and in what format (e.g., "Steak - medium rare"). If a customer tries to order something not on the menu, like "a bicycle," or provides an invalid option, like "a million steaks," a competent waiter will immediately reject the order at the table before it ever reaches the kitchen. This is data validation. + +### Technical Implementation of Data Validation + +In technical terms, data validation is the practice of checking all incoming data from a client to ensure it conforms to the expected format, type, range, and other constraints before it is processed by the application's business logic. + +For example, if an API endpoint expects a user's age, validation rules should ensure the input is an integer and falls within a reasonable range (e.g., 0-130). + +Proper data validation is a critical defense against a wide range of attacks, notably **Injection flaws**. An injection attack occurs when a malicious actor sends executable code disguised as data. + +If the API fails to validate the input and passes it directly to a database or the operating system, that malicious code could be executed. By strictly validating that all inputs are what they are supposed to be, an API can reject malicious payloads before they can do any harm. + +### SQL Injection Prevention + +For interactions with a database, the gold standard for preventing SQL injection attacks is the use of parameterized queries, also known as prepared statements. + +A parameterized query forces a separation between the SQL command (the code) and the user-supplied data, making it impossible for an attacker to alter the logic of the query. + +**Vulnerable Code (Never Do This):** +```python +# DANGEROUS: Directly interpolating user input +user_id = request.get('user_id') +query = f"SELECT * FROM users WHERE id = {user_id}" +cursor.execute(query) +``` + +**Secure Code (Use Parameterized Queries):** +```python +# SAFE: Using parameterized queries +user_id = request.get('user_id') +query = "SELECT * FROM users WHERE id = ?" +cursor.execute(query, (user_id,)) +``` + +### Schema-Based Validation as Security Contract + +OpenAPI 3.1 provides a comprehensive vocabulary for defining strict validation rules by leveraging JSON Schema Draft 2020-12. By codifying these rules directly in your API specification, validation becomes core to your API's design. + +**Secure Schema Example:** +```yaml +# openapi.yaml +components: + schemas: + NewUser: + type: object + additionalProperties: false # Prevent mass assignment + required: + - username + - email + - password + - age + properties: + username: + type: string + minLength: 4 + maxLength: 20 + pattern: "^[a-zA-Z0-9]+$" # Alphanumeric only + email: + type: string + maxLength: 254 + format: email + password: + type: string + minLength: 12 + maxLength: 128 + age: + type: integer + minimum: 18 + maximum: 130 + role: + type: string + enum: ["user", "viewer"] + default: "user" +``` + +**Redocly Governance for Validation:** + +Detailed rule configuration is available in the [Redocly CLI rules documentation](https://redocly.com/docs/cli/rules/). + +```yaml +# redocly.yaml - Enforce security validation standards +extends: + - recommended-strict + +rules: + # Rule 1: All strings must have length bounds + rule/string-must-have-maxLength: + subject: + type: Schema + where: + - subject: + property: type + assertions: + const: string + assertions: + required: + - maxLength + message: "All string properties must have 'maxLength' to prevent resource exhaustion." + severity: error + + # Rule 2: All numbers must have ranges + rule/number-must-have-range: + subject: + type: Schema + where: + - subject: + property: type + assertions: + enum: [number, integer] + assertions: + required: [minimum, maximum] + message: "Numeric properties must have 'minimum' and 'maximum' defined." + severity: error + + # Rule 3: Prevent mass assignment vulnerabilities + rule/no-additional-properties: + subject: + type: Schema + where: + - subject: + property: type + assertions: + const: object + assertions: + property: + additionalProperties: + const: false + message: "Objects must set 'additionalProperties: false' to prevent mass assignment." + severity: error +``` + +This governance approach changes security reviews. Instead of manually checking many properties for missing `maxLength` constraints, automated linting with [Redocly Workflows](https://redocly.com/workflows) handles baseline validation so security teams can focus on strategic concerns like business logic and context-dependent risks. + +### JSON Schema Security Keywords + +| Keyword | Purpose | Security Implication | +|---------|---------|---------------------| +| `type` | Constrains data type | Prevents type confusion attacks | +| `pattern` | Enforces regex on strings | Fine-grained control against injection | +| `maxLength/minLength` | Constrains string/array length | Mitigates DoS and buffer overflow | +| `maximum/minimum` | Constrains numeric ranges | Prevents integer overflows | +| `enum` | Restricts to predefined values | Blocks unexpected/malicious values | +| `required` | Mandates property presence | Ensures critical data elements exist | +| `additionalProperties: false` | Prohibits undeclared properties | Defense against mass assignment | + +### Common Validation Patterns + +| Input Type | Validation Rules | Example | +|------------|------------------|---------| +| Email | RFC 5322 format | `user@example.com` | +| Phone | E.164 format | `+1234567890` | +| URL | Valid URL scheme | `https://example.com` | +| UUID | Standard UUID format | `123e4567-e89b-12d3-a456-426614174000` | +| Date | ISO 8601 format | `2025-01-20T10:30:00Z` | +| Password | Minimum complexity | 8+ chars, mixed case, numbers, symbols | + +#### Validation troubleshooting and common pitfalls + +* Missing bounds (no `maxLength`, no numeric ranges) — leads to resource exhaustion +* Overly permissive regex patterns — allow unwanted characters and injection payloads +* Validating at the wrong layer — front-end only, or after DB calls +* Accepting undeclared properties — enables mass assignment + +Quick fixes: + +```yaml +# JSON Schema example: tighten strings and numeric bounds +type: object +additionalProperties: false +properties: + name: + type: string + minLength: 1 + maxLength: 100 + pattern: "^[a-zA-Z\\s]+$" + age: + type: integer + minimum: 0 + maximum: 130 +``` + +> Redocly insight: "We block PRs that add new string fields without `maxLength`. It's the cheapest guardrail against abuse." + +### Attack Example: Equifax (OGNL injection via Apache Struts, 2017) + +Here's another one. An input validation and deserialization flaw (CVE-2017-5638) in Apache Struts allowed attackers to inject OGNL expressions via the `Content-Type` header, leading to remote code execution and data exfiltration. + +```mermaid +sequenceDiagram + participant A as Attacker + participant W as WAF (misconfigured) + participant S as Struts App (vulnerable) + participant DB as Database + + A->>W: HTTP request with malicious Content-Type header + W-->>S: Pass-through (no block) + A->>S: OGNL payload evaluated + S->>S: Remote code execution + S->>DB: Query PII at scale + DB-->>A: Exfiltrated records (PII) +``` + +*Sequence diagram illustrating the Equifax breach: attacker exploited Apache Struts vulnerability through OGNL injection in Content-Type headers, bypassing WAF and executing code to steal personal data.* + +Why this matters: Strong schema validation, input allow-lists, and patch hygiene block entire classes of injection attacks. + +--- + + +## Rate Limiting: Preventing DoS and Abuse with API Policies + +A single client, whether intentionally malicious or simply due to a bug in its code, can send a massive number of requests to an API in a short period. This can overwhelm the server, degrading performance for all other users or even causing the service to crash. Rate limiting is the primary defense against this scenario. + +### The Library Card Analogy + +> **The Library Card**: A library card allows a patron to check out a maximum of ten books per month. Once that limit is reached, the system will not allow any more checkouts until the next month begins, regardless of how many times the patron asks. + +**Rate limiting** applies this same principle to an API. It establishes a policy that restricts the number of requests a single client can make within a specific time window (e.g., 100 requests per minute). + +### Documenting Rate Limits in OpenAPI + +While OpenAPI 3.1 doesn't include native rate-limiting objects, extension properties (prefixed with `x-`) provide a standard mechanism. The best practice is defining custom `x-rate-limit` extensions at the operation level: + +```yaml +# openapi.yaml +paths: + /auth/login: + post: + summary: User Login + tags: [Authentication] + # Define rate-limiting policy for this sensitive endpoint + x-rate-limit: + limit: 5 + window: "1m" + scope: "ip_address" + description: "Limits login attempts to 5 per minute per IP to prevent brute-force attacks." + responses: + '200': + description: "Successful login." + # Document the 429 response with proper headers + '429': + description: "Too Many Requests. Rate limit exceeded." + headers: + Retry-After: + schema: + type: integer + description: "Seconds to wait before making a new request." + X-RateLimit-Limit: + schema: + type: integer + description: "Maximum requests permitted in the window." + X-RateLimit-Remaining: + schema: + type: integer + description: "Requests remaining in current window." +``` + +**Redocly Governance for Rate Limiting:** +```yaml +# redocly.yaml +rules: + # Require rate limits on authentication endpoints + rule/require-rate-limit-on-auth: + subject: + type: Operation + where: + - subject: + property: tags + assertions: + contains: "Authentication" + assertions: + defined: + - x-rate-limit + message: "Authentication operations must have 'x-rate-limit' policy defined." + severity: error +``` + +This approach provides dual benefits: [Redocly's API Reference Docs](https://redocly.com/reference-docs) automatically displays the `x-rate-limit` object in generated documentation, making policies transparent to API consumers, while governance rules ensure sensitive endpoints never lack rate-limiting policies. + +### Why Rate Limiting Is Critical + +Rate limiting serves two crucial purposes: + +1. **Security:** It is a vital defense against automated attacks. It can thwart **Denial-of-Service (DoS)** attacks, where an attacker attempts to make a service unavailable by flooding it with traffic, which relates to **API4:2023 - Unrestricted Resource Consumption**. It also makes **brute-force** attacks against authentication endpoints (i.e., guessing passwords) much slower and less effective. Furthermore, it helps mitigate business logic abuse by preventing bots from, for example, scraping all product pricing data or buying up an entire inventory of limited-stock items, addressing **API6:2023 - Unrestricted Access to Sensitive Business Flows**. +2. **Reliability and Fair Usage:** It ensures that the API remains stable and responsive for all users by preventing any single client from monopolizing server resources. This guarantees a better and more equitable quality of service for everyone. + +### Rate Limiting Implementation Approaches + +**Common Algorithm Types:** +- **Token Bucket**: Allows burst traffic within limits, refills at steady rate +- **Sliding Window**: Precise per-window enforcement with distributed request tracking +- **Fixed Window**: Simple per-timeframe limits, prone to boundary conditions + +**Multi-tier Strategy:** +```yaml +# API Gateway configuration example +rate_limits: + global: + requests_per_minute: 1000 + requests_per_hour: 10000 + by_endpoint: + "/auth/*": + requests_per_minute: 5 + requests_per_hour: 20 + "/api/data": + requests_per_minute: 100 +``` + +### Advanced Rate Limiting Techniques + +**Multi-tier Rate Limiting:** +```yaml +# API Gateway configuration (Kong example) +plugins: +- name: rate-limiting + config: + minute: 100 # 100 requests per minute per IP + hour: 1000 # 1000 requests per hour per IP + policy: redis # Use Redis for distributed rate limiting + fault_tolerant: true + hide_client_headers: false + +# Per-endpoint overrides +- name: rate-limiting + route: auth-endpoints + config: + minute: 5 # Stricter limits for auth endpoints + hour: 20 +``` + +**Client-side Exponential Backoff:** +```javascript +class APIClient { + async makeRequest(url, options, retries = 3) { + try { + const response = await fetch(url, options); + + if (response.status === 429) { + const retryAfter = response.headers.get('Retry-After'); + const delay = retryAfter ? parseInt(retryAfter) * 1000 : + Math.pow(2, 4 - retries) * 1000; // Exponential backoff + + if (retries > 0) { + await new Promise(resolve => setTimeout(resolve, delay)); + return this.makeRequest(url, options, retries - 1); + } + + throw new Error('Rate limit exceeded'); + } + + return response; + } catch (error) { + throw error; + } + } +} +``` + +As a complementary practice, the client-side responsibility of implementing exponential backoff should also be noted. When an API client receives a rate-limiting error (e.g., HTTP 429 Too Many Requests), it should wait for an exponentially increasing period of time between retries. This prevents clients from overwhelming the server and helps the system recover gracefully from load spikes. + +> **Tip:** Combine per-IP and per-account quotas and require exponential backoff on clients. + +### Attack Example: Facebook phone number scraping (2019 dataset) + +How has rate limiting mistakes been exploted? Funny you should ask! Here's one that happened at Facebook. Attackers enumerated user data through contact import and related endpoints with insufficient rate limiting and anomaly detection, leading to the aggregation of hundreds of millions of records that later appeared publicly. + +```mermaid +sequenceDiagram + participant B as Botnet/Script + participant API as Contact Import API + + loop Enumerate phone numbers + B->>API: Batch upload numbers + API-->>B: Matched user IDs/profile data + end + Note over B,API: Missing per-account/IP limits and anomaly detection +``` + +*Sequence diagram showing how attackers used Facebook's contact import API to scrape phone numbers at scale, exploiting missing rate limits and velocity checks to harvest personal data.* + +Why this matters: Rate limiting, velocity checks, and behavior analytics are core defenses against scraping and credential-stuffing at scale. + +--- + +### Defining Security Schemes in OpenAPI + +OpenAPI 3.1 provides a robust framework for defining access control through two primary constructs: + +1. **`components.securitySchemes`**: Defines *how* clients can authenticate (JWT Bearer, OAuth2, API Keys) +2. **`security`**: Specifies *that* an endpoint is secured and by which mechanism(s) + +**JWT Bearer Token Example:** +```yaml +# openapi.yaml +components: + securitySchemes: + bearerAuth: + type: http + scheme: bearer + bearerFormat: JWT + description: "Enter JWT with 'Bearer ' prefix" + +# Apply globally to all operations +security: + - bearerAuth: [] +``` + +**OAuth2 with Scopes Example:** +```yaml +# openapi.yaml +components: + securitySchemes: + oauth2Auth: + type: oauth2 + description: "OAuth2 Authorization Code Flow with PKCE" + flows: + authorizationCode: + authorizationUrl: https://auth.example.com/authorize + tokenUrl: https://auth.example.com/token + scopes: + 'users:read': "Read access to user profiles" + 'users:write': "Modify user profiles" + +paths: + /users/{userId}: + patch: + summary: "Update user profile" + security: + - oauth2Auth: ['users:write'] # Requires specific scope +``` + +### Redocly Governance for Access Control + +The most critical built-in security rule is `security-defined`, which ensures every operation is covered by a security requirement: + +```yaml +# redocly.yaml +extends: + - recommended + +rules: + # Ensure no endpoint is accidentally left unsecured + security-defined: error + + # Custom rule: Require security on sensitive operations + rule/require-auth-on-mutations: + subject: + type: Operation + where: + - subject: + property: method + assertions: + enum: [post, put, patch, delete] + assertions: + defined: [security] + message: "All write operations must have security defined." + severity: error +``` + +When `redocly lint` runs, any endpoint without a corresponding `security` block causes the build to fail, preventing the most common API vulnerability: the unintentionally public endpoint. + +### Security Definitions as Configuration + +Defining security schemes in OpenAPI extends beyond documentation—it establishes configuration-as-code that drives consistency across your entire API ecosystem: + +- **API Gateways** (Kong, Apigee) import OpenAPI files and automatically configure JWT validation based on `securitySchemes` +- **Code generators** create boilerplate authentication handling +- **Testing tools** automate authenticated requests +- **Redocly's "Try it" console** renders appropriate UI for each scheme type + +This unified approach ensures the security policy defined in design is the same policy implemented, documented, tested, and enforced in production. + +#### Access control troubleshooting and common pitfalls + +* Missing security definitions — endpoints accidentally left public +* Overly broad scopes — `admin` scope used everywhere instead of granular permissions +* Security schemes not enforced — gateway config doesn't match OpenAPI definition +* Bearer tokens without validation — accepting any JWT without signature verification + +Quick checks: + +```bash +# Test unauthenticated access (should fail) +curl -i https://api.example.com/users/me + +# Test with invalid token (should fail) +curl -H "Authorization: Bearer invalid" https://api.example.com/users/me + +# Test scope enforcement +curl -H "Authorization: Bearer readonly_token" -X POST https://api.example.com/users +``` + +> Key insight: "The `security-defined` rule has prevented more breaches than any other single control. It's non-negotiable in our CI pipeline." Learn more about implementing this with [Redocly's API Governance solution](https://redocly.com/api-governance). + +#### Rate limiting troubleshooting and common pitfalls + +* Counting the wrong thing — per-IP only; add per-account and per-token limits +* Same limits for every endpoint — tighten auth and write endpoints separately +* No Retry-After header — clients can't back off predictably +* Stateless limits in distributed systems — use Redis or gateway-native stores + +Quick checks: + +```bash +# Observe 429 behavior and headers +curl -i https://api.example.com/login | grep -E 'HTTP/|Retry-After' + +# Simulate burst to verify buckets/windows +hey -z 10s -q 50 -c 50 https://api.example.com/api/resource +``` + +> Another insight: "Rate limiting on auth endpoints is non-negotiable. We set 5/min per IP and per account, and alert when bypass attempts appear." + + +## Monitoring and Observability + +### TLS Monitoring +```yaml +# Prometheus alerts for TLS +groups: +- name: tls_alerts + rules: + - alert: TLSCertificateExpiringSoon + expr: probe_ssl_earliest_cert_expiry - time() < 86400 * 30 + labels: + severity: warning + annotations: + summary: "TLS certificate expires in less than 30 days" + + - alert: WeakTLSVersion + expr: probe_tls_version_info{version!="TLS 1.3"} == 1 + labels: + severity: critical + annotations: + summary: "Weak TLS version detected" +``` + +### Validation Monitoring +```javascript +// Log validation failures for analysis +app.use((req, res, next) => { + const originalSend = res.send; + + res.send = function(data) { + if (res.statusCode === 400 && req.validationErrors) { + logger.warn('Validation failure', { + endpoint: req.path, + errors: req.validationErrors, + clientIP: req.ip, + userAgent: req.get('User-Agent') + }); + } + + originalSend.call(this, data); + }; + + next(); +}); +``` + +### Rate Limiting Monitoring +```python +# Track rate limiting metrics +import time +from collections import defaultdict + +class RateLimitMetrics: + def __init__(self): + self.blocked_requests = defaultdict(int) + self.total_requests = defaultdict(int) + + def record_request(self, client_id, blocked=False): + self.total_requests[client_id] += 1 + if blocked: + self.blocked_requests[client_id] += 1 + + def get_block_rate(self, client_id): + total = self.total_requests[client_id] + blocked = self.blocked_requests[client_id] + return (blocked / total) * 100 if total > 0 else 0 +``` + + +## Frequently Asked Questions + +### What is design-first API security? +Design-first API security means defining security requirements in your OpenAPI specification before writing code, then using automated governance tools like Redocly to enforce those requirements throughout the development lifecycle. This prevents vulnerabilities from reaching production rather than patching them after discovery. + +### How does OpenAPI prevent injection attacks? +OpenAPI specifications define precise data schemas with type validation, format constraints, and length limits. When enforced by governance tools, these schemas automatically reject malformed inputs that could contain injection payloads, stopping attacks before they reach your application logic. + +### Why is rate limiting important for API security? +Rate limiting prevents denial-of-service attacks, brute-force authentication attempts, and data scraping. It ensures fair resource usage among legitimate users while blocking malicious automation. Without rate limits, a single bad actor can overwhelm your API infrastructure. + +### Can I implement all four security areas with just OpenAPI? +Yes, OpenAPI 3.1 supports all four security areas: TLS enforcement through server URLs, input validation via JSON schemas, rate limiting through extensions like `x-rate-limit`, and access control via security schemes. Combined with governance automation, your specification becomes an executable security contract. + +### What's the difference between authentication and authorization in APIs? +Authentication verifies *who* the user is (like checking an ID card), while authorization determines *what* they can do (like checking permissions). Both are essential for API security, and OpenAPI provides security schemes to define and enforce both concepts through your specification. + + +## Resources + +- **[OWASP API Security Top 10](https://owasp.org/www-project-api-security/)** - Complete vulnerability guide including injection and resource consumption attacks +- **[Mozilla TLS Configuration Generator](https://ssl-config.mozilla.org/)** - Generate secure TLS configurations for various web servers and applications +- **[NIST Guidelines for TLS Implementations](https://csrc.nist.gov/publications/detail/sp/800-52/rev-2/final)** - Official guidelines for secure TLS implementation and configuration +- **[Redocly Documentation](https://redocly.com/docs/)** - Complete guide to implementing API governance and automated security validation diff --git a/learn/security/index.md b/learn/security/index.md new file mode 100644 index 00000000..0195b639 --- /dev/null +++ b/learn/security/index.md @@ -0,0 +1,13 @@ +Looking to secure your APIs by design? Start here for guides and best practices. + +## Security topics + +- **Design-first security guide** + [Secure APIs by Design](api-design-first-security-guide.md) + Learn to enforce TLS, input validation, rate limiting, and access control with OpenAPI and governance. + +--- + +Not sure where to start? +- Read the [Secure APIs by Design](api-design-first-security-guide.md) guide first. + diff --git a/learn/security/sidebars.yaml b/learn/security/sidebars.yaml new file mode 100644 index 00000000..9508dd24 --- /dev/null +++ b/learn/security/sidebars.yaml @@ -0,0 +1,2 @@ +- page: ./index.md +- page: ./api-design-first-security-guide.md diff --git a/learn/testing/tools-for-api-testing-in-2025.md b/learn/testing/tools-for-api-testing-in-2025.md new file mode 100644 index 00000000..3115994a --- /dev/null +++ b/learn/testing/tools-for-api-testing-in-2025.md @@ -0,0 +1,369 @@ +# Tools for API Testing in 2025 + +Have you seen something like this? A code refactor accidentally drops an ‘optional’ field and production errors light up both computers and cortisol for whomever is on duty. A thoughtful API testing process can help to stop the unwanted excitement before merge. + +> What this covers: A practical guide to API testing tools and approaches +> +> Why it matters: When done right, teams can reduce risk from breaking changes and improve delivery velocity with a coherent, developer-friendly stack +> +> What you'll learn: How to compare contract testing vs functional testing, choose the right tools, and add automated quality gates in CI/CD +> +> What you'll take away: A clear(er) decision path, starter config examples, and concrete next steps to run your first workflow test + +Let's jump in! + +## Beyond just a list — let's think about a framework for your API testing stack + +Is your organization struggling with the chaos of inconsistent API testing tools? When every team chooses its own solution, the result is often a mix of redundant, overlapping tools that create friction, produce inconsistent quality signals, and make it impossible to standardize best practices. + +This guide provides a path out of that chaos. Instead of just another flat list of tools, it offers a strategic framework for evaluating and building a coherent testing stack. We walk through the layers of a modern API testing strategy, from validating the design contract to ensuring production reliability, so you can empower your teams with a paved road for quality. + +### Four trends reshaping API testing in 2025 + +* **Shift-left as standard**: Testing moves into design and development, shrinking feedback loops and cost-to-fix. +* **AI/ML-assisted testing**: Automated test generation from specs, self-healing tests, and intelligent prioritization help teams scale quality. +* **Architectural fragmentation**: GraphQL and event-driven systems (AsyncAPI) demand schema-first validation and workflow-level testing, not just single request/response checks. +* **Developer Experience (DX)**: Git-friendly, CLI-first, docs-as-code workflows outperform platform-centric approaches for sustainable automation. + +```mermaid +graph TB + subgraph REST["REST APIs"] + A1[OpenAPI Description] --> A2[Contract Testing] + end + + subgraph GraphQL["GraphQL APIs"] + B1[Schema Definition] --> B2[Query Validation] + end + + subgraph AsyncAPI["Event-Driven APIs"] + C1[AsyncAPI Description] --> C2[Message Validation] + end + + D[Modern API Testing Strategy] --> REST + D --> GraphQL + D --> AsyncAPI +``` + +_Diagram: A modern API testing strategy spans REST, GraphQL, and event-driven APIs._ + +## The shift-left foundation: testing your API's design + +The most effective way to improve quality and reduce costs is to shift left—integrating testing as early as possible in the software development lifecycle (SDLC). For APIs, this starts before a single line of code is written. + +```mermaid +sequenceDiagram + participant Design as 📋 Design Phase
$1 to fix + participant Dev as 💻 Development
$5–$25 to fix + participant Test as 🔍 Testing
$50–$150 to fix + participant Prod as 🚀 Production
$1000+ to fix + + Design->>Dev: Defect flows downstream + Dev->>Test: Cost increases dramatically + Test->>Prod: Cost increases exponentially + + Note over Design: Shift-left catches issues here + Note over Prod: Emergency patches, downtime costs +``` + +_Diagram: The cost of fixing defects increases across the lifecycle; shift-left prevents late discovery._ + +### Shift-left in practice: automated API quality gates in CI/CD + +Use the same commands locally and in CI to validate both your API design and its implementation. + +```yaml {% title=".github/workflows/api-quality.yml" %} +name: API quality gates +on: + pull_request: + branches: [main] + +jobs: + api-validation: + runs-on: ubuntu-latest + permissions: + contents: read + env: + API_URL: ${{ vars.API_URL }} # or: ${{ secrets.API_URL }} + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-node@v4 + with: + node-version: 22 + cache: 'npm' + + - name: Lint API description + run: npx @redocly/cli lint openapi.yaml + + - name: Workflow testing (Arazzo) + run: npx @redocly/cli respect api-tests.arazzo.yaml --server mainApi=$API_URL +``` + +### Prerequisites + +- Node.js LTS +- Place `redocly.yaml` in your repository root +- Local: run CLI commands from your repo root; CI: use the GitHub Actions workflow shown above + +### Why your OpenAPI description is your most important testing asset + +The foundation of a modern, design-first API workflow is the OpenAPI description. Treat it as the canonical, machine-readable single source of truth for your API. By treating the OpenAPI description as an enforceable contract, you can automate quality checks at the earliest possible moment: the design phase. + +#### Core tool: API linters for contract and style conformance + +Start with a configurable API linter (via Redocly CLI) as the de facto open-source standard. See the built‑in rules and configurable rules in the CLI docs at [/docs/cli/rules/built-in-rules](/docs/cli/rules/built-in-rules) and the `lint` command at [/docs/cli/commands/lint](/docs/cli/commands/lint). Linting validates the OpenAPI description against a ruleset that can enforce everything from security best practices to semantic naming conventions. + +```yaml {% title=".redocly.yaml" %} +apis: + main: openapi.yaml +rules: + operation-2xx-response: error + operation-operationId-unique: error + operation-summary: error + rule/path-no-internal-segments: + subject: + type: Path + property: key + assertions: + notPattern: "/internal/|/_v1/" + severity: error + message: "Path must not contain '/internal/' or '/_v1/' segments" + security-defined: error +``` + +## Tools for contract testing + +### The problem it solves: preventing integration issues between services + +In a microservices architecture, how do you ensure a change to one service doesn't break another? Contract testing verifies that two services (a consumer and a provider) can communicate correctly. It's faster and less brittle than full end-to-end integration testing because it validates each service in isolation. + +### Tool spotlight: Open source options (e.g., Pact) + +One common tool for consumer-driven contract testing is Pact. In this workflow, consumer-side tests generate a contract file (a pact). These contracts are then published to a central Pact Broker. The provider's CI pipeline fetches these contracts from the broker and verifies them against the provider codebase. The broker's key feature is providing the can-i-deploy status, which tells a team if they can safely deploy a service without breaking any of its known consumers, enabling true independent deployments. + +Redocly's Respect offers a complementary approach where the OpenAPI description itself serves as the contract, ensuring that your implementation never deviates from your design. Respect can be used for both provider-driven and consumer-driven contract testing workflows. Learn how to run workflow tests with the `respect` command at [/docs/cli/commands/respect](/docs/cli/commands/respect). + + +### Respect contract testing in action + +```yaml {% title="users-test.arazzo.yaml" %} +arazzo: 1.0.1 +info: + title: Test Example API + version: 1.0.0 +sourceDescriptions: + - name: exampleApi + type: openapi + url: openapi.yaml +workflows: + - workflowId: listAndFetchUser + steps: + - stepId: listUsers + source: exampleApi + operationId: listUsers + onSuccess: + - id: firstUserId + from: body.0.id + - stepId: fetchUser + source: exampleApi + operationId: getUserById + parameters: + - name: userId + in: path + value: $steps.listUsers.outputs.firstUserId + onSuccess: + - statusCode: + equals: 200 +``` + +```bash +# Run the Arazzo workflow, targeting your live API +npx @redocly/cli respect users-test.arazzo.yaml --server exampleApi=https://api.example.com + +# With verbose output for debugging +npx @redocly/cli respect users-test.arazzo.yaml --server exampleApi=https://api.staging.com --verbose +``` + +Workflow testing executes real multi-step workflows, passing data between API calls and validating responses against your OpenAPI schemas. This catches integration issues that single-request testing misses, ensuring your API works correctly end-to-end. + +#### Aha moment: a real-world save + +Here's a scenario where the right process and toolings can make a significant difference in outcomes: + +Before: A provider team merged a refactor that removed an optional field used by a downstream service. The change slipped past manual tests. + +After: A `lint` rule flagged the schema change, and a `respect` workflow failed pre‑merge when the dependent step validated the missing field against the OpenAPI schema. + +Impact: The PR was blocked in under 5 minutes, avoiding a production incident and a half‑day rollback effort. + +What changed: The team codified the contract and validated real integration flows automatically on every PR. + +#### Choose contract testing approaches based on your needs + +- **Workflow testing**: You need end‑to‑end validation of real integration flows and want tests that always reflect the current OpenAPI. +- **Test generation from spec**: You need a quick bootstrap for manual/GUI validation and accept managing a generated artifact. +- **Validation proxy**: You need inline validation in a specific environment and can operate a proxy. + +## Tools for functional and request/response testing + +Once you've confirmed your API design is sound and the contracts between services are solid, verify that the API correctly implements the required business logic. + +### GUI-based tools (e.g., Postman) + +Great for API exploration and manual testing. GUIs lower the barrier to entry, allowing non-programmers to contribute to testing. + +### Code-based frameworks (e.g., Karate) + +For automated testing, code-based frameworks like Karate provide comprehensive functionality. They support reusable code, data-driven testing, and parallel execution for reduced execution times—ideal for building maintainable suites at scale. + +#### Choose functional testing approaches based on your needs + +- **GUI-based**: You need exploratory testing, demos, or collaborative manual checks. +- **Code-based**: You need repeatable, versioned tests in CI with code reuse and data‑driven scenarios. + +## Tools for performance and load testing + +An API that is functional but slow can be as problematic as one that is broken. Performance testing ensures reliability and scalability. + +### Open source option (e.g., k6) + +`k6` is developer‑focused and integrates into CI/CD pipelines. Define performance service‑level objectives (SLOs) directly in the test script to codify and automate performance requirements. + +#### Choose performance testing based on your needs + +- You need to validate scalability and latency budgets before production. +- You maintain SLOs/SLIs and want automated gates for regressions. +- You already have contract/functional coverage and need performance coverage to complete the picture. + +### Quick decision guide + +- Validate design quality early? Use CLI `lint` with a governance ruleset. +- Prevent breaking changes between services? Use `respect` workflow testing. +- Validate business logic and edge cases? Use code‑based functional tests. +- Explore APIs manually or for demos? Use a GUI client. +- Validate scalability and latency budgets? Use `k6` in CI. +### Comparison matrix: approaches at a glance +Use this as a quick scan to choose the right tool for the job, then dive deeper in the sections above. + +{% table %} +- Approach +- Setup effort +- Drift risk +- CI integration +- Skill profile +- Best fit +- Not a fit +--- +- Workflow testing (`respect`) +- Medium (author Arazzo) +- Low (tests tied to OpenAPI) +- First-class via CLI +- Developer/Tech Writer comfortable with YAML +- End-to-end contract validation and integrations +- One-off manual checks +--- +- Test generation (collections) +- Low initial, higher ongoing +- Medium/High (generated artifact) +- Via runners, extra plumbing +- Mixed (GUI + scripts) +- Bootstrapping quick checks or demos +- Long-term regression suites +--- +- Validation proxy +- Medium (operate proxy) +- Low +- Env-specific +- DevOps/Platform +- In-env validation where proxying is acceptable +- Highly locked-down networks +--- +- Functional (code-based) +- Medium +- Low +- First-class in CI +- SDET/Developer +- Complex business logic and data-driven tests +- Non-technical teams +--- +- GUI manual +- Low +- N/A +- Limited +- Any +- Exploration and ad-hoc validation +- Scalable automation +--- +- Performance (`k6`) +- Medium +- N/A +- First-class in CI +- Developer/Perf Eng +- Load, stress, and soak coverage +- Unit-level checks +{% /table %} + +## The architect's POV: choosing tools through a four‑pillar framework + +Evaluate tooling across product overlap, workflow cohesion, total cost of ownership, and developer experience. We advocate for favoring integrated, CLI-first workflows that align with docs-as-code and Git-based processes. + +### Redocly: integrated, not monolithic + +* Lifecycle integration: Design (OpenAPI) → lint → bundle/split → live contract validation (Respect) → publish docs, all spec-first. +* Developer-centric workflow: CLI-first, Git- and CI-native. +* Governance and contractual integrity: Enforce API design standards with lint; prevent drift with live validation against the spec. + +```mermaid +sequenceDiagram + participant Dev as Developer + participant Spec as OpenAPI Description + participant Respect as Respect + participant API as Live API + + Dev->>Spec: Update schema + Respect->>API: Send real requests + API-->>Respect: Live responses + Respect->>Respect: Validate vs updated OpenAPI + Note over Respect: ✓ Always current, no drift +``` + +## Build a coherent, developer‑friendly testing stack + +It's important to assemble a coherent, automated stack that provides the right feedback at the right stage of the development lifecycle. Codify quality gates—start with linting the OpenAPI spec, verify integrations with contract tests, and enforce SLOs with performance tests. + +### What to measure after adoption + +- PR rejection rate due to contract violations + - Why: Confirms guardrails catch breaking changes pre‑merge; expect an early spike, then stabilization as teams adapt + - How: PRs failing `respect`/`lint` checks ÷ total PRs; source: CI checks or GitHub/GitLab APIs + - Target: Stabilize under an agreed threshold after a few sprints + +- % of APIs lint‑clean on primary branches + - Why: Leading indicator of design quality and governance coverage + - How: Repos passing `@redocly/cli lint` with 0 errors ÷ total active API repos + - Target: Upward trend quarter‑over‑quarter (e.g., 80% → 95%) + +- Incidents related to API contract drift + - Why: Measures escaped defects that impact consumers + - How: Incidents tagged with provider/consumer mismatch as root cause + - Target: Decreasing trend toward zero + +- MTTR for API incidents + - Why: Faster recovery reflects clearer contracts and reproducible tests + - How: Time from incident start to mitigation/restore in your incident system + - Target: Decreasing release‑over‑release + +- Performance SLO adherence across releases + - Why: Ensures APIs remain reliable under load, not just correct + - How: % of `k6` CI runs meeting latency/throughput/error thresholds + - Target: ≥ 99% adherence + +### Next steps + +* Create a small Arazzo workflow and run it with `npx @redocly/cli respect`. See the command reference at [/docs/cli/commands/respect](/docs/cli/commands/respect) and the tutorial at [/learn/arazzo/testing-arazzo-workflows](/learn/arazzo/testing-arazzo-workflows). +* Generate a starter Arazzo workflow with the CLI: see [`generate-arazzo`](/docs/cli/commands/generate-arazzo). +* Learn the fundamentals: [/learn/testing/contract-testing-101](/learn/testing/contract-testing-101). + +### Primary CTA + +Run your first workflow test with Respect: [/docs/cli/commands/respect](/docs/cli/commands/respect) diff --git a/pages/learning-center/cards.ts b/pages/learning-center/cards.ts index 80764068..0e3bb998 100644 --- a/pages/learning-center/cards.ts +++ b/pages/learning-center/cards.ts @@ -97,22 +97,19 @@ export const cards = [ { title: 'Contract Testing 101', link: '/learn/testing/contract-testing-101' }, ], }, - // { - // id: 7, - // key: 'api-security', - // title: 'API Security', - // description: - // 'Gain insights into securing your APIs with essential resources, tools, and best practices to protect your applications.', - // thumbnail: apiSecurityThumbnail, - // moreItems: ' more topics', - // landingPage: '/', - // items: [ - // { title: 'Introduction to API Security', link: '' }, - // { title: 'Common API Vulnerabilities', link: '' }, - // { title: 'Implementing Authentication and Authorization examples', link: '' }, - // { title: 'Best Practices for Securing APIs', link: '' }, - // ], - // }, + { + id: 6, + key: 'api-security', + title: 'API Security', + description: + 'Gain insights into securing your APIs with essential resources, tools, and best practices to protect your applications.', + thumbnail: apiSecurityThumbnail, + moreItems: '1 more topic', + landingPage: '/learn/security', + items: [ + { title: 'API Design-First Security Guide', link: '/learn/security/api-design-first-security-guide' }, + ], + }, // { // id: 8, // key: 'graphql', From 527ff0317fb7463f70ae28aa9c3a3216c26f287a Mon Sep 17 00:00:00 2001 From: Matt Williams Date: Tue, 26 Aug 2025 14:03:13 -0500 Subject: [PATCH 02/27] Address review comments for API design-first security guide --- .../api-design-first-security-guide.md | 142 ++++++++++++++---- 1 file changed, 113 insertions(+), 29 deletions(-) diff --git a/learn/security/api-design-first-security-guide.md b/learn/security/api-design-first-security-guide.md index f13ad9b0..57446b68 100644 --- a/learn/security/api-design-first-security-guide.md +++ b/learn/security/api-design-first-security-guide.md @@ -4,7 +4,6 @@ _Build secure APIs from the ground up using OpenAPI security contracts and autom --- - ## Key Takeaways Many teams discover security vulnerabilities after they're already in production, but it doesn't have to be that way! @@ -19,7 +18,6 @@ In this guide, we'll walk though how to turn your OpenAPI specification into a s --- - ## From Reactive Patching to Proactive API Security High-profile data breaches frequently trace back to insecure APIs, exposing a fundamental flaw in traditional security approaches. The conventional method — identifying and patching vulnerabilities in production — is reactive, costly, and ultimately inadequate. In it's typical (and more common then we'd like) form, this paradigm treats security as more of an afterthought. @@ -32,7 +30,6 @@ However, a contract, much like a law, is only as strong as its enforcement. This *OpenAPI specifications are validated by Redocly governance engine in CI/CD pipeline, failing builds for security violations and requiring fixes before deployment.* - ## Building Secure API Infrastructure: The Technical Foundation Building secure APIs doesn't have to feel like playing whack-a-mole with vulnerabilities. Once you shift from reactive patching to proactive design, you'll wonder why you ever did it any other way. Let's explore how to make security an automatic part of your API development process. @@ -72,7 +69,6 @@ graph TD *Architecture diagram showing the four essential areas of API security (TLS encryption, input validation, rate limiting, access control) supported by OpenAPI specifications and Redocly governance automation.* - ## TLS Encryption: Protecting Data in Transit with OpenAPI When a client and an API exchange information, that data travels across the internet, a public network. Without protection, this data gets intercepted and read by malicious actors. This is where encryption comes in. @@ -271,9 +267,57 @@ sequenceDiagram Why this matters: TLS is only as strong as its implementation. Monitoring and rapid patching for library CVEs are part of infrastructure security. +### Mutual TLS (mTLS): Two-Way Authentication + +While standard TLS only authenticates the server to the client, **Mutual TLS (mTLS)** requires both parties to authenticate each other using certificates. This provides stronger security for high-trust scenarios like service-to-service communication. + +**mTLS Use Cases:** +- Microservice communication in zero-trust architectures +- API-to-API authentication between organizations +- IoT device authentication +- High-security financial and healthcare APIs + +**OpenAPI mTLS Configuration:** +```yaml +# openapi.yaml +components: + securitySchemes: + mtlsAuth: + type: mutualTLS + description: "Client certificate authentication" + +# Apply to sensitive operations +paths: + /internal/payments: + post: + security: + - mtlsAuth: [] + summary: "Process payment (internal service only)" +``` + +**Implementation Example (Nginx):** +```nginx +server { + listen 443 ssl http2; + + # Server certificate + ssl_certificate /path/to/server.crt; + ssl_certificate_key /path/to/server.key; + + # Require client certificates + ssl_verify_client on; + ssl_client_certificate /path/to/ca.crt; + + # Pass client certificate info to backend + proxy_set_header X-Client-Cert $ssl_client_cert; + proxy_set_header X-Client-Verify $ssl_client_verify; +} +``` + +> **mTLS Best Practice**: Use mTLS for service-to-service communication and regular TLS + JWT/OAuth2 for client-to-server communication. + --- - ## Input Validation: Preventing Injection Attacks with Schema-Based Security APIs are designed to accept data as input. However, an API should never blindly trust the data it receives from a client. The process of rigorously checking all incoming data is called data validation. NIST defines data validation as "The process of determining that data...is acceptable according to a predefined set of tests and the results of those tests." @@ -415,26 +459,71 @@ This governance approach changes security reviews. Instead of manually checking ### JSON Schema Security Keywords -| Keyword | Purpose | Security Implication | -|---------|---------|---------------------| -| `type` | Constrains data type | Prevents type confusion attacks | -| `pattern` | Enforces regex on strings | Fine-grained control against injection | -| `maxLength/minLength` | Constrains string/array length | Mitigates DoS and buffer overflow | -| `maximum/minimum` | Constrains numeric ranges | Prevents integer overflows | -| `enum` | Restricts to predefined values | Blocks unexpected/malicious values | -| `required` | Mandates property presence | Ensures critical data elements exist | -| `additionalProperties: false` | Prohibits undeclared properties | Defense against mass assignment | +{% table %} +* Keyword +* Purpose +* Security Implication +--- +* `type` +* Constrains data type +* Prevents type confusion attacks +--- +* `pattern` +* Enforces regex on strings +* Fine-grained control against injection +--- +* `maxLength/minLength` +* Constrains string/array length +* Mitigates DoS and buffer overflow +--- +* `maximum/minimum` +* Constrains numeric ranges +* Prevents integer overflows +--- +* `enum` +* Restricts to predefined values +* Blocks unexpected/malicious values +--- +* `required` +* Mandates property presence +* Ensures critical data elements exist +--- +* `additionalProperties: false` +* Prohibits undeclared properties +* Defense against mass assignment +{% /table %} ### Common Validation Patterns -| Input Type | Validation Rules | Example | -|------------|------------------|---------| -| Email | RFC 5322 format | `user@example.com` | -| Phone | E.164 format | `+1234567890` | -| URL | Valid URL scheme | `https://example.com` | -| UUID | Standard UUID format | `123e4567-e89b-12d3-a456-426614174000` | -| Date | ISO 8601 format | `2025-01-20T10:30:00Z` | -| Password | Minimum complexity | 8+ chars, mixed case, numbers, symbols | +{% table %} +* Input Type +* Validation Rules +* Example +--- +* Email +* RFC 5322 format +* `user@example.com` +--- +* Phone +* E.164 format +* `+1234567890` +--- +* URL +* Valid URL scheme +* `https://example.com` +--- +* UUID +* Standard UUID format +* `123e4567-e89b-12d3-a456-426614174000` +--- +* Date +* ISO 8601 format +* `2025-01-20T10:30:00Z` +--- +* Password +* Minimum complexity +* 8+ chars, mixed case, numbers, symbols +{% /table %} #### Validation troubleshooting and common pitfalls @@ -488,7 +577,6 @@ Why this matters: Strong schema validation, input allow-lists, and patch hygiene --- - ## Rate Limiting: Preventing DoS and Abuse with API Policies A single client, whether intentionally malicious or simply due to a bug in its code, can send a massive number of requests to an API in a short period. This can overwhelm the server, degrading performance for all other users or even causing the service to crash. Rate limiting is the primary defense against this scenario. @@ -503,8 +591,7 @@ A single client, whether intentionally malicious or simply due to a bug in its c While OpenAPI 3.1 doesn't include native rate-limiting objects, extension properties (prefixed with `x-`) provide a standard mechanism. The best practice is defining custom `x-rate-limit` extensions at the operation level: -```yaml -# openapi.yaml +```yaml {% title="openapi.yaml" %} paths: /auth/login: post: @@ -557,7 +644,7 @@ rules: severity: error ``` -This approach provides dual benefits: [Redocly's API Reference Docs](https://redocly.com/reference-docs) automatically displays the `x-rate-limit` object in generated documentation, making policies transparent to API consumers, while governance rules ensure sensitive endpoints never lack rate-limiting policies. +This approach provides dual benefits: [Redocly's Redoc](https://redocly.com/redoc) automatically displays the `x-rate-limit` object in generated documentation, making policies transparent to API consumers, while governance rules ensure sensitive endpoints never lack rate-limiting policies. ### Why Rate Limiting Is Critical @@ -793,7 +880,6 @@ hey -z 10s -q 50 -c 50 https://api.example.com/api/resource > Another insight: "Rate limiting on auth endpoints is non-negotiable. We set 5/min per IP and per account, and alert when bypass attempts appear." - ## Monitoring and Observability ### TLS Monitoring @@ -862,7 +948,6 @@ class RateLimitMetrics: return (blocked / total) * 100 if total > 0 else 0 ``` - ## Frequently Asked Questions ### What is design-first API security? @@ -880,7 +965,6 @@ Yes, OpenAPI 3.1 supports all four security areas: TLS enforcement through serve ### What's the difference between authentication and authorization in APIs? Authentication verifies *who* the user is (like checking an ID card), while authorization determines *what* they can do (like checking permissions). Both are essential for API security, and OpenAPI provides security schemes to define and enforce both concepts through your specification. - ## Resources - **[OWASP API Security Top 10](https://owasp.org/www-project-api-security/)** - Complete vulnerability guide including injection and resource consumption attacks From 4002cb32be6de2b0ef16734ee94ef186f40b2a53 Mon Sep 17 00:00:00 2001 From: Matt Williams Date: Wed, 27 Aug 2025 14:02:37 -0500 Subject: [PATCH 03/27] Remove accidentally included API testing article from security branch This article belongs on a separate branch for API testing, not the security branch. --- .../testing/tools-for-api-testing-in-2025.md | 369 ------------------ 1 file changed, 369 deletions(-) delete mode 100644 learn/testing/tools-for-api-testing-in-2025.md diff --git a/learn/testing/tools-for-api-testing-in-2025.md b/learn/testing/tools-for-api-testing-in-2025.md deleted file mode 100644 index 3115994a..00000000 --- a/learn/testing/tools-for-api-testing-in-2025.md +++ /dev/null @@ -1,369 +0,0 @@ -# Tools for API Testing in 2025 - -Have you seen something like this? A code refactor accidentally drops an ‘optional’ field and production errors light up both computers and cortisol for whomever is on duty. A thoughtful API testing process can help to stop the unwanted excitement before merge. - -> What this covers: A practical guide to API testing tools and approaches -> -> Why it matters: When done right, teams can reduce risk from breaking changes and improve delivery velocity with a coherent, developer-friendly stack -> -> What you'll learn: How to compare contract testing vs functional testing, choose the right tools, and add automated quality gates in CI/CD -> -> What you'll take away: A clear(er) decision path, starter config examples, and concrete next steps to run your first workflow test - -Let's jump in! - -## Beyond just a list — let's think about a framework for your API testing stack - -Is your organization struggling with the chaos of inconsistent API testing tools? When every team chooses its own solution, the result is often a mix of redundant, overlapping tools that create friction, produce inconsistent quality signals, and make it impossible to standardize best practices. - -This guide provides a path out of that chaos. Instead of just another flat list of tools, it offers a strategic framework for evaluating and building a coherent testing stack. We walk through the layers of a modern API testing strategy, from validating the design contract to ensuring production reliability, so you can empower your teams with a paved road for quality. - -### Four trends reshaping API testing in 2025 - -* **Shift-left as standard**: Testing moves into design and development, shrinking feedback loops and cost-to-fix. -* **AI/ML-assisted testing**: Automated test generation from specs, self-healing tests, and intelligent prioritization help teams scale quality. -* **Architectural fragmentation**: GraphQL and event-driven systems (AsyncAPI) demand schema-first validation and workflow-level testing, not just single request/response checks. -* **Developer Experience (DX)**: Git-friendly, CLI-first, docs-as-code workflows outperform platform-centric approaches for sustainable automation. - -```mermaid -graph TB - subgraph REST["REST APIs"] - A1[OpenAPI Description] --> A2[Contract Testing] - end - - subgraph GraphQL["GraphQL APIs"] - B1[Schema Definition] --> B2[Query Validation] - end - - subgraph AsyncAPI["Event-Driven APIs"] - C1[AsyncAPI Description] --> C2[Message Validation] - end - - D[Modern API Testing Strategy] --> REST - D --> GraphQL - D --> AsyncAPI -``` - -_Diagram: A modern API testing strategy spans REST, GraphQL, and event-driven APIs._ - -## The shift-left foundation: testing your API's design - -The most effective way to improve quality and reduce costs is to shift left—integrating testing as early as possible in the software development lifecycle (SDLC). For APIs, this starts before a single line of code is written. - -```mermaid -sequenceDiagram - participant Design as 📋 Design Phase
$1 to fix - participant Dev as 💻 Development
$5–$25 to fix - participant Test as 🔍 Testing
$50–$150 to fix - participant Prod as 🚀 Production
$1000+ to fix - - Design->>Dev: Defect flows downstream - Dev->>Test: Cost increases dramatically - Test->>Prod: Cost increases exponentially - - Note over Design: Shift-left catches issues here - Note over Prod: Emergency patches, downtime costs -``` - -_Diagram: The cost of fixing defects increases across the lifecycle; shift-left prevents late discovery._ - -### Shift-left in practice: automated API quality gates in CI/CD - -Use the same commands locally and in CI to validate both your API design and its implementation. - -```yaml {% title=".github/workflows/api-quality.yml" %} -name: API quality gates -on: - pull_request: - branches: [main] - -jobs: - api-validation: - runs-on: ubuntu-latest - permissions: - contents: read - env: - API_URL: ${{ vars.API_URL }} # or: ${{ secrets.API_URL }} - steps: - - uses: actions/checkout@v4 - - - uses: actions/setup-node@v4 - with: - node-version: 22 - cache: 'npm' - - - name: Lint API description - run: npx @redocly/cli lint openapi.yaml - - - name: Workflow testing (Arazzo) - run: npx @redocly/cli respect api-tests.arazzo.yaml --server mainApi=$API_URL -``` - -### Prerequisites - -- Node.js LTS -- Place `redocly.yaml` in your repository root -- Local: run CLI commands from your repo root; CI: use the GitHub Actions workflow shown above - -### Why your OpenAPI description is your most important testing asset - -The foundation of a modern, design-first API workflow is the OpenAPI description. Treat it as the canonical, machine-readable single source of truth for your API. By treating the OpenAPI description as an enforceable contract, you can automate quality checks at the earliest possible moment: the design phase. - -#### Core tool: API linters for contract and style conformance - -Start with a configurable API linter (via Redocly CLI) as the de facto open-source standard. See the built‑in rules and configurable rules in the CLI docs at [/docs/cli/rules/built-in-rules](/docs/cli/rules/built-in-rules) and the `lint` command at [/docs/cli/commands/lint](/docs/cli/commands/lint). Linting validates the OpenAPI description against a ruleset that can enforce everything from security best practices to semantic naming conventions. - -```yaml {% title=".redocly.yaml" %} -apis: - main: openapi.yaml -rules: - operation-2xx-response: error - operation-operationId-unique: error - operation-summary: error - rule/path-no-internal-segments: - subject: - type: Path - property: key - assertions: - notPattern: "/internal/|/_v1/" - severity: error - message: "Path must not contain '/internal/' or '/_v1/' segments" - security-defined: error -``` - -## Tools for contract testing - -### The problem it solves: preventing integration issues between services - -In a microservices architecture, how do you ensure a change to one service doesn't break another? Contract testing verifies that two services (a consumer and a provider) can communicate correctly. It's faster and less brittle than full end-to-end integration testing because it validates each service in isolation. - -### Tool spotlight: Open source options (e.g., Pact) - -One common tool for consumer-driven contract testing is Pact. In this workflow, consumer-side tests generate a contract file (a pact). These contracts are then published to a central Pact Broker. The provider's CI pipeline fetches these contracts from the broker and verifies them against the provider codebase. The broker's key feature is providing the can-i-deploy status, which tells a team if they can safely deploy a service without breaking any of its known consumers, enabling true independent deployments. - -Redocly's Respect offers a complementary approach where the OpenAPI description itself serves as the contract, ensuring that your implementation never deviates from your design. Respect can be used for both provider-driven and consumer-driven contract testing workflows. Learn how to run workflow tests with the `respect` command at [/docs/cli/commands/respect](/docs/cli/commands/respect). - - -### Respect contract testing in action - -```yaml {% title="users-test.arazzo.yaml" %} -arazzo: 1.0.1 -info: - title: Test Example API - version: 1.0.0 -sourceDescriptions: - - name: exampleApi - type: openapi - url: openapi.yaml -workflows: - - workflowId: listAndFetchUser - steps: - - stepId: listUsers - source: exampleApi - operationId: listUsers - onSuccess: - - id: firstUserId - from: body.0.id - - stepId: fetchUser - source: exampleApi - operationId: getUserById - parameters: - - name: userId - in: path - value: $steps.listUsers.outputs.firstUserId - onSuccess: - - statusCode: - equals: 200 -``` - -```bash -# Run the Arazzo workflow, targeting your live API -npx @redocly/cli respect users-test.arazzo.yaml --server exampleApi=https://api.example.com - -# With verbose output for debugging -npx @redocly/cli respect users-test.arazzo.yaml --server exampleApi=https://api.staging.com --verbose -``` - -Workflow testing executes real multi-step workflows, passing data between API calls and validating responses against your OpenAPI schemas. This catches integration issues that single-request testing misses, ensuring your API works correctly end-to-end. - -#### Aha moment: a real-world save - -Here's a scenario where the right process and toolings can make a significant difference in outcomes: - -Before: A provider team merged a refactor that removed an optional field used by a downstream service. The change slipped past manual tests. - -After: A `lint` rule flagged the schema change, and a `respect` workflow failed pre‑merge when the dependent step validated the missing field against the OpenAPI schema. - -Impact: The PR was blocked in under 5 minutes, avoiding a production incident and a half‑day rollback effort. - -What changed: The team codified the contract and validated real integration flows automatically on every PR. - -#### Choose contract testing approaches based on your needs - -- **Workflow testing**: You need end‑to‑end validation of real integration flows and want tests that always reflect the current OpenAPI. -- **Test generation from spec**: You need a quick bootstrap for manual/GUI validation and accept managing a generated artifact. -- **Validation proxy**: You need inline validation in a specific environment and can operate a proxy. - -## Tools for functional and request/response testing - -Once you've confirmed your API design is sound and the contracts between services are solid, verify that the API correctly implements the required business logic. - -### GUI-based tools (e.g., Postman) - -Great for API exploration and manual testing. GUIs lower the barrier to entry, allowing non-programmers to contribute to testing. - -### Code-based frameworks (e.g., Karate) - -For automated testing, code-based frameworks like Karate provide comprehensive functionality. They support reusable code, data-driven testing, and parallel execution for reduced execution times—ideal for building maintainable suites at scale. - -#### Choose functional testing approaches based on your needs - -- **GUI-based**: You need exploratory testing, demos, or collaborative manual checks. -- **Code-based**: You need repeatable, versioned tests in CI with code reuse and data‑driven scenarios. - -## Tools for performance and load testing - -An API that is functional but slow can be as problematic as one that is broken. Performance testing ensures reliability and scalability. - -### Open source option (e.g., k6) - -`k6` is developer‑focused and integrates into CI/CD pipelines. Define performance service‑level objectives (SLOs) directly in the test script to codify and automate performance requirements. - -#### Choose performance testing based on your needs - -- You need to validate scalability and latency budgets before production. -- You maintain SLOs/SLIs and want automated gates for regressions. -- You already have contract/functional coverage and need performance coverage to complete the picture. - -### Quick decision guide - -- Validate design quality early? Use CLI `lint` with a governance ruleset. -- Prevent breaking changes between services? Use `respect` workflow testing. -- Validate business logic and edge cases? Use code‑based functional tests. -- Explore APIs manually or for demos? Use a GUI client. -- Validate scalability and latency budgets? Use `k6` in CI. -### Comparison matrix: approaches at a glance -Use this as a quick scan to choose the right tool for the job, then dive deeper in the sections above. - -{% table %} -- Approach -- Setup effort -- Drift risk -- CI integration -- Skill profile -- Best fit -- Not a fit ---- -- Workflow testing (`respect`) -- Medium (author Arazzo) -- Low (tests tied to OpenAPI) -- First-class via CLI -- Developer/Tech Writer comfortable with YAML -- End-to-end contract validation and integrations -- One-off manual checks ---- -- Test generation (collections) -- Low initial, higher ongoing -- Medium/High (generated artifact) -- Via runners, extra plumbing -- Mixed (GUI + scripts) -- Bootstrapping quick checks or demos -- Long-term regression suites ---- -- Validation proxy -- Medium (operate proxy) -- Low -- Env-specific -- DevOps/Platform -- In-env validation where proxying is acceptable -- Highly locked-down networks ---- -- Functional (code-based) -- Medium -- Low -- First-class in CI -- SDET/Developer -- Complex business logic and data-driven tests -- Non-technical teams ---- -- GUI manual -- Low -- N/A -- Limited -- Any -- Exploration and ad-hoc validation -- Scalable automation ---- -- Performance (`k6`) -- Medium -- N/A -- First-class in CI -- Developer/Perf Eng -- Load, stress, and soak coverage -- Unit-level checks -{% /table %} - -## The architect's POV: choosing tools through a four‑pillar framework - -Evaluate tooling across product overlap, workflow cohesion, total cost of ownership, and developer experience. We advocate for favoring integrated, CLI-first workflows that align with docs-as-code and Git-based processes. - -### Redocly: integrated, not monolithic - -* Lifecycle integration: Design (OpenAPI) → lint → bundle/split → live contract validation (Respect) → publish docs, all spec-first. -* Developer-centric workflow: CLI-first, Git- and CI-native. -* Governance and contractual integrity: Enforce API design standards with lint; prevent drift with live validation against the spec. - -```mermaid -sequenceDiagram - participant Dev as Developer - participant Spec as OpenAPI Description - participant Respect as Respect - participant API as Live API - - Dev->>Spec: Update schema - Respect->>API: Send real requests - API-->>Respect: Live responses - Respect->>Respect: Validate vs updated OpenAPI - Note over Respect: ✓ Always current, no drift -``` - -## Build a coherent, developer‑friendly testing stack - -It's important to assemble a coherent, automated stack that provides the right feedback at the right stage of the development lifecycle. Codify quality gates—start with linting the OpenAPI spec, verify integrations with contract tests, and enforce SLOs with performance tests. - -### What to measure after adoption - -- PR rejection rate due to contract violations - - Why: Confirms guardrails catch breaking changes pre‑merge; expect an early spike, then stabilization as teams adapt - - How: PRs failing `respect`/`lint` checks ÷ total PRs; source: CI checks or GitHub/GitLab APIs - - Target: Stabilize under an agreed threshold after a few sprints - -- % of APIs lint‑clean on primary branches - - Why: Leading indicator of design quality and governance coverage - - How: Repos passing `@redocly/cli lint` with 0 errors ÷ total active API repos - - Target: Upward trend quarter‑over‑quarter (e.g., 80% → 95%) - -- Incidents related to API contract drift - - Why: Measures escaped defects that impact consumers - - How: Incidents tagged with provider/consumer mismatch as root cause - - Target: Decreasing trend toward zero - -- MTTR for API incidents - - Why: Faster recovery reflects clearer contracts and reproducible tests - - How: Time from incident start to mitigation/restore in your incident system - - Target: Decreasing release‑over‑release - -- Performance SLO adherence across releases - - Why: Ensures APIs remain reliable under load, not just correct - - How: % of `k6` CI runs meeting latency/throughput/error thresholds - - Target: ≥ 99% adherence - -### Next steps - -* Create a small Arazzo workflow and run it with `npx @redocly/cli respect`. See the command reference at [/docs/cli/commands/respect](/docs/cli/commands/respect) and the tutorial at [/learn/arazzo/testing-arazzo-workflows](/learn/arazzo/testing-arazzo-workflows). -* Generate a starter Arazzo workflow with the CLI: see [`generate-arazzo`](/docs/cli/commands/generate-arazzo). -* Learn the fundamentals: [/learn/testing/contract-testing-101](/learn/testing/contract-testing-101). - -### Primary CTA - -Run your first workflow test with Respect: [/docs/cli/commands/respect](/docs/cli/commands/respect) From 56e4a1db0bbbe45eace2f57db8a94457c13b97b8 Mon Sep 17 00:00:00 2001 From: Matt Williams Date: Sat, 30 Aug 2025 17:49:03 -0500 Subject: [PATCH 04/27] Refine language and tone in API security guide --- .../api-design-first-security-guide.md | 394 +++++++++--------- 1 file changed, 195 insertions(+), 199 deletions(-) diff --git a/learn/security/api-design-first-security-guide.md b/learn/security/api-design-first-security-guide.md index 57446b68..71c2677c 100644 --- a/learn/security/api-design-first-security-guide.md +++ b/learn/security/api-design-first-security-guide.md @@ -20,13 +20,15 @@ In this guide, we'll walk though how to turn your OpenAPI specification into a s ## From Reactive Patching to Proactive API Security -High-profile data breaches frequently trace back to insecure APIs, exposing a fundamental flaw in traditional security approaches. The conventional method — identifying and patching vulnerabilities in production — is reactive, costly, and ultimately inadequate. In it's typical (and more common then we'd like) form, this paradigm treats security as more of an afterthought. +High-profile data breaches frequently trace back to insecure APIs, exposing a fundamental flaw in traditional security approaches. The conventional method—identifying and patching vulnerabilities in production—is reactive, costly, and ultimately inadequate. In its typical form, this paradigm treats security as an afterthought. + +Shifting security practices to the left in the development lifecycle, known as the "shift-left" imperative, addresses this by integrating security into the earliest stages of design and development. This proactive model prevents vulnerabilities from being introduced in the first place, rather than attempting to remediate them under pressure in production environments. ### OpenAPI as Your Security Contract -The core of this strategy is treating your OpenAPI specification not as only documentation, but also as an executable security contract. This contract declaratively defines the complete set of security requirements, constraints, and policies before any application code is written. It becomes the single source of truth that dictates how an API must behave to be considered secure. +The core of this strategy is treating your OpenAPI specification not merely as documentation, but as an executable security contract. This contract declaratively defines a set of security requirements, constraints, and policies before any application code is written. It becomes the single source of truth that dictates how an API must behave to be considered secure, effectively implementing a "policy-as-code" approach for APIs. -However, a contract, much like a law, is only as strong as its enforcement. This is where [Redocly CLI](https://redocly.com/docs/cli/) governance and linting capabilities can provide value by making your contract into dynamic, automated guardrails that validate security requirements at every stage of development. +However, a contract, much like a law, is only as strong as its enforcement. This is where [Redocly CLI](https://redocly.com/docs/cli/) governance and linting capabilities provide value by transforming your contract into dynamic, automated guardrails that validate security requirements at every stage of development. When integrated into a Continuous Integration/Continuous Deployment (CI/CD) pipeline, this automated governance acts as a gatekeeper, failing builds that violate the security contract and requiring fixes before deployment. *OpenAPI specifications are validated by Redocly governance engine in CI/CD pipeline, failing builds for security violations and requiring fixes before deployment.* @@ -52,7 +54,7 @@ graph TD B --> F["• HTTPS Enforcement
• Certificate Management
• Strong Cipher Suites"] C --> G["• JSON Schema Rules
• Type Validation
• Length Constraints"] - D --> H["• x-rate-limit Extensions
• 429 Response Headers
• Multi-tier Limits"] + D --> H["• x-rateLimit Extensions
• 429 Response Headers
• Multi-tier Limits"] E --> I["• Security Schemes
• JWT/OAuth2
• Scope Management"] J["📄 OpenAPI 3.1
Specification"] --> A @@ -69,6 +71,126 @@ graph TD *Architecture diagram showing the four essential areas of API security (TLS encryption, input validation, rate limiting, access control) supported by OpenAPI specifications and Redocly governance automation.* +## Complete Security Governance Configuration + +Before diving into each security area, here's the comprehensive `redocly.yaml` configuration that enforces all security best practices discussed in this guide: + +```yaml {% title="redocly.yaml" %} +extends: + - recommended-strict + +rules: + # === Built-in Security Rules === + no-server-example-com: error # Prevent example.com in server URLs + no-unused-components: error # Remove unused components that could leak data + + # === TLS and Transport Security === + rule/enforce-production-tls: + subject: + type: Server + property: url + assertions: + pattern: "^https://api\\.(production|staging)\\.com" + message: "Server URLs must use https:// and point to approved domains." + severity: error + + # === Input Validation Rules === + # Rule 1: All strings must have length bounds + rule/string-must-have-maxLength: + subject: + type: Schema + where: + - subject: + property: type + assertions: + const: string + assertions: + required: + - maxLength + message: "All string properties must have 'maxLength' to prevent resource exhaustion." + severity: error + + # Rule 2: All numbers must have ranges + rule/number-must-have-range: + subject: + type: Schema + where: + - subject: + property: type + assertions: + enum: [number, integer] + assertions: + required: [minimum, maximum] + message: "Numeric properties must have 'minimum' and 'maximum' defined." + severity: error + + # Rule 3: Prevent mass assignment vulnerabilities + rule/no-additional-properties: + subject: + type: Schema + where: + - subject: + property: type + assertions: + const: object + assertions: + property: + additionalProperties: + const: false + message: "Objects must set 'additionalProperties: false' to prevent mass assignment." + severity: error + + # === Rate Limiting Rules === + rule/require-rate-limit-on-auth: + subject: + type: Operation + where: + - subject: + property: tags + assertions: + contains: "Authentication" + assertions: + defined: + - x-rateLimit + message: "Authentication operations must have 'x-rateLimit' policy defined." + severity: error + + # === Access Control Rules === + rule/require-auth-on-mutations: + subject: + type: Operation + where: + - subject: + property: method + assertions: + enum: [post, put, patch, delete] + assertions: + defined: [security] + message: "All write operations must have security defined." + severity: error +``` + +This configuration provides comprehensive security governance automation. Each section below explains the principles behind these rules and shows implementation examples. + +## Understanding Design-Time vs Runtime Security + +It's important to understand that OpenAPI-based security governance operates at **design-time**, not runtime. This governance approach excels at preventing configuration errors, missing security controls, and specification inconsistencies before they reach production. That said, it cannot prevent runtime vulnerabilities in the underlying implementation. + +**Design-time security governance prevents:** +- Accidentally public endpoints (missing security requirements) +- Insecure server configurations (HTTP instead of HTTPS) +- Missing input validation constraints +- Inconsistent rate limiting policies +- Data leakage through unused components + +**Runtime security still requires:** +- Patch management for frameworks and libraries (like the Heartbleed OpenSSL vulnerability) +- Secure coding practices and parameterized queries +- Infrastructure security monitoring and alerting +- Penetration testing and vulnerability scanning + +True "secure by design" requires both: design-time contracts enforced through OpenAPI governance *and* runtime security posture management as part of a comprehensive DevSecOps practice. + ## TLS Encryption: Protecting Data in Transit with OpenAPI When a client and an API exchange information, that data travels across the internet, a public network. Without protection, this data gets intercepted and read by malicious actors. This is where encryption comes in. @@ -79,7 +201,7 @@ When a client and an API exchange information, that data travels across the inte ### TLS 1.3: The Modern Standard -This secure tunnel is primarily established using Transport Layer Security (TLS) version 1.3, as specified in IETF RFC 8446. Any modern API security guidance must unequivocally mandate TLS 1.3, as older protocols—including all versions of SSL, TLS 1.0, and TLS 1.1—are deprecated and considered insecure due to known vulnerabilities. +This secure tunnel is primarily established using **Transport Layer Security (TLS) version 1.3**, as specified in [IETF RFC 8446](https://tools.ietf.org/html/rfc8446). [NIST SP 800-52 Rev. 2](https://csrc.nist.gov/publications/detail/sp/800-52/rev-2/final) guidelines for TLS implementations unequivocally mandate TLS 1.3 for modern systems, as older protocols—including all versions of SSL, TLS 1.0, and TLS 1.1—are deprecated and considered insecure due to known vulnerabilities. When a client connects to an API over `https://`, it initiates a "TLS handshake." During this handshake, the client and server perform crucial steps: @@ -164,8 +286,7 @@ testssl.sh --fast https://api.example.com The security contract for encrypted transit begins within the `servers` object of your OpenAPI specification. Every URL defined here must use the `https://` scheme—this isn't just documentation, it's a formal declaration of your API's secure endpoints. **OpenAPI Servers Declaration:** -```yaml -# openapi.yaml +```yaml {% title="openapi.yaml" %} servers: - url: https://api.production.com/v1 description: Production Server @@ -175,27 +296,7 @@ servers: **Redocly Governance Enforcement:** -For complete configuration options, see the [Redocly CLI configuration guide](https://redocly.com/docs/cli/configuration/). - -```yaml -# redocly.yaml - Advanced TLS enforcement -extends: - - recommended - -rules: - # Built-in rule: Ensure HTTPS usage - no-http-verbs-in-paths: error - - # Custom rule: Enforce production domain patterns - rule/enforce-production-tls: - subject: - type: Server - property: url - assertions: - pattern: "^https://api\\.(production|staging)\\.com" - message: "Server URLs must use https:// and point to approved domains." - severity: error -``` +The [Complete Security Governance Configuration](#complete-security-governance-configuration) section shows how to enforce HTTPS usage through the `rule/enforce-production-tls` custom rule, along with other security controls. When integrated into your CI/CD pipeline, this configuration creates an automated security gate. If a developer attempts to commit an OpenAPI file with `http://api.production.com` or `https://api.dev.internal`, the pipeline fails with a clear error message, preventing insecure configurations from ever reaching production. @@ -203,6 +304,8 @@ When integrated into your CI/CD pipeline, this configuration creates an automate ### TLS Configuration Examples +Authoritative sources like the [Mozilla SSL Configuration Generator](https://ssl-config.mozilla.org/) provide excellent, up-to-date templates for secure server configurations across different platforms and security requirements. + **Nginx Configuration:** ```nginx server { @@ -250,7 +353,9 @@ https.createServer(options, app).listen(443); ### Attack Example: Heartbleed (TLS library vulnerability, 2014) -These attacks are both real and can be problematic. Heartbleed (CVE-2014-0160) allowed attackers to read server memory via malformed TLS heartbeat messages. Real incidents, including the Canada Revenue Agency breach, demonstrated how secrets (keys, cookies) could be exfiltrated. +The Heartbleed bug (CVE-2014-0160) was a critical vulnerability in the OpenSSL library, not the TLS protocol itself. It allowed attackers to read up to 64KB of a server's memory by sending a malformed TLS heartbeat request. The server would respond with not only the small payload sent by the attacker but also adjacent memory contents, which could include session cookies, user credentials, and even the server's private encryption keys. + +This incident demonstrates a crucial point: security is multi-layered. While an OpenAPI specification can enforce the *intent* of using secure transport (https://), it cannot prevent a runtime vulnerability in the underlying software stack. As mentioned earlier, true "secure by design" requires both design-time governance via OpenAPI linting and runtime security posture management, including diligent vulnerability scanning and patch management. ```mermaid sequenceDiagram @@ -269,17 +374,16 @@ Why this matters: TLS is only as strong as its implementation. Monitoring and ra ### Mutual TLS (mTLS): Two-Way Authentication -While standard TLS only authenticates the server to the client, **Mutual TLS (mTLS)** requires both parties to authenticate each other using certificates. This provides stronger security for high-trust scenarios like service-to-service communication. +While standard TLS only authenticates the server to the client, **Mutual TLS (mTLS)** requires both parties to authenticate each other using certificates. This provides stronger security for high-trust scenarios and is essential for implementing zero-trust architecture principles. **mTLS Use Cases:** -- Microservice communication in zero-trust architectures -- API-to-API authentication between organizations -- IoT device authentication -- High-security financial and healthcare APIs +- Microservice communication in zero-trust architectures where no network segment is inherently trusted +- API-to-API authentication between organizations implementing defense-in-depth strategies +- IoT device authentication in distributed systems +- High-security financial and healthcare APIs requiring cryptographic identity verification **OpenAPI mTLS Configuration:** -```yaml -# openapi.yaml +```yaml {% title="openapi.yaml" %} components: securitySchemes: mtlsAuth: @@ -363,13 +467,12 @@ cursor.execute(query, (user_id,)) OpenAPI 3.1 provides a comprehensive vocabulary for defining strict validation rules by leveraging JSON Schema Draft 2020-12. By codifying these rules directly in your API specification, validation becomes core to your API's design. **Secure Schema Example:** -```yaml -# openapi.yaml +```yaml {% title="openapi.yaml" %} components: schemas: NewUser: type: object - additionalProperties: false # Prevent mass assignment + additionalProperties: false # Prevent mass assignment (OWASP API3:2023) required: - username - email @@ -379,11 +482,11 @@ components: username: type: string minLength: 4 - maxLength: 20 - pattern: "^[a-zA-Z0-9]+$" # Alphanumeric only + maxLength: 20 # Prevent resource exhaustion (OWASP API4:2023) + pattern: "^[a-zA-Z0-9]+$" # Prevent injection attacks email: type: string - maxLength: 254 + maxLength: 254 # Prevent resource exhaustion (OWASP API4:2023) format: email password: type: string @@ -392,106 +495,29 @@ components: age: type: integer minimum: 18 - maximum: 130 + maximum: 130 # Prevent integer overflow attacks role: type: string - enum: ["user", "viewer"] + enum: ["user", "viewer"] # Enforce allow-list approach default: "user" ``` **Redocly Governance for Validation:** -Detailed rule configuration is available in the [Redocly CLI rules documentation](https://redocly.com/docs/cli/rules/). +The [Complete Security Governance Configuration](#complete-security-governance-configuration) includes comprehensive input validation rules that automatically enforce string length bounds, numeric ranges, and prevent mass assignment vulnerabilities. See the Input Validation Rules section for the complete implementation. -```yaml -# redocly.yaml - Enforce security validation standards -extends: - - recommended-strict +This governance approach changes security reviews. Instead of manually checking many properties for missing `maxLength` constraints, automated linting with [Redocly Workflows](https://redocly.com/workflows) handles baseline validation so security teams can focus on strategic concerns like business logic and context-dependent risks. -rules: - # Rule 1: All strings must have length bounds - rule/string-must-have-maxLength: - subject: - type: Schema - where: - - subject: - property: type - assertions: - const: string - assertions: - required: - - maxLength - message: "All string properties must have 'maxLength' to prevent resource exhaustion." - severity: error +### Key Security Constraints - # Rule 2: All numbers must have ranges - rule/number-must-have-range: - subject: - type: Schema - where: - - subject: - property: type - assertions: - enum: [number, integer] - assertions: - required: [minimum, maximum] - message: "Numeric properties must have 'minimum' and 'maximum' defined." - severity: error +The most critical schema constraints for API security focus on preventing resource exhaustion and injection attacks: - # Rule 3: Prevent mass assignment vulnerabilities - rule/no-additional-properties: - subject: - type: Schema - where: - - subject: - property: type - assertions: - const: object - assertions: - property: - additionalProperties: - const: false - message: "Objects must set 'additionalProperties: false' to prevent mass assignment." - severity: error -``` - -This governance approach changes security reviews. Instead of manually checking many properties for missing `maxLength` constraints, automated linting with [Redocly Workflows](https://redocly.com/workflows) handles baseline validation so security teams can focus on strategic concerns like business logic and context-dependent risks. - -### JSON Schema Security Keywords +- **`maxLength`**: Required on all strings to prevent memory exhaustion attacks +- **`maximum/minimum`**: Required on all numbers to prevent integer overflow vulnerabilities +- **`additionalProperties: false`**: Essential for preventing mass assignment attacks +- **`pattern`**: Use restrictive regex patterns to block injection payloads -{% table %} -* Keyword -* Purpose -* Security Implication ---- -* `type` -* Constrains data type -* Prevents type confusion attacks ---- -* `pattern` -* Enforces regex on strings -* Fine-grained control against injection ---- -* `maxLength/minLength` -* Constrains string/array length -* Mitigates DoS and buffer overflow ---- -* `maximum/minimum` -* Constrains numeric ranges -* Prevents integer overflows ---- -* `enum` -* Restricts to predefined values -* Blocks unexpected/malicious values ---- -* `required` -* Mandates property presence -* Ensures critical data elements exist ---- -* `additionalProperties: false` -* Prohibits undeclared properties -* Defense against mass assignment -{% /table %} +These constraints are automatically enforced by the governance rules in our [Complete Security Governance Configuration](#complete-security-governance-configuration), ensuring no schema can bypass these fundamental protections. ### Common Validation Patterns @@ -534,8 +560,7 @@ This governance approach changes security reviews. Instead of manually checking Quick fixes: -```yaml -# JSON Schema example: tighten strings and numeric bounds +```yaml {% title="JSON Schema example" %} type: object additionalProperties: false properties: @@ -554,7 +579,9 @@ properties: ### Attack Example: Equifax (OGNL injection via Apache Struts, 2017) -Here's another one. An input validation and deserialization flaw (CVE-2017-5638) in Apache Struts allowed attackers to inject OGNL expressions via the `Content-Type` header, leading to remote code execution and data exfiltration. +The 2017 Equifax data breach was the result of a catastrophic input validation failure in the Apache Struts framework (CVE-2017-5638). The vulnerability allowed attackers to perform remote code execution by sending a specially crafted `Content-Type` header. The Struts framework failed to properly sanitize this header value, interpreting it as an Object-Graph Navigation Language (OGNL) expression and executing it. This gave attackers a direct shell on the server, which they used to access sensitive databases and exfiltrate the personal data of over 140 million people. + +This incident underscores the critical importance of validating all inputs, including HTTP headers, against a strict allow-list or pattern. A strong schema-based validation approach, enforced by governance, can block entire classes of injection attacks before they ever reach vulnerable application code. ```mermaid sequenceDiagram @@ -589,7 +616,9 @@ A single client, whether intentionally malicious or simply due to a bug in its c ### Documenting Rate Limits in OpenAPI -While OpenAPI 3.1 doesn't include native rate-limiting objects, extension properties (prefixed with `x-`) provide a standard mechanism. The best practice is defining custom `x-rate-limit` extensions at the operation level: +While OpenAPI 3.1 doesn't include native rate-limiting objects, extension properties (prefixed with `x-`) provide a standard mechanism. The best practice is defining custom `x-rateLimit` extensions at the operation level. + +**Note:** Rate limits are typically dynamic in production environments, with different limits for different clients based on service tiers, contracts, or usage patterns. The OpenAPI specification documents the baseline policy, while implementation systems apply client-specific variations: ```yaml {% title="openapi.yaml" %} paths: @@ -598,7 +627,7 @@ paths: summary: User Login tags: [Authentication] # Define rate-limiting policy for this sensitive endpoint - x-rate-limit: + x-rateLimit: limit: 5 window: "1m" scope: "ip_address" @@ -625,33 +654,18 @@ paths: ``` **Redocly Governance for Rate Limiting:** -```yaml -# redocly.yaml -rules: - # Require rate limits on authentication endpoints - rule/require-rate-limit-on-auth: - subject: - type: Operation - where: - - subject: - property: tags - assertions: - contains: "Authentication" - assertions: - defined: - - x-rate-limit - message: "Authentication operations must have 'x-rate-limit' policy defined." - severity: error -``` -This approach provides dual benefits: [Redocly's Redoc](https://redocly.com/redoc) automatically displays the `x-rate-limit` object in generated documentation, making policies transparent to API consumers, while governance rules ensure sensitive endpoints never lack rate-limiting policies. +The [Complete Security Governance Configuration](#complete-security-governance-configuration) includes the `rule/require-rate-limit-on-auth` rule that ensures authentication endpoints always have rate limiting policies defined. + +This approach provides dual benefits: [Redocly's Redoc](https://redocly.com/redoc) automatically displays the `x-rateLimit` object in generated documentation, making policies transparent to API consumers, while governance rules ensure sensitive endpoints never lack rate-limiting policies. ### Why Rate Limiting Is Critical -Rate limiting serves two crucial purposes: +Rate limiting is a critical control for both security and reliability, directly mitigating several OWASP API Security Top 10 risks: -1. **Security:** It is a vital defense against automated attacks. It can thwart **Denial-of-Service (DoS)** attacks, where an attacker attempts to make a service unavailable by flooding it with traffic, which relates to **API4:2023 - Unrestricted Resource Consumption**. It also makes **brute-force** attacks against authentication endpoints (i.e., guessing passwords) much slower and less effective. Furthermore, it helps mitigate business logic abuse by preventing bots from, for example, scraping all product pricing data or buying up an entire inventory of limited-stock items, addressing **API6:2023 - Unrestricted Access to Sensitive Business Flows**. -2. **Reliability and Fair Usage:** It ensures that the API remains stable and responsive for all users by preventing any single client from monopolizing server resources. This guarantees a better and more equitable quality of service for everyone. +1. **Security:** It thwarts Denial-of-Service (DoS) attacks by preventing traffic floods, addressing OWASP API4:2023 - Unrestricted Resource Consumption. It also makes brute-force attacks against authentication endpoints much slower and less effective, reducing the risk of credential stuffing attacks. +2. **Business Logic Abuse:** It helps mitigate abuse by preventing bots from scraping data or manipulating business flows, addressing OWASP API6:2023 - Unrestricted Access to Sensitive Business Flows. +3. **Reliability and Fair Usage:** It ensures that the API remains stable and responsive for all users by preventing any single client from monopolizing server resources. ### Rate Limiting Implementation Approaches @@ -661,8 +675,7 @@ Rate limiting serves two crucial purposes: - **Fixed Window**: Simple per-timeframe limits, prone to boundary conditions **Multi-tier Strategy:** -```yaml -# API Gateway configuration example +```yaml {% title="API Gateway configuration" %} rate_limits: global: requests_per_minute: 1000 @@ -678,8 +691,7 @@ rate_limits: ### Advanced Rate Limiting Techniques **Multi-tier Rate Limiting:** -```yaml -# API Gateway configuration (Kong example) +```yaml {% title="Kong configuration" %} plugins: - name: rate-limiting config: @@ -731,7 +743,9 @@ As a complementary practice, the client-side responsibility of implementing expo ### Attack Example: Facebook phone number scraping (2019 dataset) -How has rate limiting mistakes been exploted? Funny you should ask! Here's one that happened at Facebook. Attackers enumerated user data through contact import and related endpoints with insufficient rate limiting and anomaly detection, leading to the aggregation of hundreds of millions of records that later appeared publicly. +In 2019, malicious actors exploited a vulnerability in Facebook's contact importer feature to scrape the personal data of over 530 million users. The API endpoint itself was not technically "broken"—it performed its intended function of matching phone numbers to user profiles. The vulnerability was the absence of adequate rate limiting and business rule enforcement. Attackers used automated scripts to submit massive lists of phone numbers, and the API dutifully returned the corresponding user profiles, allowing them to build a massive database of personal information. + +This incident highlights a different type of API attacks, moving from exploiting technical flaws to abusing business logic at scale. It elevates rate limiting from an infrastructure protection mechanism to a also being a tool for enforcing business rules. The `x-rateLimit` extension in OpenAPI is a form of declarative security policy. ```mermaid sequenceDiagram @@ -759,8 +773,7 @@ OpenAPI 3.1 provides a robust framework for defining access control through two 2. **`security`**: Specifies *that* an endpoint is secured and by which mechanism(s) **JWT Bearer Token Example:** -```yaml -# openapi.yaml +```yaml {% title="openapi.yaml" %} components: securitySchemes: bearerAuth: @@ -775,8 +788,7 @@ security: ``` **OAuth2 with Scopes Example:** -```yaml -# openapi.yaml +```yaml {% title="openapi.yaml" %} components: securitySchemes: oauth2Auth: @@ -800,31 +812,7 @@ paths: ### Redocly Governance for Access Control -The most critical built-in security rule is `security-defined`, which ensures every operation is covered by a security requirement: - -```yaml -# redocly.yaml -extends: - - recommended - -rules: - # Ensure no endpoint is accidentally left unsecured - security-defined: error - - # Custom rule: Require security on sensitive operations - rule/require-auth-on-mutations: - subject: - type: Operation - where: - - subject: - property: method - assertions: - enum: [post, put, patch, delete] - assertions: - defined: [security] - message: "All write operations must have security defined." - severity: error -``` +Access control enforcement is handled through the custom `rule/require-auth-on-mutations` rule shown in the [Complete Security Governance Configuration](#complete-security-governance-configuration), which ensures all write operations have security requirements defined. When `redocly lint` runs, any endpoint without a corresponding `security` block causes the build to fail, preventing the most common API vulnerability: the unintentionally public endpoint. @@ -859,7 +847,7 @@ curl -H "Authorization: Bearer invalid" https://api.example.com/users/me curl -H "Authorization: Bearer readonly_token" -X POST https://api.example.com/users ``` -> Key insight: "The `security-defined` rule has prevented more breaches than any other single control. It's non-negotiable in our CI pipeline." Learn more about implementing this with [Redocly's API Governance solution](https://redocly.com/api-governance). +> Key insight: "Requiring security definitions on all write operations has prevented more breaches than any other single control. The `rule/require-auth-on-mutations` is non-negotiable in our CI pipeline." Learn more about implementing this with [Redocly's API Governance solution](https://redocly.com/api-governance). #### Rate limiting troubleshooting and common pitfalls @@ -883,8 +871,7 @@ hey -z 10s -q 50 -c 50 https://api.example.com/api/resource ## Monitoring and Observability ### TLS Monitoring -```yaml -# Prometheus alerts for TLS +```yaml {% title="prometheus.yml" %} groups: - name: tls_alerts rules: @@ -960,14 +947,23 @@ OpenAPI specifications define precise data schemas with type validation, format Rate limiting prevents denial-of-service attacks, brute-force authentication attempts, and data scraping. It ensures fair resource usage among legitimate users while blocking malicious automation. Without rate limits, a single bad actor can overwhelm your API infrastructure. ### Can I implement all four security areas with just OpenAPI? -Yes, OpenAPI 3.1 supports all four security areas: TLS enforcement through server URLs, input validation via JSON schemas, rate limiting through extensions like `x-rate-limit`, and access control via security schemes. Combined with governance automation, your specification becomes an executable security contract. +Yes, OpenAPI 3.1 supports all four security areas: TLS enforcement through server URLs, input validation via JSON schemas, rate limiting through extensions like `x-rateLimit`, and access control via security schemes. Combined with governance automation, your specification becomes an executable security contract. ### What's the difference between authentication and authorization in APIs? Authentication verifies *who* the user is (like checking an ID card), while authorization determines *what* they can do (like checking permissions). Both are essential for API security, and OpenAPI provides security schemes to define and enforce both concepts through your specification. ## Resources -- **[OWASP API Security Top 10](https://owasp.org/www-project-api-security/)** - Complete vulnerability guide including injection and resource consumption attacks -- **[Mozilla TLS Configuration Generator](https://ssl-config.mozilla.org/)** - Generate secure TLS configurations for various web servers and applications -- **[NIST Guidelines for TLS Implementations](https://csrc.nist.gov/publications/detail/sp/800-52/rev-2/final)** - Official guidelines for secure TLS implementation and configuration -- **[Redocly Documentation](https://redocly.com/docs/)** - Complete guide to implementing API governance and automated security validation +### Security Standards and Guidelines +- [OWASP API Security Top 10](https://owasp.org/www-project-api-security/) - Comprehensive vulnerability guide including injection attacks (API3:2023), resource consumption (API4:2023), and business logic abuse (API6:2023) +- [NIST SP 800-52 Rev. 2](https://csrc.nist.gov/publications/detail/sp/800-52/rev-2/final) - Official guidelines for secure TLS implementation and configuration requirements +- [IETF RFC 8446](https://tools.ietf.org/html/rfc8446) - TLS 1.3 protocol specification and security requirements + +### Practical Implementation Tools +- [Mozilla SSL Configuration Generator](https://ssl-config.mozilla.org/) - Generate secure, up-to-date TLS configurations for various web servers and security levels +- [Redocly CLI Documentation](https://redocly.com/docs/cli/) - Complete guide to implementing API governance, linting, and automated security validation +- [OpenAPI Specification](https://spec.openapis.org/oas/v3.1.0) - Official OpenAPI 3.1 specification including security scheme definitions + +### DevSecOps and API Governance +- [Redocly API Governance](https://redocly.com/api-governance) - Enterprise-grade API governance and security automation platform +- [API Security Best Practices](https://redocly.com/docs/cli/rules/built-in-rules) - Built-in security rules and governance patterns for API specifications From e1c869067b1712c5da159369b8f7657eaaca55e1 Mon Sep 17 00:00:00 2001 From: Matt Williams Date: Sat, 30 Aug 2025 17:58:08 -0500 Subject: [PATCH 05/27] Fix deprecated link to Redocly Workflows, replace with CLI documentation --- learn/security/api-design-first-security-guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/learn/security/api-design-first-security-guide.md b/learn/security/api-design-first-security-guide.md index 71c2677c..3ca43044 100644 --- a/learn/security/api-design-first-security-guide.md +++ b/learn/security/api-design-first-security-guide.md @@ -506,7 +506,7 @@ components: The [Complete Security Governance Configuration](#complete-security-governance-configuration) includes comprehensive input validation rules that automatically enforce string length bounds, numeric ranges, and prevent mass assignment vulnerabilities. See the Input Validation Rules section for the complete implementation. -This governance approach changes security reviews. Instead of manually checking many properties for missing `maxLength` constraints, automated linting with [Redocly Workflows](https://redocly.com/workflows) handles baseline validation so security teams can focus on strategic concerns like business logic and context-dependent risks. +This governance approach changes security reviews. Instead of manually checking many properties for missing `maxLength` constraints, automated linting with [Redocly CLI](https://redocly.com/docs/cli/) handles baseline validation so security teams can focus on strategic concerns like business logic and context-dependent risks. ### Key Security Constraints From a7db633e99d4c855a68a2be8085163b6626989a5 Mon Sep 17 00:00:00 2001 From: Matt Williams Date: Thu, 18 Sep 2025 13:57:34 -0500 Subject: [PATCH 06/27] feat: Create comprehensive API security article series with SEO optimization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Split original api-design-first-security-guide.md into 6 focused articles - Remove Redocly branding to create vendor-neutral security content - Add 3 strategic Mermaid diagrams (#4, #5, #7) for visual learning New Articles Created: • learn/security/index.md - Main landing page with article overview • api-tls-encryption-https-best-practices.md - TLS 1.3, HTTPS, mTLS guide • api-input-validation-injection-prevention.md - Schema validation, SQL injection prevention • api-rate-limiting-abuse-prevention.md - DoS protection, rate limiting algorithms • authentication-authorization-openapi.md - JWT, OAuth2, security schemes • api-design-first-security-governance.md - Automated governance, policy-as-code Navigation & UX Improvements: • Updated learn/security/sidebars.yaml with organized article structure • Enhanced pages/learning-center/cards.ts with all 6 security articles • Added strategic cross-links between related security topics • Implemented target='_blank' links to preserve user navigation context • Fixed URLs to use clean paths without .md extensions Content Quality: • Each article SEO-optimized with focused keywords and standalone value • Comprehensive cross-referencing between security domains • Real-world case studies: Heartbleed, Equifax, Facebook phone scraping • Practical code examples and governance rule implementations • Progressive learning path from infrastructure to organizational maturity --- .../api-design-first-security-governance.md | 968 ++++++++++++++++++ .../api-design-first-security-guide.md | 283 ++--- ...i-input-validation-injection-prevention.md | 384 +++++++ .../api-rate-limiting-abuse-prevention.md | 448 ++++++++ ...api-tls-encryption-https-best-practices.md | 327 ++++++ .../authentication-authorization-openapi.md | 794 ++++++++++++++ learn/security/index.md | 261 ++++- learn/security/sidebars.yaml | 9 +- pages/learning-center/cards.ts | 9 +- 9 files changed, 3348 insertions(+), 135 deletions(-) create mode 100644 learn/security/api-design-first-security-governance.md create mode 100644 learn/security/api-input-validation-injection-prevention.md create mode 100644 learn/security/api-rate-limiting-abuse-prevention.md create mode 100644 learn/security/api-tls-encryption-https-best-practices.md create mode 100644 learn/security/authentication-authorization-openapi.md diff --git a/learn/security/api-design-first-security-governance.md b/learn/security/api-design-first-security-governance.md new file mode 100644 index 00000000..cadffa4b --- /dev/null +++ b/learn/security/api-design-first-security-governance.md @@ -0,0 +1,968 @@ +# Design-First Security Governance and Automation + +_Scale security practices through automated governance, policy-as-code, and organizational maturity._ + +--- + +## Key Takeaways + +Manual security reviews don't scale. As organizations grow their API portfolios, the traditional approach of reviewing each specification manually becomes a bottleneck that slows development and introduces inconsistencies. Design-first security governance transforms this challenge by encoding security requirements as automated policies that enforce standards across every API, every time. + +In this guide, we'll explore how to implement automated security governance that shifts security left in the development lifecycle, reduces review overhead, and ensures consistent security standards across your entire API ecosystem. + +**We'll cover how to:** +- Transform security requirements into automated governance policies +- Integrate security validation into CI/CD pipelines +- Scale security practices across large development organizations +- Measure and improve security governance effectiveness +- Build organizational security maturity through automation + +--- + +## From Manual Reviews to Automated Governance + +Traditional security approaches treat reviews as gates staffed by humans who check for common issues like missing [authentication](authentication-authorization-openapi.md), weak [input validation](api-input-validation-injection-prevention.md), or insecure [transport](api-tls-encryption-https-best-practices.md). This approach has fundamental limitations: + +- **Doesn't scale**: Review time increases linearly with team size +- **Inconsistent**: Different reviewers catch different issues +- **Reactive**: Problems discovered late in the development cycle +- **Limited coverage**: Humans miss edge cases that machines catch consistently + +### The Policy-as-Code Approach + +Design-first security governance treats security requirements as executable code. Instead of documenting that "all write operations must have [authentication](authentication-authorization-openapi.md)," you write a governance rule that automatically validates this requirement: + +```yaml {% title="security-governance.yaml" %} +rules: + require-auth-on-mutations: + description: "All write operations must have security requirements" + severity: error + given: "$.paths[*][*]" + when: + function: enumerated + functionOptions: + values: ["post", "put", "patch", "delete"] + then: + field: "security" + function: truthy +``` + +When this rule runs in your CI/CD pipeline, any OpenAPI specification that violates the policy fails the build automatically. The developer gets immediate feedback and must fix the issue before the code can be merged. + +### Automated Governance Benefits + +**Consistent Enforcement:** +- Every API specification is validated against the same rules +- No human variation in what gets flagged or missed +- New team members get consistent security feedback + +**Immediate Feedback:** +- Developers learn about security issues within minutes, not days +- Problems are caught before code review, reducing back-and-forth +- Security becomes part of the development flow, not a separate gate + +**Comprehensive Coverage:** +- Machines don't get tired or miss obvious issues +- Complex cross-reference validation that humans struggle with +- Scales to hundreds of APIs without adding review overhead + +## Core Security Governance Principles + +Effective security governance requires well-defined policies that map business security requirements to technical implementation details. These policies should be comprehensive, actionable, and automatically enforceable. + +### Transport Security Governance + +**Enforce HTTPS-Only Server URLs:** +```yaml {% title="governance-rules.yaml" %} +rules: + https-only-servers: + description: "All server URLs must use HTTPS" + severity: error + given: "$.servers[*].url" + then: + function: pattern + functionOptions: + match: "^https://" + message: "Server URLs must use HTTPS for secure transport" +``` + +**Prevent Placeholder Domains in Production:** +```yaml {% title="governance-rules.yaml" %} +rules: + no-placeholder-domains: + description: "Production specs cannot use example.com domains" + severity: error + given: "$.servers[*].url" + then: + function: pattern + functionOptions: + notMatch: "(example\\.com|localhost|127\\.0\\.0\\.1)" + message: "Use actual production domains, not placeholders" +``` + +### Input Validation Governance + +**Require Length Constraints on Strings:** +```yaml {% title="governance-rules.yaml" %} +rules: + string-maxlength-required: + description: "All string properties must have maxLength constraints" + severity: error + given: "$..[?(@.type === 'string')]" + then: + field: "maxLength" + function: truthy + message: "String properties must have maxLength to prevent resource exhaustion" +``` + +**Enforce Numeric Bounds:** +```yaml {% title="governance-rules.yaml" %} +rules: + numeric-bounds-required: + description: "Numeric properties must have minimum and maximum constraints" + severity: error + given: "$..[?(@.type === 'integer' || @.type === 'number')]" + then: + - field: "minimum" + function: truthy + - field: "maximum" + function: truthy + message: "Numeric properties must have bounds to prevent overflow attacks" +``` + +**Prevent Mass Assignment Vulnerabilities:** +```yaml {% title="governance-rules.yaml" %} +rules: + no-additional-properties: + description: "Object schemas must set additionalProperties: false" + severity: error + given: "$..[?(@.type === 'object')]" + then: + field: "additionalProperties" + function: falsy + message: "Set additionalProperties: false to prevent mass assignment attacks" +``` + +### Access Control Governance + +**Require Authentication on Write Operations:** +```yaml {% title="governance-rules.yaml" %} +rules: + auth-required-on-writes: + description: "Write operations must have security requirements" + severity: error + given: "$.paths[*][post,put,patch,delete]" + then: + field: "security" + function: truthy + message: "Write operations must require authentication to prevent unauthorized access" +``` + +**Validate Security Scheme References:** +```yaml {% title="governance-rules.yaml" %} +rules: + valid-security-references: + description: "All security references must have corresponding definitions" + severity: error + given: "$.paths[*][*].security[*]" + then: + function: security-scheme-defined + message: "Security scheme must be defined in components.securitySchemes" +``` + +### Rate Limiting Governance + +**Require Rate Limiting on Authentication Endpoints:** +```yaml {% title="governance-rules.yaml" %} +rules: + rate-limits-on-auth: + description: "[Authentication endpoints](authentication-authorization-openapi.md) must have [rate limiting](api-rate-limiting-abuse-prevention.md) policies" + severity: error + given: "$.paths[*][*]" + when: + - field: "tags" + function: pattern + functionOptions: + match: "(?i)auth" + - field: "@key" + function: pattern + functionOptions: + match: "(post|put)" + then: + field: "x-rateLimit" + function: truthy + message: "Authentication endpoints must have x-rateLimit extension to prevent brute force attacks" +``` + +## Implementing Automated Governance + +### CI/CD Pipeline Integration + +Integrating security governance into your CI/CD pipeline ensures that every API change is automatically validated against your security policies. + +**GitHub Actions Example:** +```yaml {% title=".github/workflows/api-governance.yml" %} +name: API Security Governance + +on: + pull_request: + paths: + - '**/*.yaml' + - '**/*.yml' + - '**/*.json' + +jobs: + security-governance: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Install governance CLI + run: npm install -g @redocly/cli + + - name: Validate OpenAPI specifications + run: | + find . -name "*.yaml" -o -name "*.yml" | grep -E "(openapi|api)" | while read file; do + echo "Validating $file..." + redocly lint "$file" --config .redocly.yaml + done + + - name: Security governance check + run: | + find . -name "*.yaml" -o -name "*.yml" | grep -E "(openapi|api)" | while read file; do + echo "Security governance check for $file..." + redocly lint "$file" --config security-governance.yaml + done +``` + +**GitLab CI Example:** +```yaml {% title=".gitlab-ci.yml" %} +api-security-governance: + stage: test + image: node:18 + before_script: + - npm install -g @redocly/cli + script: + - | + find . -name "*.yaml" -o -name "*.yml" | grep -E "(openapi|api)" | while read file; do + echo "Validating $file against security policies..." + redocly lint "$file" --config security-governance.yaml + done + rules: + - changes: + - "**/*.yaml" + - "**/*.yml" + - "**/*.json" +``` + +### Governance Configuration Management + +**Complete Security Governance Configuration:** +```yaml {% title="security-governance.yaml" %} +extends: + - recommended + +rules: + # Transport Security + https-only-servers: + severity: error + given: "$.servers[*].url" + then: + function: pattern + functionOptions: + match: "^https://" + + no-placeholder-domains: + severity: error + given: "$.servers[*].url" + then: + function: pattern + functionOptions: + notMatch: "(example\\.com|localhost|127\\.0\\.0\\.1)" + + # Input Validation + string-maxlength-required: + severity: error + given: "$..[?(@.type === 'string')]" + then: + field: "maxLength" + function: truthy + + numeric-bounds-required: + severity: error + given: "$..[?(@.type === 'integer' || @.type === 'number')]" + then: + - field: "minimum" + function: truthy + - field: "maximum" + function: truthy + + no-additional-properties: + severity: error + given: "$..[?(@.type === 'object')]" + then: + field: "additionalProperties" + function: falsy + + # Access Control + auth-required-on-writes: + severity: error + given: "$.paths[*][post,put,patch,delete]" + then: + field: "security" + function: truthy + + # Rate Limiting + rate-limits-on-auth: + severity: warning + given: "$.paths[*][*]" + when: + field: "tags" + function: pattern + functionOptions: + match: "(?i)auth" + then: + field: "x-rateLimit" + function: truthy + + # Documentation Quality + operation-description-required: + severity: warning + given: "$.paths[*][*]" + then: + field: "description" + function: truthy + + response-schema-required: + severity: error + given: "$.paths[*][*].responses[2-3][0-9][0-9]" + then: + field: "content" + function: truthy + +# Custom functions for complex validation +functions: + security-scheme-defined: + code: | + function(targetVal, options, paths, otherValues) { + const schemes = otherValues?.components?.securitySchemes || {}; + for (const requirement of targetVal) { + for (const schemeName in requirement) { + if (!(schemeName in schemes)) { + return [ + { + message: `Security scheme '${schemeName}' is not defined in components.securitySchemes` + } + ]; + } + } + } + return []; + } +``` + +### Progressive Enforcement + +When implementing governance in existing organizations, start with warnings and gradually increase severity to avoid disrupting active development. + +**Phased Implementation Strategy:** + +**Phase 1: Observability (Weeks 1-2)** +```yaml +rules: + auth-required-on-writes: + severity: info # Start with info level + given: "$.paths[*][post,put,patch,delete]" + then: + field: "security" + function: truthy +``` + +**Phase 2: Warnings (Weeks 3-4)** +```yaml +rules: + auth-required-on-writes: + severity: warn # Escalate to warnings + given: "$.paths[*][post,put,patch,delete]" + then: + field: "security" + function: truthy +``` + +**Phase 3: Enforcement (Week 5+)** +```yaml +rules: + auth-required-on-writes: + severity: error # Full enforcement + given: "$.paths[*][post,put,patch,delete]" + then: + field: "security" + function: truthy +``` + +## Organizational Security Maturity + +### API Security Maturity Model + +Organizations typically progress through distinct maturity levels as they build more sophisticated security practices: + +```mermaid +graph TD + A[Level 0: Basic] --> B[Level 1: Structured] --> C[Level 2: Automated] --> D[Level 3: Proactive] + + A --> A1[Manual reviews
Basic HTTPS
Simple auth] + B --> B1[OpenAPI specs
Schema validation
Rate limiting] + C --> C1[Automated governance
CI/CD integration
Policy enforcement] + D --> D1[Threat modeling
Zero-trust architecture
Continuous monitoring] + + style A fill:#ffcdd2 + style B fill:#fff59d + style C fill:#c8e6c9 + style D fill:#a5d6a7 +``` + +*API security maturity progression showing the evolution from basic manual practices to proactive, automated security governance with comprehensive threat detection and prevention.* + +**Level 0 - Basic Security (Manual, Ad-hoc):** +- Manual code reviews for obvious security issues +- HTTPS enabled but not enforced through specifications +- Basic authentication (API keys or simple passwords) +- Ad-hoc security practices without consistent standards +- Security discovered through incident response + +**Level 1 - Structured Security (Documented, Consistent):** +- OpenAPI specifications document all APIs with security requirements +- [Schema-based input validation](api-input-validation-injection-prevention.md) prevents basic injection attacks +- [Rate limiting](api-rate-limiting-abuse-prevention.md) implemented on [authentication](authentication-authorization-openapi.md) and sensitive endpoints +- Consistent security patterns across API teams +- Security reviews are systematic but still manual + +**Level 2 - Automated Security (Policy-as-Code):** +- Automated governance tools enforce security standards in CI/CD pipelines +- Security policies defined as code and validated automatically +- Breaking changes to security configurations fail builds +- Security metrics tracked and monitored systematically +- Governance rules prevent common vulnerabilities automatically + +**Level 3 - Proactive Security (Threat-Aware, Adaptive):** +- Comprehensive threat modeling integrated into the design process +- Zero-trust architecture with [mutual TLS](api-tls-encryption-https-best-practices.md#mutual-tls-mtls-two-way-authentication) for service-to-service communication +- Continuous security monitoring with behavioral analysis and anomaly detection +- Security feedback loops drive iterative improvements to governance policies +- Security practices adapt based on emerging threats and attack patterns + +### Building Governance Teams + +**Security Champions Program:** +Embed security-minded developers in each team rather than centralizing all security knowledge: + +- **Champions**: One security-focused developer per 5-8 person team +- **Training**: Regular security training and threat modeling workshops +- **Responsibility**: Champions help teammates understand and implement governance rules +- **Feedback**: Champions provide feedback on governance rule effectiveness + +**Governance Center of Excellence:** +Create a small, centralized team responsible for governance policy development: + +- **Policy Development**: Create and maintain governance rules +- **Tool Management**: Manage governance tooling and CI/CD integration +- **Training**: Develop security training materials and documentation +- **Metrics**: Track governance effectiveness and security posture improvements + +### Measuring Governance Effectiveness + +**Security Metrics Dashboard:** +```yaml {% title="governance-metrics.yaml" %} +metrics: + governance_adoption: + - specs_with_security_schemes + - specs_with_input_validation + - specs_with_rate_limiting + - specs_passing_all_checks + + vulnerability_prevention: + - accidentally_public_endpoints_prevented + - missing_auth_caught_in_ci + - validation_bypass_attempts_blocked + - governance_rule_violations_per_week + + development_velocity: + - average_security_review_time + - security_feedback_loop_duration + - governance_rule_false_positive_rate + - developer_security_question_frequency +``` + +**Monthly Security Governance Report:** +```markdown +## API Security Governance Report - March 2025 + +### Governance Coverage +- 🟢 **98%** of APIs have authentication requirements defined +- 🟢 **94%** of APIs have input validation constraints +- 🟡 **78%** of APIs have rate limiting policies +- 🔴 **45%** of APIs have comprehensive error handling + +### Vulnerabilities Prevented +- **23** accidentally public endpoints caught in CI/CD +- **67** missing input validation constraints flagged +- **12** insecure server URLs rejected +- **8** undefined security schemes blocked + +### Developer Experience +- **2.3 minutes** average governance check time +- **0.8%** false positive rate on governance rules +- **94%** developer satisfaction with governance feedback + +### Recommendations +1. Increase rate limiting coverage through new governance rules +2. Improve error handling governance with custom validation functions +3. Add governance rules for API versioning consistency +``` + +## Advanced Governance Patterns + +### Context-Aware Validation + +Some security requirements depend on the context in which an API operates. Advanced governance can implement conditional logic: + +```yaml {% title="context-aware-governance.yaml" %} +rules: + external-apis-require-strict-auth: + description: "External APIs must use OAuth2, internal APIs can use API keys" + severity: error + given: "$.paths[*][*]" + when: + field: "tags" + function: pattern + functionOptions: + match: "external" + then: + field: "security[*].oauth2Auth" + function: truthy + message: "External APIs must use OAuth2 authentication" + + pii-endpoints-require-additional-validation: + description: "Endpoints handling PII must have enhanced validation" + severity: error + given: "$.paths[*][*]" + when: + field: "tags" + function: pattern + functionOptions: + match: "(?i)pii|personal" + then: + function: enhanced-pii-validation +``` + +### Custom Validation Functions + +For complex business rules that can't be expressed in standard governance syntax: + +```javascript {% title="custom-functions.js" %} +// Custom function for validating PII handling +function enhancedPiiValidation(targetVal, options, paths, otherValues) { + const errors = []; + + // Check for required audit logging + if (!targetVal['x-audit-logging']) { + errors.push({ + message: "PII endpoints must have x-audit-logging extension" + }); + } + + // Check for data retention policies + if (!targetVal['x-retention-policy']) { + errors.push({ + message: "PII endpoints must specify data retention policy" + }); + } + + // Check for enhanced rate limiting + const rateLimit = targetVal['x-rateLimit']; + if (!rateLimit || rateLimit.limit > 10) { + errors.push({ + message: "PII endpoints must have strict rate limiting (≤10 requests/minute)" + }); + } + + return errors; +} + +// Custom function for validating security scheme consistency +function consistentSecuritySchemes(targetVal, options, paths, otherValues) { + const errors = []; + const allOperations = Object.values(otherValues.paths || {}) + .flatMap(pathItem => Object.values(pathItem)); + + const securitySchemes = new Set(); + allOperations.forEach(operation => { + if (operation.security) { + operation.security.forEach(requirement => { + Object.keys(requirement).forEach(scheme => { + securitySchemes.add(scheme); + }); + }); + } + }); + + // Warn if too many different auth schemes are used + if (securitySchemes.size > 2) { + errors.push({ + message: `API uses ${securitySchemes.size} different auth schemes. Consider standardizing.` + }); + } + + return errors; +} +``` + +### Multi-Environment Governance + +Different environments may require different security standards: + +```yaml {% title="production-governance.yaml" %} +# Strict production rules +extends: + - security-governance.yaml + +rules: + # Production-specific overrides + no-mock-servers: + severity: error + given: "$.servers[*].url" + then: + function: pattern + functionOptions: + notMatch: "(mock|sandbox|test)" + + require-monitoring-extensions: + severity: error + given: "$.paths[*][*]" + then: + field: "x-monitoring" + function: truthy +``` + +```yaml {% title="development-governance.yaml" %} +# More permissive development rules +extends: + - security-governance.yaml + +rules: + # Allow mock servers in development + no-mock-servers: + severity: off + + # Relax some requirements for faster iteration + string-maxlength-required: + severity: warn # Warning instead of error +``` + +## Governance Tooling Ecosystem + +### Popular Governance Tools + +**Spectral:** +```yaml {% title=".spectral.yml" %} +extends: ["@redocly/spectral-config"] +functions: + - custom-security-functions.js +rules: + security-governance: + severity: error + given: "$.paths[*][*]" + then: + function: security-requirements-check +``` + +**Redocly CLI:** +```yaml {% title="redocly.yaml" %} +apis: + main: + root: openapi.yaml + +lint: + extends: + - recommended + rules: + security-governance/auth-required: error + security-governance/https-only: error + security-governance/input-validation: error +``` + +**Custom Governance Scripts:** +```python {% title="governance-check.py" %} +#!/usr/bin/env python3 + +import yaml +import sys +from pathlib import Path + +def check_security_governance(spec_path): + """Check OpenAPI spec against security governance rules""" + with open(spec_path) as f: + spec = yaml.safe_load(f) + + errors = [] + + # Check for HTTPS-only servers + for server in spec.get('servers', []): + if not server['url'].startswith('https://'): + errors.append(f"Server {server['url']} must use HTTPS") + + # Check for auth on write operations + for path, methods in spec.get('paths', {}).items(): + for method in ['post', 'put', 'patch', 'delete']: + if method in methods and 'security' not in methods[method]: + errors.append(f"{method.upper()} {path} missing security requirements") + + # Check for input validation + for schema_name, schema in spec.get('components', {}).get('schemas', {}).items(): + if schema.get('type') == 'object' and schema.get('additionalProperties', True): + errors.append(f"Schema {schema_name} should set additionalProperties: false") + + return errors + +if __name__ == "__main__": + spec_file = sys.argv[1] + errors = check_security_governance(spec_file) + + if errors: + print("❌ Security governance violations found:") + for error in errors: + print(f" - {error}") + sys.exit(1) + else: + print("✅ All security governance checks passed") +``` + +### Integration with API Lifecycle Tools + +**API Design Tools:** +- **Stoplight Studio**: Built-in governance rules and real-time validation +- **SwaggerHub**: Automated governance checks on specification save +- **Insomnia Designer**: Custom governance plugins for design-time validation + +**Code Generation:** +- **OpenAPI Generator**: Generate security middleware from governance-validated specs +- **Speakeasy**: Type-safe SDKs with built-in security handling +- **Fern**: End-to-end API development with governance integration + +**Documentation:** +- **Redoc**: Display governance-validated security requirements clearly +- **Stoplight Elements**: Interactive documentation with security testing +- **Readme.io**: Governance-aware API documentation with security examples + +## Troubleshooting Governance Issues + +### Common Governance Problems + +**False Positives:** +```yaml +# Problem: Rule triggers incorrectly +rules: + auth-required: + given: "$.paths[*][*]" # Too broad - includes OPTIONS, HEAD + then: + field: "security" + function: truthy + +# Solution: More specific selector +rules: + auth-required: + given: "$.paths[*][post,put,patch,delete]" # Only write operations + then: + field: "security" + function: truthy +``` + +**Performance Issues:** +```yaml +# Problem: Complex rules that slow down CI/CD +rules: + expensive-validation: + given: "$..[*]" # Searches entire document + then: + function: complex-custom-function + +# Solution: More targeted selectors +rules: + efficient-validation: + given: "$.paths[*][*].security" # Target specific areas + then: + function: simple-validation-function +``` + +**Rule Conflicts:** +```yaml +# Problem: Rules that contradict each other +rules: + require-oauth2: + given: "$.paths[*][*]" + then: + field: "security[*].oauth2" + function: truthy + + allow-api-keys: + given: "$.paths[*][*]" + then: + field: "security[*].apiKey" + function: truthy + +# Solution: Context-specific rules +rules: + external-apis-oauth2: + given: "$.paths[*][*]" + when: + field: "tags" + function: pattern + functionOptions: + match: "external" + then: + field: "security[*].oauth2" + function: truthy + + internal-apis-flexible: + given: "$.paths[*][*]" + when: + field: "tags" + function: pattern + functionOptions: + match: "internal" + then: + # Allow either oauth2 or apiKey + function: has-any-auth-scheme +``` + +### Debugging Governance Rules + +**Verbose Logging:** +```bash +# Enable detailed governance output +redocly lint openapi.yaml --config security-governance.yaml --verbose + +# Test specific rules +redocly lint openapi.yaml --config security-governance.yaml --rule auth-required-on-writes +``` + +**Rule Testing:** +```yaml {% title="test-governance.yaml" %} +# Create minimal test cases for each rule +rules: + auth-required-test: + description: "Test auth requirement rule" + severity: error + given: "$.paths['/test'][post]" + then: + field: "security" + function: truthy + +# Test with minimal OpenAPI spec +--- +openapi: 3.1.0 +info: + title: Test API + version: 1.0.0 +paths: + /test: + post: + summary: Test endpoint + # Should fail governance check + responses: + '200': + description: Success +``` + +**Rule Validation Workflow:** +```bash +#!/bin/bash +# validate-governance-rules.sh + +echo "Testing governance rules..." + +# Test with known-bad spec (should fail) +if redocly lint test/bad-spec.yaml --config security-governance.yaml > /dev/null 2>&1; then + echo "❌ Governance rules are too permissive" + exit 1 +fi + +# Test with known-good spec (should pass) +if ! redocly lint test/good-spec.yaml --config security-governance.yaml > /dev/null 2>&1; then + echo "❌ Governance rules are too strict" + exit 1 +fi + +echo "✅ Governance rules are working correctly" +``` + +## Best Practices Summary + +### Policy Development +- Start with high-impact, low-controversy rules (HTTPS enforcement, auth on writes) +- Use progressive enforcement: info → warning → error over time +- Test governance rules with both positive and negative test cases +- Document the business rationale for each governance rule + +### Implementation +- Integrate governance checks early in the development process (IDE, pre-commit hooks) +- Provide clear, actionable error messages with examples +- Create escape hatches for legitimate exceptions (with approval process) +- Monitor governance rule effectiveness and false positive rates + +### Organizational Change +- Train developers on security principles, not just governance tool usage +- Establish security champions in each development team +- Create feedback loops to improve governance rules based on developer experience +- Measure and communicate the security improvements from governance + +### Technical Excellence +- Use specific JSONPath selectors to minimize false positives +- Implement custom functions for complex business logic +- Version governance configurations alongside API specifications +- Maintain separate governance rules for different environments + +## Frequently Asked Questions + +### How do I get buy-in for governance automation? +Start with metrics that demonstrate the problem: count manually-found security issues, measure time spent on security reviews, track inconsistencies across teams. Then pilot governance on a single team and measure improvements in both security posture and developer velocity. + +### What's the difference between linting and governance? +Linting typically focuses on style, formatting, and basic structural issues. Governance enforces business rules and security policies that are specific to your organization. Good governance builds on solid linting foundations. + +### How do I handle exceptions to governance rules? +Create an exception process with clear criteria: document the business justification, get security team approval, set expiration dates for temporary exceptions, and track all exceptions for periodic review. + +### Should governance rules be the same across all environments? +No. Production should have the strictest rules, while development environments can be more permissive to enable faster iteration. Use environment-specific governance configurations that inherit from a common base. + +### How do I measure the ROI of governance automation? +Track metrics like: time saved on manual security reviews, number of vulnerabilities caught before production, consistency improvements across teams, and developer satisfaction with security feedback quality. + +## Resources + +### Governance Tools and Standards +- [Spectral](https://stoplight.io/open-source/spectral) - Open-source API linting and governance tool with custom rule support +- [Redocly CLI](https://redocly.com/docs/cli/) - Comprehensive OpenAPI toolchain with built-in governance capabilities +- [OpenAPI Specification](https://spec.openapis.org/oas/v3.1.0) - Official specification for defining governance-friendly API contracts + +### Security Standards and Frameworks +- [OWASP API Security Top 10](https://owasp.org/www-project-api-security/) - Essential security risks that governance should address +- [NIST Cybersecurity Framework](https://www.nist.gov/cyberframework) - Comprehensive framework for organizational security maturity +- [DevSecOps Reference Architecture](https://csrc.nist.gov/Projects/devsecops) - NIST guidance on integrating security into development processes + +### Organizational Change and Maturity +- [API Governance Best Practices](https://swagger.io/resources/articles/api-governance/) - Practical guidance on implementing API governance programs +- [Building Security Champions Programs](https://owasp.org/www-project-security-champions-playbook/) - OWASP playbook for distributed security expertise +- [Measuring DevSecOps Success](https://www.sans.org/white-papers/measuring-devsecops-success/) - Metrics and KPIs for security automation programs + +### Related Security Topics +- [API TLS Encryption and HTTPS Best Practices](api-tls-encryption-https-best-practices.md) - Enforce HTTPS requirements through governance +- [API Input Validation and Injection Prevention](api-input-validation-injection-prevention.md) - Automate validation rule enforcement +- [API Rate Limiting and Abuse Prevention](api-rate-limiting-abuse-prevention.md) - Govern rate limiting policies consistently +- [Authentication and Authorization with OpenAPI](authentication-authorization-openapi.md) - Automate security requirement validation +- [API Security by Design: Complete Guide](index.md) - Overview of all API security domains + +--- + +**Next Steps:** You now have the knowledge to implement comprehensive API security governance. Start with the [API Security by Design: Complete Guide](index.md) to see how all these security domains work together in practice. diff --git a/learn/security/api-design-first-security-guide.md b/learn/security/api-design-first-security-guide.md index 3ca43044..deff8d04 100644 --- a/learn/security/api-design-first-security-guide.md +++ b/learn/security/api-design-first-security-guide.md @@ -28,9 +28,9 @@ Shifting security practices to the left in the development lifecycle, known as t The core of this strategy is treating your OpenAPI specification not merely as documentation, but as an executable security contract. This contract declaratively defines a set of security requirements, constraints, and policies before any application code is written. It becomes the single source of truth that dictates how an API must behave to be considered secure, effectively implementing a "policy-as-code" approach for APIs. -However, a contract, much like a law, is only as strong as its enforcement. This is where [Redocly CLI](https://redocly.com/docs/cli/) governance and linting capabilities provide value by transforming your contract into dynamic, automated guardrails that validate security requirements at every stage of development. When integrated into a Continuous Integration/Continuous Deployment (CI/CD) pipeline, this automated governance acts as a gatekeeper, failing builds that violate the security contract and requiring fixes before deployment. +However, a contract, much like a law, is only as strong as its enforcement. This is where automated governance and linting tools provide value by transforming your contract into dynamic, automated guardrails that validate security requirements at every stage of development. When integrated into a Continuous Integration/Continuous Deployment (CI/CD) pipeline, this automated governance acts as a gatekeeper, failing builds that violate the security contract and requiring fixes before deployment. -*OpenAPI specifications are validated by Redocly governance engine in CI/CD pipeline, failing builds for security violations and requiring fixes before deployment.* +*OpenAPI specifications are validated by automated governance engines in CI/CD pipelines, failing builds for security violations and requiring fixes before deployment.* ## Building Secure API Infrastructure: The Technical Foundation @@ -58,7 +58,7 @@ graph TD E --> I["• Security Schemes
• JWT/OAuth2
• Scope Management"] J["📄 OpenAPI 3.1
Specification"] --> A - K["⚙️ Redocly
Governance"] --> A + K["⚙️ Automated
Governance"] --> A style A fill:#e8f5e8 style B fill:#e3f2fd @@ -69,113 +69,68 @@ graph TD style K fill:#f3e5f5 ``` -*Architecture diagram showing the four essential areas of API security (TLS encryption, input validation, rate limiting, access control) supported by OpenAPI specifications and Redocly governance automation.* - -## Complete Security Governance Configuration - -Before diving into each security area, here's the comprehensive `redocly.yaml` configuration that enforces all security best practices discussed in this guide: - -```yaml {% title="redocly.yaml" %} -extends: - - recommended-strict - -rules: - # === Built-in Security Rules === - no-server-example-com: error # Prevent example.com in server URLs - no-unused-components: error # Remove unused components that could leak data - - # === TLS and Transport Security === - rule/enforce-production-tls: - subject: - type: Server - property: url - assertions: - pattern: "^https://api\\.(production|staging)\\.com" - message: "Server URLs must use https:// and point to approved domains." - severity: error - - # === Input Validation Rules === - # Rule 1: All strings must have length bounds - rule/string-must-have-maxLength: - subject: - type: Schema - where: - - subject: - property: type - assertions: - const: string - assertions: - required: - - maxLength - message: "All string properties must have 'maxLength' to prevent resource exhaustion." - severity: error - - # Rule 2: All numbers must have ranges - rule/number-must-have-range: - subject: - type: Schema - where: - - subject: - property: type - assertions: - enum: [number, integer] - assertions: - required: [minimum, maximum] - message: "Numeric properties must have 'minimum' and 'maximum' defined." - severity: error - - # Rule 3: Prevent mass assignment vulnerabilities - rule/no-additional-properties: - subject: - type: Schema - where: - - subject: - property: type - assertions: - const: object - assertions: - property: - additionalProperties: - const: false - message: "Objects must set 'additionalProperties: false' to prevent mass assignment." - severity: error - - # === Rate Limiting Rules === - rule/require-rate-limit-on-auth: - subject: - type: Operation - where: - - subject: - property: tags - assertions: - contains: "Authentication" - assertions: - defined: - - x-rateLimit - message: "Authentication operations must have 'x-rateLimit' policy defined." - severity: error - - # === Access Control Rules === - rule/require-auth-on-mutations: - subject: - type: Operation - where: - - subject: - property: method - assertions: - enum: [post, put, patch, delete] - assertions: - defined: [security] - message: "All write operations must have security defined." - severity: error -``` +*Architecture diagram showing the four essential areas of API security (TLS encryption, input validation, rate limiting, access control) supported by OpenAPI specifications and automated governance tools.* + +## Security Governance Principles + +Before diving into each security area, it's important to understand how automated governance can enforce security best practices. Modern API governance tools allow you to define custom rules that validate your OpenAPI specifications against security standards. + +### Key Security Validation Areas -This configuration provides comprehensive security governance automation. Each section below explains the principles behind these rules and shows implementation examples. +**Transport Security:** +- Enforce HTTPS-only server URLs +- Prevent example.com or placeholder domains in production specs +- Validate proper TLS configuration requirements + +**Input Validation:** +- Require `maxLength` constraints on all string properties +- Mandate `minimum` and `maximum` bounds for numeric fields +- Enforce `additionalProperties: false` to prevent mass assignment vulnerabilities + +**Rate Limiting:** +- Require rate limiting policies on authentication endpoints +- Validate that sensitive operations have documented throttling +- Ensure consistent rate limiting standards across APIs + +**Access Control:** +- Mandate security definitions on all write operations (POST, PUT, PATCH, DELETE) +- Validate that authentication schemes are properly documented +- Prevent accidentally public endpoints + +These governance principles can be implemented using various API linting and validation tools. Each section below explains the security concepts behind these requirements and shows implementation examples. ## Understanding Design-Time vs Runtime Security It's important to understand that OpenAPI-based security governance operates at **design-time**, not runtime. This governance approach excels at preventing configuration errors, missing security controls, and specification inconsistencies before they reach production. That said, it cannot prevent runtime vulnerabilities in the underlying implementation. +### API Security Implementation Timeline + +```mermaid +timeline + title API Security Implementation Timeline + + section Design Phase + OpenAPI Spec : Security schemes defined + : Input validation rules + : Rate limiting policies + + section Build Phase + Code Generation : Security middleware + : Validation logic + CI/CD Pipeline : Governance checks + : Security linting + + section Runtime Phase + Production : TLS termination + : Authentication + : Rate limiting + : Input validation + Monitoring : Attack detection + : Performance metrics +``` + +*Timeline showing how API security spans from design-time specification through build automation to runtime enforcement, with different security controls applied at each phase.* + **Design-time security governance prevents:** - Accidentally public endpoints (missing security requirements) - Insecure server configurations (HTTP instead of HTTPS) @@ -294,13 +249,13 @@ servers: description: Staging Server ``` -**Redocly Governance Enforcement:** +**Automated Governance Enforcement:** -The [Complete Security Governance Configuration](#complete-security-governance-configuration) section shows how to enforce HTTPS usage through the `rule/enforce-production-tls` custom rule, along with other security controls. +The [Security Governance Principles](#security-governance-principles) section shows how modern API governance tools can enforce HTTPS usage and other security controls through automated validation rules. -When integrated into your CI/CD pipeline, this configuration creates an automated security gate. If a developer attempts to commit an OpenAPI file with `http://api.production.com` or `https://api.dev.internal`, the pipeline fails with a clear error message, preventing insecure configurations from ever reaching production. +When integrated into your CI/CD pipeline, automated governance creates security gates. If a developer attempts to commit an OpenAPI file with insecure server URLs, the pipeline fails with a clear error message, preventing insecure configurations from ever reaching production. -*Redocly governance fails a CI/CD build if an OpenAPI spec uses HTTP instead of HTTPS, requiring developers to fix security violations before deployment.* +*Automated governance tools fail CI/CD builds when OpenAPI specifications use HTTP instead of HTTPS, requiring developers to fix security violations before deployment.* ### TLS Configuration Examples @@ -502,11 +457,11 @@ components: default: "user" ``` -**Redocly Governance for Validation:** +**Automated Governance for Validation:** -The [Complete Security Governance Configuration](#complete-security-governance-configuration) includes comprehensive input validation rules that automatically enforce string length bounds, numeric ranges, and prevent mass assignment vulnerabilities. See the Input Validation Rules section for the complete implementation. +The [Security Governance Principles](#security-governance-principles) section outlines how automated governance tools can enforce input validation rules that require string length bounds, numeric ranges, and prevent mass assignment vulnerabilities. -This governance approach changes security reviews. Instead of manually checking many properties for missing `maxLength` constraints, automated linting with [Redocly CLI](https://redocly.com/docs/cli/) handles baseline validation so security teams can focus on strategic concerns like business logic and context-dependent risks. +This governance approach transforms security reviews. Instead of manually checking many properties for missing `maxLength` constraints, automated linting tools handle baseline validation so security teams can focus on strategic concerns like business logic and context-dependent risks. ### Key Security Constraints @@ -517,7 +472,7 @@ The most critical schema constraints for API security focus on preventing resour - **`additionalProperties: false`**: Essential for preventing mass assignment attacks - **`pattern`**: Use restrictive regex patterns to block injection payloads -These constraints are automatically enforced by the governance rules in our [Complete Security Governance Configuration](#complete-security-governance-configuration), ensuring no schema can bypass these fundamental protections. +These constraints can be automatically enforced by governance rules as outlined in the [Security Governance Principles](#security-governance-principles) section, ensuring no schema can bypass these fundamental protections. ### Common Validation Patterns @@ -575,7 +530,7 @@ properties: maximum: 130 ``` -> Redocly insight: "We block PRs that add new string fields without `maxLength`. It's the cheapest guardrail against abuse." +> API Security Best Practice: "Blocking PRs that add new string fields without `maxLength` constraints is one of the most cost-effective security guardrails you can implement." ### Attack Example: Equifax (OGNL injection via Apache Struts, 2017) @@ -653,11 +608,11 @@ paths: description: "Requests remaining in current window." ``` -**Redocly Governance for Rate Limiting:** +**Automated Governance for Rate Limiting:** -The [Complete Security Governance Configuration](#complete-security-governance-configuration) includes the `rule/require-rate-limit-on-auth` rule that ensures authentication endpoints always have rate limiting policies defined. +API governance tools can enforce rules that ensure authentication endpoints always have rate limiting policies defined. -This approach provides dual benefits: [Redocly's Redoc](https://redocly.com/redoc) automatically displays the `x-rateLimit` object in generated documentation, making policies transparent to API consumers, while governance rules ensure sensitive endpoints never lack rate-limiting policies. +This approach provides dual benefits: modern API documentation tools automatically display rate limiting extensions in generated documentation, making policies transparent to API consumers, while governance rules ensure sensitive endpoints never lack rate-limiting policies. ### Why Rate Limiting Is Critical @@ -772,6 +727,37 @@ OpenAPI 3.1 provides a robust framework for defining access control through two 1. **`components.securitySchemes`**: Defines *how* clients can authenticate (JWT Bearer, OAuth2, API Keys) 2. **`security`**: Specifies *that* an endpoint is secured and by which mechanism(s) +#### Authentication vs Authorization Flow + +```mermaid +sequenceDiagram + participant U as User + participant A as API Gateway + participant Auth as Auth Service + participant API as API Endpoint + + Note over U,API: Authentication Phase + U->>A: 1. Request with credentials + A->>Auth: 2. Verify identity + Auth->>A: 3. Identity confirmed + token + A->>U: 4. Return access token + + Note over U,API: Authorization Phase + U->>A: 5. API request + token + A->>A: 6. Validate token + A->>A: 7. Check permissions/scopes + + alt Authorized + A->>API: 8. Forward request + API->>A: 9. Response + A->>U: 10. Return response + else Unauthorized + A->>U: 11. 403 Forbidden + end +``` + +*Sequence diagram showing the two-phase process: authentication verifies who the user is, while authorization determines what they can do. Both phases are essential for secure API access control.* + **JWT Bearer Token Example:** ```yaml {% title="openapi.yaml" %} components: @@ -810,11 +796,11 @@ paths: - oauth2Auth: ['users:write'] # Requires specific scope ``` -### Redocly Governance for Access Control +### Automated Governance for Access Control -Access control enforcement is handled through the custom `rule/require-auth-on-mutations` rule shown in the [Complete Security Governance Configuration](#complete-security-governance-configuration), which ensures all write operations have security requirements defined. +Access control enforcement can be handled through custom governance rules that ensure all write operations have security requirements defined. -When `redocly lint` runs, any endpoint without a corresponding `security` block causes the build to fail, preventing the most common API vulnerability: the unintentionally public endpoint. +When automated linting runs, any endpoint without a corresponding `security` block causes the build to fail, preventing the most common API vulnerability: the unintentionally public endpoint. ### Security Definitions as Configuration @@ -823,7 +809,7 @@ Defining security schemes in OpenAPI extends beyond documentation—it establish - **API Gateways** (Kong, Apigee) import OpenAPI files and automatically configure JWT validation based on `securitySchemes` - **Code generators** create boilerplate authentication handling - **Testing tools** automate authenticated requests -- **Redocly's "Try it" console** renders appropriate UI for each scheme type +- **API documentation tools** render appropriate interactive UI for each scheme type This unified approach ensures the security policy defined in design is the same policy implemented, documented, tested, and enforced in production. @@ -847,7 +833,7 @@ curl -H "Authorization: Bearer invalid" https://api.example.com/users/me curl -H "Authorization: Bearer readonly_token" -X POST https://api.example.com/users ``` -> Key insight: "Requiring security definitions on all write operations has prevented more breaches than any other single control. The `rule/require-auth-on-mutations` is non-negotiable in our CI pipeline." Learn more about implementing this with [Redocly's API Governance solution](https://redocly.com/api-governance). +> Key insight: "Requiring security definitions on all write operations has prevented more breaches than any other single control. Automated enforcement of authentication requirements on mutation operations should be non-negotiable in your CI pipeline." #### Rate limiting troubleshooting and common pitfalls @@ -935,10 +921,57 @@ class RateLimitMetrics: return (blocked / total) * 100 if total > 0 else 0 ``` +## API Security Maturity Model + +Implementing comprehensive API security is a journey. Organizations typically progress through distinct maturity levels as they build more sophisticated security practices: + +```mermaid +graph TD + A[Level 0: Basic] --> B[Level 1: Structured] --> C[Level 2: Automated] --> D[Level 3: Proactive] + + A --> A1[Manual reviews
Basic HTTPS
Simple auth] + B --> B1[OpenAPI specs
Schema validation
Rate limiting] + C --> C1[Automated governance
CI/CD integration
Policy enforcement] + D --> D1[Threat modeling
Zero-trust architecture
Continuous monitoring] + + style A fill:#ffcdd2 + style B fill:#fff59d + style C fill:#c8e6c9 + style D fill:#a5d6a7 +``` + +*API security maturity progression showing the evolution from basic manual practices to proactive, automated security governance with comprehensive threat detection and prevention.* + +**Level 0 - Basic Security:** +- Manual code reviews for obvious security issues +- HTTPS enabled but not enforced through specifications +- Basic authentication (API keys or simple passwords) +- Ad-hoc security practices without consistent standards + +**Level 1 - Structured Security:** +- OpenAPI specifications document all APIs with security requirements +- Schema-based input validation prevents basic injection attacks +- Rate limiting implemented on authentication and sensitive endpoints +- Consistent security patterns across API teams + +**Level 2 - Automated Security:** +- Automated governance tools enforce security standards in CI/CD pipelines +- Security policies defined as code and validated automatically +- Breaking changes to security configurations fail builds +- Security metrics tracked and monitored systematically + +**Level 3 - Proactive Security:** +- Comprehensive threat modeling integrated into the design process +- Zero-trust architecture with mutual TLS for service-to-service communication +- Continuous security monitoring with behavioral analysis and anomaly detection +- Security feedback loops drive iterative improvements to governance policies + +Most organizations find that advancing one level at a time provides the most sustainable improvement path. The techniques covered in this guide primarily support progression from Level 0 to Level 2, with Level 3 requiring additional infrastructure and organizational maturity. + ## Frequently Asked Questions ### What is design-first API security? -Design-first API security means defining security requirements in your OpenAPI specification before writing code, then using automated governance tools like Redocly to enforce those requirements throughout the development lifecycle. This prevents vulnerabilities from reaching production rather than patching them after discovery. +Design-first API security means defining security requirements in your OpenAPI specification before writing code, then using automated governance tools to enforce those requirements throughout the development lifecycle. This prevents vulnerabilities from reaching production rather than patching them after discovery. ### How does OpenAPI prevent injection attacks? OpenAPI specifications define precise data schemas with type validation, format constraints, and length limits. When enforced by governance tools, these schemas automatically reject malformed inputs that could contain injection payloads, stopping attacks before they reach your application logic. @@ -961,9 +994,9 @@ Authentication verifies *who* the user is (like checking an ID card), while auth ### Practical Implementation Tools - [Mozilla SSL Configuration Generator](https://ssl-config.mozilla.org/) - Generate secure, up-to-date TLS configurations for various web servers and security levels -- [Redocly CLI Documentation](https://redocly.com/docs/cli/) - Complete guide to implementing API governance, linting, and automated security validation +- [OpenAPI Generator](https://openapi-generator.tech/) - Code generation tool for creating secure client SDKs and server stubs from OpenAPI specifications - [OpenAPI Specification](https://spec.openapis.org/oas/v3.1.0) - Official OpenAPI 3.1 specification including security scheme definitions ### DevSecOps and API Governance -- [Redocly API Governance](https://redocly.com/api-governance) - Enterprise-grade API governance and security automation platform -- [API Security Best Practices](https://redocly.com/docs/cli/rules/built-in-rules) - Built-in security rules and governance patterns for API specifications +- [OWASP API Security Project](https://owasp.org/www-project-api-security/) - Community-driven API security best practices and threat modeling +- [OpenAPI Security Schemes](https://spec.openapis.org/oas/v3.1.0#security-scheme-object) - Official specification for defining authentication and authorization in OpenAPI diff --git a/learn/security/api-input-validation-injection-prevention.md b/learn/security/api-input-validation-injection-prevention.md new file mode 100644 index 00000000..a6aef93a --- /dev/null +++ b/learn/security/api-input-validation-injection-prevention.md @@ -0,0 +1,384 @@ +# Input Validation and Injection Prevention with OpenAPI + +_Stop injection attacks using OpenAPI schema validation and automated governance rules that reject malicious data before it reaches your application._ + +--- + +## Key Takeaways + +APIs are designed to accept data as input. However, an API should never blindly trust the data it receives from a client. The process of rigorously checking all incoming data is called data validation. + +**In this guide, you'll learn:** +- How to implement schema-based validation as a security contract +- JSON Schema security constraints and validation patterns +- Mass assignment attack prevention techniques +- SQL injection and OGNL injection defense strategies +- Real-world lessons from the Equifax breach +- Automated validation governance and linting rules + +--- + +## The Restaurant Waiter Principle + +> **The Restaurant Waiter**: The API is the waiter, and its documentation (or schema) is the menu. The menu explicitly states what can be ordered and in what format (e.g., "Steak - medium rare"). If a customer tries to order something not on the menu, like "a bicycle," or provides an invalid option, like "a million steaks," a competent waiter will immediately reject the order at the table before it ever reaches the kitchen. This is data validation. + +## Technical Implementation of Data Validation + +In technical terms, data validation is the practice of checking all incoming data from a client to ensure it conforms to the expected format, type, range, and other constraints before it is processed by the application's business logic. + +For example, if an API endpoint expects a user's age, validation rules should ensure the input is an integer and falls within a reasonable range (e.g., 0-130). + +Proper data validation is a critical defense against a wide range of attacks, notably **Injection flaws**. An injection attack occurs when a malicious actor sends executable code disguised as data. + +If the API fails to validate the input and passes it directly to a database or the operating system, that malicious code could be executed. By strictly validating that all inputs are what they are supposed to be, an API can reject malicious payloads before they can do any harm. + +## SQL Injection Prevention + +For interactions with a database, the gold standard for preventing SQL injection attacks is the use of parameterized queries, also known as prepared statements. + +A parameterized query forces a separation between the SQL command (the code) and the user-supplied data, making it impossible for an attacker to alter the logic of the query. + +**Vulnerable Code (Never Do This):** +```python +# DANGEROUS: Directly interpolating user input +user_id = request.get('user_id') +query = f"SELECT * FROM users WHERE id = {user_id}" +cursor.execute(query) +``` + +**Secure Code (Use Parameterized Queries):** +```python +# SAFE: Using parameterized queries +user_id = request.get('user_id') +query = "SELECT * FROM users WHERE id = ?" +cursor.execute(query, (user_id,)) +``` + +## Schema-Based Validation as Security Contract + +OpenAPI 3.1 provides a comprehensive vocabulary for defining strict validation rules by leveraging JSON Schema Draft 2020-12. By codifying these rules directly in your API specification, validation becomes core to your API's design. + +**Secure Schema Example:** +```yaml {% title="openapi.yaml" %} +components: + schemas: + NewUser: + type: object + additionalProperties: false # Prevent mass assignment (OWASP API3:2023) + required: + - username + - email + - password + - age + properties: + username: + type: string + minLength: 4 + maxLength: 20 # Prevent resource exhaustion (OWASP API4:2023) + pattern: "^[a-zA-Z0-9]+$" # Prevent injection attacks + email: + type: string + maxLength: 254 # Prevent resource exhaustion (OWASP API4:2023) + format: email + password: + type: string + minLength: 12 + maxLength: 128 + age: + type: integer + minimum: 18 + maximum: 130 # Prevent integer overflow attacks + role: + type: string + enum: ["user", "viewer"] # Enforce allow-list approach + default: "user" +``` + +### Automated Governance for Validation + +[Modern API governance tools](api-design-first-security-governance.md) can enforce input validation rules that require string length bounds, numeric ranges, and prevent mass assignment vulnerabilities. + +This governance approach transforms security reviews. Instead of manually checking many properties for missing `maxLength` constraints, automated linting tools handle baseline validation so security teams can focus on strategic concerns like business logic and context-dependent risks. + +## Key Security Constraints + +The most critical schema constraints for API security focus on preventing resource exhaustion and injection attacks: + +- **`maxLength`**: Required on all strings to prevent memory exhaustion attacks +- **`maximum/minimum`**: Required on all numbers to prevent integer overflow vulnerabilities +- **`additionalProperties: false`**: Essential for preventing mass assignment attacks +- **`pattern`**: Use restrictive regex patterns to block injection payloads + +These constraints can be automatically enforced by [governance rules](api-design-first-security-governance.md), ensuring no schema can bypass these fundamental protections. + +## Common Validation Patterns + +{% table %} +* Input Type +* Validation Rules +* Example +--- +* Email +* RFC 5322 format +* `user@example.com` +--- +* Phone +* E.164 format +* `+1234567890` +--- +* URL +* Valid URL scheme +* `https://example.com` +--- +* UUID +* Standard UUID format +* `123e4567-e89b-12d3-a456-426614174000` +--- +* Date +* ISO 8601 format +* `2025-01-20T10:30:00Z` +--- +* Password +* Minimum complexity +* 8+ chars, mixed case, numbers, symbols +{% /table %} + +### Validation troubleshooting and common pitfalls + +* Missing bounds (no `maxLength`, no numeric ranges) — leads to resource exhaustion +* Overly permissive regex patterns — allow unwanted characters and injection payloads +* Validating at the wrong layer — front-end only, or after DB calls +* Accepting undeclared properties — enables mass assignment + +Quick fixes: + +```yaml {% title="JSON Schema example" %} +type: object +additionalProperties: false +properties: + name: + type: string + minLength: 1 + maxLength: 100 + pattern: "^[a-zA-Z\\s]+$" + age: + type: integer + minimum: 0 + maximum: 130 +``` + +> API Security Best Practice: "Blocking PRs that add new string fields without `maxLength` constraints is one of the most cost-effective security guardrails you can implement." + +## Attack Example: Equifax (OGNL injection via Apache Struts, 2017) + +The 2017 Equifax data breach was the result of a catastrophic input validation failure in the Apache Struts framework (CVE-2017-5638). The vulnerability allowed attackers to perform remote code execution by sending a specially crafted `Content-Type` header. The Struts framework failed to properly sanitize this header value, interpreting it as an Object-Graph Navigation Language (OGNL) expression and executing it. This gave attackers a direct shell on the server, which they used to access sensitive databases and exfiltrate the personal data of over 140 million people. + +This incident underscores the critical importance of validating all inputs, including HTTP headers, against a strict allow-list or pattern. A strong schema-based validation approach, enforced by governance, can block entire classes of injection attacks before they ever reach vulnerable application code. + +```mermaid +sequenceDiagram + participant A as Attacker + participant W as WAF (misconfigured) + participant S as Struts App (vulnerable) + participant DB as Database + + A->>W: HTTP request with malicious Content-Type header + W-->>S: Pass-through (no block) + A->>S: OGNL payload evaluated + S->>S: Remote code execution + S->>DB: Query PII at scale + DB-->>A: Exfiltrated records (PII) +``` + +*Sequence diagram illustrating the Equifax breach: attacker exploited Apache Struts vulnerability through OGNL injection in Content-Type headers, bypassing WAF and executing code to steal personal data.* + +Why this matters: Strong schema validation, input allow-lists, and patch hygiene block entire classes of injection attacks. + +## Mass Assignment Attack Prevention + +Mass assignment attacks occur when an application accepts more input parameters than expected, allowing attackers to modify fields they shouldn't have access to. The `additionalProperties: false` constraint is essential for preventing these attacks. + +**Vulnerable API (allows additional properties):** +```yaml +# BAD: Allows any additional properties +NewUser: + type: object + # additionalProperties defaults to true - DANGEROUS! + properties: + name: + type: string + email: + type: string +``` + +**Secure API (blocks additional properties):** +```yaml +# GOOD: Explicitly blocks additional properties +NewUser: + type: object + additionalProperties: false # Critical for security + properties: + name: + type: string + email: + type: string +``` + +**Attack scenario:** +```json +// Attacker sends this payload +{ + "name": "John Doe", + "email": "john@example.com", + "role": "admin" // Mass assignment attack! +} +``` + +With `additionalProperties: false`, the API rejects the entire request. Without it, the attacker might successfully elevate their privileges. + +## Input Validation Monitoring + +### Validation Failure Logging +```javascript +// Log validation failures for analysis +app.use((req, res, next) => { + const originalSend = res.send; + + res.send = function(data) { + if (res.statusCode === 400 && req.validationErrors) { + logger.warn('Validation failure', { + endpoint: req.path, + errors: req.validationErrors, + clientIP: req.ip, + userAgent: req.get('User-Agent') + }); + } + + originalSend.call(this, data); + }; + + next(); +}); +``` + +### Validation Metrics +```python +# Track validation patterns for security analysis +class ValidationMetrics: + def __init__(self): + self.validation_failures = defaultdict(int) + self.attack_patterns = defaultdict(int) + + def record_failure(self, endpoint, field, error_type): + key = f"{endpoint}:{field}:{error_type}" + self.validation_failures[key] += 1 + + # Detect potential attack patterns + if error_type in ['pattern_violation', 'length_exceeded', 'additional_property']: + self.attack_patterns[endpoint] += 1 + + def get_attack_summary(self): + return dict(self.attack_patterns) +``` + +## Advanced Validation Techniques + +### Custom Format Validators +```javascript +// Custom OpenAPI format validators +const customFormats = { + 'safe-html': { + validate: (value) => { + // Strip dangerous HTML tags and attributes + const clean = DOMPurify.sanitize(value, { + ALLOWED_TAGS: ['p', 'br', 'strong', 'em'], + ALLOWED_ATTR: [] + }); + return clean === value; + } + }, + 'sql-safe': { + validate: (value) => { + // Block SQL injection patterns + const sqlPatterns = /('|(\\x27)|(\\x2D\\x2D)|(%27)|(%2D%2D))/i; + return !sqlPatterns.test(value); + } + } +}; + +// Use in OpenAPI schema +const schema = { + type: "string", + format: "safe-html", + maxLength: 1000 +}; +``` + +### Contextual Validation Rules +```yaml {% title="openapi.yaml" %} +# Different validation rules based on context +components: + schemas: + PublicProfile: + type: object + additionalProperties: false + properties: + displayName: + type: string + maxLength: 50 + pattern: "^[a-zA-Z0-9\\s._-]+$" # More restrictive for public display + + InternalUser: + type: object + additionalProperties: false + properties: + displayName: + type: string + maxLength: 100 + pattern: "^[\\w\\s._@-]+$" # Less restrictive for internal use +``` + +## Frequently Asked Questions + +### How does OpenAPI validation prevent injection attacks? +OpenAPI specifications define precise data schemas with type validation, format constraints, and length limits. When enforced by governance tools, these schemas automatically reject malformed inputs that could contain injection payloads, stopping attacks before they reach your application logic. + +### What's the difference between client-side and server-side validation? +Client-side validation improves user experience by providing immediate feedback, but it can be bypassed by attackers. Server-side validation is the critical security control—never trust data from the client. Always validate on the server even if you also validate on the client. + +### Should I validate HTTP headers and query parameters? +Yes! The Equifax breach occurred through a malicious `Content-Type` header. All inputs—including headers, query parameters, path parameters, and request bodies—should be validated against strict schemas. Don't assume any input is safe. + +### How do I handle file uploads securely? +File uploads require special attention: validate file types using content inspection (not just extensions), enforce size limits, scan for malware, store files outside the web root, and use content-disposition headers to prevent execution. Consider using dedicated file storage services. + +### What's the performance impact of extensive validation? +Modern validation libraries are highly optimized. The security benefit far outweighs the minimal performance cost. Consider caching compiled schemas and using efficient validation libraries like `ajv` for JavaScript or `jsonschema` for Python. + +## Resources and Next Steps + +### Essential Reading +- [OWASP API Security Top 10](https://owasp.org/www-project-api-security/) - Comprehensive vulnerability guide including injection attacks (API3:2023) and resource consumption (API4:2023) +- [JSON Schema Specification](https://json-schema.org/specification.html) - Complete reference for OpenAPI validation capabilities +- [OpenAPI Data Types](https://spec.openapis.org/oas/v3.1.0#data-types) - Official OpenAPI data type and format specifications + +### Implementation Tools +- [AJV JSON Schema Validator](https://ajv.js.org/) - Fast JSON Schema validation for JavaScript/Node.js +- [Joi Validation](https://joi.dev/) - Object schema validation library with expressive API +- [Cerberus](https://docs.python-cerberus.org/) - Lightweight, extensible data validation library for Python + +### Security Testing Tools +- [OWASP ZAP](https://owasp.org/www-project-zap/) - Security testing proxy for finding injection vulnerabilities +- [Postman Security Testing](https://learning.postman.com/docs/writing-scripts/test-scripts/) - API security test automation +- [Burp Suite](https://portswigger.net/burp) - Web application security testing platform + +### Related Security Topics +- [API TLS Encryption and HTTPS Best Practices](api-tls-encryption-https-best-practices.md) - Secure data in transit +- [API Rate Limiting and Abuse Prevention](api-rate-limiting-abuse-prevention.md) - Prevent DoS attacks and abuse +- [Authentication and Authorization with OpenAPI](authentication-authorization-openapi.md) - Implement secure access control +- [API Design-First Security Governance and Automation](api-design-first-security-governance.md) - Automate security validation +- [API Security by Design: Complete Guide](index.md) - Overview of all API security domains + +--- + +**Next Steps:** Now that you have input validation covered, learn about [API Rate Limiting and Abuse Prevention](api-rate-limiting-abuse-prevention.md) to protect your APIs from denial-of-service attacks and business logic abuse. diff --git a/learn/security/api-rate-limiting-abuse-prevention.md b/learn/security/api-rate-limiting-abuse-prevention.md new file mode 100644 index 00000000..41883990 --- /dev/null +++ b/learn/security/api-rate-limiting-abuse-prevention.md @@ -0,0 +1,448 @@ +# Rate Limiting and Abuse Prevention for APIs + +_Prevent DoS attacks, brute force attempts, and business logic abuse through strategic rate limiting policies documented in OpenAPI specifications._ + +--- + +## Key Takeaways + +A single client, whether intentionally malicious or simply due to a bug in its code, can send a massive number of requests to an API in a short period. This can overwhelm the server, degrading performance for all other users or even causing the service to crash. Rate limiting is the primary defense against this scenario. + +**In this guide, you'll learn:** +- How to implement rate limiting as a security and reliability control +- OpenAPI x-rateLimit extensions and documentation strategies +- Rate limiting algorithms and multi-tier implementation patterns +- Client-side exponential backoff and error handling +- Real-world lessons from the Facebook phone number scraping incident +- Advanced rate limiting techniques and monitoring approaches + +--- + +## The Library Card Principle + +> **The Library Card**: A library card allows a patron to check out a maximum of ten books per month. Once that limit is reached, the system will not allow any more checkouts until the next month begins, regardless of how many times the patron asks. + +**Rate limiting** applies this same principle to an API. It establishes a policy that restricts the number of requests a single client can make within a specific time window (e.g., 100 requests per minute). + +## Why Rate Limiting Is Critical for API Security + +Rate limiting is a critical control for both security and reliability, directly mitigating several OWASP API Security Top 10 risks: + +1. **Security:** It thwarts Denial-of-Service (DoS) attacks by preventing traffic floods, addressing OWASP API4:2023 - Unrestricted Resource Consumption. It also makes brute-force attacks against [authentication endpoints](authentication-authorization-openapi.md) much slower and less effective, reducing the risk of credential stuffing attacks. + +2. **Business Logic Abuse:** It helps mitigate abuse by preventing bots from scraping data or manipulating business flows, addressing OWASP API6:2023 - Unrestricted Access to Sensitive Business Flows. + +3. **Reliability and Fair Usage:** It ensures that the API remains stable and responsive for all users by preventing any single client from monopolizing server resources. + +## Documenting Rate Limits in OpenAPI + +While OpenAPI 3.1 doesn't include native rate-limiting objects, extension properties (prefixed with `x-`) provide a standard mechanism. The best practice is defining custom `x-rateLimit` extensions at the operation level. + +**Note:** Rate limits are typically dynamic in production environments, with different limits for different clients based on service tiers, contracts, or usage patterns. The OpenAPI specification documents the baseline policy, while implementation systems apply client-specific variations. + +```yaml {% title="openapi.yaml" %} +paths: + /auth/login: + post: + summary: User Login + tags: [Authentication] + # Define rate-limiting policy for this sensitive endpoint + x-rateLimit: + limit: 5 + window: "1m" + scope: "ip_address" + description: "Limits login attempts to 5 per minute per IP to prevent brute-force attacks." + responses: + '200': + description: "Successful login." + # Document the 429 response with proper headers + '429': + description: "Too Many Requests. Rate limit exceeded." + headers: + Retry-After: + schema: + type: integer + description: "Seconds to wait before making a new request." + X-RateLimit-Limit: + schema: + type: integer + description: "Maximum requests permitted in the window." + X-RateLimit-Remaining: + schema: + type: integer + description: "Requests remaining in current window." +``` + +### Automated Governance for Rate Limiting + +[API governance tools](api-design-first-security-governance.md) can enforce rules that ensure [authentication endpoints](authentication-authorization-openapi.md) always have rate limiting policies defined. + +This approach provides dual benefits: modern API documentation tools automatically display rate limiting extensions in generated documentation, making policies transparent to API consumers, while governance rules ensure sensitive endpoints never lack rate-limiting policies. + +## Rate Limiting Implementation Approaches + +### Common Algorithm Types + +**Token Bucket**: Allows burst traffic within limits, refills at steady rate +- Best for: APIs that need to handle legitimate traffic spikes +- Pros: Flexible, allows bursts, smooth long-term rate limiting +- Cons: More complex to implement, requires state management + +**Sliding Window**: Precise per-window enforcement with distributed request tracking +- Best for: APIs requiring exact rate limiting precision +- Pros: Most accurate, prevents boundary condition abuse +- Cons: Memory intensive, complex distributed implementation + +**Fixed Window**: Simple per-timeframe limits, prone to boundary conditions +- Best for: Simple use cases, easy implementation +- Pros: Simple to implement and understand +- Cons: Allows traffic spikes at window boundaries + +### Multi-tier Strategy Example + +```yaml {% title="API Gateway configuration" %} +rate_limits: + global: + requests_per_minute: 1000 + requests_per_hour: 10000 + by_endpoint: + "/auth/*": + requests_per_minute: 5 + requests_per_hour: 20 + "/api/data": + requests_per_minute: 100 + requests_per_hour: 2000 + "/api/search": + requests_per_minute: 50 + requests_per_hour: 1000 +``` + +## Advanced Rate Limiting Techniques + +### Multi-tier Rate Limiting Configuration + +```yaml {% title="Kong configuration" %} +plugins: +- name: rate-limiting + config: + minute: 100 # 100 requests per minute per IP + hour: 1000 # 1000 requests per hour per IP + policy: redis # Use Redis for distributed rate limiting + fault_tolerant: true + hide_client_headers: false + +# Per-endpoint overrides +- name: rate-limiting + route: auth-endpoints + config: + minute: 5 # Stricter limits for auth endpoints + hour: 20 + policy: redis +``` + +### Client-side Exponential Backoff + +```javascript +class APIClient { + async makeRequest(url, options, retries = 3) { + try { + const response = await fetch(url, options); + + if (response.status === 429) { + const retryAfter = response.headers.get('Retry-After'); + const delay = retryAfter ? parseInt(retryAfter) * 1000 : + Math.pow(2, 4 - retries) * 1000; // Exponential backoff + + if (retries > 0) { + await new Promise(resolve => setTimeout(resolve, delay)); + return this.makeRequest(url, options, retries - 1); + } + + throw new Error('Rate limit exceeded'); + } + + return response; + } catch (error) { + throw error; + } + } +} +``` + +As a complementary practice, the client-side responsibility of implementing exponential backoff should also be noted. When an API client receives a rate-limiting error (e.g., HTTP 429 Too Many Requests), it should wait for an exponentially increasing period of time between retries. This prevents clients from overwhelming the server and helps the system recover gracefully from load spikes. + +> **Tip:** Combine per-IP and per-account quotas and require exponential backoff on clients. + +## Attack Example: Facebook Phone Number Scraping (2019) + +In 2019, malicious actors exploited a vulnerability in Facebook's contact importer feature to scrape the personal data of over 530 million users. The API endpoint itself was not technically "broken"—it performed its intended function of matching phone numbers to user profiles. The vulnerability was the absence of adequate rate limiting and business rule enforcement. + +Attackers used automated scripts to submit massive lists of phone numbers, and the API dutifully returned the corresponding user profiles, allowing them to build a massive database of personal information. + +This incident highlights a different type of API attack, moving from exploiting technical flaws to abusing business logic at scale. It elevates rate limiting from an infrastructure protection mechanism to also being a tool for enforcing business rules. The `x-rateLimit` extension in OpenAPI is a form of declarative security policy. + +```mermaid +sequenceDiagram + participant B as Botnet/Script + participant API as Contact Import API + + loop Enumerate phone numbers + B->>API: Batch upload numbers + API-->>B: Matched user IDs/profile data + end + Note over B,API: Missing per-account/IP limits and anomaly detection +``` + +*Sequence diagram showing how attackers used Facebook's contact import API to scrape phone numbers at scale, exploiting missing rate limits and velocity checks to harvest personal data.* + +Why this matters: Rate limiting, velocity checks, and behavior analytics are core defenses against scraping and credential-stuffing at scale. + +## Rate Limiting Monitoring and Observability + +### Rate Limiting Metrics Collection + +```python +# Track rate limiting metrics for security analysis +import time +from collections import defaultdict + +class RateLimitMetrics: + def __init__(self): + self.blocked_requests = defaultdict(int) + self.total_requests = defaultdict(int) + self.suspicious_patterns = defaultdict(list) + + def record_request(self, client_id, blocked=False, endpoint=None): + self.total_requests[client_id] += 1 + if blocked: + self.blocked_requests[client_id] += 1 + # Track suspicious patterns + self.suspicious_patterns[client_id].append({ + 'timestamp': time.time(), + 'endpoint': endpoint, + 'blocked': True + }) + + def get_block_rate(self, client_id): + total = self.total_requests[client_id] + blocked = self.blocked_requests[client_id] + return (blocked / total) * 100 if total > 0 else 0 + + def get_attack_indicators(self, client_id, window_minutes=5): + """Detect rapid repeated attempts that might indicate an attack""" + recent_blocks = [ + event for event in self.suspicious_patterns[client_id] + if time.time() - event['timestamp'] < window_minutes * 60 + ] + return len(recent_blocks) +``` + +### Alerting Configuration + +```yaml {% title="prometheus-alerts.yml" %} +groups: +- name: rate_limiting_alerts + rules: + - alert: HighRateLimitBlocks + expr: rate(rate_limit_blocked_total[5m]) > 10 + for: 2m + labels: + severity: warning + annotations: + summary: "High rate of blocked requests detected" + description: "{{ $value }} requests per second being blocked" + + - alert: SuspiciousRateLimitPattern + expr: rate_limit_block_rate > 80 + for: 1m + labels: + severity: critical + annotations: + summary: "Possible DDoS or brute force attack" + description: "Client {{ $labels.client_id }} has {{ $value }}% blocked rate" +``` + +### Rate Limiting Troubleshooting + +**Common Issues and Solutions:** + +* **Counting the wrong thing** — per-IP only; add per-account and per-token limits +* **Same limits for every endpoint** — tighten auth and write endpoints separately +* **No Retry-After header** — clients can't back off predictably +* **Stateless limits in distributed systems** — use Redis or gateway-native stores +* **Legitimate bursts blocked** — implement token bucket algorithm for flexibility + +**Quick Diagnostic Commands:** + +```bash +# Observe 429 behavior and headers +curl -i https://api.example.com/login | grep -E 'HTTP/|Retry-After|X-RateLimit' + +# Simulate burst to verify rate limiting +hey -z 10s -q 50 -c 50 https://api.example.com/api/resource + +# Test different client patterns +for i in {1..10}; do + curl -H "Authorization: Bearer $TOKEN" https://api.example.com/api/data + sleep 1 +done +``` + +### Advanced Rate Limiting Patterns + +**Adaptive Rate Limiting:** +```javascript +// Adjust limits based on server health +class AdaptiveRateLimit { + constructor() { + this.baseLimit = 100; + this.currentLimit = 100; + this.healthThreshold = 0.8; + } + + adjustLimit(serverLoad, errorRate) { + if (serverLoad > this.healthThreshold || errorRate > 0.1) { + this.currentLimit = Math.max(10, this.currentLimit * 0.8); + } else if (serverLoad < 0.5 && errorRate < 0.01) { + this.currentLimit = Math.min(this.baseLimit, this.currentLimit * 1.1); + } + } +} +``` + +**Geographic Rate Limiting:** +```yaml {% title="nginx-rate-limit.conf" %} +# Different limits based on geographic regions +geo $rate_limit_zone { + default $binary_remote_addr; + # More restrictive limits for high-risk regions + ~^192\.168\. $binary_remote_addr_strict; + ~^10\. $binary_remote_addr_internal; +} + +limit_req_zone $rate_limit_zone zone=general:10m rate=100r/m; +limit_req_zone $binary_remote_addr_strict zone=restricted:10m rate=20r/m; +limit_req_zone $binary_remote_addr_internal zone=internal:10m rate=1000r/m; +``` + +> Rate Limiting Best Practice: "Rate limiting on auth endpoints is non-negotiable. We set 5/min per IP and per account, and alert when bypass attempts appear." + +## Frequently Asked Questions + +### Why is rate limiting important for API security? +Rate limiting prevents denial-of-service attacks, brute-force authentication attempts, and data scraping. It ensures fair resource usage among legitimate users while blocking malicious automation. Without rate limits, a single bad actor can overwhelm your API infrastructure. + +### What's the difference between rate limiting and throttling? +Rate limiting sets hard limits on request volume (e.g., 100 requests per minute), rejecting excess requests with 429 status codes. Throttling typically involves slowing down or queuing requests rather than rejecting them outright. Rate limiting is more common for APIs as it provides clearer client feedback. + +### Should rate limits be per-IP, per-user, or both? +Implement multiple layers: per-IP limits prevent DDoS attacks from single sources, per-user limits enforce fair usage policies, and per-API-key limits support tiered service levels. Combine all three for comprehensive protection against different attack patterns. + +### How do I handle legitimate traffic spikes? +Use token bucket algorithms that allow controlled bursts within overall rate limits. Consider implementing adaptive rate limiting that adjusts limits based on server health. For predictable spikes, provide rate limit increase APIs or temporary exemption mechanisms for verified clients. + +### What rate limiting algorithm should I choose? +- **Token Bucket**: Best for APIs needing burst flexibility +- **Sliding Window**: Most accurate but memory intensive +- **Fixed Window**: Simple but allows boundary condition abuse +- **Sliding Window Log**: Precise but computationally expensive + +Choose based on your accuracy requirements, traffic patterns, and implementation complexity tolerance. + +### How do I communicate rate limits to API consumers? +Document limits in OpenAPI specifications using `x-rateLimit` extensions, include rate limit headers in responses (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `Retry-After`), provide clear error messages with 429 responses, and maintain public documentation about your rate limiting policies. + +## Rate Limiting Strategy Framework + +### Implementation Priority + +1. **Critical Endpoints First** + - Authentication endpoints: 5-10 requests per minute per IP + - Password reset: 3 requests per hour per email + - Account creation: 5 requests per hour per IP + - Payment processing: Strict limits based on business rules + +2. **Resource-Intensive Operations** + - Search endpoints: Higher limits but monitor query complexity + - File uploads: Size-based and frequency-based limits + - Data export: Very restrictive limits with queuing + +3. **General API Access** + - Read operations: Generous limits for good user experience + - Write operations: More restrictive than reads + - Administrative endpoints: Very restrictive with strong authentication + +### Rate Limit Testing Strategy + +```python +# Rate limit testing framework +import asyncio +import aiohttp +import time + +async def test_rate_limit(url, requests_count, window_seconds): + """Test rate limiting behavior""" + start_time = time.time() + successful_requests = 0 + blocked_requests = 0 + + async with aiohttp.ClientSession() as session: + tasks = [] + for i in range(requests_count): + tasks.append(make_request(session, url)) + + responses = await asyncio.gather(*tasks, return_exceptions=True) + + for response in responses: + if isinstance(response, Exception): + continue + if response.status == 200: + successful_requests += 1 + elif response.status == 429: + blocked_requests += 1 + + elapsed = time.time() - start_time + print(f"Rate limit test results:") + print(f"Successful: {successful_requests}, Blocked: {blocked_requests}") + print(f"Effective rate: {successful_requests/elapsed:.2f} req/sec") + +async def make_request(session, url): + try: + async with session.get(url) as response: + return response + except Exception as e: + return e +``` + +## Resources and Next Steps + +### Essential Reading +- [OWASP API Security Top 10](https://owasp.org/www-project-api-security/) - Comprehensive guide including unrestricted resource consumption (API4:2023) and business logic abuse (API6:2023) +- [RFC 6585](https://tools.ietf.org/html/rfc6585) - HTTP status code 429 (Too Many Requests) specification +- [Rate Limiting Algorithms](https://en.wikipedia.org/wiki/Rate_limiting) - Technical overview of different rate limiting approaches + +### Implementation Tools +- [Redis](https://redis.io/) - In-memory data store commonly used for distributed rate limiting +- [Kong Rate Limiting Plugin](https://docs.konghq.com/hub/kong-inc/rate-limiting/) - Enterprise-grade API gateway rate limiting +- [nginx limit_req_zone](https://nginx.org/en/docs/http/ngx_http_limit_req_module.html) - High-performance rate limiting at the reverse proxy level + +### Monitoring and Analytics +- [Prometheus](https://prometheus.io/) - Metrics collection and alerting for rate limiting monitoring +- [Grafana](https://grafana.com/) - Visualization dashboards for rate limiting metrics +- [Elastic Stack](https://www.elastic.co/elastic-stack/) - Log analysis and pattern detection for abuse identification + +### Load Testing Tools +- [hey](https://github.com/rakyll/hey) - Simple load testing tool for rate limit verification +- [Apache Bench (ab)](https://httpd.apache.org/docs/2.4/programs/ab.html) - Basic HTTP server benchmarking +- [JMeter](https://jmeter.apache.org/) - Comprehensive performance testing with rate limiting scenarios + +### Related Security Topics +- [API Input Validation and Injection Prevention](api-input-validation-injection-prevention.md) - Protect APIs from malicious data +- [Authentication and Authorization with OpenAPI](authentication-authorization-openapi.md) - Implement secure access control +- [API TLS Encryption and HTTPS Best Practices](api-tls-encryption-https-best-practices.md) - Secure data in transit +- [API Design-First Security Governance and Automation](api-design-first-security-governance.md) - Automate security validation +- [API Security by Design: Complete Guide](index.md) - Overview of all API security domains + +--- + +**Next Steps:** Now that you have rate limiting protection in place, learn about [Authentication and Authorization with OpenAPI](authentication-authorization-openapi.md) to implement comprehensive access control for your APIs. diff --git a/learn/security/api-tls-encryption-https-best-practices.md b/learn/security/api-tls-encryption-https-best-practices.md new file mode 100644 index 00000000..71faccaf --- /dev/null +++ b/learn/security/api-tls-encryption-https-best-practices.md @@ -0,0 +1,327 @@ +# TLS Encryption and HTTPS Best Practices for APIs + +_Protect data in transit with proper TLS configuration, certificate management, and HTTPS enforcement using OpenAPI security contracts._ + +--- + +## Key Takeaways + +When a client and an API exchange information, that data travels across the internet, a public network. Without protection, this data gets intercepted and read by malicious actors. This is where encryption comes in. + +**In this guide, you'll learn:** +- How TLS 1.3 provides secure communication for APIs +- OpenAPI server URL security contracts and enforcement +- Certificate management and cipher suite selection +- Mutual TLS (mTLS) for service-to-service communication +- Real-world lessons from the Heartbleed vulnerability +- Automated governance for transport security + +--- + +## The Banking Vault Principle + +> **The Banking Vault Principle**: When banks transfer large sums between branches, they don't send cash in regular envelopes. They use armored vehicles with multiple security layers. TLS encryption works similarly — it creates a secure transport layer that protects your API data during transit, even across untrusted networks. + +**Encryption in transit** works similarly, creating a secure, private tunnel for API data as it moves between the client and the server. + +## TLS 1.3: The Modern Standard + +This secure tunnel is primarily established using **Transport Layer Security (TLS) version 1.3**, as specified in [IETF RFC 8446](https://tools.ietf.org/html/rfc8446). [NIST SP 800-52 Rev. 2](https://csrc.nist.gov/publications/detail/sp/800-52/rev-2/final) guidelines for TLS implementations unequivocally mandate TLS 1.3 for modern systems, as older protocols—including all versions of SSL, TLS 1.0, and TLS 1.1—are deprecated and considered insecure due to known vulnerabilities. + +When a client connects to an API over `https://`, it initiates a "TLS handshake." During this handshake, the client and server perform crucial steps: + +1. **Authentication:** The server presents its TLS certificate to the client to prove its identity, ensuring the client is talking to the legitimate server and not an impostor. +2. **Agreement on Encryption:** They agree on a set of cryptographic algorithms (a "cipher suite") to use for the session. +3. **Key Exchange:** They securely generate and exchange unique session keys that will be used to encrypt and decrypt all data for the remainder of the conversation. + +### TLS Handshake Process + +```mermaid +sequenceDiagram + participant C as Client + participant S as Server + + Note over C,S: TLS Handshake Process + + C->>S: 1. Client Hello (Supported cipher suites) + + S->>C: 2. Server Hello + Certificate + Note right of S: Server presents TLS certificate to prove identity + + C->>C: 3. Certificate Validation + Note left of C: Client verifies server certificate is trusted + + C->>S: 4. Cipher Suite Selection + Note over C,S: Both agree on cryptographic algorithms + + C->>S: 5. Key Exchange + S->>C: 6. Key Exchange Complete + Note over C,S: Generate and exchange unique session keys + + Note over C,S: 🔒 Secure Communication Begins + + C->>S: Encrypted API Request + S->>C: Encrypted API Response + +``` + +*Sequence diagram illustrating the TLS handshake process between client and server, showing certificate validation, cipher suite selection, and secure key exchange that ensures encrypted API communication.* + +## TLS Security Guarantees + +TLS, when done right, provides three essential security guarantees: + +* **Confidentiality:** It encrypts the data, preventing eavesdroppers from reading it. +* **Integrity:** It ensures that the data has not been altered or tampered with during transit. +* **Authentication:** It verifies the identity of the server, protecting against man-in-the-middle attacks. + +This is why secure APIs always use URLs that start with `https://` instead of `http://`. The 's' stands for 'secure' and indicates that the connection is protected by TLS encryption. + +## TLS Implementation Best Practices + +In production environments, telling teams to "use HTTPS" without specifics sometimes leads to misconfigured TLS and a false sense of security. Proper TLS implementation requires: + +* **Enforcing Strong Cipher Suites**: Configure servers to only negotiate cryptographic algorithms that are considered secure, disabling weak or obsolete ciphers +* **Proper Certificate Management**: Use certificates from trusted Certificate Authorities (CAs), ensure they are not expired, and implement robust processes for certificate issuance, renewal, and revocation +* **Protection Against Man-in-the-Middle (MiTM) Attacks**: Implement HTTP Strict Transport Security (HSTS) to instruct browsers to only communicate over HTTPS, preventing protocol downgrade attacks + +### Common TLS misconfigurations + +* Weak or legacy protocols enabled (SSL, TLS 1.0/1.1) — disable them explicitly +* Missing HSTS header — add Strict-Transport-Security with long max-age +* Mixed content or accidental HTTP endpoints — redirect to HTTPS at the edge +* Expiring certificates — monitor expiry and automate renewal + +Quick checks: + +```bash +# Verify protocol and cipher suites +openssl s_client -connect api.example.com:443 -tls1_3 -cipher 'TLS_AES_256_GCM_SHA384' < /dev/null | grep -E 'Protocol|Cipher' + +# Scan for common TLS issues +testssl.sh --fast https://api.example.com +``` + +> Expert insight: "Treat TLS as a product with owners and SLAs. We track TLS health on dashboards the same way we track latency and errors." + +## Enforcing HTTPS in Your API Specification + +The security contract for encrypted transit begins within the `servers` object of your OpenAPI specification. Every URL defined here must use the `https://` scheme—this isn't just documentation, it's a formal declaration of your API's secure endpoints. + +**OpenAPI Servers Declaration:** +```yaml {% title="openapi.yaml" %} +servers: + - url: https://api.production.com/v1 + description: Production Server + - url: https://api.staging.com/v1 + description: Staging Server +``` + +### Automated Governance Enforcement + +Modern API governance tools can enforce HTTPS usage through automated validation rules. When integrated into your CI/CD pipeline, automated governance creates security gates. If a developer attempts to commit an OpenAPI file with insecure server URLs, the pipeline fails with a clear error message, preventing insecure configurations from ever reaching production. + +> Learn more about implementing comprehensive governance policies in our [API Design-First Security Governance and Automation](api-design-first-security-governance.md) guide. + +*Automated governance tools fail CI/CD builds when OpenAPI specifications use HTTP instead of HTTPS, requiring developers to fix security violations before deployment.* + +## TLS Configuration Examples + +Authoritative sources like the [Mozilla SSL Configuration Generator](https://ssl-config.mozilla.org/) provide excellent, up-to-date templates for secure server configurations across different platforms and security requirements. + +**Nginx Configuration:** +```nginx +server { + listen 443 ssl http2; + server_name api.example.com; + + # TLS 1.3 only + ssl_protocols TLSv1.3; + + # Strong cipher suites + ssl_ciphers TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256; + + # HSTS header + add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; + + # Certificate files + ssl_certificate /path/to/certificate.crt; + ssl_certificate_key /path/to/private.key; +} +``` + +**Express.js Configuration:** +```javascript +const https = require('https'); +const fs = require('fs'); +const express = require('express'); + +const app = express(); + +// HSTS middleware +app.use((req, res, next) => { + res.setHeader('Strict-Transport-Security', 'max-age=31536000; includeSubDomains'); + next(); +}); + +const options = { + key: fs.readFileSync('private.key'), + cert: fs.readFileSync('certificate.crt'), + // Force TLS 1.3 + secureProtocol: 'TLSv1_3_method' +}; + +https.createServer(options, app).listen(443); +``` + +## Attack Example: Heartbleed (TLS library vulnerability, 2014) + +The Heartbleed bug (CVE-2014-0160) was a critical vulnerability in the OpenSSL library, not the TLS protocol itself. It allowed attackers to read up to 64KB of a server's memory by sending a malformed TLS heartbeat request. The server would respond with not only the small payload sent by the attacker but also adjacent memory contents, which could include session cookies, user credentials, and even the server's private encryption keys. + +This incident demonstrates a crucial point: security is multi-layered. While an OpenAPI specification can enforce the *intent* of using secure transport (https://), it cannot prevent a runtime vulnerability in the underlying software stack. True "secure by design" requires both [design-time governance](api-design-first-security-governance.md) via OpenAPI linting and runtime security posture management, including diligent vulnerability scanning and patch management. + +```mermaid +sequenceDiagram + participant A as Attacker + participant S as Vulnerable Server (OpenSSL) + + A->>S: TLS handshake + A->>S: Malformed Heartbeat Request (len >> data) + S-->>A: Memory contents leak (keys, session cookies) + A->>S: Follow-on requests using stolen secrets +``` + +*Sequence diagram showing the Heartbleed attack: malformed TLS heartbeat requests cause vulnerable OpenSSL servers to leak memory contents including encryption keys and session data.* + +Why this matters: TLS is only as strong as its implementation. Monitoring and rapid patching for library CVEs are part of infrastructure security. + +## Mutual TLS (mTLS): Two-Way Authentication + +While standard TLS only authenticates the server to the client, **Mutual TLS (mTLS)** requires both parties to authenticate each other using certificates. This provides stronger security for high-trust scenarios and is essential for implementing zero-trust architecture principles. + +**mTLS Use Cases:** +- Microservice communication in zero-trust architectures where no network segment is inherently trusted +- API-to-API authentication between organizations implementing defense-in-depth strategies +- IoT device authentication in distributed systems +- High-security financial and healthcare APIs requiring cryptographic identity verification + +**OpenAPI mTLS Configuration:** +```yaml {% title="openapi.yaml" %} +components: + securitySchemes: + mtlsAuth: + type: mutualTLS + description: "Client certificate authentication" + +# Apply to sensitive operations +paths: + /internal/payments: + post: + security: + - mtlsAuth: [] + summary: "Process payment (internal service only)" +``` + +**Implementation Example (Nginx):** +```nginx +server { + listen 443 ssl http2; + + # Server certificate + ssl_certificate /path/to/server.crt; + ssl_certificate_key /path/to/server.key; + + # Require client certificates + ssl_verify_client on; + ssl_client_certificate /path/to/ca.crt; + + # Pass client certificate info to backend + proxy_set_header X-Client-Cert $ssl_client_cert; + proxy_set_header X-Client-Verify $ssl_client_verify; +} +``` + +> **mTLS Best Practice**: Use mTLS for service-to-service communication and regular TLS + [JWT/OAuth2](authentication-authorization-openapi.md) for client-to-server communication. + +## TLS Monitoring and Troubleshooting + +### Certificate Monitoring +```yaml {% title="prometheus.yml" %} +groups: +- name: tls_alerts + rules: + - alert: TLSCertificateExpiringSoon + expr: probe_ssl_earliest_cert_expiry - time() < 86400 * 30 + labels: + severity: warning + annotations: + summary: "TLS certificate expires in less than 30 days" + + - alert: WeakTLSVersion + expr: probe_tls_version_info{version!="TLS 1.3"} == 1 + labels: + severity: critical + annotations: + summary: "Weak TLS version detected" +``` + +### Common TLS Troubleshooting Steps + +**Certificate Issues:** +- Expired certificates — monitor expiry dates and automate renewal +- Certificate chain problems — verify intermediate certificates are included +- Certificate-hostname mismatch — ensure certificate covers all domains used + +**Configuration Issues:** +- Weak cipher suites — disable deprecated algorithms and enable only strong ciphers +- Missing HSTS headers — add Strict-Transport-Security to prevent downgrade attacks +- Mixed content warnings — ensure all resources load over HTTPS + +**Quick Verification Commands:** +```bash +# Test TLS connection and certificate +curl -vI https://api.example.com 2>&1 | grep -E 'SSL|TLS|certificate' + +# Verify certificate chain +openssl s_client -showcerts -connect api.example.com:443 < /dev/null + +# Check certificate expiry +echo | openssl s_client -servername api.example.com -connect api.example.com:443 2>/dev/null | \ +openssl x509 -noout -dates +``` + +## Frequently Asked Questions + +### Why can't I use HTTP for internal APIs? +Even internal networks can be compromised. Using HTTPS everywhere (zero-trust approach) protects against insider threats, lateral movement attacks, and accidental data exposure. The performance overhead of TLS is minimal with modern hardware and HTTP/2. + +### How often should I rotate TLS certificates? +Most organizations use certificates with 1-year validity and rotate them every 6-12 months. Automated certificate management tools like Let's Encrypt or cloud provider certificate services can handle this automatically. + +### What's the difference between TLS and SSL? +SSL (Secure Sockets Layer) is the predecessor to TLS. SSL versions are deprecated and insecure. When people say "SSL certificate" or "SSL/TLS," they're usually referring to modern TLS. Always use TLS 1.2 or preferably TLS 1.3. + +### Should I implement certificate pinning for API clients? +Certificate pinning can improve security by preventing man-in-the-middle attacks, but it adds operational complexity. Consider it for high-security applications, but ensure you have a robust certificate rotation and backup pin management process. + +## Resources and Next Steps + +### Essential Reading +- [IETF RFC 8446](https://tools.ietf.org/html/rfc8446) - TLS 1.3 protocol specification and security requirements +- [NIST SP 800-52 Rev. 2](https://csrc.nist.gov/publications/detail/sp/800-52/rev-2/final) - Official guidelines for secure TLS implementation +- [Mozilla SSL Configuration Generator](https://ssl-config.mozilla.org/) - Generate secure TLS configurations for various platforms + +### Implementation Tools +- [Let's Encrypt](https://letsencrypt.org/) - Free, automated certificate authority for TLS certificates +- [testssl.sh](https://testssl.sh/) - Command-line tool for testing TLS/SSL implementations +- [SSL Labs Server Test](https://www.ssllabs.com/ssltest/) - Online tool for testing TLS configuration + +### Related Security Topics +- [API Input Validation and Injection Prevention](api-input-validation-injection-prevention.md) - Protect APIs from malicious data +- [Authentication and Authorization with OpenAPI](authentication-authorization-openapi.md) - Implement secure access control +- [API Rate Limiting and Abuse Prevention](api-rate-limiting-abuse-prevention.md) - Prevent DoS attacks and brute force attempts +- [API Security by Design: Complete Guide](index.md) - Overview of all API security domains + +--- + +**Next Steps:** Now that you have secure transport with TLS, learn about [API Input Validation and Injection Prevention](api-input-validation-injection-prevention.md) to protect your APIs from malicious data inputs. diff --git a/learn/security/authentication-authorization-openapi.md b/learn/security/authentication-authorization-openapi.md new file mode 100644 index 00000000..21c9eb9f --- /dev/null +++ b/learn/security/authentication-authorization-openapi.md @@ -0,0 +1,794 @@ +# Authentication and Authorization with OpenAPI + +_Implement secure access control using OpenAPI security schemes and modern authentication patterns._ + +--- + +## Key Takeaways + +Authentication and authorization form the foundation of API access control. While often used interchangeably, these concepts serve distinct purposes: authentication verifies *who* the user is, while authorization determines *what* they can do. Modern APIs require both layers to prevent unauthorized access and enforce business rules. + +In this guide, we'll explore how to use OpenAPI 3.1 security schemes to define robust access control patterns that integrate seamlessly with [automated governance](api-design-first-security-governance.md) and modern authentication providers. + +**We'll cover how to:** +- Define JWT Bearer token authentication in OpenAPI specifications +- Implement OAuth2 with granular scope-based authorization +- Enforce security requirements through [automated governance](api-design-first-security-governance.md) +- Configure API gateways from OpenAPI security definitions +- Monitor and troubleshoot authentication and authorization failures + +--- + +## Understanding Authentication vs Authorization + +The distinction between authentication and authorization is fundamental to API security design. Understanding this difference helps you implement the right controls at the right layers. + +### The Two-Phase Security Process + +```mermaid +sequenceDiagram + participant U as User + participant A as API Gateway + participant Auth as Auth Service + participant API as API Endpoint + + Note over U,API: Authentication Phase + U->>A: 1. Request with credentials + A->>Auth: 2. Verify identity + Auth->>A: 3. Identity confirmed + token + A->>U: 4. Return access token + + Note over U,API: Authorization Phase + U->>A: 5. API request + token + A->>A: 6. Validate token + A->>A: 7. Check permissions/scopes + + alt Authorized + A->>API: 8. Forward request + API->>A: 9. Response + A->>U: 10. Return response + else Unauthorized + A->>U: 11. 403 Forbidden + end +``` + +*Sequence diagram showing the two-phase process: authentication verifies who the user is, while authorization determines what they can do. Both phases are essential for secure API access control.* + +**Authentication (Who are you?):** +- Verifies the identity of the caller +- Typically involves credentials like passwords, API keys, or certificates +- Results in a token or session that proves identity +- Usually happens once per session or token lifetime + +**Authorization (What can you do?):** +- Determines what resources and operations the authenticated user can access +- Based on permissions, roles, scopes, or policies +- Evaluated for each request to protected resources +- Can be fine-grained (specific endpoints) or coarse-grained (broad permissions) + +### Common Authentication Patterns + +**API Keys:** +- Simple, stateless authentication +- Often used for service-to-service communication +- Limited authorization capabilities (typically binary: access or no access) + +**JWT Bearer Tokens:** +- Self-contained tokens with embedded claims +- Support fine-grained authorization through scopes and claims +- Stateless validation (no database lookup required) +- Industry standard for modern APIs + +**OAuth2 with PKCE:** +- Delegated authorization framework +- Supports multiple grant types and client types +- Built-in scope-based authorization +- Recommended for user-facing applications + +## Defining Security Schemes in OpenAPI + +OpenAPI 3.1 provides a robust framework for defining access control through two primary constructs: + +1. **`components.securitySchemes`**: Defines *how* clients can authenticate (JWT Bearer, OAuth2, API Keys) +2. **`security`**: Specifies *that* an endpoint is secured and by which mechanism(s) + +### JWT Bearer Token Authentication + +JWT (JSON Web Token) Bearer authentication is the most common pattern for modern APIs. The token contains encoded claims about the user and can be validated without database lookups. + +```yaml {% title="openapi.yaml" %} +components: + securitySchemes: + bearerAuth: + type: http + scheme: bearer + bearerFormat: JWT + description: "Enter JWT with 'Bearer ' prefix" + +# Apply globally to all operations +security: + - bearerAuth: [] +``` + +**JWT Token Structure:** +```javascript +// Header +{ + "alg": "RS256", + "typ": "JWT" +} + +// Payload (Claims) +{ + "sub": "user123", + "iss": "https://auth.example.com", + "aud": "api.example.com", + "exp": 1640995200, + "iat": 1640991600, + "scopes": ["users:read", "orders:write"] +} + +// Signature (RS256) +RSASHA256( + base64UrlEncode(header) + "." + + base64UrlEncode(payload), + private_key +) +``` + +### OAuth2 with Scope-Based Authorization + +OAuth2 provides the most flexible authorization framework, supporting fine-grained permissions through scopes and multiple authentication flows. + +```yaml {% title="openapi.yaml" %} +components: + securitySchemes: + oauth2Auth: + type: oauth2 + description: "OAuth2 Authorization Code Flow with PKCE" + flows: + authorizationCode: + authorizationUrl: https://auth.example.com/authorize + tokenUrl: https://auth.example.com/token + scopes: + 'users:read': "Read access to user profiles" + 'users:write': "Modify user profiles" + 'orders:read': "View order history" + 'orders:write': "Create and modify orders" + 'admin:users': "Full user management access" + +paths: + /users/{userId}: + get: + summary: "Get user profile" + security: + - oauth2Auth: ['users:read'] # Requires read access + responses: + '200': + description: "User profile data" + '401': + description: "Authentication required" + '403': + description: "Insufficient permissions" + + patch: + summary: "Update user profile" + security: + - oauth2Auth: ['users:write'] # Requires write access + responses: + '200': + description: "Profile updated successfully" + '401': + description: "Authentication required" + '403': + description: "Insufficient permissions" +``` + +### API Key Authentication + +For service-to-service communication and simpler use cases, API keys provide straightforward authentication. + +```yaml {% title="openapi.yaml" %} +components: + securitySchemes: + apiKeyAuth: + type: apiKey + in: header + name: X-API-Key + description: "API key for service authentication" + +paths: + /internal/health: + get: + summary: "Internal health check" + security: + - apiKeyAuth: [] + responses: + '200': + description: "Service health status" +``` + +### Mutual TLS (mTLS) for Service Authentication + +For high-security environments and service-to-service communication, [mutual TLS](api-tls-encryption-https-best-practices.md#mutual-tls-mtls-two-way-authentication) provides cryptographic identity verification. + +```yaml {% title="openapi.yaml" %} +components: + securitySchemes: + mtlsAuth: + type: mutualTLS + description: "Client certificate authentication" + +paths: + /internal/payments: + post: + security: + - mtlsAuth: [] + summary: "Process payment (internal service only)" + responses: + '200': + description: "Payment processed" + '401': + description: "Invalid client certificate" +``` + +## Automated Governance for Access Control + +One of the most common API vulnerabilities is the accidentally public endpoint—an operation that should require authentication but doesn't have security requirements defined. [Automated governance](api-design-first-security-governance.md) prevents this by enforcing security rules during development. + +### Security Governance Rules + +**Mandatory Authentication on Write Operations:** +```yaml {% title="governance-rules.yaml" %} +rules: + require-auth-on-mutations: + description: "All write operations must have security requirements" + severity: error + given: "$.paths[*][*]" + when: + function: enumerated + functionOptions: + values: ["post", "put", "patch", "delete"] + then: + field: "security" + function: truthy +``` + +**Validate Security Scheme Definitions:** +```yaml {% title="governance-rules.yaml" %} +rules: + security-schemes-defined: + description: "All security references must have corresponding definitions" + severity: error + given: "$.paths[*][*].security[*]" + then: + function: defined-security-scheme +``` + +When these rules run in your CI/CD pipeline, any endpoint without proper security definitions causes the build to fail, preventing accidentally public endpoints from reaching production. + +### Implementation Example + +**Before Governance (Vulnerable):** +```yaml +paths: + /users/{userId}: + delete: + summary: "Delete user account" + # Missing security requirement - accidentally public! + responses: + '204': + description: "User deleted" +``` + +**After Governance (Secure):** +```yaml +paths: + /users/{userId}: + delete: + summary: "Delete user account" + security: + - oauth2Auth: ['admin:users'] # Required by governance rules + responses: + '204': + description: "User deleted" + '401': + description: "Authentication required" + '403': + description: "Insufficient permissions" +``` + +## Security Definitions as Configuration + +Defining security schemes in OpenAPI extends beyond documentation—it establishes configuration-as-code that drives consistency across your entire API ecosystem: + +### API Gateway Integration + +Modern API gateways can import OpenAPI specifications and automatically configure authentication and authorization based on your security definitions. + +**Kong Gateway Configuration:** +```yaml {% title="kong.yaml" %} +# Generated from OpenAPI securitySchemes +plugins: +- name: jwt + config: + key_claim_name: iss + secret_is_base64: false + claims_to_verify: + - exp + - iat + run_on_preflight: false + +# Generated from OAuth2 scopes +- name: openapi-validator + config: + validate_request_body: true + validate_response_body: false + api_spec: "/path/to/openapi.yaml" +``` + +**AWS API Gateway Integration:** +```yaml {% title="serverless.yml" %} +functions: + getUserProfile: + handler: users.getProfile + events: + - http: + path: users/{userId} + method: get + # Generated from OpenAPI security requirements + authorizer: + name: jwtAuthorizer + scopes: + - users:read +``` + +### Code Generation + +OpenAPI security schemes enable automated generation of authentication handling in client SDKs and server stubs. + +**Generated Client SDK (TypeScript):** +```typescript +// Auto-generated from OpenAPI security schemes +class APIClient { + private bearerToken?: string; + + setBearerToken(token: string) { + this.bearerToken = token; + } + + async getUserProfile(userId: string): Promise { + const headers: Record = {}; + + // Auto-added based on security requirements + if (this.bearerToken) { + headers['Authorization'] = `Bearer ${this.bearerToken}`; + } + + const response = await fetch(`/users/${userId}`, { headers }); + + if (response.status === 401) { + throw new AuthenticationError('Bearer token required'); + } + + if (response.status === 403) { + throw new AuthorizationError('Insufficient permissions'); + } + + return response.json(); + } +} +``` + +## Advanced Authorization Patterns + +### Role-Based Access Control (RBAC) + +While OpenAPI doesn't have built-in RBAC support, you can model roles through scopes or custom extensions. + +```yaml {% title="openapi.yaml" %} +components: + securitySchemes: + oauth2Auth: + type: oauth2 + flows: + authorizationCode: + authorizationUrl: https://auth.example.com/authorize + tokenUrl: https://auth.example.com/token + scopes: + # Role-based scopes + 'role:admin': "Administrative access to all resources" + 'role:manager': "Management access within assigned teams" + 'role:user': "Standard user access to own resources" + + # Resource-based scopes + 'users:read': "Read user profiles" + 'users:write': "Modify user profiles" + 'orders:read': "View orders" + 'orders:write': "Create and modify orders" + +paths: + /admin/users: + get: + summary: "List all users (admin only)" + security: + - oauth2Auth: ['role:admin'] + responses: + '200': + description: "List of all users" + + /users/me: + get: + summary: "Get own profile" + security: + - oauth2Auth: ['role:user', 'users:read'] + responses: + '200': + description: "User's own profile" +``` + +### Context-Dependent Authorization + +Some authorization decisions depend on request context, such as resource ownership or dynamic policies. + +```yaml {% title="openapi.yaml" %} +paths: + /users/{userId}/orders: + get: + summary: "Get user's orders" + security: + - oauth2Auth: ['orders:read'] + parameters: + - name: userId + in: path + required: true + schema: + type: string + responses: + '200': + description: "User's order history" + '403': + description: "Can only access own orders unless admin" + # Custom extension for context-dependent rules + x-authorization-context: + resource-owner-check: true + admin-override: true +``` + +### Fine-Grained Permissions + +For complex applications, you might need very specific permissions that combine multiple factors. + +```yaml {% title="openapi.yaml" %} +components: + securitySchemes: + oauth2Auth: + type: oauth2 + flows: + authorizationCode: + authorizationUrl: https://auth.example.com/authorize + tokenUrl: https://auth.example.com/token + scopes: + # Operation + Resource + Condition + 'orders:read:own': "Read own orders" + 'orders:read:team': "Read team orders" + 'orders:read:all': "Read all orders" + 'orders:write:own': "Modify own orders" + 'orders:write:team': "Modify team orders" + 'orders:cancel:all': "Cancel any order" + +paths: + /orders/{orderId}: + patch: + summary: "Update order" + security: + - oauth2Auth: ['orders:write:own', 'orders:write:team'] + responses: + '200': + description: "Order updated" +``` + +## Authentication and Authorization Monitoring + +### Token Validation Metrics + +Monitor authentication success and failure patterns to detect potential attacks and system issues. + +```javascript +// Express.js middleware for auth monitoring +const authMetrics = { + successful_auths: 0, + failed_auths: 0, + expired_tokens: 0, + invalid_signatures: 0 +}; + +app.use('/api', (req, res, next) => { + const token = req.headers.authorization?.replace('Bearer ', ''); + + if (!token) { + authMetrics.failed_auths++; + return res.status(401).json({ error: 'Bearer token required' }); + } + + try { + const decoded = jwt.verify(token, publicKey, { + algorithms: ['RS256'], + audience: 'api.example.com', + issuer: 'https://auth.example.com' + }); + + // Check token expiration + if (decoded.exp < Date.now() / 1000) { + authMetrics.expired_tokens++; + return res.status(401).json({ error: 'Token expired' }); + } + + authMetrics.successful_auths++; + req.user = decoded; + next(); + + } catch (error) { + if (error.name === 'JsonWebTokenError') { + authMetrics.invalid_signatures++; + } else { + authMetrics.failed_auths++; + } + + return res.status(401).json({ error: 'Invalid token' }); + } +}); +``` + +### Authorization Failure Analysis + +Track authorization failures to identify potential privilege escalation attempts or misconfigured permissions. + +```python +# Python middleware for authorization monitoring +import logging +from collections import defaultdict + +class AuthorizationMonitor: + def __init__(self): + self.permission_denials = defaultdict(int) + self.scope_violations = defaultdict(int) + + def check_scopes(self, required_scopes, user_scopes, endpoint): + missing_scopes = set(required_scopes) - set(user_scopes) + + if missing_scopes: + self.scope_violations[endpoint] += 1 + logging.warning(f"Scope violation at {endpoint}", extra={ + 'required_scopes': required_scopes, + 'user_scopes': user_scopes, + 'missing_scopes': list(missing_scopes), + 'user_id': getattr(g, 'user_id', 'unknown') + }) + return False + + return True + + def get_violation_report(self): + return { + 'permission_denials': dict(self.permission_denials), + 'scope_violations': dict(self.scope_violations) + } +``` + +### Security Event Logging + +Implement comprehensive logging for security events to support incident response and compliance requirements. + +```yaml {% title="logging-config.yaml" %} +# Structured logging for security events +security_events: + authentication_success: + level: INFO + fields: [user_id, client_ip, user_agent, timestamp] + + authentication_failure: + level: WARN + fields: [client_ip, user_agent, failure_reason, timestamp] + + authorization_failure: + level: WARN + fields: [user_id, endpoint, required_scopes, user_scopes, timestamp] + + token_expiration: + level: INFO + fields: [user_id, token_issued_at, token_expired_at, timestamp] +``` + +## Troubleshooting Common Issues + +### Authentication Problems + +**Missing or Invalid Bearer Token:** +```bash +# Test unauthenticated access (should fail with 401) +curl -i https://api.example.com/users/me + +# Expected response: +# HTTP/1.1 401 Unauthorized +# Content-Type: application/json +# {"error": "Bearer token required"} +``` + +**Invalid Token Signature:** +```bash +# Test with invalid token (should fail with 401) +curl -H "Authorization: Bearer invalid_token" \ + https://api.example.com/users/me + +# Expected response: +# HTTP/1.1 401 Unauthorized +# {"error": "Invalid token signature"} +``` + +**Expired Token:** +```bash +# Test with expired token +curl -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9..." \ + https://api.example.com/users/me + +# Expected response: +# HTTP/1.1 401 Unauthorized +# {"error": "Token expired"} +``` + +### Authorization Problems + +**Insufficient Scopes:** +```bash +# Test scope enforcement (readonly token trying to write) +curl -H "Authorization: Bearer readonly_token" \ + -X POST \ + -H "Content-Type: application/json" \ + -d '{"name": "test"}' \ + https://api.example.com/users + +# Expected response: +# HTTP/1.1 403 Forbidden +# {"error": "Insufficient permissions", "required_scopes": ["users:write"]} +``` + +**Missing Security Requirements:** +```yaml +# Common issue: forgetting security on sensitive endpoints +paths: + /admin/users: + delete: + summary: "Delete all users" + # BUG: Missing security requirement! + # security: + # - oauth2Auth: ['admin:users'] + responses: + '204': + description: "All users deleted" +``` + +### Configuration Mismatches + +**Gateway Config Doesn't Match OpenAPI:** +```bash +# Verify gateway is enforcing the same rules as OpenAPI spec +curl -H "Authorization: Bearer user_token" \ + -X DELETE \ + https://api.example.com/admin/users + +# If this succeeds, gateway config is out of sync with OpenAPI +``` + +### Debugging Checklist + +1. **Verify token format and claims:** + ```bash + # Decode JWT to inspect claims (don't use in production) + echo "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9..." | base64 -d + ``` + +2. **Check security scheme definitions:** + ```yaml + # Ensure all referenced security schemes are defined + components: + securitySchemes: + oauth2Auth: # Must match security references + type: oauth2 + # ... configuration + ``` + +3. **Validate scope requirements:** + ```yaml + # Ensure required scopes exist in security scheme + security: + - oauth2Auth: ['users:write'] # Must be defined in scopes + ``` + +4. **Test authentication flow:** + ```bash + # Full OAuth2 flow test + # 1. Get authorization code + open "https://auth.example.com/authorize?response_type=code&client_id=..." + + # 2. Exchange code for token + curl -X POST https://auth.example.com/token \ + -d "grant_type=authorization_code&code=..." + + # 3. Use token for API access + curl -H "Authorization: Bearer access_token" \ + https://api.example.com/users/me + ``` + +## Best Practices Summary + +### Security Scheme Design +- Use JWT Bearer tokens for stateless authentication +- Implement OAuth2 with PKCE for user-facing applications +- Define granular scopes that map to business operations +- Use mTLS for high-trust service-to-service communication + +### Governance and Automation +- Require security definitions on all write operations +- Validate that all security references have corresponding definitions +- Fail builds when security requirements are missing +- Generate gateway configurations from OpenAPI security schemes + +### Monitoring and Observability +- Track authentication success/failure rates +- Monitor authorization violations by endpoint +- Log security events with sufficient context for incident response +- Set up alerts for unusual authentication patterns + +### Implementation +- Generate client SDKs with built-in authentication handling +- Use OpenAPI security schemes to configure API gateways +- Implement proper error responses (401 vs 403) +- Test authentication and authorization scenarios in CI/CD + +## Frequently Asked Questions + +### What's the difference between authentication and authorization? +Authentication verifies *who* the user is (like checking an ID card), while authorization determines *what* they can do (like checking permissions). Authentication happens first and provides identity, while authorization uses that identity to make access decisions for each request. + +### Should I use JWT or OAuth2 for my API? +JWT is a token format, while OAuth2 is an authorization framework. They work together: OAuth2 defines how to obtain tokens, and JWT defines the token format. Use OAuth2 with JWT tokens for user-facing applications, and consider simpler JWT Bearer authentication for service-to-service communication. + +### How do I implement fine-grained permissions with OpenAPI? +Use OAuth2 scopes to define specific permissions like `users:read`, `orders:write`, or `admin:users`. You can also model roles through scopes (e.g., `role:admin`) or use custom extensions for complex authorization logic that depends on request context. + +### What happens if I forget to add security requirements to an endpoint? +The endpoint becomes accidentally public, which is one of the most common API vulnerabilities. Automated governance rules can prevent this by failing builds when write operations (POST, PUT, PATCH, DELETE) don't have security requirements defined. + +### How do I handle authorization that depends on resource ownership? +OpenAPI security schemes handle authentication and basic authorization (scopes/roles), but context-dependent authorization (like "users can only access their own resources") typically requires custom logic in your application. Document these requirements using custom extensions like `x-authorization-context`. + +## Resources + +### Standards and Specifications +- [OpenAPI Security Schemes](https://spec.openapis.org/oas/v3.1.0#security-scheme-object) - Official specification for defining authentication and authorization +- [JWT RFC 7519](https://tools.ietf.org/html/rfc7519) - JSON Web Token standard for secure information transmission +- [OAuth2 RFC 6749](https://tools.ietf.org/html/rfc6749) - Authorization framework for delegated access +- [OAuth2 PKCE RFC 7636](https://tools.ietf.org/html/rfc7636) - Proof Key for Code Exchange extension for public clients + +### Implementation Tools +- [Auth0](https://auth0.com/) - Managed authentication and authorization platform with OpenAPI integration +- [Keycloak](https://www.keycloak.org/) - Open-source identity and access management with OAuth2/JWT support +- [Kong](https://konghq.com/) - API gateway with native OpenAPI security scheme support +- [AWS API Gateway](https://aws.amazon.com/api-gateway/) - Managed API gateway with built-in authentication and authorization + +### Security Best Practices +- [OWASP API Security Top 10](https://owasp.org/www-project-api-security/) - Including API1:2023 (Broken Object Level Authorization) and API2:2023 (Broken Authentication) +- [NIST Digital Identity Guidelines](https://pages.nist.gov/800-63-3/) - Comprehensive guidance on authentication and identity verification +- [OAuth2 Security Best Practices](https://tools.ietf.org/html/draft-ietf-oauth-security-topics) - Latest security recommendations for OAuth2 implementations + +### Related Security Topics +- [API TLS Encryption and HTTPS Best Practices](api-tls-encryption-https-best-practices.md) - Secure data in transit with mTLS +- [API Input Validation and Injection Prevention](api-input-validation-injection-prevention.md) - Protect APIs from malicious data +- [API Rate Limiting and Abuse Prevention](api-rate-limiting-abuse-prevention.md) - Prevent brute force attacks on auth endpoints +- [API Design-First Security Governance and Automation](api-design-first-security-governance.md) - Automate auth requirement validation +- [API Security by Design: Complete Guide](index.md) - Overview of all API security domains + +--- + +**Next Steps:** Now that you have authentication and authorization in place, learn about [API Design-First Security Governance and Automation](api-design-first-security-governance.md) to automate the validation of security requirements across your entire API ecosystem. diff --git a/learn/security/index.md b/learn/security/index.md index 0195b639..b5d22291 100644 --- a/learn/security/index.md +++ b/learn/security/index.md @@ -1,13 +1,260 @@ -Looking to secure your APIs by design? Start here for guides and best practices. +# API Security by Design: Complete Guide -## Security topics +_Build secure APIs from the ground up using OpenAPI security contracts and automated governance._ -- **Design-first security guide** - [Secure APIs by Design](api-design-first-security-guide.md) - Learn to enforce TLS, input validation, rate limiting, and access control with OpenAPI and governance. +--- + +## Key Takeaways + +Many teams discover security vulnerabilities after they're already in production, but it doesn't have to be that way! + +This comprehensive guide shows you how to turn your OpenAPI specification into a security contract that actually gets enforced. You'll learn to implement TLS encryption, input validation, rate limiting policies, and access control. By the time you're done, you'll know how to catch security issues during the design phase instead of scrambling to fix them once they're in production. + +**What you'll learn:** +- Transform your OpenAPI specs into executable security policies +- Automate security enforcement in your CI/CD pipeline +- Reduce vulnerability discovery time (from months to minutes in some cases) +- Build APIs that are secure by design upfront --- -Not sure where to start? -- Read the [Secure APIs by Design](api-design-first-security-guide.md) guide first. +## From Reactive Patching to Proactive API Security + +High-profile data breaches frequently trace back to insecure APIs, exposing a fundamental flaw in traditional security approaches. The conventional method—identifying and patching vulnerabilities in production—is reactive, costly, and ultimately inadequate. In its typical form, this paradigm treats security as an afterthought. + +Shifting security practices to the left in the development lifecycle, known as the "shift-left" imperative, addresses this by integrating security into the earliest stages of design and development. This proactive model prevents vulnerabilities from being introduced in the first place, rather than attempting to remediate them under pressure in production environments. + +### OpenAPI as Your Security Contract + +The core of this strategy is treating your OpenAPI specification not merely as documentation, but as an executable security contract. This contract declaratively defines a set of security requirements, constraints, and policies before any application code is written. It becomes the single source of truth that dictates how an API must behave to be considered secure, effectively implementing a "policy-as-code" approach for APIs. + +However, a contract, much like a law, is only as strong as its enforcement. This is where automated governance and linting tools provide value by transforming your contract into dynamic, automated guardrails that validate security requirements at every stage of development. When integrated into a Continuous Integration/Continuous Deployment (CI/CD) pipeline, this automated governance acts as a gatekeeper, failing builds that violate the security contract and requiring fixes before deployment. + +## The Four Pillars of API Security + +Building secure APIs doesn't have to feel like playing whack-a-mole with vulnerabilities. Once you shift from reactive patching to proactive design, you'll wonder why you ever did it any other way. Let's explore how to make security an automatic part of your API development process. + +```mermaid +graph TD + A["🏛️ Secure API Foundation"] --> B["🔐 TLS Encryption
Data in Transit"] + A --> C["✅ Input Validation
Schema Contracts"] + A --> D["⚡ Rate Limiting
Abuse Prevention"] + A --> E["🔑 Access Control
Auth & Authorization"] + + B --> F["• HTTPS Enforcement
• Certificate Management
• Strong Cipher Suites"] + C --> G["• JSON Schema Rules
• Type Validation
• Length Constraints"] + D --> H["• x-rateLimit Extensions
• 429 Response Headers
• Multi-tier Limits"] + E --> I["• Security Schemes
• JWT/OAuth2
• Scope Management"] + + J["📄 OpenAPI 3.1
Specification"] --> A + K["⚙️ Automated
Governance"] --> A + + style A fill:#e8f5e8 + style B fill:#e3f2fd + style C fill:#fff3e0 + style D fill:#fce4ec + style E fill:#f1f8e9 + style J fill:#e1f5fe + style K fill:#f3e5f5 +``` + +*Architecture diagram showing the four essential areas of API security (TLS encryption, input validation, rate limiting, access control) supported by OpenAPI specifications and automated governance tools.* + +## Deep Dive Guides + +Each security domain requires specific knowledge and implementation techniques. Choose the guide that matches your current focus: + +### API TLS Encryption and HTTPS Best Practices +**What you'll learn:** Protect data in transit with proper TLS configuration, certificate management, and HTTPS enforcement. + +**Key topics:** +- TLS 1.3 implementation and cipher suite selection +- OpenAPI server URL security contracts +- Mutual TLS (mTLS) for service-to-service communication +- Real-world case study: Heartbleed vulnerability and lessons learned +- Automated governance for transport security + +**Perfect for:** Infrastructure teams, DevOps engineers, and security architects + +--- + +### API Input Validation and Injection Prevention +**What you'll learn:** Stop injection attacks using OpenAPI schema validation and automated governance rules. + +**Key topics:** +- JSON Schema security constraints and validation patterns +- Mass assignment attack prevention +- SQL injection and OGNL injection defense strategies +- Real-world case study: Equifax breach analysis +- Automated validation governance and linting + +**Perfect for:** Backend developers, security engineers, and API architects + +--- + +### API Rate Limiting and Abuse Prevention +**What you'll learn:** Prevent DoS attacks, brute force attempts, and business logic abuse through strategic rate limiting. + +**Key topics:** +- Rate limiting algorithms and implementation patterns +- OpenAPI x-rateLimit extensions and documentation +- Multi-tier rate limiting strategies +- Real-world case study: Facebook phone number scraping incident +- Client-side backoff and error handling + +**Perfect for:** API product managers, DevOps teams, and security operations + +--- + +### Authentication and Authorization with OpenAPI +**What you'll learn:** Implement secure access control using OpenAPI security schemes and modern authentication patterns. + +**Key topics:** +- OpenAPI security schemes (JWT, OAuth2, API Keys, mTLS) +- Authentication vs authorization flow patterns +- Scope-based access control and permission systems +- Security scheme governance and automation +- Token validation and session management + +**Perfect for:** Identity and access management teams, full-stack developers, and security engineers + +--- + +### API Design-First Security Governance and Automation +**What you'll learn:** Scale security practices through automated governance, policy-as-code, and organizational maturity. + +**Key topics:** +- API security governance principles and automation +- CI/CD integration for security validation +- Security policy-as-code implementation +- API security maturity model and progression strategies +- Monitoring, observability, and continuous improvement + +**Perfect for:** API platform teams, security architects, and engineering leadership + +## Understanding Design-Time vs Runtime Security + +It's important to understand that OpenAPI-based security governance operates at **design-time**, not runtime. This governance approach excels at preventing configuration errors, missing security controls, and specification inconsistencies before they reach production. That said, it cannot prevent runtime vulnerabilities in the underlying implementation. + +### API Security Implementation Timeline + +```mermaid +timeline + title API Security Implementation Timeline + + section Design Phase + OpenAPI Spec : Security schemes defined + : Input validation rules + : Rate limiting policies + + section Build Phase + Code Generation : Security middleware + : Validation logic + CI/CD Pipeline : Governance checks + : Security linting + + section Runtime Phase + Production : TLS termination + : Authentication + : Rate limiting + : Input validation + Monitoring : Attack detection + : Performance metrics +``` + +*Timeline showing how API security spans from design-time specification through build automation to runtime enforcement, with different security controls applied at each phase.* + +**Design-time security governance prevents:** +- Accidentally public endpoints (missing security requirements) +- Insecure server configurations (HTTP instead of HTTPS) +- Missing input validation constraints +- Inconsistent rate limiting policies +- Data leakage through unused components + +**Runtime security still requires:** +- Patch management for frameworks and libraries (like the Heartbleed OpenSSL vulnerability) +- Secure coding practices and parameterized queries +- Infrastructure security monitoring and alerting +- Penetration testing and vulnerability scanning + +True "secure by design" requires both: design-time contracts enforced through OpenAPI governance *and* runtime security posture management as part of a comprehensive DevSecOps practice. + +## API Security Maturity Model + +Implementing comprehensive API security is a journey. Organizations typically progress through distinct maturity levels as they build more sophisticated security practices: + +```mermaid +graph TD + A[Level 0: Basic] --> B[Level 1: Structured] --> C[Level 2: Automated] --> D[Level 3: Proactive] + + A --> A1[Manual reviews
Basic HTTPS
Simple auth] + B --> B1[OpenAPI specs
Schema validation
Rate limiting] + C --> C1[Automated governance
CI/CD integration
Policy enforcement] + D --> D1[Threat modeling
Zero-trust architecture
Continuous monitoring] + + style A fill:#ffcdd2 + style B fill:#fff59d + style C fill:#c8e6c9 + style D fill:#a5d6a7 +``` + +*API security maturity progression showing the evolution from basic manual practices to proactive, automated security governance with comprehensive threat detection and prevention.* + +**Level 0 - Basic Security:** +- Manual code reviews for obvious security issues +- HTTPS enabled but not enforced through specifications +- Basic authentication (API keys or simple passwords) +- Ad-hoc security practices without consistent standards + +**Level 1 - Structured Security:** +- OpenAPI specifications document all APIs with security requirements +- Schema-based input validation prevents basic injection attacks +- Rate limiting implemented on authentication and sensitive endpoints +- Consistent security patterns across API teams + +**Level 2 - Automated Security:** +- Automated governance tools enforce security standards in CI/CD pipelines +- Security policies defined as code and validated automatically +- Breaking changes to security configurations fail builds +- Security metrics tracked and monitored systematically + +**Level 3 - Proactive Security:** +- Comprehensive threat modeling integrated into the design process +- Zero-trust architecture with mutual TLS for service-to-service communication +- Continuous security monitoring with behavioral analysis and anomaly detection +- Security feedback loops drive iterative improvements to governance policies + +Most organizations find that advancing one level at a time provides the most sustainable improvement path. The techniques covered in this guide primarily support progression from Level 0 to Level 2, with Level 3 requiring additional infrastructure and organizational maturity. + +## Frequently Asked Questions + +### What is design-first API security? +Design-first API security means defining security requirements in your OpenAPI specification before writing code, then using automated governance tools to enforce those requirements throughout the development lifecycle. This prevents vulnerabilities from reaching production rather than patching them after discovery. + +### How does OpenAPI prevent injection attacks? +OpenAPI specifications define precise data schemas with type validation, format constraints, and length limits. When enforced by governance tools, these schemas automatically reject malformed inputs that could contain injection payloads, stopping attacks before they reach your application logic. + +### Why is rate limiting important for API security? +Rate limiting prevents denial-of-service attacks, brute-force authentication attempts, and data scraping. It ensures fair resource usage among legitimate users while blocking malicious automation. Without rate limits, a single bad actor can overwhelm your API infrastructure. + +### Can I implement all four security areas with just OpenAPI? +Yes, OpenAPI 3.1 supports all four security areas: TLS enforcement through server URLs, input validation via JSON schemas, rate limiting through extensions like `x-rateLimit`, and access control via security schemes. Combined with governance automation, your specification becomes an executable security contract. + +### What's the difference between authentication and authorization in APIs? +Authentication verifies *who* the user is (like checking an ID card), while authorization determines *what* they can do (like checking permissions). Both are essential for API security, and OpenAPI provides security schemes to define and enforce both concepts through your specification. + +## Resources + +### Security Standards and Guidelines +- [OWASP API Security Top 10](https://owasp.org/www-project-api-security/) - Comprehensive vulnerability guide including injection attacks (API3:2023), resource consumption (API4:2023), and business logic abuse (API6:2023) +- [NIST SP 800-52 Rev. 2](https://csrc.nist.gov/publications/detail/sp/800-52/rev-2/final) - Official guidelines for secure TLS implementation and configuration requirements +- [IETF RFC 8446](https://tools.ietf.org/html/rfc8446) - TLS 1.3 protocol specification and security requirements + +### Practical Implementation Tools +- [Mozilla SSL Configuration Generator](https://ssl-config.mozilla.org/) - Generate secure, up-to-date TLS configurations for various web servers and security levels +- [OpenAPI Generator](https://openapi-generator.tech/) - Code generation tool for creating secure client SDKs and server stubs from OpenAPI specifications +- [OpenAPI Specification](https://spec.openapis.org/oas/v3.1.0) - Official OpenAPI 3.1 specification including security scheme definitions +### DevSecOps and API Governance +- [OWASP API Security Project](https://owasp.org/www-project-api-security/) - Community-driven API security best practices and threat modeling +- [OpenAPI Security Schemes](https://spec.openapis.org/oas/v3.1.0#security-scheme-object) - Official specification for defining authentication and authorization in OpenAPI \ No newline at end of file diff --git a/learn/security/sidebars.yaml b/learn/security/sidebars.yaml index 9508dd24..a0fb57c7 100644 --- a/learn/security/sidebars.yaml +++ b/learn/security/sidebars.yaml @@ -1,2 +1,9 @@ - page: ./index.md -- page: ./api-design-first-security-guide.md +- group: API Security Fundamentals + pages: + - page: ./api-tls-encryption-https-best-practices.md + - page: ./api-input-validation-injection-prevention.md + - page: ./api-rate-limiting-abuse-prevention.md + - page: ./authentication-authorization-openapi.md + - page: ./api-design-first-security-governance.md + - page: ./api-design-first-security-guide.md diff --git a/pages/learning-center/cards.ts b/pages/learning-center/cards.ts index 6940d0f8..5d3fe41a 100644 --- a/pages/learning-center/cards.ts +++ b/pages/learning-center/cards.ts @@ -105,10 +105,15 @@ export const cards = [ description: 'Gain insights into securing your APIs with essential resources, tools, and best practices to protect your applications.', thumbnail: apiSecurityThumbnail, - moreItems: '1 more topic', + moreItems: '2 more topics', landingPage: '/learn/security', items: [ - { title: 'API Design-First Security Guide', link: '/learn/security/api-design-first-security-guide' }, + { title: 'API Security by Design: Complete Guide', link: '/learn/security' }, + { title: 'API TLS Encryption and HTTPS Best Practices', link: '/learn/security/api-tls-encryption-https-best-practices' }, + { title: 'API Input Validation and Injection Prevention', link: '/learn/security/api-input-validation-injection-prevention' }, + { title: 'API Rate Limiting and Abuse Prevention', link: '/learn/security/api-rate-limiting-abuse-prevention' }, + { title: 'Authentication and Authorization with OpenAPI', link: '/learn/security/authentication-authorization-openapi' }, + { title: 'API Design-First Security Governance and Automation', link: '/learn/security/api-design-first-security-governance' }, ], }, // { From 981960928915a0be548cc3f9476ca7e7916244e7 Mon Sep 17 00:00:00 2001 From: Matt Williams Date: Wed, 24 Sep 2025 10:53:27 -0500 Subject: [PATCH 07/27] WIP add security articles --- learn/security/_filesets/README.md | 26 + learn/security/_filesets/basic-security.yaml | 78 ++ learn/security/_filesets/example-api.yaml | 137 +++ learn/security/_filesets/package.json | 45 + learn/security/_filesets/redocly.yaml | 524 ++++++++++ .../security/_filesets/security-functions.js | 225 ++++ .../api-design-first-security-governance.md | 968 ------------------ ...i-input-validation-injection-prevention.md | 27 +- .../api-rate-limiting-abuse-prevention.md | 27 +- ...api-tls-encryption-https-best-practices.md | 26 +- .../authentication-authorization-openapi.md | 29 +- ...tomated-security-validation-walkthrough.md | 123 +++ learn/security/index.md | 14 - learn/security/sidebars.yaml | 2 +- 14 files changed, 1224 insertions(+), 1027 deletions(-) create mode 100644 learn/security/_filesets/README.md create mode 100644 learn/security/_filesets/basic-security.yaml create mode 100644 learn/security/_filesets/example-api.yaml create mode 100644 learn/security/_filesets/package.json create mode 100644 learn/security/_filesets/redocly.yaml create mode 100644 learn/security/_filesets/security-functions.js delete mode 100644 learn/security/api-design-first-security-governance.md create mode 100644 learn/security/automated-security-validation-walkthrough.md diff --git a/learn/security/_filesets/README.md b/learn/security/_filesets/README.md new file mode 100644 index 00000000..6d7eac55 --- /dev/null +++ b/learn/security/_filesets/README.md @@ -0,0 +1,26 @@ +# API Security Validation Configuration Files + +This directory contains the configuration files used in the Interactive Security Validation Walkthrough. + +## Files + +- **`redocly.yaml`** - Complete OWASP API Security Top 10 2023 ruleset +- **`basic-security.yaml`** - Simplified starter configuration +- **`security-functions.js`** - Custom JavaScript validation functions +- **`package.json`** - Package configuration and npm scripts + +## Usage + +1. Choose your approach (Basic or Complete) in the walkthrough +2. Download the appropriate configuration files +3. Follow the implementation guide in the walkthrough +4. Customize rules based on your specific security requirements + +## Integration + +These files are designed to work with: +- Redocly CLI v1.0.0+ +- OpenAPI 3.0+ specifications +- CI/CD pipelines (GitHub Actions, GitLab CI, etc.) + +For detailed usage instructions, see the Interactive Security Validation Walkthrough. diff --git a/learn/security/_filesets/basic-security.yaml b/learn/security/_filesets/basic-security.yaml new file mode 100644 index 00000000..48ad5df7 --- /dev/null +++ b/learn/security/_filesets/basic-security.yaml @@ -0,0 +1,78 @@ +# @chunk {"steps": ["basic-setup"]} +# Basic Redocly Security Ruleset +# Starter configuration for API security validation +# Based on OWASP API Security Top 10 2023 - Essential Rules Only + +rules: + # Built-in Redocly security rules + security-defined: error + operation-4xx-response: warn + operation-2xx-response: error + no-unresolved-refs: error + + # Essential Security Rules - API2:2023 Authentication + + # Enforce HTTPS for all server URLs + rule/https-server-urls: + subject: + type: Server + property: url + assertions: + pattern: /^https:/ + message: "Server URLs must use HTTPS protocol. HTTP is insecure." + severity: error + + # Prevent HTTP Basic authentication + rule/no-http-basic-auth: + subject: + type: SecurityScheme + property: scheme + where: + - subject: + type: SecurityScheme + property: type + assertions: + const: http + assertions: + notPattern: /^basic$/i + message: "HTTP Basic authentication is insecure. Use OAuth 2.0 or API keys in headers." + severity: error + + # API4:2023 - Resource Consumption Protection + + # String schemas must have length constraints + rule/string-length-limit: + subject: + type: Schema + where: + - subject: + type: Schema + property: type + assertions: + const: string + assertions: + requireAny: + - maxLength + - enum + - const + - pattern + message: "String schemas must specify maxLength, enum, const, or pattern to limit resource consumption." + severity: warn + + # Array schemas must specify maxItems + rule/array-max-items: + subject: + type: Schema + property: maxItems + where: + - subject: + type: Schema + property: type + assertions: + const: array + assertions: + defined: true + message: "Array schemas must specify maxItems to prevent resource exhaustion attacks." + severity: warn + +# @chunk-end \ No newline at end of file diff --git a/learn/security/_filesets/example-api.yaml b/learn/security/_filesets/example-api.yaml new file mode 100644 index 00000000..8d08d710 --- /dev/null +++ b/learn/security/_filesets/example-api.yaml @@ -0,0 +1,137 @@ +# @chunk {"steps": ["api-example"]} +# Example OpenAPI spec for security validation demonstration +openapi: 3.0.3 +info: + title: API Security Demo + version: 1.0.0 + description: Example API demonstrating security validation rules + +servers: + - url: https://api.example.com/v1 + description: Production server (HTTPS required) + +components: + securitySchemes: + BearerAuth: + type: http + scheme: bearer + bearerFormat: JWT + description: JWT tokens must follow RFC8725 compliance for security best practices + + schemas: + User: + type: object + additionalProperties: false + required: + - id + - name + - email + properties: + id: + type: string + format: uuid + description: UUID format prevents object-level authorization attacks + name: + type: string + maxLength: 100 + pattern: "^[a-zA-Z\\s]+$" + email: + type: string + format: email + maxLength: 254 + permissions: + type: array + maxItems: 50 + items: + type: string + enum: [read, write, admin] + +paths: + /users/{userId}: + get: + summary: Get user by ID + security: + - BearerAuth: [] + parameters: + - name: userId + in: path + required: true + schema: + type: string + format: uuid + description: UUID format prevents enumeration attacks + responses: + '200': + description: User found + headers: + RateLimit-Limit: + schema: + type: integer + description: Rate limit per hour + RateLimit-Remaining: + schema: + type: integer + description: Remaining requests + content: + application/json: + schema: + $ref: '#/components/schemas/User' + '401': + description: Unauthorized - invalid or missing token + '403': + description: Forbidden - insufficient permissions + '404': + description: User not found + '429': + description: Rate limit exceeded + headers: + Retry-After: + schema: + type: integer + description: Seconds to wait before retrying + '500': + description: Internal server error + + put: + summary: Update user + security: + - BearerAuth: [admin] + parameters: + - name: userId + in: path + required: true + schema: + type: string + format: uuid + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/User' + responses: + '200': + description: User updated successfully + headers: + RateLimit-Limit: + schema: + type: integer + '400': + description: Invalid input data + '401': + description: Unauthorized + '403': + description: Forbidden + '404': + description: User not found + '422': + description: Validation error + '429': + description: Rate limit exceeded + headers: + Retry-After: + schema: + type: integer + '500': + description: Internal server error +# @chunk-end diff --git a/learn/security/_filesets/package.json b/learn/security/_filesets/package.json new file mode 100644 index 00000000..de718e8b --- /dev/null +++ b/learn/security/_filesets/package.json @@ -0,0 +1,45 @@ +{ + "name": "redocly-security-validation", + "version": "1.0.0", + "description": "Custom security validation functions for Redocly CLI implementing OWASP API Security Top 10 2023", + "main": "security-functions.js", + "scripts": { + "lint": "redocly lint openapi.yaml --config=redocly.yaml", + "lint-basic": "redocly lint openapi.yaml --config=basic-security.yaml", + "test-security": "npm run lint && echo 'Security validation tests passed'", + "validate": "redocly build-docs openapi.yaml --config=redocly.yaml" + }, + "keywords": [ + "api-security", + "owasp", + "redocly", + "validation", + "openapi", + "security-validation", + "api-validation" + ], + "author": "API Security Team", + "license": "MIT", + "devDependencies": { + "@redocly/cli": "^1.0.0" + }, + "peerDependencies": { + "@redocly/cli": ">=1.0.0" + }, + "files": [ + "redocly.yaml", + "basic-security.yaml", + "security-functions.js", + "README.md" + ], + "engines": { + "node": ">=16.0.0" + }, + "repository": { + "type": "git", + "url": "https://github.com/your-org/api-security-validation" + }, + "bugs": { + "url": "https://github.com/your-org/api-security-validation/issues" + } +} diff --git a/learn/security/_filesets/redocly.yaml b/learn/security/_filesets/redocly.yaml new file mode 100644 index 00000000..603b5081 --- /dev/null +++ b/learn/security/_filesets/redocly.yaml @@ -0,0 +1,524 @@ +# @chunk {"steps": ["setup-plugins"]} +# Redocly Security Ruleset +# Based on OWASP API Security Top 10 2023 +# https://owasp.org/www-project-api-security/ + +# Note: Plugin reference removed for walkthrough demonstration +# In production, add: plugins: ['./security-functions.js'] + +# Enable built-in security rules +rules: + # Built-in Redocly security rules + security-defined: error + operation-4xx-response: error + operation-2xx-response: error + no-unresolved-refs: error +# @chunk-end + + # @chunk {"steps": ["api1-object-auth"], "when": {"category": "api1"}} + # ========================================== + # API1:2023 - Broken Object Level Authorization + # ========================================== + + # Prevent numeric IDs that can be easily guessed + rule/no-numeric-ids: + subject: + type: Schema + property: type + filterInParentKeys: [path] + where: + - subject: + type: Parameter + property: name + assertions: + pattern: /(^id$|_id$|Id$|-id$)/ + assertions: + enum: [string] + message: "Use random IDs that cannot be guessed (UUIDs are preferred). Avoid integer IDs in path parameters." + severity: error + + # Ensure ID parameters use appropriate formats + rule/id-format-required: + subject: + type: Schema + property: format + filterInParentKeys: [path] + where: + - subject: + type: Parameter + property: name + assertions: + pattern: /(^id$|_id$|Id$|-id$)/ + assertions: + enum: [uuid, uri, password] + message: "ID parameters should specify a secure format like 'uuid'." + severity: warn + # @chunk-end + + # @chunk {"steps": ["api2-broken-auth"], "when": {"category": "api2"}} + # ========================================== + # API2:2023 - Broken Authentication + # ========================================== + + # Enforce HTTPS for all server URLs + rule/https-server-urls: + subject: + type: Server + property: url + assertions: + pattern: /^https:/ + message: "Server URLs must use HTTPS protocol. HTTP is insecure and exposes data to interception." + severity: error + + # Prevent HTTP Basic authentication + rule/no-http-basic-auth: + subject: + type: SecurityScheme + property: scheme + where: + - subject: + type: SecurityScheme + property: type + assertions: + const: http + assertions: + notPattern: /^basic$/i + message: "HTTP Basic authentication is insecure. Use OAuth 2.0, API keys in headers, or other secure methods." + severity: error + + # Prevent API keys in URL (query/path) + rule/no-api-keys-in-url: + subject: + type: SecurityScheme + property: in + where: + - subject: + type: SecurityScheme + property: type + assertions: + const: apiKey + assertions: + enum: [header, cookie] + message: "API keys must not be in URL (query or path parameters). Use headers or cookies instead." + severity: error + + # Prevent credentials in parameter names + rule/no-credentials-in-parameters: + subject: + type: Parameter + property: name + filterInParentKeys: [query, path] + assertions: + notPattern: /(secret|token|access.?token|refresh.?token|id.?token|password|api.?key|credential)/i + message: "Parameter names must not contain credential-related terms. Use secure authentication headers instead." + severity: error + + # Ensure write operations are protected + rule/write-operations-secured: + subject: + type: Operation + property: security + filterInParentKeys: [post, put, patch, delete] + assertions: + defined: true + nonEmpty: true + message: "Write operations (POST, PUT, PATCH, DELETE) must be protected by security schemes." + severity: error + + # JWT bearer format security schemes should reference RFC8725 + rule/jwt-rfc8725-compliance: + subject: + type: SecurityScheme + property: description + where: + - subject: + type: SecurityScheme + property: bearerFormat + assertions: + pattern: /jwt/i + assertions: + pattern: /RFC\s*8725/i + message: "JWT security schemes must reference RFC8725 compliance in description for security best practices." + severity: error + + # Advanced cross-operation security validation (requires custom functions) + rule/comprehensive-security-check: + subject: + type: Root + assertions: + security/checkOperationSecurity: + methods: [post, put, patch, delete] + nullable: false + message: "All write operations must have properly configured security schemes" + severity: error + # @chunk-end + + # @chunk {"steps": ["api3-property-auth"], "when": {"category": "api3"}} + # ========================================== + # API3:2023 - Broken Object Property Level Authorization + # ========================================== + + # Prevent unconstrained additionalProperties + rule/no-additional-properties: + subject: + type: Schema + property: additionalProperties + where: + - subject: + type: Schema + property: type + assertions: + const: object + assertions: + const: false + message: "Objects should not allow additionalProperties. Set to false to prevent mass assignment vulnerabilities." + severity: warn + + # Require maxProperties when additionalProperties is not false + rule/constrained-additional-properties: + subject: + type: Schema + property: maxProperties + where: + - subject: + type: Schema + property: type + assertions: + const: object + - subject: + type: Schema + property: additionalProperties + assertions: + defined: true + notPattern: /^false$/ + assertions: + defined: true + message: "Objects with additionalProperties should define maxProperties to limit resource consumption." + severity: warn + # @chunk-end + + # @chunk {"steps": ["api4-resource-consumption"], "when": {"category": "api4"}} + # ========================================== + # API4:2023 - Unrestricted Resource Consumption + # ========================================== + + # Require rate limiting headers in responses + rule/rate-limit-headers-present: + subject: + type: Header + where: + - subject: + type: Response + filterInParentKeys: ["200", "201", "202", "204", "400", "401", "403", "404", "422", "429"] + assertions: + defined: true + assertions: + pattern: /^(RateLimit|RateLimit-Limit|X-RateLimit-Limit|X-Rate-Limit-Limit)$/i + message: "2XX and 4XX responses should include rate limiting headers (RateLimit, RateLimit-Limit, X-RateLimit-Limit, or X-Rate-Limit-Limit)." + severity: warn + + # Require 429 Too Many Requests response + rule/require-429-response: + subject: + type: Responses + property: "429" + assertions: + defined: true + message: "Operations should define a 429 (Too Many Requests) response for rate limiting." + severity: warn + + # Retry-After header required for 429 responses + rule/retry-after-header-429: + subject: + type: Header + where: + - subject: + type: Response + filterInParentKeys: ["429"] + assertions: + defined: true + assertions: + pattern: /^Retry-After$/i + message: "429 responses must include a Retry-After header to indicate when clients can retry." + severity: error + + # Array schemas must specify maxItems + rule/array-max-items: + subject: + type: Schema + property: maxItems + where: + - subject: + type: Schema + property: type + assertions: + const: array + assertions: + defined: true + message: "Array schemas must specify maxItems to prevent resource exhaustion attacks." + severity: error + + # String schemas must have length constraints + rule/string-length-limit: + subject: + type: Schema + where: + - subject: + type: Schema + property: type + assertions: + const: string + assertions: + requireAny: + - maxLength + - enum + - const + - pattern + message: "String schemas must specify maxLength, enum, const, or pattern to limit resource consumption." + severity: error + + # Integer schemas must have min/max constraints + rule/integer-constraints: + subject: + type: Schema + where: + - subject: + type: Schema + property: type + assertions: + const: integer + assertions: + required: [minimum, maximum] + message: "Integer schemas must specify minimum and maximum values to prevent resource exhaustion." + severity: error + + # Integer schemas should specify format + rule/integer-format: + subject: + type: Schema + property: format + where: + - subject: + type: Schema + property: type + assertions: + const: integer + assertions: + enum: [int32, int64] + message: "Integer schemas should specify format (int32 or int64) for precise validation." + severity: warn + + # Advanced rate limiting consistency validation (requires custom functions) + rule/rate-limit-consistency: + subject: + type: Root + assertions: + security/validateRateLimitConsistency: + requiredHeaders: [RateLimit, X-RateLimit-Limit, X-Rate-Limit-Limit] + message: "Rate limiting configurations should be consistent across operations" + severity: warn + # @chunk-end + + # @chunk {"steps": ["api5-function-auth"], "when": {"category": "api5"}} + # ========================================== + # API5:2023 - Broken Function Level Authorization + # ========================================== + + # Administrative endpoints should have stricter security + rule/admin-endpoints-secured: + subject: + type: Operation + property: security + where: + - subject: + type: PathItem + assertions: + pattern: /(admin|manage|control|configure)/i + assertions: + defined: true + nonEmpty: true + message: "Administrative endpoints must have defined security schemes with appropriate authorization levels." + severity: error + + # Advanced admin security isolation validation (requires custom functions) + rule/admin-security-isolation: + subject: + type: Root + assertions: + security/validateAdminSecurity: + adminUrlPattern: "/admin" + message: "Administrative endpoints must use different security schemes than regular operations" + severity: error + + # Advanced OAuth scope validation (requires custom functions) + rule/oauth-scope-validation: + subject: + type: Root + assertions: + security/validateOAuthScopes: + adminOperations: [delete, post, put, patch] + requiredAdminScopes: [admin, write, manage] + adminPathPatterns: ["/admin", "/manage", "/config", "/system"] + message: "OAuth scopes must be appropriate for operation sensitivity" + severity: error + # @chunk-end + + # @chunk {"steps": ["api7-ssrf"], "when": {"category": "api7"}} + # ========================================== + # API7:2023 - Server Side Request Forgery + # ========================================== + + # Warn about URL parameters that might lead to SSRF + rule/ssrf-url-parameters: + subject: + type: Parameter + property: name + assertions: + notPattern: /(callback|redirect|url|uri|endpoint|webhook|fetch|proxy)/i + message: "URL-related parameters may be vulnerable to Server Side Request Forgery. Ensure proper validation and allowlisting." + severity: warn + # @chunk-end + + # @chunk {"steps": ["api8-misconfiguration"], "when": {"category": "api8"}} + # ========================================== + # API8:2023 - Security Misconfiguration + # ========================================== + + # Require CORS headers in responses + rule/cors-access-control-allow-origin: + subject: + type: Header + where: + - subject: + type: Response + assertions: + defined: true + assertions: + pattern: /^Access-Control-Allow-Origin$/i + message: "Responses should define CORS headers (Access-Control-Allow-Origin) to control cross-origin access." + severity: warn + + # Require error response schemas (400, 401, 403, 500) + rule/error-responses-defined: + subject: + type: Responses + assertions: + requireAny: ["400", "401", "403", "422", "4XX"] + message: "Operations should define appropriate error responses (400, 401, 403, 422, or 4XX) with proper schemas." + severity: warn + + # Require 401 unauthorized responses for secured operations + rule/unauthorized-response-required: + subject: + type: Responses + property: "401" + where: + - subject: + type: Operation + property: security + assertions: + defined: true + assertions: + defined: true + message: "Secured operations should define 401 (Unauthorized) responses." + severity: warn + + # Require 500 server error responses + rule/server-error-response: + subject: + type: Responses + property: "500" + assertions: + defined: true + message: "Operations should define 500 (Internal Server Error) responses to handle server errors gracefully." + severity: warn + # @chunk-end + + # @chunk {"steps": ["api9-inventory"], "when": {"category": "api9"}} + # ========================================== + # API9:2023 - Improper Inventory Management + # ========================================== + + # Server objects should declare internal/external audience + rule/server-audience-declaration: + subject: + type: Server + property: x-internal + assertions: + defined: true + enum: ['true', 'false'] + message: "Servers should declare their intended audience using x-internal (true for internal, false for external)." + severity: error + + # Server descriptions should indicate environment + rule/server-environment-declaration: + subject: + type: Server + property: description + assertions: + pattern: /(local|dev|development|test|testing|stage|staging|prod|production|live|sandbox)/i + message: "Server descriptions should clearly indicate the environment (development, testing, staging, production)." + severity: error + + # API version should be clearly defined + rule/api-version-defined: + subject: + type: Info + property: version + assertions: + defined: true + pattern: /^\d+\.\d+\.\d+/ + message: "API version should be clearly defined using semantic versioning (e.g., 1.0.0)." + severity: error + # @chunk-end + + # @chunk {"steps": ["custom-validation"], "when": {"component": "functions"}} + # ========================================== + # Additional Security Rules + # ========================================== + + # Prevent sensitive data in examples + rule/no-sensitive-data-in-examples: + subject: + type: Schema + property: example + assertions: + notPattern: /(password|secret|token|key|credential|ssn|social.?security|credit.?card|api.?key)/i + message: "Examples should not contain sensitive data like passwords, tokens, or personal information." + severity: warn + + # Ensure request bodies have proper content types + rule/secure-content-types: + subject: + type: MediaType + where: + - subject: + type: RequestBody + assertions: + defined: true + assertions: + enum: + - application/json + - application/xml + - application/x-www-form-urlencoded + - multipart/form-data + - text/plain + message: "Use secure and well-defined content types. Avoid allowing arbitrary content types." + severity: warn + + # Prevent overly broad schemas + rule/no-empty-schemas: + subject: + type: Schema + assertions: + requireAny: + - type + - properties + - items + - allOf + - anyOf + - oneOf + - $ref + message: "Schemas should not be empty. Define proper constraints to prevent accepting arbitrary data." + severity: error + # @chunk-end diff --git a/learn/security/_filesets/security-functions.js b/learn/security/_filesets/security-functions.js new file mode 100644 index 00000000..ae4a75fd --- /dev/null +++ b/learn/security/_filesets/security-functions.js @@ -0,0 +1,225 @@ +// @chunk {"steps": ["custom-validation"], "when": {"component": "functions"}} +/** + * Custom Security Validation Functions for Redocly + * Implements advanced security checks for OWASP API Security Top 10 2023 + */ + +const SecurityFunctions = { + // @chunk {"steps": ["custom-validation"]} + /** + * Validates that all write operations have properly configured security schemes + * Implements comprehensive cross-operation security validation + */ + checkOperationSecurity: (options) => { + return (root, ctx) => { + const problems = []; + const { methods = ['post', 'put', 'patch', 'delete'], nullable = false } = options; + + // Walk through all paths and operations + for (const [pathName, pathItem] of Object.entries(root.paths || {})) { + for (const method of methods) { + const operation = pathItem[method]; + if (!operation) continue; + + // Check if security is defined and non-empty + const security = operation.security || pathItem.security || root.security; + + if (!security || (Array.isArray(security) && security.length === 0)) { + problems.push(ctx.createProblem({ + message: `${method.toUpperCase()} operation at ${pathName} lacks security requirements`, + location: ctx.location.child(['paths', pathName, method]), + })); + } + + // Validate security scheme references exist + if (security && Array.isArray(security)) { + for (const securityRequirement of security) { + for (const schemeName of Object.keys(securityRequirement)) { + if (!root.components?.securitySchemes?.[schemeName]) { + problems.push(ctx.createProblem({ + message: `Security scheme '${schemeName}' referenced but not defined in components.securitySchemes`, + location: ctx.location.child(['paths', pathName, method, 'security']), + })); + } + } + } + } + } + } + + return problems; + }; + }, + // @chunk-end + + // @chunk {"steps": ["custom-validation"]} + /** + * Validates OAuth scope configurations for administrative operations + * Ensures admin operations require appropriate scopes + */ + validateOAuthScopes: (options) => { + return (root, ctx) => { + const problems = []; + const { + adminOperations = ['delete', 'post', 'put', 'patch'], + requiredAdminScopes = ['admin', 'write', 'manage'], + adminPathPatterns = ['/admin', '/manage', '/config', '/system'] + } = options; + + // Check paths that match admin patterns + for (const [pathName, pathItem] of Object.entries(root.paths || {})) { + const isAdminPath = adminPathPatterns.some(pattern => pathName.includes(pattern)); + + if (isAdminPath) { + for (const method of adminOperations) { + const operation = pathItem[method]; + if (!operation) continue; + + const security = operation.security || pathItem.security || root.security; + if (!security) continue; + + // Check if OAuth security schemes have appropriate scopes + for (const securityRequirement of security) { + for (const [schemeName, scopes] of Object.entries(securityRequirement)) { + const scheme = root.components?.securitySchemes?.[schemeName]; + if (scheme?.type === 'oauth2') { + const hasAdminScope = scopes.some(scope => + requiredAdminScopes.some(adminScope => scope.includes(adminScope)) + ); + + if (!hasAdminScope) { + problems.push(ctx.createProblem({ + message: `Admin operation ${method.toUpperCase()} ${pathName} should require admin scopes (${requiredAdminScopes.join(', ')})`, + location: ctx.location.child(['paths', pathName, method, 'security']), + })); + } + } + } + } + } + } + } + + return problems; + }; + }, + // @chunk-end + + // @chunk {"steps": ["custom-validation"]} + /** + * Validates administrative endpoint security isolation + * Ensures admin endpoints use different security schemes than regular operations + */ + validateAdminSecurity: (options) => { + return (root, ctx) => { + const problems = []; + const { adminUrlPattern = '/admin' } = options; + + const regularSchemes = new Set(); + const adminSchemes = new Set(); + + // Collect security schemes from different endpoint types + for (const [pathName, pathItem] of Object.entries(root.paths || {})) { + const isAdminPath = pathName.includes(adminUrlPattern); + + for (const [method, operation] of Object.entries(pathItem)) { + if (typeof operation !== 'object' || !operation.security) continue; + + for (const securityRequirement of operation.security) { + for (const schemeName of Object.keys(securityRequirement)) { + if (isAdminPath) { + adminSchemes.add(schemeName); + } else { + regularSchemes.add(schemeName); + } + } + } + } + } + + // Check for overlap between admin and regular schemes + const overlap = [...adminSchemes].filter(scheme => regularSchemes.has(scheme)); + if (overlap.length > 0) { + problems.push(ctx.createProblem({ + message: `Admin endpoints share security schemes with regular endpoints: ${overlap.join(', ')}. Consider using separate schemes for admin operations.`, + location: ctx.location.child(['paths']), + })); + } + + return problems; + }; + }, + // @chunk-end + + // @chunk {"steps": ["custom-validation"]} + /** + * Validates rate limiting header consistency across operations + * Ensures consistent rate limiting implementation + */ + validateRateLimitConsistency: (options) => { + return (root, ctx) => { + const problems = []; + const { requiredHeaders = ['RateLimit', 'X-RateLimit-Limit'] } = options; + + const rateLimitHeaders = new Set(); + const inconsistentOperations = []; + + // Collect all rate limiting headers used + for (const [pathName, pathItem] of Object.entries(root.paths || {})) { + for (const [method, operation] of Object.entries(pathItem)) { + if (typeof operation !== 'object' || !operation.responses) continue; + + for (const [statusCode, response] of Object.entries(operation.responses)) { + if (!response.headers) continue; + + const operationRateLimitHeaders = Object.keys(response.headers).filter(header => + requiredHeaders.some(required => header.toLowerCase().includes(required.toLowerCase())) + ); + + if (operationRateLimitHeaders.length > 0) { + if (rateLimitHeaders.size === 0) { + // First operation with rate limit headers - set the standard + operationRateLimitHeaders.forEach(header => rateLimitHeaders.add(header)); + } else { + // Check consistency with established pattern + const currentHeaders = new Set(operationRateLimitHeaders); + const standardHeaders = new Set([...rateLimitHeaders]); + + if (currentHeaders.size !== standardHeaders.size || + [...currentHeaders].some(h => !standardHeaders.has(h))) { + inconsistentOperations.push(`${method.toUpperCase()} ${pathName}`); + } + } + } + } + } + } + + if (inconsistentOperations.length > 0) { + problems.push(ctx.createProblem({ + message: `Inconsistent rate limiting headers found in: ${inconsistentOperations.join(', ')}. Use consistent header naming across all operations.`, + location: ctx.location.child(['paths']), + })); + } + + return problems; + }; + } + // @chunk-end +}; + +// @chunk {"steps": ["custom-validation"]} +// Export functions for Redocly CLI (ES Module syntax) +// Note: In a real implementation, this would be exported as a plugin +// For this demonstration, the export is commented out to avoid loading errors + +/* +export default { + id: 'security', + assertions: SecurityFunctions +}; +*/ + +// For demonstration purposes - functions are available but not loaded as plugin +export { SecurityFunctions }; +// @chunk-end diff --git a/learn/security/api-design-first-security-governance.md b/learn/security/api-design-first-security-governance.md deleted file mode 100644 index cadffa4b..00000000 --- a/learn/security/api-design-first-security-governance.md +++ /dev/null @@ -1,968 +0,0 @@ -# Design-First Security Governance and Automation - -_Scale security practices through automated governance, policy-as-code, and organizational maturity._ - ---- - -## Key Takeaways - -Manual security reviews don't scale. As organizations grow their API portfolios, the traditional approach of reviewing each specification manually becomes a bottleneck that slows development and introduces inconsistencies. Design-first security governance transforms this challenge by encoding security requirements as automated policies that enforce standards across every API, every time. - -In this guide, we'll explore how to implement automated security governance that shifts security left in the development lifecycle, reduces review overhead, and ensures consistent security standards across your entire API ecosystem. - -**We'll cover how to:** -- Transform security requirements into automated governance policies -- Integrate security validation into CI/CD pipelines -- Scale security practices across large development organizations -- Measure and improve security governance effectiveness -- Build organizational security maturity through automation - ---- - -## From Manual Reviews to Automated Governance - -Traditional security approaches treat reviews as gates staffed by humans who check for common issues like missing [authentication](authentication-authorization-openapi.md), weak [input validation](api-input-validation-injection-prevention.md), or insecure [transport](api-tls-encryption-https-best-practices.md). This approach has fundamental limitations: - -- **Doesn't scale**: Review time increases linearly with team size -- **Inconsistent**: Different reviewers catch different issues -- **Reactive**: Problems discovered late in the development cycle -- **Limited coverage**: Humans miss edge cases that machines catch consistently - -### The Policy-as-Code Approach - -Design-first security governance treats security requirements as executable code. Instead of documenting that "all write operations must have [authentication](authentication-authorization-openapi.md)," you write a governance rule that automatically validates this requirement: - -```yaml {% title="security-governance.yaml" %} -rules: - require-auth-on-mutations: - description: "All write operations must have security requirements" - severity: error - given: "$.paths[*][*]" - when: - function: enumerated - functionOptions: - values: ["post", "put", "patch", "delete"] - then: - field: "security" - function: truthy -``` - -When this rule runs in your CI/CD pipeline, any OpenAPI specification that violates the policy fails the build automatically. The developer gets immediate feedback and must fix the issue before the code can be merged. - -### Automated Governance Benefits - -**Consistent Enforcement:** -- Every API specification is validated against the same rules -- No human variation in what gets flagged or missed -- New team members get consistent security feedback - -**Immediate Feedback:** -- Developers learn about security issues within minutes, not days -- Problems are caught before code review, reducing back-and-forth -- Security becomes part of the development flow, not a separate gate - -**Comprehensive Coverage:** -- Machines don't get tired or miss obvious issues -- Complex cross-reference validation that humans struggle with -- Scales to hundreds of APIs without adding review overhead - -## Core Security Governance Principles - -Effective security governance requires well-defined policies that map business security requirements to technical implementation details. These policies should be comprehensive, actionable, and automatically enforceable. - -### Transport Security Governance - -**Enforce HTTPS-Only Server URLs:** -```yaml {% title="governance-rules.yaml" %} -rules: - https-only-servers: - description: "All server URLs must use HTTPS" - severity: error - given: "$.servers[*].url" - then: - function: pattern - functionOptions: - match: "^https://" - message: "Server URLs must use HTTPS for secure transport" -``` - -**Prevent Placeholder Domains in Production:** -```yaml {% title="governance-rules.yaml" %} -rules: - no-placeholder-domains: - description: "Production specs cannot use example.com domains" - severity: error - given: "$.servers[*].url" - then: - function: pattern - functionOptions: - notMatch: "(example\\.com|localhost|127\\.0\\.0\\.1)" - message: "Use actual production domains, not placeholders" -``` - -### Input Validation Governance - -**Require Length Constraints on Strings:** -```yaml {% title="governance-rules.yaml" %} -rules: - string-maxlength-required: - description: "All string properties must have maxLength constraints" - severity: error - given: "$..[?(@.type === 'string')]" - then: - field: "maxLength" - function: truthy - message: "String properties must have maxLength to prevent resource exhaustion" -``` - -**Enforce Numeric Bounds:** -```yaml {% title="governance-rules.yaml" %} -rules: - numeric-bounds-required: - description: "Numeric properties must have minimum and maximum constraints" - severity: error - given: "$..[?(@.type === 'integer' || @.type === 'number')]" - then: - - field: "minimum" - function: truthy - - field: "maximum" - function: truthy - message: "Numeric properties must have bounds to prevent overflow attacks" -``` - -**Prevent Mass Assignment Vulnerabilities:** -```yaml {% title="governance-rules.yaml" %} -rules: - no-additional-properties: - description: "Object schemas must set additionalProperties: false" - severity: error - given: "$..[?(@.type === 'object')]" - then: - field: "additionalProperties" - function: falsy - message: "Set additionalProperties: false to prevent mass assignment attacks" -``` - -### Access Control Governance - -**Require Authentication on Write Operations:** -```yaml {% title="governance-rules.yaml" %} -rules: - auth-required-on-writes: - description: "Write operations must have security requirements" - severity: error - given: "$.paths[*][post,put,patch,delete]" - then: - field: "security" - function: truthy - message: "Write operations must require authentication to prevent unauthorized access" -``` - -**Validate Security Scheme References:** -```yaml {% title="governance-rules.yaml" %} -rules: - valid-security-references: - description: "All security references must have corresponding definitions" - severity: error - given: "$.paths[*][*].security[*]" - then: - function: security-scheme-defined - message: "Security scheme must be defined in components.securitySchemes" -``` - -### Rate Limiting Governance - -**Require Rate Limiting on Authentication Endpoints:** -```yaml {% title="governance-rules.yaml" %} -rules: - rate-limits-on-auth: - description: "[Authentication endpoints](authentication-authorization-openapi.md) must have [rate limiting](api-rate-limiting-abuse-prevention.md) policies" - severity: error - given: "$.paths[*][*]" - when: - - field: "tags" - function: pattern - functionOptions: - match: "(?i)auth" - - field: "@key" - function: pattern - functionOptions: - match: "(post|put)" - then: - field: "x-rateLimit" - function: truthy - message: "Authentication endpoints must have x-rateLimit extension to prevent brute force attacks" -``` - -## Implementing Automated Governance - -### CI/CD Pipeline Integration - -Integrating security governance into your CI/CD pipeline ensures that every API change is automatically validated against your security policies. - -**GitHub Actions Example:** -```yaml {% title=".github/workflows/api-governance.yml" %} -name: API Security Governance - -on: - pull_request: - paths: - - '**/*.yaml' - - '**/*.yml' - - '**/*.json' - -jobs: - security-governance: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - - name: Install governance CLI - run: npm install -g @redocly/cli - - - name: Validate OpenAPI specifications - run: | - find . -name "*.yaml" -o -name "*.yml" | grep -E "(openapi|api)" | while read file; do - echo "Validating $file..." - redocly lint "$file" --config .redocly.yaml - done - - - name: Security governance check - run: | - find . -name "*.yaml" -o -name "*.yml" | grep -E "(openapi|api)" | while read file; do - echo "Security governance check for $file..." - redocly lint "$file" --config security-governance.yaml - done -``` - -**GitLab CI Example:** -```yaml {% title=".gitlab-ci.yml" %} -api-security-governance: - stage: test - image: node:18 - before_script: - - npm install -g @redocly/cli - script: - - | - find . -name "*.yaml" -o -name "*.yml" | grep -E "(openapi|api)" | while read file; do - echo "Validating $file against security policies..." - redocly lint "$file" --config security-governance.yaml - done - rules: - - changes: - - "**/*.yaml" - - "**/*.yml" - - "**/*.json" -``` - -### Governance Configuration Management - -**Complete Security Governance Configuration:** -```yaml {% title="security-governance.yaml" %} -extends: - - recommended - -rules: - # Transport Security - https-only-servers: - severity: error - given: "$.servers[*].url" - then: - function: pattern - functionOptions: - match: "^https://" - - no-placeholder-domains: - severity: error - given: "$.servers[*].url" - then: - function: pattern - functionOptions: - notMatch: "(example\\.com|localhost|127\\.0\\.0\\.1)" - - # Input Validation - string-maxlength-required: - severity: error - given: "$..[?(@.type === 'string')]" - then: - field: "maxLength" - function: truthy - - numeric-bounds-required: - severity: error - given: "$..[?(@.type === 'integer' || @.type === 'number')]" - then: - - field: "minimum" - function: truthy - - field: "maximum" - function: truthy - - no-additional-properties: - severity: error - given: "$..[?(@.type === 'object')]" - then: - field: "additionalProperties" - function: falsy - - # Access Control - auth-required-on-writes: - severity: error - given: "$.paths[*][post,put,patch,delete]" - then: - field: "security" - function: truthy - - # Rate Limiting - rate-limits-on-auth: - severity: warning - given: "$.paths[*][*]" - when: - field: "tags" - function: pattern - functionOptions: - match: "(?i)auth" - then: - field: "x-rateLimit" - function: truthy - - # Documentation Quality - operation-description-required: - severity: warning - given: "$.paths[*][*]" - then: - field: "description" - function: truthy - - response-schema-required: - severity: error - given: "$.paths[*][*].responses[2-3][0-9][0-9]" - then: - field: "content" - function: truthy - -# Custom functions for complex validation -functions: - security-scheme-defined: - code: | - function(targetVal, options, paths, otherValues) { - const schemes = otherValues?.components?.securitySchemes || {}; - for (const requirement of targetVal) { - for (const schemeName in requirement) { - if (!(schemeName in schemes)) { - return [ - { - message: `Security scheme '${schemeName}' is not defined in components.securitySchemes` - } - ]; - } - } - } - return []; - } -``` - -### Progressive Enforcement - -When implementing governance in existing organizations, start with warnings and gradually increase severity to avoid disrupting active development. - -**Phased Implementation Strategy:** - -**Phase 1: Observability (Weeks 1-2)** -```yaml -rules: - auth-required-on-writes: - severity: info # Start with info level - given: "$.paths[*][post,put,patch,delete]" - then: - field: "security" - function: truthy -``` - -**Phase 2: Warnings (Weeks 3-4)** -```yaml -rules: - auth-required-on-writes: - severity: warn # Escalate to warnings - given: "$.paths[*][post,put,patch,delete]" - then: - field: "security" - function: truthy -``` - -**Phase 3: Enforcement (Week 5+)** -```yaml -rules: - auth-required-on-writes: - severity: error # Full enforcement - given: "$.paths[*][post,put,patch,delete]" - then: - field: "security" - function: truthy -``` - -## Organizational Security Maturity - -### API Security Maturity Model - -Organizations typically progress through distinct maturity levels as they build more sophisticated security practices: - -```mermaid -graph TD - A[Level 0: Basic] --> B[Level 1: Structured] --> C[Level 2: Automated] --> D[Level 3: Proactive] - - A --> A1[Manual reviews
Basic HTTPS
Simple auth] - B --> B1[OpenAPI specs
Schema validation
Rate limiting] - C --> C1[Automated governance
CI/CD integration
Policy enforcement] - D --> D1[Threat modeling
Zero-trust architecture
Continuous monitoring] - - style A fill:#ffcdd2 - style B fill:#fff59d - style C fill:#c8e6c9 - style D fill:#a5d6a7 -``` - -*API security maturity progression showing the evolution from basic manual practices to proactive, automated security governance with comprehensive threat detection and prevention.* - -**Level 0 - Basic Security (Manual, Ad-hoc):** -- Manual code reviews for obvious security issues -- HTTPS enabled but not enforced through specifications -- Basic authentication (API keys or simple passwords) -- Ad-hoc security practices without consistent standards -- Security discovered through incident response - -**Level 1 - Structured Security (Documented, Consistent):** -- OpenAPI specifications document all APIs with security requirements -- [Schema-based input validation](api-input-validation-injection-prevention.md) prevents basic injection attacks -- [Rate limiting](api-rate-limiting-abuse-prevention.md) implemented on [authentication](authentication-authorization-openapi.md) and sensitive endpoints -- Consistent security patterns across API teams -- Security reviews are systematic but still manual - -**Level 2 - Automated Security (Policy-as-Code):** -- Automated governance tools enforce security standards in CI/CD pipelines -- Security policies defined as code and validated automatically -- Breaking changes to security configurations fail builds -- Security metrics tracked and monitored systematically -- Governance rules prevent common vulnerabilities automatically - -**Level 3 - Proactive Security (Threat-Aware, Adaptive):** -- Comprehensive threat modeling integrated into the design process -- Zero-trust architecture with [mutual TLS](api-tls-encryption-https-best-practices.md#mutual-tls-mtls-two-way-authentication) for service-to-service communication -- Continuous security monitoring with behavioral analysis and anomaly detection -- Security feedback loops drive iterative improvements to governance policies -- Security practices adapt based on emerging threats and attack patterns - -### Building Governance Teams - -**Security Champions Program:** -Embed security-minded developers in each team rather than centralizing all security knowledge: - -- **Champions**: One security-focused developer per 5-8 person team -- **Training**: Regular security training and threat modeling workshops -- **Responsibility**: Champions help teammates understand and implement governance rules -- **Feedback**: Champions provide feedback on governance rule effectiveness - -**Governance Center of Excellence:** -Create a small, centralized team responsible for governance policy development: - -- **Policy Development**: Create and maintain governance rules -- **Tool Management**: Manage governance tooling and CI/CD integration -- **Training**: Develop security training materials and documentation -- **Metrics**: Track governance effectiveness and security posture improvements - -### Measuring Governance Effectiveness - -**Security Metrics Dashboard:** -```yaml {% title="governance-metrics.yaml" %} -metrics: - governance_adoption: - - specs_with_security_schemes - - specs_with_input_validation - - specs_with_rate_limiting - - specs_passing_all_checks - - vulnerability_prevention: - - accidentally_public_endpoints_prevented - - missing_auth_caught_in_ci - - validation_bypass_attempts_blocked - - governance_rule_violations_per_week - - development_velocity: - - average_security_review_time - - security_feedback_loop_duration - - governance_rule_false_positive_rate - - developer_security_question_frequency -``` - -**Monthly Security Governance Report:** -```markdown -## API Security Governance Report - March 2025 - -### Governance Coverage -- 🟢 **98%** of APIs have authentication requirements defined -- 🟢 **94%** of APIs have input validation constraints -- 🟡 **78%** of APIs have rate limiting policies -- 🔴 **45%** of APIs have comprehensive error handling - -### Vulnerabilities Prevented -- **23** accidentally public endpoints caught in CI/CD -- **67** missing input validation constraints flagged -- **12** insecure server URLs rejected -- **8** undefined security schemes blocked - -### Developer Experience -- **2.3 minutes** average governance check time -- **0.8%** false positive rate on governance rules -- **94%** developer satisfaction with governance feedback - -### Recommendations -1. Increase rate limiting coverage through new governance rules -2. Improve error handling governance with custom validation functions -3. Add governance rules for API versioning consistency -``` - -## Advanced Governance Patterns - -### Context-Aware Validation - -Some security requirements depend on the context in which an API operates. Advanced governance can implement conditional logic: - -```yaml {% title="context-aware-governance.yaml" %} -rules: - external-apis-require-strict-auth: - description: "External APIs must use OAuth2, internal APIs can use API keys" - severity: error - given: "$.paths[*][*]" - when: - field: "tags" - function: pattern - functionOptions: - match: "external" - then: - field: "security[*].oauth2Auth" - function: truthy - message: "External APIs must use OAuth2 authentication" - - pii-endpoints-require-additional-validation: - description: "Endpoints handling PII must have enhanced validation" - severity: error - given: "$.paths[*][*]" - when: - field: "tags" - function: pattern - functionOptions: - match: "(?i)pii|personal" - then: - function: enhanced-pii-validation -``` - -### Custom Validation Functions - -For complex business rules that can't be expressed in standard governance syntax: - -```javascript {% title="custom-functions.js" %} -// Custom function for validating PII handling -function enhancedPiiValidation(targetVal, options, paths, otherValues) { - const errors = []; - - // Check for required audit logging - if (!targetVal['x-audit-logging']) { - errors.push({ - message: "PII endpoints must have x-audit-logging extension" - }); - } - - // Check for data retention policies - if (!targetVal['x-retention-policy']) { - errors.push({ - message: "PII endpoints must specify data retention policy" - }); - } - - // Check for enhanced rate limiting - const rateLimit = targetVal['x-rateLimit']; - if (!rateLimit || rateLimit.limit > 10) { - errors.push({ - message: "PII endpoints must have strict rate limiting (≤10 requests/minute)" - }); - } - - return errors; -} - -// Custom function for validating security scheme consistency -function consistentSecuritySchemes(targetVal, options, paths, otherValues) { - const errors = []; - const allOperations = Object.values(otherValues.paths || {}) - .flatMap(pathItem => Object.values(pathItem)); - - const securitySchemes = new Set(); - allOperations.forEach(operation => { - if (operation.security) { - operation.security.forEach(requirement => { - Object.keys(requirement).forEach(scheme => { - securitySchemes.add(scheme); - }); - }); - } - }); - - // Warn if too many different auth schemes are used - if (securitySchemes.size > 2) { - errors.push({ - message: `API uses ${securitySchemes.size} different auth schemes. Consider standardizing.` - }); - } - - return errors; -} -``` - -### Multi-Environment Governance - -Different environments may require different security standards: - -```yaml {% title="production-governance.yaml" %} -# Strict production rules -extends: - - security-governance.yaml - -rules: - # Production-specific overrides - no-mock-servers: - severity: error - given: "$.servers[*].url" - then: - function: pattern - functionOptions: - notMatch: "(mock|sandbox|test)" - - require-monitoring-extensions: - severity: error - given: "$.paths[*][*]" - then: - field: "x-monitoring" - function: truthy -``` - -```yaml {% title="development-governance.yaml" %} -# More permissive development rules -extends: - - security-governance.yaml - -rules: - # Allow mock servers in development - no-mock-servers: - severity: off - - # Relax some requirements for faster iteration - string-maxlength-required: - severity: warn # Warning instead of error -``` - -## Governance Tooling Ecosystem - -### Popular Governance Tools - -**Spectral:** -```yaml {% title=".spectral.yml" %} -extends: ["@redocly/spectral-config"] -functions: - - custom-security-functions.js -rules: - security-governance: - severity: error - given: "$.paths[*][*]" - then: - function: security-requirements-check -``` - -**Redocly CLI:** -```yaml {% title="redocly.yaml" %} -apis: - main: - root: openapi.yaml - -lint: - extends: - - recommended - rules: - security-governance/auth-required: error - security-governance/https-only: error - security-governance/input-validation: error -``` - -**Custom Governance Scripts:** -```python {% title="governance-check.py" %} -#!/usr/bin/env python3 - -import yaml -import sys -from pathlib import Path - -def check_security_governance(spec_path): - """Check OpenAPI spec against security governance rules""" - with open(spec_path) as f: - spec = yaml.safe_load(f) - - errors = [] - - # Check for HTTPS-only servers - for server in spec.get('servers', []): - if not server['url'].startswith('https://'): - errors.append(f"Server {server['url']} must use HTTPS") - - # Check for auth on write operations - for path, methods in spec.get('paths', {}).items(): - for method in ['post', 'put', 'patch', 'delete']: - if method in methods and 'security' not in methods[method]: - errors.append(f"{method.upper()} {path} missing security requirements") - - # Check for input validation - for schema_name, schema in spec.get('components', {}).get('schemas', {}).items(): - if schema.get('type') == 'object' and schema.get('additionalProperties', True): - errors.append(f"Schema {schema_name} should set additionalProperties: false") - - return errors - -if __name__ == "__main__": - spec_file = sys.argv[1] - errors = check_security_governance(spec_file) - - if errors: - print("❌ Security governance violations found:") - for error in errors: - print(f" - {error}") - sys.exit(1) - else: - print("✅ All security governance checks passed") -``` - -### Integration with API Lifecycle Tools - -**API Design Tools:** -- **Stoplight Studio**: Built-in governance rules and real-time validation -- **SwaggerHub**: Automated governance checks on specification save -- **Insomnia Designer**: Custom governance plugins for design-time validation - -**Code Generation:** -- **OpenAPI Generator**: Generate security middleware from governance-validated specs -- **Speakeasy**: Type-safe SDKs with built-in security handling -- **Fern**: End-to-end API development with governance integration - -**Documentation:** -- **Redoc**: Display governance-validated security requirements clearly -- **Stoplight Elements**: Interactive documentation with security testing -- **Readme.io**: Governance-aware API documentation with security examples - -## Troubleshooting Governance Issues - -### Common Governance Problems - -**False Positives:** -```yaml -# Problem: Rule triggers incorrectly -rules: - auth-required: - given: "$.paths[*][*]" # Too broad - includes OPTIONS, HEAD - then: - field: "security" - function: truthy - -# Solution: More specific selector -rules: - auth-required: - given: "$.paths[*][post,put,patch,delete]" # Only write operations - then: - field: "security" - function: truthy -``` - -**Performance Issues:** -```yaml -# Problem: Complex rules that slow down CI/CD -rules: - expensive-validation: - given: "$..[*]" # Searches entire document - then: - function: complex-custom-function - -# Solution: More targeted selectors -rules: - efficient-validation: - given: "$.paths[*][*].security" # Target specific areas - then: - function: simple-validation-function -``` - -**Rule Conflicts:** -```yaml -# Problem: Rules that contradict each other -rules: - require-oauth2: - given: "$.paths[*][*]" - then: - field: "security[*].oauth2" - function: truthy - - allow-api-keys: - given: "$.paths[*][*]" - then: - field: "security[*].apiKey" - function: truthy - -# Solution: Context-specific rules -rules: - external-apis-oauth2: - given: "$.paths[*][*]" - when: - field: "tags" - function: pattern - functionOptions: - match: "external" - then: - field: "security[*].oauth2" - function: truthy - - internal-apis-flexible: - given: "$.paths[*][*]" - when: - field: "tags" - function: pattern - functionOptions: - match: "internal" - then: - # Allow either oauth2 or apiKey - function: has-any-auth-scheme -``` - -### Debugging Governance Rules - -**Verbose Logging:** -```bash -# Enable detailed governance output -redocly lint openapi.yaml --config security-governance.yaml --verbose - -# Test specific rules -redocly lint openapi.yaml --config security-governance.yaml --rule auth-required-on-writes -``` - -**Rule Testing:** -```yaml {% title="test-governance.yaml" %} -# Create minimal test cases for each rule -rules: - auth-required-test: - description: "Test auth requirement rule" - severity: error - given: "$.paths['/test'][post]" - then: - field: "security" - function: truthy - -# Test with minimal OpenAPI spec ---- -openapi: 3.1.0 -info: - title: Test API - version: 1.0.0 -paths: - /test: - post: - summary: Test endpoint - # Should fail governance check - responses: - '200': - description: Success -``` - -**Rule Validation Workflow:** -```bash -#!/bin/bash -# validate-governance-rules.sh - -echo "Testing governance rules..." - -# Test with known-bad spec (should fail) -if redocly lint test/bad-spec.yaml --config security-governance.yaml > /dev/null 2>&1; then - echo "❌ Governance rules are too permissive" - exit 1 -fi - -# Test with known-good spec (should pass) -if ! redocly lint test/good-spec.yaml --config security-governance.yaml > /dev/null 2>&1; then - echo "❌ Governance rules are too strict" - exit 1 -fi - -echo "✅ Governance rules are working correctly" -``` - -## Best Practices Summary - -### Policy Development -- Start with high-impact, low-controversy rules (HTTPS enforcement, auth on writes) -- Use progressive enforcement: info → warning → error over time -- Test governance rules with both positive and negative test cases -- Document the business rationale for each governance rule - -### Implementation -- Integrate governance checks early in the development process (IDE, pre-commit hooks) -- Provide clear, actionable error messages with examples -- Create escape hatches for legitimate exceptions (with approval process) -- Monitor governance rule effectiveness and false positive rates - -### Organizational Change -- Train developers on security principles, not just governance tool usage -- Establish security champions in each development team -- Create feedback loops to improve governance rules based on developer experience -- Measure and communicate the security improvements from governance - -### Technical Excellence -- Use specific JSONPath selectors to minimize false positives -- Implement custom functions for complex business logic -- Version governance configurations alongside API specifications -- Maintain separate governance rules for different environments - -## Frequently Asked Questions - -### How do I get buy-in for governance automation? -Start with metrics that demonstrate the problem: count manually-found security issues, measure time spent on security reviews, track inconsistencies across teams. Then pilot governance on a single team and measure improvements in both security posture and developer velocity. - -### What's the difference between linting and governance? -Linting typically focuses on style, formatting, and basic structural issues. Governance enforces business rules and security policies that are specific to your organization. Good governance builds on solid linting foundations. - -### How do I handle exceptions to governance rules? -Create an exception process with clear criteria: document the business justification, get security team approval, set expiration dates for temporary exceptions, and track all exceptions for periodic review. - -### Should governance rules be the same across all environments? -No. Production should have the strictest rules, while development environments can be more permissive to enable faster iteration. Use environment-specific governance configurations that inherit from a common base. - -### How do I measure the ROI of governance automation? -Track metrics like: time saved on manual security reviews, number of vulnerabilities caught before production, consistency improvements across teams, and developer satisfaction with security feedback quality. - -## Resources - -### Governance Tools and Standards -- [Spectral](https://stoplight.io/open-source/spectral) - Open-source API linting and governance tool with custom rule support -- [Redocly CLI](https://redocly.com/docs/cli/) - Comprehensive OpenAPI toolchain with built-in governance capabilities -- [OpenAPI Specification](https://spec.openapis.org/oas/v3.1.0) - Official specification for defining governance-friendly API contracts - -### Security Standards and Frameworks -- [OWASP API Security Top 10](https://owasp.org/www-project-api-security/) - Essential security risks that governance should address -- [NIST Cybersecurity Framework](https://www.nist.gov/cyberframework) - Comprehensive framework for organizational security maturity -- [DevSecOps Reference Architecture](https://csrc.nist.gov/Projects/devsecops) - NIST guidance on integrating security into development processes - -### Organizational Change and Maturity -- [API Governance Best Practices](https://swagger.io/resources/articles/api-governance/) - Practical guidance on implementing API governance programs -- [Building Security Champions Programs](https://owasp.org/www-project-security-champions-playbook/) - OWASP playbook for distributed security expertise -- [Measuring DevSecOps Success](https://www.sans.org/white-papers/measuring-devsecops-success/) - Metrics and KPIs for security automation programs - -### Related Security Topics -- [API TLS Encryption and HTTPS Best Practices](api-tls-encryption-https-best-practices.md) - Enforce HTTPS requirements through governance -- [API Input Validation and Injection Prevention](api-input-validation-injection-prevention.md) - Automate validation rule enforcement -- [API Rate Limiting and Abuse Prevention](api-rate-limiting-abuse-prevention.md) - Govern rate limiting policies consistently -- [Authentication and Authorization with OpenAPI](authentication-authorization-openapi.md) - Automate security requirement validation -- [API Security by Design: Complete Guide](index.md) - Overview of all API security domains - ---- - -**Next Steps:** You now have the knowledge to implement comprehensive API security governance. Start with the [API Security by Design: Complete Guide](index.md) to see how all these security domains work together in practice. diff --git a/learn/security/api-input-validation-injection-prevention.md b/learn/security/api-input-validation-injection-prevention.md index a6aef93a..632832e0 100644 --- a/learn/security/api-input-validation-injection-prevention.md +++ b/learn/security/api-input-validation-injection-prevention.md @@ -1,6 +1,12 @@ -# Input Validation and Injection Prevention with OpenAPI +--- +title: Input Validation and Injection Prevention +description: Prevent API injection attacks and mass assignment vulnerabilities using OpenAPI schema validation and automated governance. +seo: + title: Input Validation and Injection Prevention + description: Prevent API injection attacks and mass assignment vulnerabilities using OpenAPI schema validation and automated governance. +--- -_Stop injection attacks using OpenAPI schema validation and automated governance rules that reject malicious data before it reaches your application._ +# Input Validation and Injection Prevention with OpenAPI --- @@ -96,10 +102,12 @@ components: ### Automated Governance for Validation -[Modern API governance tools](api-design-first-security-governance.md) can enforce input validation rules that require string length bounds, numeric ranges, and prevent mass assignment vulnerabilities. +Modern API governance tools can enforce input validation rules that require string length bounds, numeric ranges, and prevent mass assignment vulnerabilities. This governance approach transforms security reviews. Instead of manually checking many properties for missing `maxLength` constraints, automated linting tools handle baseline validation so security teams can focus on strategic concerns like business logic and context-dependent risks. +> **🚀 Interactive Implementation**: Learn to set up comprehensive input validation with our [Automated Security Validation Walkthrough](automated-security-validation-walkthrough), which includes production-ready rules for OWASP API Security Top 10 2023 compliance. + ## Key Security Constraints The most critical schema constraints for API security focus on preventing resource exhaustion and injection attacks: @@ -109,7 +117,7 @@ The most critical schema constraints for API security focus on preventing resour - **`additionalProperties: false`**: Essential for preventing mass assignment attacks - **`pattern`**: Use restrictive regex patterns to block injection payloads -These constraints can be automatically enforced by [governance rules](api-design-first-security-governance.md), ensuring no schema can bypass these fundamental protections. +These constraints can be automatically enforced by governance rules, ensuring no schema can bypass these fundamental protections. ## Common Validation Patterns @@ -373,12 +381,11 @@ Modern validation libraries are highly optimized. The security benefit far outwe - [Burp Suite](https://portswigger.net/burp) - Web application security testing platform ### Related Security Topics -- [API TLS Encryption and HTTPS Best Practices](api-tls-encryption-https-best-practices.md) - Secure data in transit -- [API Rate Limiting and Abuse Prevention](api-rate-limiting-abuse-prevention.md) - Prevent DoS attacks and abuse -- [Authentication and Authorization with OpenAPI](authentication-authorization-openapi.md) - Implement secure access control -- [API Design-First Security Governance and Automation](api-design-first-security-governance.md) - Automate security validation -- [API Security by Design: Complete Guide](index.md) - Overview of all API security domains +- [API TLS Encryption and HTTPS Best Practices](api-tls-encryption-https-best-practices) - Secure data in transit +- [API Rate Limiting and Abuse Prevention](api-rate-limiting-abuse-prevention) - Prevent DoS attacks and abuse +- [Authentication and Authorization with OpenAPI](authentication-authorization-openapi) - Implement secure access control +- [API Security by Design: Complete Guide](/learn/security) - Overview of all API security domains --- -**Next Steps:** Now that you have input validation covered, learn about [API Rate Limiting and Abuse Prevention](api-rate-limiting-abuse-prevention.md) to protect your APIs from denial-of-service attacks and business logic abuse. +**Next Steps:** Now that you have input validation covered, learn about [API Rate Limiting and Abuse Prevention](api-rate-limiting-abuse-prevention) to protect your APIs from denial-of-service attacks and business logic abuse. \ No newline at end of file diff --git a/learn/security/api-rate-limiting-abuse-prevention.md b/learn/security/api-rate-limiting-abuse-prevention.md index 41883990..3c00822b 100644 --- a/learn/security/api-rate-limiting-abuse-prevention.md +++ b/learn/security/api-rate-limiting-abuse-prevention.md @@ -1,6 +1,12 @@ -# Rate Limiting and Abuse Prevention for APIs +--- +title: Rate Limiting and Abuse Prevention +description: Implement API rate limiting strategies to prevent DoS attacks, brute force attempts, and business logic abuse. +seo: + title: Rate Limiting and Abuse Prevention + description: Implement API rate limiting strategies to prevent DoS attacks, brute force attempts, and business logic abuse. +--- -_Prevent DoS attacks, brute force attempts, and business logic abuse through strategic rate limiting policies documented in OpenAPI specifications._ +# Rate Limiting and Abuse Prevention for APIs --- @@ -28,7 +34,7 @@ A single client, whether intentionally malicious or simply due to a bug in its c Rate limiting is a critical control for both security and reliability, directly mitigating several OWASP API Security Top 10 risks: -1. **Security:** It thwarts Denial-of-Service (DoS) attacks by preventing traffic floods, addressing OWASP API4:2023 - Unrestricted Resource Consumption. It also makes brute-force attacks against [authentication endpoints](authentication-authorization-openapi.md) much slower and less effective, reducing the risk of credential stuffing attacks. +1. **Security:** It thwarts Denial-of-Service (DoS) attacks by preventing traffic floods, addressing OWASP API4:2023 - Unrestricted Resource Consumption. It also makes brute-force attacks against [authentication endpoints](authentication-authorization-openapi) much slower and less effective, reducing the risk of credential stuffing attacks. 2. **Business Logic Abuse:** It helps mitigate abuse by preventing bots from scraping data or manipulating business flows, addressing OWASP API6:2023 - Unrestricted Access to Sensitive Business Flows. @@ -75,10 +81,12 @@ paths: ### Automated Governance for Rate Limiting -[API governance tools](api-design-first-security-governance.md) can enforce rules that ensure [authentication endpoints](authentication-authorization-openapi.md) always have rate limiting policies defined. +API governance tools can enforce rules that ensure [authentication endpoints](authentication-authorization-openapi) always have rate limiting policies defined. This approach provides dual benefits: modern API documentation tools automatically display rate limiting extensions in generated documentation, making policies transparent to API consumers, while governance rules ensure sensitive endpoints never lack rate-limiting policies. +> **🔧 Implementation Guide**: See our [Automated Security Validation Walkthrough](automated-security-validation-walkthrough) for step-by-step instructions on implementing rate limiting validation rules, including 429 response validation and header consistency checks. + ## Rate Limiting Implementation Approaches ### Common Algorithm Types @@ -437,12 +445,11 @@ async def make_request(session, url): - [JMeter](https://jmeter.apache.org/) - Comprehensive performance testing with rate limiting scenarios ### Related Security Topics -- [API Input Validation and Injection Prevention](api-input-validation-injection-prevention.md) - Protect APIs from malicious data -- [Authentication and Authorization with OpenAPI](authentication-authorization-openapi.md) - Implement secure access control -- [API TLS Encryption and HTTPS Best Practices](api-tls-encryption-https-best-practices.md) - Secure data in transit -- [API Design-First Security Governance and Automation](api-design-first-security-governance.md) - Automate security validation -- [API Security by Design: Complete Guide](index.md) - Overview of all API security domains +- [API Input Validation and Injection Prevention](api-input-validation-injection-prevention) - Protect APIs from malicious data +- [Authentication and Authorization with OpenAPI](authentication-authorization-openapi) - Implement secure access control +- [API TLS Encryption and HTTPS Best Practices](api-tls-encryption-https-best-practices) - Secure data in transit +- [API Security by Design: Complete Guide](/learn/security) - Overview of all API security domains --- -**Next Steps:** Now that you have rate limiting protection in place, learn about [Authentication and Authorization with OpenAPI](authentication-authorization-openapi.md) to implement comprehensive access control for your APIs. +**Next Steps:** Now that you have rate limiting protection in place, learn about [Authentication and Authorization with OpenAPI](authentication-authorization-openapi) to implement comprehensive access control for your APIs. \ No newline at end of file diff --git a/learn/security/api-tls-encryption-https-best-practices.md b/learn/security/api-tls-encryption-https-best-practices.md index 71faccaf..91b254aa 100644 --- a/learn/security/api-tls-encryption-https-best-practices.md +++ b/learn/security/api-tls-encryption-https-best-practices.md @@ -1,6 +1,12 @@ -# TLS Encryption and HTTPS Best Practices for APIs +--- +title: TLS Encryption and HTTPS Best Practices for APIs +description: Protect data in transit with proper TLS configuration, certificate management, and HTTPS enforcement using OpenAPI security contracts. +seo: + title: TLS Encryption and HTTPS Best Practices for APIs + description: Protect data in transit with proper TLS configuration, certificate management, and HTTPS enforcement using OpenAPI security contracts. +--- -_Protect data in transit with proper TLS configuration, certificate management, and HTTPS enforcement using OpenAPI security contracts._ +# TLS Encryption and HTTPS Best Practices for APIs --- @@ -121,8 +127,6 @@ servers: Modern API governance tools can enforce HTTPS usage through automated validation rules. When integrated into your CI/CD pipeline, automated governance creates security gates. If a developer attempts to commit an OpenAPI file with insecure server URLs, the pipeline fails with a clear error message, preventing insecure configurations from ever reaching production. -> Learn more about implementing comprehensive governance policies in our [API Design-First Security Governance and Automation](api-design-first-security-governance.md) guide. - *Automated governance tools fail CI/CD builds when OpenAPI specifications use HTTP instead of HTTPS, requiring developers to fix security violations before deployment.* ## TLS Configuration Examples @@ -178,7 +182,7 @@ https.createServer(options, app).listen(443); The Heartbleed bug (CVE-2014-0160) was a critical vulnerability in the OpenSSL library, not the TLS protocol itself. It allowed attackers to read up to 64KB of a server's memory by sending a malformed TLS heartbeat request. The server would respond with not only the small payload sent by the attacker but also adjacent memory contents, which could include session cookies, user credentials, and even the server's private encryption keys. -This incident demonstrates a crucial point: security is multi-layered. While an OpenAPI specification can enforce the *intent* of using secure transport (https://), it cannot prevent a runtime vulnerability in the underlying software stack. True "secure by design" requires both [design-time governance](api-design-first-security-governance.md) via OpenAPI linting and runtime security posture management, including diligent vulnerability scanning and patch management. +This incident demonstrates a crucial point: security is multi-layered. While an OpenAPI specification can enforce the *intent* of using secure transport (https://), it cannot prevent a runtime vulnerability in the underlying software stack. True "secure by design" requires both design-time governance via OpenAPI linting and runtime security posture management, including diligent vulnerability scanning and patch management. ```mermaid sequenceDiagram @@ -241,7 +245,7 @@ server { } ``` -> **mTLS Best Practice**: Use mTLS for service-to-service communication and regular TLS + [JWT/OAuth2](authentication-authorization-openapi.md) for client-to-server communication. +> **mTLS Best Practice**: Use mTLS for service-to-service communication and regular TLS + [JWT/OAuth2](authentication-authorization-openapi) for client-to-server communication. ## TLS Monitoring and Troubleshooting @@ -317,11 +321,11 @@ Certificate pinning can improve security by preventing man-in-the-middle attacks - [SSL Labs Server Test](https://www.ssllabs.com/ssltest/) - Online tool for testing TLS configuration ### Related Security Topics -- [API Input Validation and Injection Prevention](api-input-validation-injection-prevention.md) - Protect APIs from malicious data -- [Authentication and Authorization with OpenAPI](authentication-authorization-openapi.md) - Implement secure access control -- [API Rate Limiting and Abuse Prevention](api-rate-limiting-abuse-prevention.md) - Prevent DoS attacks and brute force attempts -- [API Security by Design: Complete Guide](index.md) - Overview of all API security domains +- [API Input Validation and Injection Prevention](api-input-validation-injection-prevention) - Protect APIs from malicious data +- [Authentication and Authorization with OpenAPI](authentication-authorization-openapi) - Implement secure access control +- [API Rate Limiting and Abuse Prevention](api-rate-limiting-abuse-prevention) - Prevent DoS attacks and brute force attempts +- [API Security by Design: Complete Guide](/learn/security) - Overview of all API security domains --- -**Next Steps:** Now that you have secure transport with TLS, learn about [API Input Validation and Injection Prevention](api-input-validation-injection-prevention.md) to protect your APIs from malicious data inputs. +**Next Steps:** Now that you have secure transport with TLS, learn about [API Input Validation and Injection Prevention](api-input-validation-injection-prevention) to protect your APIs from malicious data inputs. \ No newline at end of file diff --git a/learn/security/authentication-authorization-openapi.md b/learn/security/authentication-authorization-openapi.md index 21c9eb9f..2d1d3c23 100644 --- a/learn/security/authentication-authorization-openapi.md +++ b/learn/security/authentication-authorization-openapi.md @@ -1,6 +1,10 @@ -# Authentication and Authorization with OpenAPI - -_Implement secure access control using OpenAPI security schemes and modern authentication patterns._ +--- +title: Authentication and Authorization with OpenAPI +description: Implement secure access control using OpenAPI security schemes and modern authentication patterns. +seo: + title: Authentication and Authorization with OpenAPI + description: Implement secure access control using OpenAPI security schemes and modern authentication patterns. +--- --- @@ -8,12 +12,12 @@ _Implement secure access control using OpenAPI security schemes and modern authe Authentication and authorization form the foundation of API access control. While often used interchangeably, these concepts serve distinct purposes: authentication verifies *who* the user is, while authorization determines *what* they can do. Modern APIs require both layers to prevent unauthorized access and enforce business rules. -In this guide, we'll explore how to use OpenAPI 3.1 security schemes to define robust access control patterns that integrate seamlessly with [automated governance](api-design-first-security-governance.md) and modern authentication providers. +In this guide, we'll explore how to use OpenAPI 3.1 security schemes to define robust access control patterns that integrate seamlessly with automated governance and modern authentication providers. **We'll cover how to:** - Define JWT Bearer token authentication in OpenAPI specifications - Implement OAuth2 with granular scope-based authorization -- Enforce security requirements through [automated governance](api-design-first-security-governance.md) +- Enforce security requirements through automated governance - Configure API gateways from OpenAPI security definitions - Monitor and troubleshoot authentication and authorization failures @@ -210,7 +214,7 @@ paths: ### Mutual TLS (mTLS) for Service Authentication -For high-security environments and service-to-service communication, [mutual TLS](api-tls-encryption-https-best-practices.md#mutual-tls-mtls-two-way-authentication) provides cryptographic identity verification. +For high-security environments and service-to-service communication, [mutual TLS](api-tls-encryption-https-best-practices#mutual-tls-mtls-two-way-authentication) provides cryptographic identity verification. ```yaml {% title="openapi.yaml" %} components: @@ -234,7 +238,7 @@ paths: ## Automated Governance for Access Control -One of the most common API vulnerabilities is the accidentally public endpoint—an operation that should require authentication but doesn't have security requirements defined. [Automated governance](api-design-first-security-governance.md) prevents this by enforcing security rules during development. +One of the most common API vulnerabilities is the accidentally public endpoint—an operation that should require authentication but doesn't have security requirements defined. Automated governance prevents this by enforcing security rules during development. ### Security Governance Rules @@ -783,12 +787,11 @@ OpenAPI security schemes handle authentication and basic authorization (scopes/r - [OAuth2 Security Best Practices](https://tools.ietf.org/html/draft-ietf-oauth-security-topics) - Latest security recommendations for OAuth2 implementations ### Related Security Topics -- [API TLS Encryption and HTTPS Best Practices](api-tls-encryption-https-best-practices.md) - Secure data in transit with mTLS -- [API Input Validation and Injection Prevention](api-input-validation-injection-prevention.md) - Protect APIs from malicious data -- [API Rate Limiting and Abuse Prevention](api-rate-limiting-abuse-prevention.md) - Prevent brute force attacks on auth endpoints -- [API Design-First Security Governance and Automation](api-design-first-security-governance.md) - Automate auth requirement validation -- [API Security by Design: Complete Guide](index.md) - Overview of all API security domains +- [API TLS Encryption and HTTPS Best Practices](api-tls-encryption-https-best-practices) - Secure data in transit with mTLS +- [API Input Validation and Injection Prevention](api-input-validation-injection-prevention) - Protect APIs from malicious data +- [API Rate Limiting and Abuse Prevention](api-rate-limiting-abuse-prevention) - Prevent brute force attacks on auth endpoints +- [API Security by Design: Complete Guide](/learn/security) - Overview of all API security domains --- -**Next Steps:** Now that you have authentication and authorization in place, learn about [API Design-First Security Governance and Automation](api-design-first-security-governance.md) to automate the validation of security requirements across your entire API ecosystem. +**Next Steps:** Now that you have authentication and authorization in place, explore the complete [API Security by Design guide](/learn/security) to learn about other essential security domains like TLS encryption, input validation, and rate limiting. \ No newline at end of file diff --git a/learn/security/automated-security-validation-walkthrough.md b/learn/security/automated-security-validation-walkthrough.md new file mode 100644 index 00000000..a3370d1c --- /dev/null +++ b/learn/security/automated-security-validation-walkthrough.md @@ -0,0 +1,123 @@ +--- +title: "Automated API Security Validation - Interactive Walkthrough" +description: "Learn to implement OWASP API Security Top 10 2023 rules using interactive Redocly security validation configurations with step-by-step guidance." +seo: + title: "Automated API Security Validation - Interactive Walkthrough" + description: "Learn to implement OWASP API Security Top 10 2023 rules using interactive Redocly security validation configurations with step-by-step guidance." +--- + +# Automated API Security Validation - Interactive Walkthrough + +*Transform your API security from manual reviews to automated enforcement using production-ready validation rules.* + +--- + +## What You'll Learn + +This interactive walkthrough guides you through implementing **automated security validation** that enforces the **OWASP API Security Top 10 2023** using Redocly's validation engine. By the end, you'll have a complete security ruleset that prevents vulnerabilities before they reach production. + +**You'll master:** +- Setting up comprehensive security validation rules +- Automating OWASP API Security Top 10 2023 compliance +- Implementing custom security validation functions +- Integrating security checks into CI/CD pipelines +- Troubleshooting common validation issues + +--- + +{% code-walkthrough + filesets=[ + { + "files": ["./_filesets/basic-security.yaml"], + "when": { + "approach": "basic" + } + }, + { + "files": ["./_filesets/example-api.yaml"], + "when": { + "approach": "complete" + } + } + ], + filters={ + "approach": { + "label": "Implementation Approach", + "items": [ + {"value": "basic"}, + {"value": "complete"} + ] + } + } +%} + +## Security Validation Foundation + +{% step id="basic-setup" heading="Basic Security Configuration" when={"approach": "basic"} %} + +The basic configuration provides essential security rules for getting started with API validation: + +- **Core Security Rules**: Ensures security schemes are defined +- **Response Validation**: Requires proper HTTP response codes +- **Built-in Protections**: Leverages Redocly's built-in security checks + +This starter configuration is perfect for teams new to automated security validation. + +{% /step %} + +{% step id="api-example" heading="Example API Specification" when={"approach": "complete"} %} + +This example OpenAPI specification demonstrates proper security implementation following validation best practices: + +**Security Best Practices:** +- HTTPS-only server URLs +- UUID-based IDs to prevent enumeration +- Comprehensive security schemes with JWT/OAuth2 +- Proper input validation with string length limits +- Rate limiting headers in all responses +- Complete error response definitions +- `additionalProperties: false` to prevent mass assignment + +Use this as a reference when implementing your own secure APIs. + +{% /step %} + +{% /code-walkthrough %} + +--- + +## Implementation Strategy + +Implementing automated security validation is an iterative process. Here's a recommended approach: + +**Phase 1: Foundation (Weeks 1-2)** +- Implement basic built-in rules +- Set up HTTPS enforcement and basic authentication checks +- Integrate into CI/CD pipeline with warning-level severity + +**Phase 2: Core Security (Weeks 3-4)** +- Add input validation and resource consumption rules +- Implement mass assignment prevention +- Escalate critical rules to error-level severity + +--- + +## Next Steps and Resources + +### **Immediate Actions** +1. **Download the configuration files** using the code walkthrough above +2. **Start with basic approach** if you're new to API security validation +3. **Test in development** before enforcing in production +4. **Customize rules** based on your specific security requirements + +### **Integration with Security Articles** +This validation walkthrough complements our other security guides: + +- **[TLS Encryption Best Practices](api-tls-encryption-https-best-practices)** - Implement the HTTPS enforcement rules +- **[Input Validation Guide](api-input-validation-injection-prevention)** - Apply the resource consumption and schema validation rules +- **[Rate Limiting Guide](api-rate-limiting-abuse-prevention)** - Use the rate limiting validation rules +- **[Authentication Guide](authentication-authorization-openapi)** - Implement the authentication and authorization rules + +--- + +**🔐 Security Note**: This walkthrough provides comprehensive coverage of OWASP API Security Top 10 2023. For production deployment, review each rule's severity level and customize based on your organization's risk tolerance and compliance requirements. diff --git a/learn/security/index.md b/learn/security/index.md index b5d22291..d5b8113c 100644 --- a/learn/security/index.md +++ b/learn/security/index.md @@ -118,20 +118,6 @@ Each security domain requires specific knowledge and implementation techniques. **Perfect for:** Identity and access management teams, full-stack developers, and security engineers ---- - -### API Design-First Security Governance and Automation -**What you'll learn:** Scale security practices through automated governance, policy-as-code, and organizational maturity. - -**Key topics:** -- API security governance principles and automation -- CI/CD integration for security validation -- Security policy-as-code implementation -- API security maturity model and progression strategies -- Monitoring, observability, and continuous improvement - -**Perfect for:** API platform teams, security architects, and engineering leadership - ## Understanding Design-Time vs Runtime Security It's important to understand that OpenAPI-based security governance operates at **design-time**, not runtime. This governance approach excels at preventing configuration errors, missing security controls, and specification inconsistencies before they reach production. That said, it cannot prevent runtime vulnerabilities in the underlying implementation. diff --git a/learn/security/sidebars.yaml b/learn/security/sidebars.yaml index a0fb57c7..260b0ef3 100644 --- a/learn/security/sidebars.yaml +++ b/learn/security/sidebars.yaml @@ -5,5 +5,5 @@ - page: ./api-input-validation-injection-prevention.md - page: ./api-rate-limiting-abuse-prevention.md - page: ./authentication-authorization-openapi.md - - page: ./api-design-first-security-governance.md + - page: ./automated-security-validation-walkthrough.md - page: ./api-design-first-security-guide.md From e2c5dd3cf843bc3d5489c4011f5bca22a001c6ee Mon Sep 17 00:00:00 2001 From: Matt Williams Date: Wed, 24 Sep 2025 14:33:42 -0500 Subject: [PATCH 08/27] Add originals folder with production-ready security files - Add originals/redocly.yaml: Clean production version without chunk annotations - Add originals/security-functions.ts: TypeScript implementation of custom security validation functions - Includes 4 advanced security validation functions: checkOperationSecurity, validateAdminSecurity, validateOAuthScopes, validateRateLimitConsistency --- .../security/_filesets/originals/redocly.yaml | 505 ++++++++++++++++++ .../_filesets/originals/security-functions.ts | 239 +++++++++ 2 files changed, 744 insertions(+) create mode 100644 learn/security/_filesets/originals/redocly.yaml create mode 100644 learn/security/_filesets/originals/security-functions.ts diff --git a/learn/security/_filesets/originals/redocly.yaml b/learn/security/_filesets/originals/redocly.yaml new file mode 100644 index 00000000..e83beb0d --- /dev/null +++ b/learn/security/_filesets/originals/redocly.yaml @@ -0,0 +1,505 @@ +# Redocly Security Ruleset +# Based on OWASP API Security Top 10 2023 +# https://owasp.org/www-project-api-security/ + +plugins: + - './security-functions.js' + + +# Enable built-in security rules +rules: + # Built-in Redocly security rules + security-defined: error + operation-4xx-response: error + operation-2xx-response: error + no-unresolved-refs: error + + # ========================================== + # API1:2023 - Broken Object Level Authorization + # ========================================== + + # Prevent numeric IDs that can be easily guessed + rule/no-numeric-ids: + subject: + type: Schema + property: type + filterInParentKeys: [path] + where: + - subject: + type: Parameter + property: name + assertions: + pattern: /(^id$|_id$|Id$|-id$)/ + assertions: + enum: [string] + message: "Use random IDs that cannot be guessed (UUIDs are preferred). Avoid integer IDs in path parameters." + severity: error + + # Ensure ID parameters use appropriate formats + rule/id-format-required: + subject: + type: Schema + property: format + filterInParentKeys: [path] + where: + - subject: + type: Parameter + property: name + assertions: + pattern: /(^id$|_id$|Id$|-id$)/ + assertions: + enum: [uuid, uri, password] + message: "ID parameters should specify a secure format like 'uuid'." + severity: warn + + # ========================================== + # API2:2023 - Broken Authentication + # ========================================== + + # Enforce HTTPS for all server URLs + rule/https-server-urls: + subject: + type: Server + property: url + assertions: + pattern: /^https:/ + message: "Server URLs must use HTTPS protocol. HTTP is insecure and exposes data to interception." + severity: error + + # Prevent HTTP Basic authentication + rule/no-http-basic-auth: + subject: + type: SecurityScheme + property: scheme + where: + - subject: + type: SecurityScheme + property: type + assertions: + const: http + assertions: + notPattern: /^basic$/i + message: "HTTP Basic authentication is insecure. Use OAuth 2.0, API keys in headers, or other secure methods." + severity: error + + # Prevent API keys in URL (query/path) + rule/no-api-keys-in-url: + subject: + type: SecurityScheme + property: in + where: + - subject: + type: SecurityScheme + property: type + assertions: + const: apiKey + assertions: + enum: [header, cookie] + message: "API keys must not be in URL (query or path parameters). Use headers or cookies instead." + severity: error + + # Prevent credentials in parameter names + rule/no-credentials-in-parameters: + subject: + type: Parameter + property: name + filterInParentKeys: [query, path] + assertions: + notPattern: /(secret|token|access.?token|refresh.?token|id.?token|password|api.?key|credential)/i + message: "Parameter names must not contain credential-related terms. Use secure authentication headers instead." + severity: error + + # Ensure write operations are protected + rule/write-operations-secured: + subject: + type: Operation + property: security + filterInParentKeys: [post, put, patch, delete] + assertions: + defined: true + nonEmpty: true + message: "Write operations (POST, PUT, PATCH, DELETE) must be protected by security schemes." + severity: error + + # JWT bearer format security schemes should reference RFC8725 + rule/jwt-rfc8725-compliance: + subject: + type: SecurityScheme + property: description + where: + - subject: + type: SecurityScheme + property: bearerFormat + assertions: + pattern: /jwt/i + assertions: + pattern: /RFC\s*8725/i + message: "JWT security schemes must reference RFC8725 compliance in description for security best practices." + severity: error + + # Advanced cross-operation security validation (requires custom functions) + rule/comprehensive-security-check: + subject: + type: Root + assertions: + security/checkOperationSecurity: + methods: [post, put, patch, delete] + nullable: false + message: "All write operations must have properly configured security schemes" + severity: error + + # ========================================== + # API3:2023 - Broken Object Property Level Authorization + # ========================================== + + # Prevent unconstrained additionalProperties + rule/no-additional-properties: + subject: + type: Schema + property: additionalProperties + where: + - subject: + type: Schema + property: type + assertions: + const: object + assertions: + const: false + message: "Objects should not allow additionalProperties. Set to false to prevent mass assignment vulnerabilities." + severity: warn + + # Require maxProperties when additionalProperties is not false + rule/constrained-additional-properties: + subject: + type: Schema + property: maxProperties + where: + - subject: + type: Schema + property: type + assertions: + const: object + - subject: + type: Schema + property: additionalProperties + assertions: + defined: true + notPattern: /^false$/ + assertions: + defined: true + message: "Objects with additionalProperties should define maxProperties to limit resource consumption." + severity: warn + + # ========================================== + # API4:2023 - Unrestricted Resource Consumption + # ========================================== + + # Require rate limiting headers in responses + rule/rate-limit-headers-present: + subject: + type: Header + where: + - subject: + type: Response + filterInParentKeys: ["200", "201", "202", "204", "400", "401", "403", "404", "422", "429"] + assertions: + defined: true + assertions: + pattern: /^(RateLimit|RateLimit-Limit|X-RateLimit-Limit|X-Rate-Limit-Limit)$/i + message: "2XX and 4XX responses should include rate limiting headers (RateLimit, RateLimit-Limit, X-RateLimit-Limit, or X-Rate-Limit-Limit)." + severity: warn + + # Require 429 Too Many Requests response + rule/require-429-response: + subject: + type: Responses + property: "429" + assertions: + defined: true + message: "Operations should define a 429 (Too Many Requests) response for rate limiting." + severity: warn + + # Retry-After header required for 429 responses + rule/retry-after-header-429: + subject: + type: Header + where: + - subject: + type: Response + filterInParentKeys: ["429"] + assertions: + defined: true + assertions: + pattern: /^Retry-After$/i + message: "429 responses must include a Retry-After header to indicate when clients can retry." + severity: error + + # Array schemas must specify maxItems + rule/array-max-items: + subject: + type: Schema + property: maxItems + where: + - subject: + type: Schema + property: type + assertions: + const: array + assertions: + defined: true + message: "Array schemas must specify maxItems to prevent resource exhaustion attacks." + severity: error + + # String schemas must have length constraints + rule/string-length-limit: + subject: + type: Schema + where: + - subject: + type: Schema + property: type + assertions: + const: string + assertions: + requireAny: + - maxLength + - enum + - const + - pattern + message: "String schemas must specify maxLength, enum, const, or pattern to limit resource consumption." + severity: error + + # Integer schemas must have min/max constraints + rule/integer-constraints: + subject: + type: Schema + where: + - subject: + type: Schema + property: type + assertions: + const: integer + assertions: + required: [minimum, maximum] + message: "Integer schemas must specify minimum and maximum values to prevent resource exhaustion." + severity: error + + # Integer schemas should specify format + rule/integer-format: + subject: + type: Schema + property: format + where: + - subject: + type: Schema + property: type + assertions: + const: integer + assertions: + enum: [int32, int64] + message: "Integer schemas should specify format (int32 or int64) for precise validation." + severity: warn + + # Advanced rate limiting consistency validation (requires custom functions) + rule/rate-limit-consistency: + subject: + type: Root + assertions: + security/validateRateLimitConsistency: + requiredHeaders: [RateLimit, X-RateLimit-Limit, X-Rate-Limit-Limit] + message: "Rate limiting configurations should be consistent across operations" + severity: warn + + # ========================================== + # API5:2023 - Broken Function Level Authorization + # ========================================== + + # Administrative endpoints should have stricter security + rule/admin-endpoints-secured: + subject: + type: Operation + property: security + where: + - subject: + type: PathItem + assertions: + pattern: /(admin|manage|control|configure)/i + assertions: + defined: true + nonEmpty: true + message: "Administrative endpoints must have defined security schemes with appropriate authorization levels." + severity: error + + # Advanced admin security isolation validation (requires custom functions) + rule/admin-security-isolation: + subject: + type: Root + assertions: + security/validateAdminSecurity: + adminUrlPattern: "/admin" + message: "Administrative endpoints must use different security schemes than regular operations" + severity: error + + # Advanced OAuth scope validation (requires custom functions) + rule/oauth-scope-validation: + subject: + type: Root + assertions: + security/validateOAuthScopes: + adminOperations: [delete, post, put, patch] + requiredAdminScopes: [admin, write, manage] + adminPathPatterns: ["/admin", "/manage", "/config", "/system"] + message: "OAuth scopes must be appropriate for operation sensitivity" + severity: error + + # ========================================== + # API7:2023 - Server Side Request Forgery + # ========================================== + + # Warn about URL parameters that might lead to SSRF + rule/ssrf-url-parameters: + subject: + type: Parameter + property: name + assertions: + notPattern: /(callback|redirect|url|uri|endpoint|webhook|fetch|proxy)/i + message: "URL-related parameters may be vulnerable to Server Side Request Forgery. Ensure proper validation and allowlisting." + severity: warn + + # ========================================== + # API8:2023 - Security Misconfiguration + # ========================================== + + # Require CORS headers in responses + rule/cors-access-control-allow-origin: + subject: + type: Header + where: + - subject: + type: Response + assertions: + defined: true + assertions: + pattern: /^Access-Control-Allow-Origin$/i + message: "Responses should define CORS headers (Access-Control-Allow-Origin) to control cross-origin access." + severity: warn + + # Require error response schemas (400, 401, 403, 500) + rule/error-responses-defined: + subject: + type: Responses + assertions: + requireAny: ["400", "401", "403", "422", "4XX"] + message: "Operations should define appropriate error responses (400, 401, 403, 422, or 4XX) with proper schemas." + severity: warn + + # Require 401 unauthorized responses for secured operations + rule/unauthorized-response-required: + subject: + type: Responses + property: "401" + where: + - subject: + type: Operation + property: security + assertions: + defined: true + assertions: + defined: true + message: "Secured operations should define 401 (Unauthorized) responses." + severity: warn + + # Require 500 server error responses + rule/server-error-response: + subject: + type: Responses + property: "500" + assertions: + defined: true + message: "Operations should define 500 (Internal Server Error) responses to handle server errors gracefully." + severity: warn + + # ========================================== + # API9:2023 - Improper Inventory Management + # ========================================== + + # Server objects should declare internal/external audience + rule/server-audience-declaration: + subject: + type: Server + property: x-internal + assertions: + defined: true + enum: ['true', 'false'] + message: "Servers should declare their intended audience using x-internal (true for internal, false for external)." + severity: error + + # Server descriptions should indicate environment + rule/server-environment-declaration: + subject: + type: Server + property: description + assertions: + pattern: /(local|dev|development|test|testing|stage|staging|prod|production|live|sandbox)/i + message: "Server descriptions should clearly indicate the environment (development, testing, staging, production)." + severity: error + + # API version should be clearly defined + rule/api-version-defined: + subject: + type: Info + property: version + assertions: + defined: true + pattern: /^\d+\.\d+\.\d+/ + message: "API version should be clearly defined using semantic versioning (e.g., 1.0.0)." + severity: error + + # ========================================== + # Additional Security Rules + # ========================================== + + # Prevent sensitive data in examples + rule/no-sensitive-data-in-examples: + subject: + type: Schema + property: example + assertions: + notPattern: /(password|secret|token|key|credential|ssn|social.?security|credit.?card|api.?key)/i + message: "Examples should not contain sensitive data like passwords, tokens, or personal information." + severity: warn + + # Ensure request bodies have proper content types + rule/secure-content-types: + subject: + type: MediaType + where: + - subject: + type: RequestBody + assertions: + defined: true + assertions: + enum: + - application/json + - application/xml + - application/x-www-form-urlencoded + - multipart/form-data + - text/plain + message: "Use secure and well-defined content types. Avoid allowing arbitrary content types." + severity: warn + + # Prevent overly broad schemas + rule/no-empty-schemas: + subject: + type: Schema + assertions: + requireAny: + - type + - properties + - items + - allOf + - anyOf + - oneOf + - $ref + message: "Schemas should not be empty. Define proper constraints to prevent accepting arbitrary data." + severity: error diff --git a/learn/security/_filesets/originals/security-functions.ts b/learn/security/_filesets/originals/security-functions.ts new file mode 100644 index 00000000..9e91d6ae --- /dev/null +++ b/learn/security/_filesets/originals/security-functions.ts @@ -0,0 +1,239 @@ +// Custom security validation functions for Redocly +// These implement the advanced security checks from the Spectral OWASP ruleset + +export default function securityPlugin() { + return { + id: 'security', + assertions: { + // Validates that operations have appropriate security based on HTTP method + checkOperationSecurity: (openapi, options, ctx) => { + const errors = []; + const { methods = [], nullable = false } = options; + const { paths, security: globalSecurity } = openapi; + + if (!paths || typeof paths !== 'object') { + return errors; + } + + // Iterate through all operations + for (const [pathKey, pathItem] of Object.entries(paths)) { + if (!pathItem || typeof pathItem !== 'object') continue; + + const httpMethods = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']; + + for (const method of httpMethods) { + const operation = pathItem[method]; + if (!operation || typeof operation !== 'object') continue; + + // Skip if method not in configured methods list + if (methods.length > 0 && !methods.includes(method)) continue; + + let operationSecurity = operation.security; + + // Fall back to global security if operation security not defined + if (operationSecurity === undefined) { + operationSecurity = globalSecurity; + } + + // Check if security is properly defined + if (!operationSecurity || operationSecurity.length === 0) { + errors.push({ + message: `${method.toUpperCase()} operation at ${pathKey} has no security scheme defined`, + location: ctx.baseLocation.child(['paths', pathKey, method, 'security']), + }); + continue; + } + + // Validate each security requirement + if (Array.isArray(operationSecurity)) { + for (const [idx, securityEntry] of operationSecurity.entries()) { + if (typeof securityEntry !== 'object') continue; + + const securitySchemeIds = Object.keys(securityEntry); + if (securitySchemeIds.length === 0 && !nullable) { + errors.push({ + message: `${method.toUpperCase()} operation at ${pathKey} has empty security requirement at index ${idx}`, + location: ctx.baseLocation.child(['paths', pathKey, method, 'security', idx]), + }); + } + } + } + } + } + + return errors; + }, + + // Ensures admin endpoints use different security schemes than regular endpoints + validateAdminSecurity: (openapi, options, ctx) => { + const errors = []; + const { adminUrlPattern = '/admin' } = options; + const { paths } = openapi; + + if (!paths || typeof paths !== 'object') { + return errors; + } + + const nonAdminSecurityHashes = new Set(); + const adminSecurityEntries = []; + + // First pass: collect all security configurations + for (const [pathKey, pathItem] of Object.entries(paths)) { + if (!pathItem || typeof pathItem !== 'object') continue; + + const httpMethods = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']; + + for (const method of httpMethods) { + const operation = pathItem[method]; + if (!operation || typeof operation !== 'object') continue; + + const operationSecurity = operation.security; + if (!operationSecurity || !Array.isArray(operationSecurity)) continue; + + // Create hash of security configuration for comparison + const securityHash = JSON.stringify(operationSecurity); + + if (pathKey.includes(adminUrlPattern)) { + adminSecurityEntries.push({ + path: pathKey, + method, + hash: securityHash, + location: ctx.baseLocation.child(['paths', pathKey, method, 'security']), + }); + } else { + nonAdminSecurityHashes.add(securityHash); + } + } + } + + // Second pass: validate admin endpoints use unique security + for (const adminEntry of adminSecurityEntries) { + if (nonAdminSecurityHashes.has(adminEntry.hash)) { + errors.push({ + message: `Admin endpoint ${adminEntry.path} (${adminEntry.method.toUpperCase()}) uses the same security scheme as non-admin endpoints. Admin operations should have stricter authentication.`, + location: adminEntry.location, + }); + } + } + + return errors; + }, + + // Validates OAuth scopes are appropriate for operation sensitivity + validateOAuthScopes: (openapi, options, ctx) => { + const errors = []; + const { + adminOperations = ['delete', 'post', 'put', 'patch'], + requiredAdminScopes = ['admin', 'write', 'manage'], + adminPathPatterns = ['/admin', '/manage', '/config'] + } = options; + + const { paths, components } = openapi; + + if (!paths || !components?.securitySchemes) { + return errors; + } + + // Find OAuth2 security schemes + const oauthSchemes = Object.entries(components.securitySchemes) + .filter(([_, scheme]) => scheme.type === 'oauth2') + .map(([name, _]) => name); + + if (oauthSchemes.length === 0) return errors; + + for (const [pathKey, pathItem] of Object.entries(paths)) { + if (!pathItem || typeof pathItem !== 'object') continue; + + const isAdminPath = adminPathPatterns.some(pattern => pathKey.includes(pattern)); + + for (const method of adminOperations) { + const operation = pathItem[method]; + if (!operation || typeof operation !== 'object') continue; + + const operationSecurity = operation.security; + if (!operationSecurity || !Array.isArray(operationSecurity)) continue; + + // Check if this operation uses OAuth and has appropriate scopes + for (const securityReq of operationSecurity) { + for (const [schemeName, scopes] of Object.entries(securityReq)) { + if (oauthSchemes.includes(schemeName)) { + const hasAdminScope = requiredAdminScopes.some(scope => + Array.isArray(scopes) && scopes.includes(scope) + ); + + if ((isAdminPath || adminOperations.includes(method)) && !hasAdminScope) { + errors.push({ + message: `${method.toUpperCase()} operation at ${pathKey} should require admin scopes (${requiredAdminScopes.join(', ')}) for sensitive operations`, + location: ctx.baseLocation.child(['paths', pathKey, method, 'security']), + }); + } + } + } + } + } + } + + return errors; + }, + + // Validates rate limiting configuration consistency + validateRateLimitConsistency: (openapi, options, ctx) => { + const errors = []; + const { requiredHeaders = ['RateLimit', 'X-RateLimit-Limit'] } = options; + const { paths } = openapi; + + if (!paths || typeof paths !== 'object') { + return errors; + } + + const rateLimitConfigs = new Map(); + + // Collect all rate limiting configurations + for (const [pathKey, pathItem] of Object.entries(paths)) { + if (!pathItem || typeof pathItem !== 'object') continue; + + const httpMethods = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options']; + + for (const method of httpMethods) { + const operation = pathItem[method]; + if (!operation?.responses) continue; + + for (const [statusCode, response] of Object.entries(operation.responses)) { + if (!statusCode.match(/^[24]/)) continue; // Only 2xx and 4xx responses + + const headers = response.headers || {}; + const hasRateLimit = requiredHeaders.some(header => headers[header]); + + if (hasRateLimit) { + const config = requiredHeaders + .filter(header => headers[header]) + .map(header => ({ header, schema: headers[header] })); + + const configKey = `${pathKey}:${method}`; + rateLimitConfigs.set(configKey, config); + } + } + } + } + + // Validate consistency across operations + const configValues = Array.from(rateLimitConfigs.values()); + if (configValues.length > 1) { + const firstConfig = JSON.stringify(configValues[0]); + + for (const [pathMethod, config] of rateLimitConfigs.entries()) { + if (JSON.stringify(config) !== firstConfig) { + const [path, method] = pathMethod.split(':'); + errors.push({ + message: `Rate limiting configuration at ${path} (${method.toUpperCase()}) differs from other operations. Consider using consistent rate limiting headers across your API.`, + location: ctx.baseLocation.child(['paths', path, method, 'responses']), + }); + } + } + } + + return errors; + } + }, + }; +} From 2101172781be8bc3227f7fdd172a11d2ba6647bc Mon Sep 17 00:00:00 2001 From: Matt Williams Date: Thu, 25 Sep 2025 11:16:04 -0500 Subject: [PATCH 09/27] Clean up filesets directory and update walkthrough files - Remove original files from _filesets (moved to originals/ folder) - Update automated-security-validation-walkthrough.md - Add new walkthrough versions: automated-security-validation-walkthrough-v2.md and test-simple-walkthrough.md - Update learning center cards and root redocly.yaml configuration --- learn/security/_filesets/README.md | 26 - learn/security/_filesets/basic-security.yaml | 78 --- learn/security/_filesets/example-api.yaml | 137 ----- learn/security/_filesets/package.json | 45 -- learn/security/_filesets/redocly.yaml | 524 ------------------ .../security/_filesets/security-functions.js | 225 -------- ...ated-security-validation-walkthrough-v2.md | 122 ++++ ...tomated-security-validation-walkthrough.md | 2 +- learn/security/test-simple-walkthrough.md | 20 + pages/learning-center/cards.ts | 2 +- redocly.yaml | 1 + 11 files changed, 145 insertions(+), 1037 deletions(-) delete mode 100644 learn/security/_filesets/README.md delete mode 100644 learn/security/_filesets/basic-security.yaml delete mode 100644 learn/security/_filesets/example-api.yaml delete mode 100644 learn/security/_filesets/package.json delete mode 100644 learn/security/_filesets/redocly.yaml delete mode 100644 learn/security/_filesets/security-functions.js create mode 100644 learn/security/automated-security-validation-walkthrough-v2.md create mode 100644 learn/security/test-simple-walkthrough.md diff --git a/learn/security/_filesets/README.md b/learn/security/_filesets/README.md deleted file mode 100644 index 6d7eac55..00000000 --- a/learn/security/_filesets/README.md +++ /dev/null @@ -1,26 +0,0 @@ -# API Security Validation Configuration Files - -This directory contains the configuration files used in the Interactive Security Validation Walkthrough. - -## Files - -- **`redocly.yaml`** - Complete OWASP API Security Top 10 2023 ruleset -- **`basic-security.yaml`** - Simplified starter configuration -- **`security-functions.js`** - Custom JavaScript validation functions -- **`package.json`** - Package configuration and npm scripts - -## Usage - -1. Choose your approach (Basic or Complete) in the walkthrough -2. Download the appropriate configuration files -3. Follow the implementation guide in the walkthrough -4. Customize rules based on your specific security requirements - -## Integration - -These files are designed to work with: -- Redocly CLI v1.0.0+ -- OpenAPI 3.0+ specifications -- CI/CD pipelines (GitHub Actions, GitLab CI, etc.) - -For detailed usage instructions, see the Interactive Security Validation Walkthrough. diff --git a/learn/security/_filesets/basic-security.yaml b/learn/security/_filesets/basic-security.yaml deleted file mode 100644 index 48ad5df7..00000000 --- a/learn/security/_filesets/basic-security.yaml +++ /dev/null @@ -1,78 +0,0 @@ -# @chunk {"steps": ["basic-setup"]} -# Basic Redocly Security Ruleset -# Starter configuration for API security validation -# Based on OWASP API Security Top 10 2023 - Essential Rules Only - -rules: - # Built-in Redocly security rules - security-defined: error - operation-4xx-response: warn - operation-2xx-response: error - no-unresolved-refs: error - - # Essential Security Rules - API2:2023 Authentication - - # Enforce HTTPS for all server URLs - rule/https-server-urls: - subject: - type: Server - property: url - assertions: - pattern: /^https:/ - message: "Server URLs must use HTTPS protocol. HTTP is insecure." - severity: error - - # Prevent HTTP Basic authentication - rule/no-http-basic-auth: - subject: - type: SecurityScheme - property: scheme - where: - - subject: - type: SecurityScheme - property: type - assertions: - const: http - assertions: - notPattern: /^basic$/i - message: "HTTP Basic authentication is insecure. Use OAuth 2.0 or API keys in headers." - severity: error - - # API4:2023 - Resource Consumption Protection - - # String schemas must have length constraints - rule/string-length-limit: - subject: - type: Schema - where: - - subject: - type: Schema - property: type - assertions: - const: string - assertions: - requireAny: - - maxLength - - enum - - const - - pattern - message: "String schemas must specify maxLength, enum, const, or pattern to limit resource consumption." - severity: warn - - # Array schemas must specify maxItems - rule/array-max-items: - subject: - type: Schema - property: maxItems - where: - - subject: - type: Schema - property: type - assertions: - const: array - assertions: - defined: true - message: "Array schemas must specify maxItems to prevent resource exhaustion attacks." - severity: warn - -# @chunk-end \ No newline at end of file diff --git a/learn/security/_filesets/example-api.yaml b/learn/security/_filesets/example-api.yaml deleted file mode 100644 index 8d08d710..00000000 --- a/learn/security/_filesets/example-api.yaml +++ /dev/null @@ -1,137 +0,0 @@ -# @chunk {"steps": ["api-example"]} -# Example OpenAPI spec for security validation demonstration -openapi: 3.0.3 -info: - title: API Security Demo - version: 1.0.0 - description: Example API demonstrating security validation rules - -servers: - - url: https://api.example.com/v1 - description: Production server (HTTPS required) - -components: - securitySchemes: - BearerAuth: - type: http - scheme: bearer - bearerFormat: JWT - description: JWT tokens must follow RFC8725 compliance for security best practices - - schemas: - User: - type: object - additionalProperties: false - required: - - id - - name - - email - properties: - id: - type: string - format: uuid - description: UUID format prevents object-level authorization attacks - name: - type: string - maxLength: 100 - pattern: "^[a-zA-Z\\s]+$" - email: - type: string - format: email - maxLength: 254 - permissions: - type: array - maxItems: 50 - items: - type: string - enum: [read, write, admin] - -paths: - /users/{userId}: - get: - summary: Get user by ID - security: - - BearerAuth: [] - parameters: - - name: userId - in: path - required: true - schema: - type: string - format: uuid - description: UUID format prevents enumeration attacks - responses: - '200': - description: User found - headers: - RateLimit-Limit: - schema: - type: integer - description: Rate limit per hour - RateLimit-Remaining: - schema: - type: integer - description: Remaining requests - content: - application/json: - schema: - $ref: '#/components/schemas/User' - '401': - description: Unauthorized - invalid or missing token - '403': - description: Forbidden - insufficient permissions - '404': - description: User not found - '429': - description: Rate limit exceeded - headers: - Retry-After: - schema: - type: integer - description: Seconds to wait before retrying - '500': - description: Internal server error - - put: - summary: Update user - security: - - BearerAuth: [admin] - parameters: - - name: userId - in: path - required: true - schema: - type: string - format: uuid - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/User' - responses: - '200': - description: User updated successfully - headers: - RateLimit-Limit: - schema: - type: integer - '400': - description: Invalid input data - '401': - description: Unauthorized - '403': - description: Forbidden - '404': - description: User not found - '422': - description: Validation error - '429': - description: Rate limit exceeded - headers: - Retry-After: - schema: - type: integer - '500': - description: Internal server error -# @chunk-end diff --git a/learn/security/_filesets/package.json b/learn/security/_filesets/package.json deleted file mode 100644 index de718e8b..00000000 --- a/learn/security/_filesets/package.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "name": "redocly-security-validation", - "version": "1.0.0", - "description": "Custom security validation functions for Redocly CLI implementing OWASP API Security Top 10 2023", - "main": "security-functions.js", - "scripts": { - "lint": "redocly lint openapi.yaml --config=redocly.yaml", - "lint-basic": "redocly lint openapi.yaml --config=basic-security.yaml", - "test-security": "npm run lint && echo 'Security validation tests passed'", - "validate": "redocly build-docs openapi.yaml --config=redocly.yaml" - }, - "keywords": [ - "api-security", - "owasp", - "redocly", - "validation", - "openapi", - "security-validation", - "api-validation" - ], - "author": "API Security Team", - "license": "MIT", - "devDependencies": { - "@redocly/cli": "^1.0.0" - }, - "peerDependencies": { - "@redocly/cli": ">=1.0.0" - }, - "files": [ - "redocly.yaml", - "basic-security.yaml", - "security-functions.js", - "README.md" - ], - "engines": { - "node": ">=16.0.0" - }, - "repository": { - "type": "git", - "url": "https://github.com/your-org/api-security-validation" - }, - "bugs": { - "url": "https://github.com/your-org/api-security-validation/issues" - } -} diff --git a/learn/security/_filesets/redocly.yaml b/learn/security/_filesets/redocly.yaml deleted file mode 100644 index 603b5081..00000000 --- a/learn/security/_filesets/redocly.yaml +++ /dev/null @@ -1,524 +0,0 @@ -# @chunk {"steps": ["setup-plugins"]} -# Redocly Security Ruleset -# Based on OWASP API Security Top 10 2023 -# https://owasp.org/www-project-api-security/ - -# Note: Plugin reference removed for walkthrough demonstration -# In production, add: plugins: ['./security-functions.js'] - -# Enable built-in security rules -rules: - # Built-in Redocly security rules - security-defined: error - operation-4xx-response: error - operation-2xx-response: error - no-unresolved-refs: error -# @chunk-end - - # @chunk {"steps": ["api1-object-auth"], "when": {"category": "api1"}} - # ========================================== - # API1:2023 - Broken Object Level Authorization - # ========================================== - - # Prevent numeric IDs that can be easily guessed - rule/no-numeric-ids: - subject: - type: Schema - property: type - filterInParentKeys: [path] - where: - - subject: - type: Parameter - property: name - assertions: - pattern: /(^id$|_id$|Id$|-id$)/ - assertions: - enum: [string] - message: "Use random IDs that cannot be guessed (UUIDs are preferred). Avoid integer IDs in path parameters." - severity: error - - # Ensure ID parameters use appropriate formats - rule/id-format-required: - subject: - type: Schema - property: format - filterInParentKeys: [path] - where: - - subject: - type: Parameter - property: name - assertions: - pattern: /(^id$|_id$|Id$|-id$)/ - assertions: - enum: [uuid, uri, password] - message: "ID parameters should specify a secure format like 'uuid'." - severity: warn - # @chunk-end - - # @chunk {"steps": ["api2-broken-auth"], "when": {"category": "api2"}} - # ========================================== - # API2:2023 - Broken Authentication - # ========================================== - - # Enforce HTTPS for all server URLs - rule/https-server-urls: - subject: - type: Server - property: url - assertions: - pattern: /^https:/ - message: "Server URLs must use HTTPS protocol. HTTP is insecure and exposes data to interception." - severity: error - - # Prevent HTTP Basic authentication - rule/no-http-basic-auth: - subject: - type: SecurityScheme - property: scheme - where: - - subject: - type: SecurityScheme - property: type - assertions: - const: http - assertions: - notPattern: /^basic$/i - message: "HTTP Basic authentication is insecure. Use OAuth 2.0, API keys in headers, or other secure methods." - severity: error - - # Prevent API keys in URL (query/path) - rule/no-api-keys-in-url: - subject: - type: SecurityScheme - property: in - where: - - subject: - type: SecurityScheme - property: type - assertions: - const: apiKey - assertions: - enum: [header, cookie] - message: "API keys must not be in URL (query or path parameters). Use headers or cookies instead." - severity: error - - # Prevent credentials in parameter names - rule/no-credentials-in-parameters: - subject: - type: Parameter - property: name - filterInParentKeys: [query, path] - assertions: - notPattern: /(secret|token|access.?token|refresh.?token|id.?token|password|api.?key|credential)/i - message: "Parameter names must not contain credential-related terms. Use secure authentication headers instead." - severity: error - - # Ensure write operations are protected - rule/write-operations-secured: - subject: - type: Operation - property: security - filterInParentKeys: [post, put, patch, delete] - assertions: - defined: true - nonEmpty: true - message: "Write operations (POST, PUT, PATCH, DELETE) must be protected by security schemes." - severity: error - - # JWT bearer format security schemes should reference RFC8725 - rule/jwt-rfc8725-compliance: - subject: - type: SecurityScheme - property: description - where: - - subject: - type: SecurityScheme - property: bearerFormat - assertions: - pattern: /jwt/i - assertions: - pattern: /RFC\s*8725/i - message: "JWT security schemes must reference RFC8725 compliance in description for security best practices." - severity: error - - # Advanced cross-operation security validation (requires custom functions) - rule/comprehensive-security-check: - subject: - type: Root - assertions: - security/checkOperationSecurity: - methods: [post, put, patch, delete] - nullable: false - message: "All write operations must have properly configured security schemes" - severity: error - # @chunk-end - - # @chunk {"steps": ["api3-property-auth"], "when": {"category": "api3"}} - # ========================================== - # API3:2023 - Broken Object Property Level Authorization - # ========================================== - - # Prevent unconstrained additionalProperties - rule/no-additional-properties: - subject: - type: Schema - property: additionalProperties - where: - - subject: - type: Schema - property: type - assertions: - const: object - assertions: - const: false - message: "Objects should not allow additionalProperties. Set to false to prevent mass assignment vulnerabilities." - severity: warn - - # Require maxProperties when additionalProperties is not false - rule/constrained-additional-properties: - subject: - type: Schema - property: maxProperties - where: - - subject: - type: Schema - property: type - assertions: - const: object - - subject: - type: Schema - property: additionalProperties - assertions: - defined: true - notPattern: /^false$/ - assertions: - defined: true - message: "Objects with additionalProperties should define maxProperties to limit resource consumption." - severity: warn - # @chunk-end - - # @chunk {"steps": ["api4-resource-consumption"], "when": {"category": "api4"}} - # ========================================== - # API4:2023 - Unrestricted Resource Consumption - # ========================================== - - # Require rate limiting headers in responses - rule/rate-limit-headers-present: - subject: - type: Header - where: - - subject: - type: Response - filterInParentKeys: ["200", "201", "202", "204", "400", "401", "403", "404", "422", "429"] - assertions: - defined: true - assertions: - pattern: /^(RateLimit|RateLimit-Limit|X-RateLimit-Limit|X-Rate-Limit-Limit)$/i - message: "2XX and 4XX responses should include rate limiting headers (RateLimit, RateLimit-Limit, X-RateLimit-Limit, or X-Rate-Limit-Limit)." - severity: warn - - # Require 429 Too Many Requests response - rule/require-429-response: - subject: - type: Responses - property: "429" - assertions: - defined: true - message: "Operations should define a 429 (Too Many Requests) response for rate limiting." - severity: warn - - # Retry-After header required for 429 responses - rule/retry-after-header-429: - subject: - type: Header - where: - - subject: - type: Response - filterInParentKeys: ["429"] - assertions: - defined: true - assertions: - pattern: /^Retry-After$/i - message: "429 responses must include a Retry-After header to indicate when clients can retry." - severity: error - - # Array schemas must specify maxItems - rule/array-max-items: - subject: - type: Schema - property: maxItems - where: - - subject: - type: Schema - property: type - assertions: - const: array - assertions: - defined: true - message: "Array schemas must specify maxItems to prevent resource exhaustion attacks." - severity: error - - # String schemas must have length constraints - rule/string-length-limit: - subject: - type: Schema - where: - - subject: - type: Schema - property: type - assertions: - const: string - assertions: - requireAny: - - maxLength - - enum - - const - - pattern - message: "String schemas must specify maxLength, enum, const, or pattern to limit resource consumption." - severity: error - - # Integer schemas must have min/max constraints - rule/integer-constraints: - subject: - type: Schema - where: - - subject: - type: Schema - property: type - assertions: - const: integer - assertions: - required: [minimum, maximum] - message: "Integer schemas must specify minimum and maximum values to prevent resource exhaustion." - severity: error - - # Integer schemas should specify format - rule/integer-format: - subject: - type: Schema - property: format - where: - - subject: - type: Schema - property: type - assertions: - const: integer - assertions: - enum: [int32, int64] - message: "Integer schemas should specify format (int32 or int64) for precise validation." - severity: warn - - # Advanced rate limiting consistency validation (requires custom functions) - rule/rate-limit-consistency: - subject: - type: Root - assertions: - security/validateRateLimitConsistency: - requiredHeaders: [RateLimit, X-RateLimit-Limit, X-Rate-Limit-Limit] - message: "Rate limiting configurations should be consistent across operations" - severity: warn - # @chunk-end - - # @chunk {"steps": ["api5-function-auth"], "when": {"category": "api5"}} - # ========================================== - # API5:2023 - Broken Function Level Authorization - # ========================================== - - # Administrative endpoints should have stricter security - rule/admin-endpoints-secured: - subject: - type: Operation - property: security - where: - - subject: - type: PathItem - assertions: - pattern: /(admin|manage|control|configure)/i - assertions: - defined: true - nonEmpty: true - message: "Administrative endpoints must have defined security schemes with appropriate authorization levels." - severity: error - - # Advanced admin security isolation validation (requires custom functions) - rule/admin-security-isolation: - subject: - type: Root - assertions: - security/validateAdminSecurity: - adminUrlPattern: "/admin" - message: "Administrative endpoints must use different security schemes than regular operations" - severity: error - - # Advanced OAuth scope validation (requires custom functions) - rule/oauth-scope-validation: - subject: - type: Root - assertions: - security/validateOAuthScopes: - adminOperations: [delete, post, put, patch] - requiredAdminScopes: [admin, write, manage] - adminPathPatterns: ["/admin", "/manage", "/config", "/system"] - message: "OAuth scopes must be appropriate for operation sensitivity" - severity: error - # @chunk-end - - # @chunk {"steps": ["api7-ssrf"], "when": {"category": "api7"}} - # ========================================== - # API7:2023 - Server Side Request Forgery - # ========================================== - - # Warn about URL parameters that might lead to SSRF - rule/ssrf-url-parameters: - subject: - type: Parameter - property: name - assertions: - notPattern: /(callback|redirect|url|uri|endpoint|webhook|fetch|proxy)/i - message: "URL-related parameters may be vulnerable to Server Side Request Forgery. Ensure proper validation and allowlisting." - severity: warn - # @chunk-end - - # @chunk {"steps": ["api8-misconfiguration"], "when": {"category": "api8"}} - # ========================================== - # API8:2023 - Security Misconfiguration - # ========================================== - - # Require CORS headers in responses - rule/cors-access-control-allow-origin: - subject: - type: Header - where: - - subject: - type: Response - assertions: - defined: true - assertions: - pattern: /^Access-Control-Allow-Origin$/i - message: "Responses should define CORS headers (Access-Control-Allow-Origin) to control cross-origin access." - severity: warn - - # Require error response schemas (400, 401, 403, 500) - rule/error-responses-defined: - subject: - type: Responses - assertions: - requireAny: ["400", "401", "403", "422", "4XX"] - message: "Operations should define appropriate error responses (400, 401, 403, 422, or 4XX) with proper schemas." - severity: warn - - # Require 401 unauthorized responses for secured operations - rule/unauthorized-response-required: - subject: - type: Responses - property: "401" - where: - - subject: - type: Operation - property: security - assertions: - defined: true - assertions: - defined: true - message: "Secured operations should define 401 (Unauthorized) responses." - severity: warn - - # Require 500 server error responses - rule/server-error-response: - subject: - type: Responses - property: "500" - assertions: - defined: true - message: "Operations should define 500 (Internal Server Error) responses to handle server errors gracefully." - severity: warn - # @chunk-end - - # @chunk {"steps": ["api9-inventory"], "when": {"category": "api9"}} - # ========================================== - # API9:2023 - Improper Inventory Management - # ========================================== - - # Server objects should declare internal/external audience - rule/server-audience-declaration: - subject: - type: Server - property: x-internal - assertions: - defined: true - enum: ['true', 'false'] - message: "Servers should declare their intended audience using x-internal (true for internal, false for external)." - severity: error - - # Server descriptions should indicate environment - rule/server-environment-declaration: - subject: - type: Server - property: description - assertions: - pattern: /(local|dev|development|test|testing|stage|staging|prod|production|live|sandbox)/i - message: "Server descriptions should clearly indicate the environment (development, testing, staging, production)." - severity: error - - # API version should be clearly defined - rule/api-version-defined: - subject: - type: Info - property: version - assertions: - defined: true - pattern: /^\d+\.\d+\.\d+/ - message: "API version should be clearly defined using semantic versioning (e.g., 1.0.0)." - severity: error - # @chunk-end - - # @chunk {"steps": ["custom-validation"], "when": {"component": "functions"}} - # ========================================== - # Additional Security Rules - # ========================================== - - # Prevent sensitive data in examples - rule/no-sensitive-data-in-examples: - subject: - type: Schema - property: example - assertions: - notPattern: /(password|secret|token|key|credential|ssn|social.?security|credit.?card|api.?key)/i - message: "Examples should not contain sensitive data like passwords, tokens, or personal information." - severity: warn - - # Ensure request bodies have proper content types - rule/secure-content-types: - subject: - type: MediaType - where: - - subject: - type: RequestBody - assertions: - defined: true - assertions: - enum: - - application/json - - application/xml - - application/x-www-form-urlencoded - - multipart/form-data - - text/plain - message: "Use secure and well-defined content types. Avoid allowing arbitrary content types." - severity: warn - - # Prevent overly broad schemas - rule/no-empty-schemas: - subject: - type: Schema - assertions: - requireAny: - - type - - properties - - items - - allOf - - anyOf - - oneOf - - $ref - message: "Schemas should not be empty. Define proper constraints to prevent accepting arbitrary data." - severity: error - # @chunk-end diff --git a/learn/security/_filesets/security-functions.js b/learn/security/_filesets/security-functions.js deleted file mode 100644 index ae4a75fd..00000000 --- a/learn/security/_filesets/security-functions.js +++ /dev/null @@ -1,225 +0,0 @@ -// @chunk {"steps": ["custom-validation"], "when": {"component": "functions"}} -/** - * Custom Security Validation Functions for Redocly - * Implements advanced security checks for OWASP API Security Top 10 2023 - */ - -const SecurityFunctions = { - // @chunk {"steps": ["custom-validation"]} - /** - * Validates that all write operations have properly configured security schemes - * Implements comprehensive cross-operation security validation - */ - checkOperationSecurity: (options) => { - return (root, ctx) => { - const problems = []; - const { methods = ['post', 'put', 'patch', 'delete'], nullable = false } = options; - - // Walk through all paths and operations - for (const [pathName, pathItem] of Object.entries(root.paths || {})) { - for (const method of methods) { - const operation = pathItem[method]; - if (!operation) continue; - - // Check if security is defined and non-empty - const security = operation.security || pathItem.security || root.security; - - if (!security || (Array.isArray(security) && security.length === 0)) { - problems.push(ctx.createProblem({ - message: `${method.toUpperCase()} operation at ${pathName} lacks security requirements`, - location: ctx.location.child(['paths', pathName, method]), - })); - } - - // Validate security scheme references exist - if (security && Array.isArray(security)) { - for (const securityRequirement of security) { - for (const schemeName of Object.keys(securityRequirement)) { - if (!root.components?.securitySchemes?.[schemeName]) { - problems.push(ctx.createProblem({ - message: `Security scheme '${schemeName}' referenced but not defined in components.securitySchemes`, - location: ctx.location.child(['paths', pathName, method, 'security']), - })); - } - } - } - } - } - } - - return problems; - }; - }, - // @chunk-end - - // @chunk {"steps": ["custom-validation"]} - /** - * Validates OAuth scope configurations for administrative operations - * Ensures admin operations require appropriate scopes - */ - validateOAuthScopes: (options) => { - return (root, ctx) => { - const problems = []; - const { - adminOperations = ['delete', 'post', 'put', 'patch'], - requiredAdminScopes = ['admin', 'write', 'manage'], - adminPathPatterns = ['/admin', '/manage', '/config', '/system'] - } = options; - - // Check paths that match admin patterns - for (const [pathName, pathItem] of Object.entries(root.paths || {})) { - const isAdminPath = adminPathPatterns.some(pattern => pathName.includes(pattern)); - - if (isAdminPath) { - for (const method of adminOperations) { - const operation = pathItem[method]; - if (!operation) continue; - - const security = operation.security || pathItem.security || root.security; - if (!security) continue; - - // Check if OAuth security schemes have appropriate scopes - for (const securityRequirement of security) { - for (const [schemeName, scopes] of Object.entries(securityRequirement)) { - const scheme = root.components?.securitySchemes?.[schemeName]; - if (scheme?.type === 'oauth2') { - const hasAdminScope = scopes.some(scope => - requiredAdminScopes.some(adminScope => scope.includes(adminScope)) - ); - - if (!hasAdminScope) { - problems.push(ctx.createProblem({ - message: `Admin operation ${method.toUpperCase()} ${pathName} should require admin scopes (${requiredAdminScopes.join(', ')})`, - location: ctx.location.child(['paths', pathName, method, 'security']), - })); - } - } - } - } - } - } - } - - return problems; - }; - }, - // @chunk-end - - // @chunk {"steps": ["custom-validation"]} - /** - * Validates administrative endpoint security isolation - * Ensures admin endpoints use different security schemes than regular operations - */ - validateAdminSecurity: (options) => { - return (root, ctx) => { - const problems = []; - const { adminUrlPattern = '/admin' } = options; - - const regularSchemes = new Set(); - const adminSchemes = new Set(); - - // Collect security schemes from different endpoint types - for (const [pathName, pathItem] of Object.entries(root.paths || {})) { - const isAdminPath = pathName.includes(adminUrlPattern); - - for (const [method, operation] of Object.entries(pathItem)) { - if (typeof operation !== 'object' || !operation.security) continue; - - for (const securityRequirement of operation.security) { - for (const schemeName of Object.keys(securityRequirement)) { - if (isAdminPath) { - adminSchemes.add(schemeName); - } else { - regularSchemes.add(schemeName); - } - } - } - } - } - - // Check for overlap between admin and regular schemes - const overlap = [...adminSchemes].filter(scheme => regularSchemes.has(scheme)); - if (overlap.length > 0) { - problems.push(ctx.createProblem({ - message: `Admin endpoints share security schemes with regular endpoints: ${overlap.join(', ')}. Consider using separate schemes for admin operations.`, - location: ctx.location.child(['paths']), - })); - } - - return problems; - }; - }, - // @chunk-end - - // @chunk {"steps": ["custom-validation"]} - /** - * Validates rate limiting header consistency across operations - * Ensures consistent rate limiting implementation - */ - validateRateLimitConsistency: (options) => { - return (root, ctx) => { - const problems = []; - const { requiredHeaders = ['RateLimit', 'X-RateLimit-Limit'] } = options; - - const rateLimitHeaders = new Set(); - const inconsistentOperations = []; - - // Collect all rate limiting headers used - for (const [pathName, pathItem] of Object.entries(root.paths || {})) { - for (const [method, operation] of Object.entries(pathItem)) { - if (typeof operation !== 'object' || !operation.responses) continue; - - for (const [statusCode, response] of Object.entries(operation.responses)) { - if (!response.headers) continue; - - const operationRateLimitHeaders = Object.keys(response.headers).filter(header => - requiredHeaders.some(required => header.toLowerCase().includes(required.toLowerCase())) - ); - - if (operationRateLimitHeaders.length > 0) { - if (rateLimitHeaders.size === 0) { - // First operation with rate limit headers - set the standard - operationRateLimitHeaders.forEach(header => rateLimitHeaders.add(header)); - } else { - // Check consistency with established pattern - const currentHeaders = new Set(operationRateLimitHeaders); - const standardHeaders = new Set([...rateLimitHeaders]); - - if (currentHeaders.size !== standardHeaders.size || - [...currentHeaders].some(h => !standardHeaders.has(h))) { - inconsistentOperations.push(`${method.toUpperCase()} ${pathName}`); - } - } - } - } - } - } - - if (inconsistentOperations.length > 0) { - problems.push(ctx.createProblem({ - message: `Inconsistent rate limiting headers found in: ${inconsistentOperations.join(', ')}. Use consistent header naming across all operations.`, - location: ctx.location.child(['paths']), - })); - } - - return problems; - }; - } - // @chunk-end -}; - -// @chunk {"steps": ["custom-validation"]} -// Export functions for Redocly CLI (ES Module syntax) -// Note: In a real implementation, this would be exported as a plugin -// For this demonstration, the export is commented out to avoid loading errors - -/* -export default { - id: 'security', - assertions: SecurityFunctions -}; -*/ - -// For demonstration purposes - functions are available but not loaded as plugin -export { SecurityFunctions }; -// @chunk-end diff --git a/learn/security/automated-security-validation-walkthrough-v2.md b/learn/security/automated-security-validation-walkthrough-v2.md new file mode 100644 index 00000000..df55e09d --- /dev/null +++ b/learn/security/automated-security-validation-walkthrough-v2.md @@ -0,0 +1,122 @@ +--- +title: "Automated API Security Validation - Interactive Walkthrough" +description: "Learn to implement OWASP API Security Top 10 2023 rules using interactive Redocly security validation configurations with step-by-step guidance." +seo: + title: "Automated API Security Validation - Interactive Walkthrough" + description: "Learn to implement OWASP API Security Top 10 2023 rules using interactive Redocly security validation configurations with step-by-step guidance." +--- + +# Automated API Security Validation - Interactive Walkthrough + +*Transform your API security from manual reviews to automated enforcement using production-ready validation rules.* + +--- + +## What You'll Learn + +This interactive walkthrough guides you through implementing **automated security validation** that enforces the **OWASP API Security Top 10 2023** using Redocly's validation engine. By the end, you'll have a complete security ruleset that prevents vulnerabilities before they reach production. + +**You'll master:** +- Setting up comprehensive security validation rules +- Automating OWASP API Security Top 10 2023 compliance +- Implementing custom security validation functions +- Integrating security checks into CI/CD pipelines +- Troubleshooting common validation issues + +--- + +{% code-walkthrough + filesets=[ + { + "files": ["./_filesets/basic-security.yaml"], + "when": { + "config": "basic" + } + }, + { + "files": ["./_filesets/example-api.yaml"], + "when": { + "config": "example" + } + } + ] + filters={ + "config": { + "label": "Configuration Type", + "items": [ + {"value": "basic"}, + {"value": "example"} + ] + } + } +%} + +## Getting Started + +{% step id="basic-rules" heading="Basic Security Rules" when={"config": "basic"} %} + +Start with these essential security validation rules that provide the foundation for API security: + +- **Security schemes required**: Ensures all operations have proper authentication +- **HTTPS enforcement**: Prevents insecure HTTP connections +- **Input validation**: Requires proper constraints on strings and arrays +- **Response validation**: Ensures proper error response definitions + +This basic configuration is perfect for teams getting started with automated security validation. + +{% /step %} + +{% step id="api-spec" heading="Example API Specification" when={"config": "example"} %} + +This example OpenAPI specification demonstrates security best practices: + +**Key Security Features:** +- HTTPS-only server URLs prevent man-in-the-middle attacks +- UUID-based IDs prevent object-level authorization vulnerabilities +- JWT authentication with proper bearer token handling +- Comprehensive input validation with length limits and patterns +- Rate limiting headers in all responses +- Complete error response definitions (400, 401, 403, 404, 422, 429, 500) +- `additionalProperties: false` prevents mass assignment attacks + +Use this as a reference when building your own secure APIs. + +{% /step %} + +{% /code-walkthrough %} + +--- + +## Implementation Strategy + +Implementing automated security validation is an iterative process. Here's a recommended approach: + +**Phase 1: Foundation (Week 1)** +- Implement basic built-in rules from the configuration above +- Test in development environment +- Set up CI/CD integration with warning-level severity + +**Phase 2: Enhancement (Week 2)** +- Add custom security rules based on your API requirements +- Escalate critical rules to error-level severity +- Train team on validation rule interpretation + +--- + +## Next Steps and Resources + +### **Quick Start Actions** +1. **Download the basic configuration** using the walkthrough above +2. **Test with your OpenAPI specification** in development +3. **Integrate into CI/CD pipeline** to catch issues early +4. **Customize rules** based on your specific security requirements + +### **Related Security Guides** +- **[TLS Encryption Best Practices](api-tls-encryption-https-best-practices)** - HTTPS implementation +- **[Input Validation Guide](api-input-validation-injection-prevention)** - Prevent injection attacks +- **[Rate Limiting Guide](api-rate-limiting-abuse-prevention)** - Prevent abuse and DoS +- **[Authentication Guide](authentication-authorization-openapi)** - Secure access control + +--- + +**🔐 Security Note**: This walkthrough covers essential OWASP API Security Top 10 2023 practices. For production deployment, review and customize rules based on your organization's specific security requirements and risk tolerance. diff --git a/learn/security/automated-security-validation-walkthrough.md b/learn/security/automated-security-validation-walkthrough.md index a3370d1c..b0f6d081 100644 --- a/learn/security/automated-security-validation-walkthrough.md +++ b/learn/security/automated-security-validation-walkthrough.md @@ -39,7 +39,7 @@ This interactive walkthrough guides you through implementing **automated securit "approach": "complete" } } - ], + ] filters={ "approach": { "label": "Implementation Approach", diff --git a/learn/security/test-simple-walkthrough.md b/learn/security/test-simple-walkthrough.md new file mode 100644 index 00000000..115cb96f --- /dev/null +++ b/learn/security/test-simple-walkthrough.md @@ -0,0 +1,20 @@ +--- +title: "Simple Test Walkthrough" +description: "Test basic walkthrough functionality" +--- + +# Simple Test Walkthrough + +{% code-walkthrough + filesets=[ + { "files": ["./_filesets/basic-security.yaml"] } + ] +%} + +## Basic Configuration + +{% step id="test-step" heading="Test Step" %} +This is a simple test step to verify walkthrough functionality. +{% /step %} + +{% /code-walkthrough %} diff --git a/pages/learning-center/cards.ts b/pages/learning-center/cards.ts index 5d3fe41a..d31300e2 100644 --- a/pages/learning-center/cards.ts +++ b/pages/learning-center/cards.ts @@ -113,7 +113,7 @@ export const cards = [ { title: 'API Input Validation and Injection Prevention', link: '/learn/security/api-input-validation-injection-prevention' }, { title: 'API Rate Limiting and Abuse Prevention', link: '/learn/security/api-rate-limiting-abuse-prevention' }, { title: 'Authentication and Authorization with OpenAPI', link: '/learn/security/authentication-authorization-openapi' }, - { title: 'API Design-First Security Governance and Automation', link: '/learn/security/api-design-first-security-governance' }, + { title: 'Automated Security Validation - Interactive Walkthrough', link: '/learn/security/automated-security-validation-walkthrough' }, ], }, // { diff --git a/redocly.yaml b/redocly.yaml index ef782f74..a2ab6772 100644 --- a/redocly.yaml +++ b/redocly.yaml @@ -11,6 +11,7 @@ redirects: ignore: - '.github' - 'learn/arazzo/_filesets/**' + - 'learn/security/_filesets/**' - '**/code-walkthrough-files/**' - docs/realm/.templates From e4eded377907360e3d7184fcea9d872dc97b9ab9 Mon Sep 17 00:00:00 2001 From: Matt Williams Date: Fri, 26 Sep 2025 16:22:15 -0500 Subject: [PATCH 10/27] Convert all security article code examples to Node.js - Convert SQL injection examples from Python to JavaScript with Express.js - Convert rate limiting algorithms from Python/Go to JavaScript (Token Bucket, Sliding Window, Fixed Window) - Convert authorization monitoring from Python to JavaScript with Express middleware - Convert validation metrics from Python to JavaScript with Map/Set data structures - Convert rate limit testing framework from Python asyncio/aiohttp to JavaScript fetch/Promise.all - Update all tab labels and code block titles to reflect JavaScript - Maintain all security highlighting and educational explanations - Provide consistent Node.js developer experience across all security articles --- .../security/_filesets/originals/redocly.yaml | 505 ------------- .../_filesets/originals/security-functions.ts | 239 ------ .../api-design-first-security-guide.md | 80 +- ...i-input-validation-injection-prevention.md | 443 ++++++++--- .../api-rate-limiting-abuse-prevention.md | 571 +++++++++++---- ...api-tls-encryption-https-best-practices.md | 224 ++++-- .../authentication-authorization-openapi.md | 686 ++++++++++++++---- ...tomated-security-validation-walkthrough.md | 98 ++- learn/security/index.md | 24 +- 9 files changed, 1596 insertions(+), 1274 deletions(-) delete mode 100644 learn/security/_filesets/originals/redocly.yaml delete mode 100644 learn/security/_filesets/originals/security-functions.ts diff --git a/learn/security/_filesets/originals/redocly.yaml b/learn/security/_filesets/originals/redocly.yaml deleted file mode 100644 index e83beb0d..00000000 --- a/learn/security/_filesets/originals/redocly.yaml +++ /dev/null @@ -1,505 +0,0 @@ -# Redocly Security Ruleset -# Based on OWASP API Security Top 10 2023 -# https://owasp.org/www-project-api-security/ - -plugins: - - './security-functions.js' - - -# Enable built-in security rules -rules: - # Built-in Redocly security rules - security-defined: error - operation-4xx-response: error - operation-2xx-response: error - no-unresolved-refs: error - - # ========================================== - # API1:2023 - Broken Object Level Authorization - # ========================================== - - # Prevent numeric IDs that can be easily guessed - rule/no-numeric-ids: - subject: - type: Schema - property: type - filterInParentKeys: [path] - where: - - subject: - type: Parameter - property: name - assertions: - pattern: /(^id$|_id$|Id$|-id$)/ - assertions: - enum: [string] - message: "Use random IDs that cannot be guessed (UUIDs are preferred). Avoid integer IDs in path parameters." - severity: error - - # Ensure ID parameters use appropriate formats - rule/id-format-required: - subject: - type: Schema - property: format - filterInParentKeys: [path] - where: - - subject: - type: Parameter - property: name - assertions: - pattern: /(^id$|_id$|Id$|-id$)/ - assertions: - enum: [uuid, uri, password] - message: "ID parameters should specify a secure format like 'uuid'." - severity: warn - - # ========================================== - # API2:2023 - Broken Authentication - # ========================================== - - # Enforce HTTPS for all server URLs - rule/https-server-urls: - subject: - type: Server - property: url - assertions: - pattern: /^https:/ - message: "Server URLs must use HTTPS protocol. HTTP is insecure and exposes data to interception." - severity: error - - # Prevent HTTP Basic authentication - rule/no-http-basic-auth: - subject: - type: SecurityScheme - property: scheme - where: - - subject: - type: SecurityScheme - property: type - assertions: - const: http - assertions: - notPattern: /^basic$/i - message: "HTTP Basic authentication is insecure. Use OAuth 2.0, API keys in headers, or other secure methods." - severity: error - - # Prevent API keys in URL (query/path) - rule/no-api-keys-in-url: - subject: - type: SecurityScheme - property: in - where: - - subject: - type: SecurityScheme - property: type - assertions: - const: apiKey - assertions: - enum: [header, cookie] - message: "API keys must not be in URL (query or path parameters). Use headers or cookies instead." - severity: error - - # Prevent credentials in parameter names - rule/no-credentials-in-parameters: - subject: - type: Parameter - property: name - filterInParentKeys: [query, path] - assertions: - notPattern: /(secret|token|access.?token|refresh.?token|id.?token|password|api.?key|credential)/i - message: "Parameter names must not contain credential-related terms. Use secure authentication headers instead." - severity: error - - # Ensure write operations are protected - rule/write-operations-secured: - subject: - type: Operation - property: security - filterInParentKeys: [post, put, patch, delete] - assertions: - defined: true - nonEmpty: true - message: "Write operations (POST, PUT, PATCH, DELETE) must be protected by security schemes." - severity: error - - # JWT bearer format security schemes should reference RFC8725 - rule/jwt-rfc8725-compliance: - subject: - type: SecurityScheme - property: description - where: - - subject: - type: SecurityScheme - property: bearerFormat - assertions: - pattern: /jwt/i - assertions: - pattern: /RFC\s*8725/i - message: "JWT security schemes must reference RFC8725 compliance in description for security best practices." - severity: error - - # Advanced cross-operation security validation (requires custom functions) - rule/comprehensive-security-check: - subject: - type: Root - assertions: - security/checkOperationSecurity: - methods: [post, put, patch, delete] - nullable: false - message: "All write operations must have properly configured security schemes" - severity: error - - # ========================================== - # API3:2023 - Broken Object Property Level Authorization - # ========================================== - - # Prevent unconstrained additionalProperties - rule/no-additional-properties: - subject: - type: Schema - property: additionalProperties - where: - - subject: - type: Schema - property: type - assertions: - const: object - assertions: - const: false - message: "Objects should not allow additionalProperties. Set to false to prevent mass assignment vulnerabilities." - severity: warn - - # Require maxProperties when additionalProperties is not false - rule/constrained-additional-properties: - subject: - type: Schema - property: maxProperties - where: - - subject: - type: Schema - property: type - assertions: - const: object - - subject: - type: Schema - property: additionalProperties - assertions: - defined: true - notPattern: /^false$/ - assertions: - defined: true - message: "Objects with additionalProperties should define maxProperties to limit resource consumption." - severity: warn - - # ========================================== - # API4:2023 - Unrestricted Resource Consumption - # ========================================== - - # Require rate limiting headers in responses - rule/rate-limit-headers-present: - subject: - type: Header - where: - - subject: - type: Response - filterInParentKeys: ["200", "201", "202", "204", "400", "401", "403", "404", "422", "429"] - assertions: - defined: true - assertions: - pattern: /^(RateLimit|RateLimit-Limit|X-RateLimit-Limit|X-Rate-Limit-Limit)$/i - message: "2XX and 4XX responses should include rate limiting headers (RateLimit, RateLimit-Limit, X-RateLimit-Limit, or X-Rate-Limit-Limit)." - severity: warn - - # Require 429 Too Many Requests response - rule/require-429-response: - subject: - type: Responses - property: "429" - assertions: - defined: true - message: "Operations should define a 429 (Too Many Requests) response for rate limiting." - severity: warn - - # Retry-After header required for 429 responses - rule/retry-after-header-429: - subject: - type: Header - where: - - subject: - type: Response - filterInParentKeys: ["429"] - assertions: - defined: true - assertions: - pattern: /^Retry-After$/i - message: "429 responses must include a Retry-After header to indicate when clients can retry." - severity: error - - # Array schemas must specify maxItems - rule/array-max-items: - subject: - type: Schema - property: maxItems - where: - - subject: - type: Schema - property: type - assertions: - const: array - assertions: - defined: true - message: "Array schemas must specify maxItems to prevent resource exhaustion attacks." - severity: error - - # String schemas must have length constraints - rule/string-length-limit: - subject: - type: Schema - where: - - subject: - type: Schema - property: type - assertions: - const: string - assertions: - requireAny: - - maxLength - - enum - - const - - pattern - message: "String schemas must specify maxLength, enum, const, or pattern to limit resource consumption." - severity: error - - # Integer schemas must have min/max constraints - rule/integer-constraints: - subject: - type: Schema - where: - - subject: - type: Schema - property: type - assertions: - const: integer - assertions: - required: [minimum, maximum] - message: "Integer schemas must specify minimum and maximum values to prevent resource exhaustion." - severity: error - - # Integer schemas should specify format - rule/integer-format: - subject: - type: Schema - property: format - where: - - subject: - type: Schema - property: type - assertions: - const: integer - assertions: - enum: [int32, int64] - message: "Integer schemas should specify format (int32 or int64) for precise validation." - severity: warn - - # Advanced rate limiting consistency validation (requires custom functions) - rule/rate-limit-consistency: - subject: - type: Root - assertions: - security/validateRateLimitConsistency: - requiredHeaders: [RateLimit, X-RateLimit-Limit, X-Rate-Limit-Limit] - message: "Rate limiting configurations should be consistent across operations" - severity: warn - - # ========================================== - # API5:2023 - Broken Function Level Authorization - # ========================================== - - # Administrative endpoints should have stricter security - rule/admin-endpoints-secured: - subject: - type: Operation - property: security - where: - - subject: - type: PathItem - assertions: - pattern: /(admin|manage|control|configure)/i - assertions: - defined: true - nonEmpty: true - message: "Administrative endpoints must have defined security schemes with appropriate authorization levels." - severity: error - - # Advanced admin security isolation validation (requires custom functions) - rule/admin-security-isolation: - subject: - type: Root - assertions: - security/validateAdminSecurity: - adminUrlPattern: "/admin" - message: "Administrative endpoints must use different security schemes than regular operations" - severity: error - - # Advanced OAuth scope validation (requires custom functions) - rule/oauth-scope-validation: - subject: - type: Root - assertions: - security/validateOAuthScopes: - adminOperations: [delete, post, put, patch] - requiredAdminScopes: [admin, write, manage] - adminPathPatterns: ["/admin", "/manage", "/config", "/system"] - message: "OAuth scopes must be appropriate for operation sensitivity" - severity: error - - # ========================================== - # API7:2023 - Server Side Request Forgery - # ========================================== - - # Warn about URL parameters that might lead to SSRF - rule/ssrf-url-parameters: - subject: - type: Parameter - property: name - assertions: - notPattern: /(callback|redirect|url|uri|endpoint|webhook|fetch|proxy)/i - message: "URL-related parameters may be vulnerable to Server Side Request Forgery. Ensure proper validation and allowlisting." - severity: warn - - # ========================================== - # API8:2023 - Security Misconfiguration - # ========================================== - - # Require CORS headers in responses - rule/cors-access-control-allow-origin: - subject: - type: Header - where: - - subject: - type: Response - assertions: - defined: true - assertions: - pattern: /^Access-Control-Allow-Origin$/i - message: "Responses should define CORS headers (Access-Control-Allow-Origin) to control cross-origin access." - severity: warn - - # Require error response schemas (400, 401, 403, 500) - rule/error-responses-defined: - subject: - type: Responses - assertions: - requireAny: ["400", "401", "403", "422", "4XX"] - message: "Operations should define appropriate error responses (400, 401, 403, 422, or 4XX) with proper schemas." - severity: warn - - # Require 401 unauthorized responses for secured operations - rule/unauthorized-response-required: - subject: - type: Responses - property: "401" - where: - - subject: - type: Operation - property: security - assertions: - defined: true - assertions: - defined: true - message: "Secured operations should define 401 (Unauthorized) responses." - severity: warn - - # Require 500 server error responses - rule/server-error-response: - subject: - type: Responses - property: "500" - assertions: - defined: true - message: "Operations should define 500 (Internal Server Error) responses to handle server errors gracefully." - severity: warn - - # ========================================== - # API9:2023 - Improper Inventory Management - # ========================================== - - # Server objects should declare internal/external audience - rule/server-audience-declaration: - subject: - type: Server - property: x-internal - assertions: - defined: true - enum: ['true', 'false'] - message: "Servers should declare their intended audience using x-internal (true for internal, false for external)." - severity: error - - # Server descriptions should indicate environment - rule/server-environment-declaration: - subject: - type: Server - property: description - assertions: - pattern: /(local|dev|development|test|testing|stage|staging|prod|production|live|sandbox)/i - message: "Server descriptions should clearly indicate the environment (development, testing, staging, production)." - severity: error - - # API version should be clearly defined - rule/api-version-defined: - subject: - type: Info - property: version - assertions: - defined: true - pattern: /^\d+\.\d+\.\d+/ - message: "API version should be clearly defined using semantic versioning (e.g., 1.0.0)." - severity: error - - # ========================================== - # Additional Security Rules - # ========================================== - - # Prevent sensitive data in examples - rule/no-sensitive-data-in-examples: - subject: - type: Schema - property: example - assertions: - notPattern: /(password|secret|token|key|credential|ssn|social.?security|credit.?card|api.?key)/i - message: "Examples should not contain sensitive data like passwords, tokens, or personal information." - severity: warn - - # Ensure request bodies have proper content types - rule/secure-content-types: - subject: - type: MediaType - where: - - subject: - type: RequestBody - assertions: - defined: true - assertions: - enum: - - application/json - - application/xml - - application/x-www-form-urlencoded - - multipart/form-data - - text/plain - message: "Use secure and well-defined content types. Avoid allowing arbitrary content types." - severity: warn - - # Prevent overly broad schemas - rule/no-empty-schemas: - subject: - type: Schema - assertions: - requireAny: - - type - - properties - - items - - allOf - - anyOf - - oneOf - - $ref - message: "Schemas should not be empty. Define proper constraints to prevent accepting arbitrary data." - severity: error diff --git a/learn/security/_filesets/originals/security-functions.ts b/learn/security/_filesets/originals/security-functions.ts deleted file mode 100644 index 9e91d6ae..00000000 --- a/learn/security/_filesets/originals/security-functions.ts +++ /dev/null @@ -1,239 +0,0 @@ -// Custom security validation functions for Redocly -// These implement the advanced security checks from the Spectral OWASP ruleset - -export default function securityPlugin() { - return { - id: 'security', - assertions: { - // Validates that operations have appropriate security based on HTTP method - checkOperationSecurity: (openapi, options, ctx) => { - const errors = []; - const { methods = [], nullable = false } = options; - const { paths, security: globalSecurity } = openapi; - - if (!paths || typeof paths !== 'object') { - return errors; - } - - // Iterate through all operations - for (const [pathKey, pathItem] of Object.entries(paths)) { - if (!pathItem || typeof pathItem !== 'object') continue; - - const httpMethods = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']; - - for (const method of httpMethods) { - const operation = pathItem[method]; - if (!operation || typeof operation !== 'object') continue; - - // Skip if method not in configured methods list - if (methods.length > 0 && !methods.includes(method)) continue; - - let operationSecurity = operation.security; - - // Fall back to global security if operation security not defined - if (operationSecurity === undefined) { - operationSecurity = globalSecurity; - } - - // Check if security is properly defined - if (!operationSecurity || operationSecurity.length === 0) { - errors.push({ - message: `${method.toUpperCase()} operation at ${pathKey} has no security scheme defined`, - location: ctx.baseLocation.child(['paths', pathKey, method, 'security']), - }); - continue; - } - - // Validate each security requirement - if (Array.isArray(operationSecurity)) { - for (const [idx, securityEntry] of operationSecurity.entries()) { - if (typeof securityEntry !== 'object') continue; - - const securitySchemeIds = Object.keys(securityEntry); - if (securitySchemeIds.length === 0 && !nullable) { - errors.push({ - message: `${method.toUpperCase()} operation at ${pathKey} has empty security requirement at index ${idx}`, - location: ctx.baseLocation.child(['paths', pathKey, method, 'security', idx]), - }); - } - } - } - } - } - - return errors; - }, - - // Ensures admin endpoints use different security schemes than regular endpoints - validateAdminSecurity: (openapi, options, ctx) => { - const errors = []; - const { adminUrlPattern = '/admin' } = options; - const { paths } = openapi; - - if (!paths || typeof paths !== 'object') { - return errors; - } - - const nonAdminSecurityHashes = new Set(); - const adminSecurityEntries = []; - - // First pass: collect all security configurations - for (const [pathKey, pathItem] of Object.entries(paths)) { - if (!pathItem || typeof pathItem !== 'object') continue; - - const httpMethods = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']; - - for (const method of httpMethods) { - const operation = pathItem[method]; - if (!operation || typeof operation !== 'object') continue; - - const operationSecurity = operation.security; - if (!operationSecurity || !Array.isArray(operationSecurity)) continue; - - // Create hash of security configuration for comparison - const securityHash = JSON.stringify(operationSecurity); - - if (pathKey.includes(adminUrlPattern)) { - adminSecurityEntries.push({ - path: pathKey, - method, - hash: securityHash, - location: ctx.baseLocation.child(['paths', pathKey, method, 'security']), - }); - } else { - nonAdminSecurityHashes.add(securityHash); - } - } - } - - // Second pass: validate admin endpoints use unique security - for (const adminEntry of adminSecurityEntries) { - if (nonAdminSecurityHashes.has(adminEntry.hash)) { - errors.push({ - message: `Admin endpoint ${adminEntry.path} (${adminEntry.method.toUpperCase()}) uses the same security scheme as non-admin endpoints. Admin operations should have stricter authentication.`, - location: adminEntry.location, - }); - } - } - - return errors; - }, - - // Validates OAuth scopes are appropriate for operation sensitivity - validateOAuthScopes: (openapi, options, ctx) => { - const errors = []; - const { - adminOperations = ['delete', 'post', 'put', 'patch'], - requiredAdminScopes = ['admin', 'write', 'manage'], - adminPathPatterns = ['/admin', '/manage', '/config'] - } = options; - - const { paths, components } = openapi; - - if (!paths || !components?.securitySchemes) { - return errors; - } - - // Find OAuth2 security schemes - const oauthSchemes = Object.entries(components.securitySchemes) - .filter(([_, scheme]) => scheme.type === 'oauth2') - .map(([name, _]) => name); - - if (oauthSchemes.length === 0) return errors; - - for (const [pathKey, pathItem] of Object.entries(paths)) { - if (!pathItem || typeof pathItem !== 'object') continue; - - const isAdminPath = adminPathPatterns.some(pattern => pathKey.includes(pattern)); - - for (const method of adminOperations) { - const operation = pathItem[method]; - if (!operation || typeof operation !== 'object') continue; - - const operationSecurity = operation.security; - if (!operationSecurity || !Array.isArray(operationSecurity)) continue; - - // Check if this operation uses OAuth and has appropriate scopes - for (const securityReq of operationSecurity) { - for (const [schemeName, scopes] of Object.entries(securityReq)) { - if (oauthSchemes.includes(schemeName)) { - const hasAdminScope = requiredAdminScopes.some(scope => - Array.isArray(scopes) && scopes.includes(scope) - ); - - if ((isAdminPath || adminOperations.includes(method)) && !hasAdminScope) { - errors.push({ - message: `${method.toUpperCase()} operation at ${pathKey} should require admin scopes (${requiredAdminScopes.join(', ')}) for sensitive operations`, - location: ctx.baseLocation.child(['paths', pathKey, method, 'security']), - }); - } - } - } - } - } - } - - return errors; - }, - - // Validates rate limiting configuration consistency - validateRateLimitConsistency: (openapi, options, ctx) => { - const errors = []; - const { requiredHeaders = ['RateLimit', 'X-RateLimit-Limit'] } = options; - const { paths } = openapi; - - if (!paths || typeof paths !== 'object') { - return errors; - } - - const rateLimitConfigs = new Map(); - - // Collect all rate limiting configurations - for (const [pathKey, pathItem] of Object.entries(paths)) { - if (!pathItem || typeof pathItem !== 'object') continue; - - const httpMethods = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options']; - - for (const method of httpMethods) { - const operation = pathItem[method]; - if (!operation?.responses) continue; - - for (const [statusCode, response] of Object.entries(operation.responses)) { - if (!statusCode.match(/^[24]/)) continue; // Only 2xx and 4xx responses - - const headers = response.headers || {}; - const hasRateLimit = requiredHeaders.some(header => headers[header]); - - if (hasRateLimit) { - const config = requiredHeaders - .filter(header => headers[header]) - .map(header => ({ header, schema: headers[header] })); - - const configKey = `${pathKey}:${method}`; - rateLimitConfigs.set(configKey, config); - } - } - } - } - - // Validate consistency across operations - const configValues = Array.from(rateLimitConfigs.values()); - if (configValues.length > 1) { - const firstConfig = JSON.stringify(configValues[0]); - - for (const [pathMethod, config] of rateLimitConfigs.entries()) { - if (JSON.stringify(config) !== firstConfig) { - const [path, method] = pathMethod.split(':'); - errors.push({ - message: `Rate limiting configuration at ${path} (${method.toUpperCase()}) differs from other operations. Consider using consistent rate limiting headers across your API.`, - location: ctx.baseLocation.child(['paths', path, method, 'responses']), - }); - } - } - } - - return errors; - } - }, - }; -} diff --git a/learn/security/api-design-first-security-guide.md b/learn/security/api-design-first-security-guide.md index deff8d04..cdcff339 100644 --- a/learn/security/api-design-first-security-guide.md +++ b/learn/security/api-design-first-security-guide.md @@ -402,19 +402,19 @@ For interactions with a database, the gold standard for preventing SQL injection A parameterized query forces a separation between the SQL command (the code) and the user-supplied data, making it impossible for an attacker to alter the logic of the query. **Vulnerable Code (Never Do This):** -```python -# DANGEROUS: Directly interpolating user input -user_id = request.get('user_id') -query = f"SELECT * FROM users WHERE id = {user_id}" -cursor.execute(query) +```javascript +// DANGEROUS: Directly interpolating user input # [!code error] +const userId = req.query.user_id; +const query = `SELECT * FROM users WHERE id = ${userId}`; // [!code --] +const result = await db.query(query); // [!code --] ``` **Secure Code (Use Parameterized Queries):** -```python -# SAFE: Using parameterized queries -user_id = request.get('user_id') -query = "SELECT * FROM users WHERE id = ?" -cursor.execute(query, (user_id,)) +```javascript +// SAFE: Using parameterized queries # [!code ++] +const userId = req.query.user_id; +const query = "SELECT * FROM users WHERE id = $1"; // [!code ++] +const result = await db.query(query, [userId]); // [!code ++] ``` ### Schema-Based Validation as Security Contract @@ -427,7 +427,7 @@ components: schemas: NewUser: type: object - additionalProperties: false # Prevent mass assignment (OWASP API3:2023) + additionalProperties: false # [!code highlight] Prevent mass assignment (OWASP API3:2023) required: - username - email @@ -437,23 +437,23 @@ components: username: type: string minLength: 4 - maxLength: 20 # Prevent resource exhaustion (OWASP API4:2023) - pattern: "^[a-zA-Z0-9]+$" # Prevent injection attacks + maxLength: 20 # [!code highlight] Prevent resource exhaustion (OWASP API4:2023) + pattern: "^[a-zA-Z0-9]+$" # [!code highlight] Prevent injection attacks email: type: string - maxLength: 254 # Prevent resource exhaustion (OWASP API4:2023) - format: email + maxLength: 254 # [!code highlight] Prevent resource exhaustion (OWASP API4:2023) + format: email # [!code highlight] Built-in email validation password: type: string - minLength: 12 + minLength: 12 # [!code highlight] Strong password requirement maxLength: 128 age: type: integer - minimum: 18 - maximum: 130 # Prevent integer overflow attacks + minimum: 18 # [!code highlight] Age verification + maximum: 130 # [!code highlight] Prevent integer overflow attacks role: type: string - enum: ["user", "viewer"] # Enforce allow-list approach + enum: ["user", "viewer"] # [!code highlight] Enforce allow-list approach default: "user" ``` @@ -900,25 +900,33 @@ app.use((req, res, next) => { ``` ### Rate Limiting Monitoring -```python -# Track rate limiting metrics -import time -from collections import defaultdict - -class RateLimitMetrics: - def __init__(self): - self.blocked_requests = defaultdict(int) - self.total_requests = defaultdict(int) +```javascript +// Track rate limiting metrics +class RateLimitMetrics { + constructor() { + this.blockedRequests = new Map(); + this.totalRequests = new Map(); + } - def record_request(self, client_id, blocked=False): - self.total_requests[client_id] += 1 - if blocked: - self.blocked_requests[client_id] += 1 + recordRequest(clientId, blocked = false) { + // Initialize counters if client is new + if (!this.totalRequests.has(clientId)) { + this.totalRequests.set(clientId, 0); + this.blockedRequests.set(clientId, 0); + } + + this.totalRequests.set(clientId, this.totalRequests.get(clientId) + 1); + if (blocked) { + this.blockedRequests.set(clientId, this.blockedRequests.get(clientId) + 1); + } + } - def get_block_rate(self, client_id): - total = self.total_requests[client_id] - blocked = self.blocked_requests[client_id] - return (blocked / total) * 100 if total > 0 else 0 + getBlockRate(clientId) { + const total = this.totalRequests.get(clientId) || 0; + const blocked = this.blockedRequests.get(clientId) || 0; + return total > 0 ? (blocked / total) * 100 : 0; + } +} ``` ## API Security Maturity Model diff --git a/learn/security/api-input-validation-injection-prevention.md b/learn/security/api-input-validation-injection-prevention.md index 632832e0..52a5f9aa 100644 --- a/learn/security/api-input-validation-injection-prevention.md +++ b/learn/security/api-input-validation-injection-prevention.md @@ -15,12 +15,26 @@ seo: APIs are designed to accept data as input. However, an API should never blindly trust the data it receives from a client. The process of rigorously checking all incoming data is called data validation. **In this guide, you'll learn:** -- How to implement schema-based validation as a security contract -- JSON Schema security constraints and validation patterns -- Mass assignment attack prevention techniques -- SQL injection and OGNL injection defense strategies -- Real-world lessons from the Equifax breach -- Automated validation governance and linting rules +- [How to implement schema-based validation](#schema-based-validation-as-security-contract) as a security contract +- [JSON Schema security constraints and validation patterns](#key-security-constraints) +- [Attack prevention techniques](#attack-prevention-strategies) for SQL injection, OGNL injection, and mass assignment +- [Real-world lessons from the Equifax breach](#attack-example-equifax-ognl-injection-via-apache-struts-2017) +- [Automated validation governance and linting rules](#automated-governance-for-validation) +- [Input validation monitoring and troubleshooting](#input-validation-monitoring) + +--- + +## Quick Start Guide + +Ready to implement secure input validation? Follow these steps: + +1. **Define validation rules:** Start with [schema-based validation](#schema-based-validation-as-security-contract) to create security contracts in your OpenAPI specifications +2. **Implement attack prevention:** Set up [SQL injection and mass assignment protection](#attack-prevention-strategies) using parameterized queries and `additionalProperties: false` +3. **Add governance rules:** Configure [automated governance](#automated-governance-for-validation) to prevent accidentally unvalidated endpoints +4. **Set up monitoring:** Implement [validation monitoring](#input-validation-monitoring) to detect attack attempts and track security metrics +5. **Handle edge cases:** Use [advanced validation techniques](#advanced-validation-techniques) for custom formats and contextual rules + +**Next Steps:** Now that you have input validation covered, learn about [API Rate Limiting and Abuse Prevention](api-rate-limiting-abuse-prevention) to protect your APIs from denial-of-service attacks and business logic abuse. --- @@ -38,68 +52,250 @@ Proper data validation is a critical defense against a wide range of attacks, no If the API fails to validate the input and passes it directly to a database or the operating system, that malicious code could be executed. By strictly validating that all inputs are what they are supposed to be, an API can reject malicious payloads before they can do any harm. -## SQL Injection Prevention +## Attack Prevention Strategies + +Choose the appropriate prevention strategy based on the attack vector you're protecting against: + +{% tabs %} + {% tab label="SQL Injection Prevention" %} + +### SQL Injection Prevention For interactions with a database, the gold standard for preventing SQL injection attacks is the use of parameterized queries, also known as prepared statements. A parameterized query forces a separation between the SQL command (the code) and the user-supplied data, making it impossible for an attacker to alter the logic of the query. -**Vulnerable Code (Never Do This):** -```python -# DANGEROUS: Directly interpolating user input -user_id = request.get('user_id') -query = f"SELECT * FROM users WHERE id = {user_id}" -cursor.execute(query) +**Before vs After: Preventing SQL Injection** + +```javascript {% title="Secure Database Query Implementation" %} +// Step 1: Receive user input from request (potentially malicious) +const userId = req.query.user_id; // Could contain: "1; DROP TABLE users;--" + +// VULNERABLE APPROACH - NEVER DO THIS # [!code error] +// Problem: Direct string interpolation allows malicious code injection +const vulnerableQuery = `SELECT * FROM users WHERE id = ${userId}`; // Creates: SELECT * FROM users WHERE id = 1; DROP TABLE users;-- +// The database sees this as TWO commands: a SELECT and a DROP TABLE +const vulnerableResult = await db.query(vulnerableQuery); // Executes both commands - deletes entire table! + +// SECURE APPROACH - ALWAYS USE PARAMETERIZED QUERIES # [!code highlight] +// Solution: SQL structure and data are separated at database level +const secureQuery = "SELECT * FROM users WHERE id = $1"; // SQL structure defined first +const secureResult = await db.query(secureQuery, [userId]); // Data bound separately as parameter + +// Why this works: # [!code highlight] +// - Database parses SQL structure before receiving user data # [!code highlight] +// - User input is treated as literal data, never as executable code # [!code highlight] +// - Even "1; DROP TABLE users;--" becomes a harmless literal string value # [!code highlight] + +// Full Express.js route example: +app.get('/users/:id', async (req, res) => { + try { + const userId = req.params.id; + const result = await db.query('SELECT * FROM users WHERE id = $1', [userId]); + res.json(result.rows[0] || { error: 'User not found' }); + } catch (error) { + console.error('Database error:', error); + res.status(500).json({ error: 'Internal server error' }); + } +}); ``` -**Secure Code (Use Parameterized Queries):** -```python -# SAFE: Using parameterized queries -user_id = request.get('user_id') -query = "SELECT * FROM users WHERE id = ?" -cursor.execute(query, (user_id,)) +**How SQL injection prevention works:** +- **Parameterized queries**: The SQL structure is defined separately from user data +- **Data binding**: User input is bound to parameters after the SQL structure is parsed +- **No code injection**: Even malicious input like `1 OR 1=1; DROP TABLE users;` is treated as literal data +- **Database driver security**: Modern database drivers automatically escape parameter values + +{% /tab %} +{% tab label="Mass Assignment Prevention" %} + +### Mass Assignment Attack Prevention + +Mass assignment attacks occur when an application accepts more input parameters than expected, allowing attackers to modify fields they shouldn't have access to. The `additionalProperties: false` constraint is essential for preventing these attacks. + +**Mass Assignment Prevention: Before vs After** + +```yaml {% title="Securing Against Mass Assignment (OWASP API3:2023)" %} +NewUser: + type: object + # CRITICAL SECURITY SETTING: additionalProperties defaults to true - DANGEROUS! # [!code error] + # Without this setting, attackers can inject ANY extra fields into requests # [!code highlight] + additionalProperties: false # [!code error] ESSENTIAL: Blocks mass assignment - REQUIRED for security + + # STEP 1: Define ONLY the fields that should be accepted # [!code highlight] + properties: + name: + type: string + minLength: 1 # Prevent empty names + maxLength: 100 # Prevent buffer overflow attacks + pattern: "^[a-zA-Z\\s]+$" # Allow only letters and spaces + email: + type: string + format: email # Built-in email validation prevents malformed input + maxLength: 254 # Prevent resource exhaustion (RFC 5321 limit) + + # STEP 2: Require critical fields to prevent incomplete records # [!code highlight] + required: # These fields MUST be provided + - name # User identification required + - email # Contact method required + +# What this prevents: # [!code highlight] +# Malicious request: {"name": "John", "email": "john@test.com", "isAdmin": true, "balance": 999999} # [!code highlight] +# Result: isAdmin and balance fields are BLOCKED and ignored # [!code highlight] +``` + +**How mass assignment prevention works:** +- **`additionalProperties: false`**: Rejects any properties not explicitly defined in the schema +- **Explicit allow-listing**: Only defined properties are accepted, unknown fields are blocked +- **Field-level validation**: Each allowed property has its own validation constraints +- **Attack surface reduction**: Prevents unauthorized modification of sensitive fields like `isAdmin`, `balance`, or `role` + +**What this prevents**: +```json {% title="Malicious Request Example" %} +// This attack payload is blocked with additionalProperties: false +{ + "name": "John Doe", + "email": "john@example.com", + "isAdmin": true, // [!code error] Blocked - not in schema + "balance": 1000000 // [!code error] Blocked - not in schema +} ``` +{% /tab %} +{% /tabs %} + ## Schema-Based Validation as Security Contract OpenAPI 3.1 provides a comprehensive vocabulary for defining strict validation rules by leveraging JSON Schema Draft 2020-12. By codifying these rules directly in your API specification, validation becomes core to your API's design. -**Secure Schema Example:** -```yaml {% title="openapi.yaml" %} +**Secure API Schema with Input Validation** + +```yaml {% title="openapi.yaml - Comprehensive Security Validation Schema" %} components: schemas: NewUser: type: object - additionalProperties: false # Prevent mass assignment (OWASP API3:2023) + # STEP 1: CRITICAL MASS ASSIGNMENT PROTECTION - blocks OWASP API3:2023 # [!code error] + additionalProperties: false # [!code error] ESSENTIAL: Prevents attackers from injecting extra fields + + # STEP 2: Define required fields to prevent incomplete records # [!code highlight] required: - - username - - email - - password - - age + - username # User identification - mandatory + - email # Contact method - mandatory + - password # Authentication credential - mandatory + - age # Legal compliance (COPPA, etc.) + properties: + # STEP 3: Username validation - prevent enumeration and injection # [!code highlight] username: type: string - minLength: 4 - maxLength: 20 # Prevent resource exhaustion (OWASP API4:2023) - pattern: "^[a-zA-Z0-9]+$" # Prevent injection attacks + minLength: 4 # Prevent too-short usernames (harder to guess) + maxLength: 20 # OWASP API4:2023: Prevent resource exhaustion + pattern: "^[a-zA-Z0-9_-]+$" # Allow-list only safe characters (blocks XSS, injection) + description: "Alphanumeric characters, underscores, and hyphens only" + example: "john_doe123" + + # STEP 4: Email validation - prevent malformed addresses and attacks # [!code highlight] email: type: string - maxLength: 254 # Prevent resource exhaustion (OWASP API4:2023) - format: email + minLength: 5 # Shortest valid email: "a@b.c" + maxLength: 254 # RFC 5321 limit - prevents buffer overflow + format: email # Built-in validation (RFC 5322 format) + description: "Must be a valid email address according to RFC 5322" + example: "user@example.com" + + # STEP 5: Password constraints - security + usability balance # [!code highlight] password: type: string - minLength: 12 - maxLength: 128 + minLength: 12 # NIST recommends 12+ chars for user passwords + maxLength: 128 # Allow long passphrases but prevent DoS + description: | + Password requirements: + - Minimum 12 characters (strong security baseline) + - Maximum 128 characters (prevents resource exhaustion) + - No composition requirements (per NIST 800-63B) + example: "MySecurePassphrase123!" + writeOnly: true # [!code error] CRITICAL: NEVER return passwords in responses + + # STEP 6: Age validation - legal compliance and reasonableness checks # [!code highlight] age: type: integer - minimum: 18 - maximum: 130 # Prevent integer overflow attacks + minimum: 13 # COPPA compliance (US law for child privacy) + maximum: 130 # Prevent integer overflow attacks + description: "User age in years (COPPA compliance requires 13+)" + example: 25 + + # STEP 7: Role-based access control with allow-list approach # [!code highlight] role: type: string - enum: ["user", "viewer"] # Enforce allow-list approach - default: "user" + enum: ["user", "premium", "moderator"] # [!code error] CRITICAL: Allow-list prevents privilege escalation + default: "user" # Secure default (least privilege) + description: "User role determines access permissions" + + # STEP 8: Optional fields with validation (shows pattern for expansion) # [!code highlight] + profile: + type: object + additionalProperties: false # [!code highlight] Nested objects also need mass assignment protection + properties: + firstName: + type: string + minLength: 1 + maxLength: 50 # Reasonable limits prevent storage abuse + pattern: "^[\\p{L}\\s'-]+$" # Unicode letters, spaces, hyphens, apostrophes + description: "First name (supports international characters)" + lastName: + type: string + minLength: 1 + maxLength: 50 + pattern: "^[\\p{L}\\s'-]+$" + description: "Last name (supports international characters)" + bio: + type: string + maxLength: 500 # Prevent excessive text storage + description: "User biography (plain text only)" + + # STEP 9: Contact preferences with validation # [!code highlight] + preferences: + type: object + additionalProperties: false # [!code highlight] Every nested object needs this protection + properties: + newsletter: + type: boolean + default: false # Privacy-friendly default (opt-in) + description: "Subscribe to newsletter (GDPR compliant opt-in)" + notifications: + type: array + maxItems: 10 # [!code error] CRITICAL: Prevent array abuse/DoS attacks + uniqueItems: true # No duplicate notification types + items: + type: string + enum: ["email", "sms", "push", "in-app"] # Allow-list notification channels + description: "Preferred notification channels" + +# STEP 10: Common validation patterns for reuse # [!code highlight] +ValidationPattern: + # Phone number with international support + PhoneNumber: + type: string + pattern: "^\\+[1-9]\\d{1,14}$" # [!code highlight] SECURITY: E.164 format prevents malformed numbers + maxLength: 15 # International standard maximum + example: "+1234567890" + + # URL validation for security + SecureUrl: + type: string + format: uri # Basic URI validation + pattern: "^https://.*" # [!code error] CRITICAL: FORCE HTTPS - no HTTP allowed + maxLength: 2048 # Prevent excessively long URLs + example: "https://example.com" ``` +**Key Security Controls**: +- **`additionalProperties: false`** blocks mass assignment attacks +- **Length constraints** prevent buffer overflow and resource exhaustion +- **Pattern validation** blocks injection attempts and malformed data +- **Enum restrictions** enforce allow-lists instead of dangerous validation bypass + ### Automated Governance for Validation Modern API governance tools can enforce input validation rules that require string length bounds, numeric ranges, and prevent mass assignment vulnerabilities. @@ -202,63 +398,32 @@ sequenceDiagram Why this matters: Strong schema validation, input allow-lists, and patch hygiene block entire classes of injection attacks. -## Mass Assignment Attack Prevention +**Security operations:** When schema validation and [attack prevention strategies](#attack-prevention-strategies) are in place, implement [monitoring](#input-validation-monitoring) to detect attempted breaches and [advanced validation techniques](#advanced-validation-techniques) for complex scenarios. -Mass assignment attacks occur when an application accepts more input parameters than expected, allowing attackers to modify fields they shouldn't have access to. The `additionalProperties: false` constraint is essential for preventing these attacks. - -**Vulnerable API (allows additional properties):** -```yaml -# BAD: Allows any additional properties -NewUser: - type: object - # additionalProperties defaults to true - DANGEROUS! - properties: - name: - type: string - email: - type: string -``` +## Input Validation Monitoring -**Secure API (blocks additional properties):** -```yaml -# GOOD: Explicitly blocks additional properties -NewUser: - type: object - additionalProperties: false # Critical for security - properties: - name: - type: string - email: - type: string -``` +Choose your monitoring approach based on your security operations needs: -**Attack scenario:** -```json -// Attacker sends this payload -{ - "name": "John Doe", - "email": "john@example.com", - "role": "admin" // Mass assignment attack! -} -``` +{% tabs %} + {% tab label="Validation Logging (JavaScript)" %} -With `additionalProperties: false`, the API rejects the entire request. Without it, the attacker might successfully elevate their privileges. +### Validation Failure Logging -## Input Validation Monitoring +**Express.js Middleware for Security Monitoring** -### Validation Failure Logging -```javascript -// Log validation failures for analysis +```javascript {% title="validation-logger.js" %} +// Middleware to log validation failures for security analysis app.use((req, res, next) => { const originalSend = res.send; res.send = function(data) { - if (res.statusCode === 400 && req.validationErrors) { - logger.warn('Validation failure', { - endpoint: req.path, - errors: req.validationErrors, - clientIP: req.ip, - userAgent: req.get('User-Agent') + // Track validation failures for potential attack patterns + if (res.statusCode === 400 && req.validationErrors) { // [!code highlight] + logger.warn('Validation failure', { // [!code highlight] + endpoint: req.path, // [!code highlight] Track which endpoints are targeted + errors: req.validationErrors, // [!code highlight] Log specific validation failures + clientIP: req.ip, // [!code highlight] Track source IPs for analysis + userAgent: req.get('User-Agent') // [!code highlight] Detect automated attacks }); } @@ -269,26 +434,92 @@ app.use((req, res, next) => { }); ``` +**How validation logging works:** +- **Middleware interception**: Captures all responses before they're sent to clients +- **Status code filtering**: Only logs when `statusCode === 400` (validation failures) +- **Structured logging**: Records endpoint, errors, IP, and user agent for security analysis +- **Attack pattern detection**: Unusual spikes or repeated failures from same IPs indicate potential attacks + +**Why this matters**: Logging validation failures helps detect attack patterns, frequent probe attempts, and potential security issues before they escalate. Monitor these logs for unusual spikes or repeated failures from the same IP addresses. + +{% /tab %} +{% tab label="Validation Metrics (JavaScript)" %} + ### Validation Metrics -```python -# Track validation patterns for security analysis -class ValidationMetrics: - def __init__(self): - self.validation_failures = defaultdict(int) - self.attack_patterns = defaultdict(int) + +```javascript +// Track validation patterns for security analysis +class ValidationMetrics { + constructor() { + this.validationFailures = new Map(); // [!code highlight] Count failures by type + this.attackPatterns = new Map(); // [!code highlight] Track potential attacks + } - def record_failure(self, endpoint, field, error_type): - key = f"{endpoint}:{field}:{error_type}" - self.validation_failures[key] += 1 + recordFailure(endpoint, field, errorType) { + const key = `${endpoint}:${field}:${errorType}`; - # Detect potential attack patterns - if error_type in ['pattern_violation', 'length_exceeded', 'additional_property']: - self.attack_patterns[endpoint] += 1 + // Initialize counter if key doesn't exist + if (!this.validationFailures.has(key)) { + this.validationFailures.set(key, 0); + } + this.validationFailures.set(key, this.validationFailures.get(key) + 1); // [!code highlight] Increment failure counter + + // Detect potential attack patterns // [!code highlight] + const attackTypes = ['pattern_violation', 'length_exceeded', 'additional_property']; + if (attackTypes.includes(errorType)) { + if (!this.attackPatterns.has(endpoint)) { + this.attackPatterns.set(endpoint, 0); + } + this.attackPatterns.set(endpoint, this.attackPatterns.get(endpoint) + 1); // [!code highlight] Flag suspicious activity + } + } + + getAttackSummary() { + return Object.fromEntries(this.attackPatterns); // [!code highlight] Return attack metrics + } - def get_attack_summary(self): - return dict(self.attack_patterns) + // Additional utility method for comprehensive metrics + getFailureReport() { + return { + totalFailures: this.validationFailures.size, + attackPatterns: this.getAttackSummary(), + topFailureTypes: Object.fromEntries(this.validationFailures) + }; + } +} + +// Usage in Express.js validation middleware +const validationMetrics = new ValidationMetrics(); + +function trackValidationError(req, field, errorType) { + const endpoint = req.route?.path || req.path; + validationMetrics.recordFailure(endpoint, field, errorType); + + // Log for immediate monitoring + console.warn('Validation failure tracked', { + endpoint, + field, + errorType, + ip: req.ip, + userAgent: req.get('User-Agent') + }); +} ``` +**How validation metrics work:** +- **Failure tracking**: Counts validation failures by endpoint, field, and error type +- **Pattern detection**: Identifies suspicious error types that often indicate attacks +- **Attack scoring**: Tracks which endpoints receive the most attack attempts +- **Metrics export**: Provides data for security dashboards and alerting systems + +**Key metrics to monitor:** +- **`pattern_violation`**: Input doesn't match expected format (possible injection attempt) +- **`length_exceeded`**: Input too long (buffer overflow or DoS attempt) +- **`additional_property`**: Extra fields in request (mass assignment attack) + +{% /tab %} +{% /tabs %} + ## Advanced Validation Techniques ### Custom Format Validators @@ -349,19 +580,19 @@ components: ## Frequently Asked Questions ### How does OpenAPI validation prevent injection attacks? -OpenAPI specifications define precise data schemas with type validation, format constraints, and length limits. When enforced by governance tools, these schemas automatically reject malformed inputs that could contain injection payloads, stopping attacks before they reach your application logic. +OpenAPI specifications define precise data schemas with type validation, format constraints, and length limits. When enforced by [automated governance](#automated-governance-for-validation), these schemas automatically reject malformed inputs that could contain injection payloads, stopping attacks before they reach your application logic. See [Schema-Based Validation as Security Contract](#schema-based-validation-as-security-contract) for implementation details. ### What's the difference between client-side and server-side validation? -Client-side validation improves user experience by providing immediate feedback, but it can be bypassed by attackers. Server-side validation is the critical security control—never trust data from the client. Always validate on the server even if you also validate on the client. +Client-side validation improves user experience by providing immediate feedback, but it can be bypassed by attackers. Server-side validation is the critical security control—never trust data from the client. Always validate on the server even if you also validate on the client. Review our [attack prevention strategies](#attack-prevention-strategies) to understand why server-side validation is essential. ### Should I validate HTTP headers and query parameters? -Yes! The Equifax breach occurred through a malicious `Content-Type` header. All inputs—including headers, query parameters, path parameters, and request bodies—should be validated against strict schemas. Don't assume any input is safe. +Yes! The [Equifax breach](#attack-example-equifax-ognl-injection-via-apache-struts-2017) occurred through a malicious `Content-Type` header. All inputs—including headers, query parameters, path parameters, and request bodies—should be validated against strict schemas. Don't assume any input is safe. ### How do I handle file uploads securely? -File uploads require special attention: validate file types using content inspection (not just extensions), enforce size limits, scan for malware, store files outside the web root, and use content-disposition headers to prevent execution. Consider using dedicated file storage services. +File uploads require special attention: validate file types using content inspection (not just extensions), enforce size limits, scan for malware, store files outside the web root, and use content-disposition headers to prevent execution. Consider using dedicated file storage services with [advanced validation techniques](#advanced-validation-techniques). ### What's the performance impact of extensive validation? -Modern validation libraries are highly optimized. The security benefit far outweighs the minimal performance cost. Consider caching compiled schemas and using efficient validation libraries like `ajv` for JavaScript or `jsonschema` for Python. +Modern validation libraries are highly optimized. The security benefit far outweighs the minimal performance cost. Consider caching compiled schemas and using efficient validation libraries like `ajv` for JavaScript or `jsonschema` for Python. Implement [validation monitoring](#input-validation-monitoring) to track performance impacts. ## Resources and Next Steps @@ -384,8 +615,4 @@ Modern validation libraries are highly optimized. The security benefit far outwe - [API TLS Encryption and HTTPS Best Practices](api-tls-encryption-https-best-practices) - Secure data in transit - [API Rate Limiting and Abuse Prevention](api-rate-limiting-abuse-prevention) - Prevent DoS attacks and abuse - [Authentication and Authorization with OpenAPI](authentication-authorization-openapi) - Implement secure access control -- [API Security by Design: Complete Guide](/learn/security) - Overview of all API security domains - ---- - -**Next Steps:** Now that you have input validation covered, learn about [API Rate Limiting and Abuse Prevention](api-rate-limiting-abuse-prevention) to protect your APIs from denial-of-service attacks and business logic abuse. \ No newline at end of file +- [API Security by Design: Complete Guide](/learn/security) - Overview of all API security domains \ No newline at end of file diff --git a/learn/security/api-rate-limiting-abuse-prevention.md b/learn/security/api-rate-limiting-abuse-prevention.md index 3c00822b..823b7624 100644 --- a/learn/security/api-rate-limiting-abuse-prevention.md +++ b/learn/security/api-rate-limiting-abuse-prevention.md @@ -15,12 +15,26 @@ seo: A single client, whether intentionally malicious or simply due to a bug in its code, can send a massive number of requests to an API in a short period. This can overwhelm the server, degrading performance for all other users or even causing the service to crash. Rate limiting is the primary defense against this scenario. **In this guide, you'll learn:** -- How to implement rate limiting as a security and reliability control -- OpenAPI x-rateLimit extensions and documentation strategies -- Rate limiting algorithms and multi-tier implementation patterns -- Client-side exponential backoff and error handling -- Real-world lessons from the Facebook phone number scraping incident -- Advanced rate limiting techniques and monitoring approaches +- [How to implement rate limiting](#documenting-rate-limits-in-openapi) as a security and reliability control +- [OpenAPI x-rateLimit extensions](#documenting-rate-limits-in-openapi) and documentation strategies +- [Rate limiting algorithms and implementation patterns](#rate-limiting-implementation-approaches) +- [Client-side exponential backoff](#client-side-exponential-backoff) and error handling +- [Real-world lessons from the Facebook phone number scraping incident](#attack-example-facebook-phone-number-scraping-2019) +- [Advanced techniques and monitoring approaches](#rate-limiting-monitoring-and-observability) + +--- + +## Quick Start Guide + +Ready to implement effective rate limiting? Follow these steps: + +1. **Document rate limits:** Add [OpenAPI x-rateLimit extensions](#documenting-rate-limits-in-openapi) to your API specifications +2. **Choose an algorithm:** Select from [Token Bucket, Sliding Window, or Fixed Window](#rate-limiting-implementation-approaches) based on your needs +3. **Implement multi-tier limits:** Set up global, per-endpoint, and per-client [rate limiting configurations](#advanced-rate-limiting-techniques) +4. **Set up monitoring:** Implement [metrics collection and alerting](#rate-limiting-monitoring-and-observability) to detect attacks +5. **Test and tune:** Use the [implementation strategy framework](#rate-limiting-strategy-framework) to prioritize critical endpoints and validate limits + +**Next Steps:** Now that you have rate limiting protection in place, learn about [Authentication and Authorization with OpenAPI](authentication-authorization-openapi) to implement comprehensive access control for your APIs. --- @@ -52,28 +66,28 @@ paths: post: summary: User Login tags: [Authentication] - # Define rate-limiting policy for this sensitive endpoint + # Define rate-limiting policy for this sensitive endpoint # [!code highlight] x-rateLimit: - limit: 5 - window: "1m" - scope: "ip_address" + limit: 5 # [!code highlight] Strict limit for auth endpoints + window: "1m" # [!code highlight] Short time window + scope: "ip_address" # [!code highlight] IP-based rate limiting description: "Limits login attempts to 5 per minute per IP to prevent brute-force attacks." responses: '200': description: "Successful login." - # Document the 429 response with proper headers + # Document the 429 response with proper headers # [!code highlight] '429': description: "Too Many Requests. Rate limit exceeded." headers: - Retry-After: + Retry-After: # [!code highlight] Required for proper client behavior schema: type: integer description: "Seconds to wait before making a new request." - X-RateLimit-Limit: + X-RateLimit-Limit: # [!code highlight] Inform clients of limits schema: type: integer description: "Maximum requests permitted in the window." - X-RateLimit-Remaining: + X-RateLimit-Remaining: # [!code highlight] Help clients pace requests schema: type: integer description: "Requests remaining in current window." @@ -89,42 +103,257 @@ This approach provides dual benefits: modern API documentation tools automatical ## Rate Limiting Implementation Approaches -### Common Algorithm Types - -**Token Bucket**: Allows burst traffic within limits, refills at steady rate -- Best for: APIs that need to handle legitimate traffic spikes -- Pros: Flexible, allows bursts, smooth long-term rate limiting -- Cons: More complex to implement, requires state management - -**Sliding Window**: Precise per-window enforcement with distributed request tracking -- Best for: APIs requiring exact rate limiting precision -- Pros: Most accurate, prevents boundary condition abuse -- Cons: Memory intensive, complex distributed implementation - -**Fixed Window**: Simple per-timeframe limits, prone to boundary conditions -- Best for: Simple use cases, easy implementation -- Pros: Simple to implement and understand -- Cons: Allows traffic spikes at window boundaries - -### Multi-tier Strategy Example - -```yaml {% title="API Gateway configuration" %} -rate_limits: - global: - requests_per_minute: 1000 - requests_per_hour: 10000 - by_endpoint: - "/auth/*": - requests_per_minute: 5 - requests_per_hour: 20 - "/api/data": - requests_per_minute: 100 - requests_per_hour: 2000 - "/api/search": - requests_per_minute: 50 - requests_per_hour: 1000 +Choose the rate limiting algorithm that best fits your traffic patterns and precision requirements: + +{% tabs %} + {% tab label="Token Bucket" %} + +### Token Bucket Algorithm + +**Best for:** APIs that need to handle legitimate traffic spikes + +**How it works:** +- Tokens are added to a bucket at a steady rate (refill rate) +- Each request consumes one token from the bucket +- If bucket is empty, requests are rejected or queued +- Allows burst traffic up to bucket capacity + +**Pros:** +- **Flexible burst handling**: Accommodates legitimate traffic spikes +- **Smooth long-term limiting**: Maintains steady average rate +- **User-friendly**: Doesn't penalize users for occasional bursts + +**Cons:** +- **Implementation complexity**: Requires token state management +- **Memory overhead**: Need to track bucket state per client +- **Distributed challenges**: Synchronizing token state across servers + +**Implementation example:** +```javascript {% title="token-bucket.js - Secure Rate Limiting Algorithm" %} +class TokenBucket { + constructor(capacity, refillRate) { + // STEP 1: Initialize bucket parameters + this.capacity = capacity; // Max burst size (e.g., 100 requests) + this.tokens = capacity; // Start with full bucket (allows immediate bursts) + this.refillRate = refillRate; // Steady rate (e.g., 10 requests/second) + this.lastRefill = Date.now(); // Track when we last added tokens + } + + // STEP 2: Process incoming request - the main security enforcement point + consume(tokens = 1) { + // First, add any tokens we've earned since last request + this.refill(); // CRITICAL: Always refill before checking + + // STEP 3: Security decision - allow or block the request + if (this.tokens >= tokens) { + this.tokens -= tokens; // Consume tokens for this request + return true; // ✅ REQUEST ALLOWED - user under limit + } + + // STEP 4: Rate limit exceeded - implement security response + console.warn(`Rate limit exceeded. Tokens available: ${this.tokens}, requested: ${tokens}`); + return false; // ❌ BLOCK REQUEST - user over limit + } + + // STEP 5: Token refill logic - implements the "steady rate" behavior + refill() { + const now = Date.now(); + const timePassed = (now - this.lastRefill) / 1000; // Convert to seconds + + // Calculate tokens earned: time × rate + const tokensToAdd = Math.floor(timePassed * this.refillRate); // Floor prevents fractional tokens + + if (tokensToAdd > 0) { + // Add tokens but never exceed capacity (prevents bucket overflow) + this.tokens = Math.min(this.capacity, this.tokens + tokensToAdd); + this.lastRefill = now; // Update timestamp for next calculation + + console.debug(`Added ${tokensToAdd} tokens. Current: ${this.tokens}/${this.capacity}`); + } + } + + // STEP 6: Utility methods for monitoring and debugging + getStatus() { + this.refill(); // Ensure current state + return { + tokens: this.tokens, // Available tokens right now + capacity: this.capacity, // Maximum burst size + utilizationPercent: ((this.capacity - this.tokens) / this.capacity * 100).toFixed(1) + }; + } +} + +// EXAMPLE USAGE: Protect login endpoint from brute force +const loginRateLimit = new TokenBucket(5, 0.1); // 5 attempts, refill 1 every 10 seconds + +// In your API endpoint: +app.post('/auth/login', (req, res) => { + const clientId = req.ip || req.headers['x-client-id']; // Identify the client + + if (!loginRateLimit.consume()) { + return res.status(429).json({ // HTTP 429 = Too Many Requests + error: 'Rate limit exceeded', + retryAfter: Math.ceil((1 / loginRateLimit.refillRate)) // Tell client when to retry + }); + } + + // Process login attempt... // Only reached if under rate limit +}); ``` + {% /tab %} + {% tab label="Sliding Window" %} + +### Sliding Window Algorithm + +**Best for:** APIs requiring exact rate limiting precision + +**How it works:** +- Tracks exact timestamps of requests within a rolling time window +- Continuously slides the window forward with each request +- Provides most accurate rate limiting without boundary conditions + +**Pros:** +- **Maximum accuracy**: No boundary condition exploits +- **Precise enforcement**: Exact request counting within time windows +- **Fair distribution**: Prevents gaming of window boundaries + +**Cons:** +- **Memory intensive**: Stores timestamp for each request +- **Complex implementation**: Requires efficient data structures +- **Distributed complexity**: Hard to synchronize across multiple servers + +**Implementation example:** +```javascript {% title="sliding-window.js" %} +class SlidingWindowRateLimit { + constructor(maxRequests, windowSeconds) { + this.maxRequests = maxRequests; // [!code highlight] Maximum requests allowed + this.windowSeconds = windowSeconds; // [!code highlight] Time window in seconds + this.requests = []; // [!code highlight] Store request timestamps + } + + isAllowed() { + const now = Date.now(); + const windowMs = this.windowSeconds * 1000; + + // Remove requests outside current window // [!code highlight] + while (this.requests.length > 0 && this.requests[0] <= now - windowMs) { + this.requests.shift(); // [!code highlight] Clean old timestamps + } + + // Check if we're under the limit + if (this.requests.length < this.maxRequests) { + this.requests.push(now); // [!code highlight] Record this request + return true; // [!code highlight] Request allowed + } + + return false; // [!code error] Rate limit exceeded + } + + // Utility method to get current status + getStatus() { + const now = Date.now(); + const windowMs = this.windowSeconds * 1000; + + // Clean old requests first + while (this.requests.length > 0 && this.requests[0] <= now - windowMs) { + this.requests.shift(); + } + + return { + currentRequests: this.requests.length, + maxRequests: this.maxRequests, + remaining: this.maxRequests - this.requests.length, + windowSeconds: this.windowSeconds + }; + } +} +``` + + {% /tab %} + {% tab label="Fixed Window" %} + +### Fixed Window Algorithm + +**Best for:** Simple use cases with easy implementation requirements + +**How it works:** +- Divides time into fixed intervals (e.g., per minute, per hour) +- Counts requests within each fixed window +- Resets counter at the start of each new window + +**Pros:** +- **Simple implementation**: Easy to understand and code +- **Low memory usage**: Only need counter per time window +- **Distributed-friendly**: Easy to implement with shared counters + +**Cons:** +- **Boundary condition abuse**: 2x rate limit possible at window edges +- **Traffic spikes**: All requests could arrive at start of window +- **Less user-friendly**: Sudden cutoffs can impact user experience + +**Implementation example:** +```javascript {% title="fixed-window.js" %} +class FixedWindowRateLimit { + constructor(maxRequests, windowMs) { + this.maxRequests = maxRequests; // [!code highlight] Maximum requests per window + this.windowMs = windowMs; // [!code highlight] Window duration in milliseconds + this.counter = new Map(); // [!code highlight] Request counters by client + this.windowStart = new Map(); // [!code highlight] Window start times + } + + isAllowed(clientId) { + const now = Date.now(); + const windowStart = this.windowStart.get(clientId); + + // Check if we're in a new window // [!code highlight] + if (!windowStart || (now - windowStart) >= this.windowMs) { + this.windowStart.set(clientId, now); // [!code highlight] Start new window + this.counter.set(clientId, 1); // [!code highlight] Reset counter + return true; // [!code highlight] Request allowed + } + + // Check current window limit + const currentCount = this.counter.get(clientId) || 0; + if (currentCount < this.maxRequests) { + this.counter.set(clientId, currentCount + 1); // [!code highlight] Increment counter + return true; // [!code highlight] Request allowed + } + + return false; // [!code error] Rate limit exceeded + } + + // Utility method to get window status for a client + getWindowStatus(clientId) { + const now = Date.now(); + const windowStart = this.windowStart.get(clientId); + const currentCount = this.counter.get(clientId) || 0; + + if (!windowStart) { + return { + requests: 0, + maxRequests: this.maxRequests, + remaining: this.maxRequests, + timeUntilReset: this.windowMs + }; + } + + const timeElapsed = now - windowStart; + const timeUntilReset = Math.max(0, this.windowMs - timeElapsed); + + return { + requests: currentCount, + maxRequests: this.maxRequests, + remaining: Math.max(0, this.maxRequests - currentCount), + timeUntilReset + }; + } +} +``` + + {% /tab %} +{% /tabs %} + ## Advanced Rate Limiting Techniques ### Multi-tier Rate Limiting Configuration @@ -207,44 +436,72 @@ Why this matters: Rate limiting, velocity checks, and behavior analytics are cor ## Rate Limiting Monitoring and Observability -### Rate Limiting Metrics Collection +Choose your monitoring approach based on your security operations needs: + +{% tabs %} + {% tab label="Metrics Collection (JavaScript)" %} -```python -# Track rate limiting metrics for security analysis -import time -from collections import defaultdict +### Rate Limiting Metrics Collection -class RateLimitMetrics: - def __init__(self): - self.blocked_requests = defaultdict(int) - self.total_requests = defaultdict(int) - self.suspicious_patterns = defaultdict(list) +```javascript +// Track rate limiting metrics for security analysis +class RateLimitMetrics { + constructor() { + this.blockedRequests = new Map(); // [!code highlight] Count blocked requests by client + this.totalRequests = new Map(); // [!code highlight] Count total requests by client + this.suspiciousPatterns = new Map(); // [!code highlight] Track attack patterns + } - def record_request(self, client_id, blocked=False, endpoint=None): - self.total_requests[client_id] += 1 - if blocked: - self.blocked_requests[client_id] += 1 - # Track suspicious patterns - self.suspicious_patterns[client_id].append({ - 'timestamp': time.time(), - 'endpoint': endpoint, - 'blocked': True - }) + recordRequest(clientId, blocked = false, endpoint = null) { + // Initialize counters if client is new + if (!this.totalRequests.has(clientId)) { + this.totalRequests.set(clientId, 0); + this.blockedRequests.set(clientId, 0); + this.suspiciousPatterns.set(clientId, []); + } + + this.totalRequests.set(clientId, this.totalRequests.get(clientId) + 1); // [!code highlight] Increment request counter + + if (blocked) { + this.blockedRequests.set(clientId, this.blockedRequests.get(clientId) + 1); // [!code highlight] Track blocked request + + // Track suspicious patterns // [!code highlight] + const patterns = this.suspiciousPatterns.get(clientId); + patterns.push({ + timestamp: Date.now(), // [!code highlight] When attack occurred + endpoint: endpoint, // [!code highlight] Which endpoint targeted + blocked: true // [!code highlight] Request was blocked + }); + this.suspiciousPatterns.set(clientId, patterns); + } + } - def get_block_rate(self, client_id): - total = self.total_requests[client_id] - blocked = self.blocked_requests[client_id] - return (blocked / total) * 100 if total > 0 else 0 + getBlockRate(clientId) { + const total = this.totalRequests.get(clientId) || 0; + const blocked = this.blockedRequests.get(clientId) || 0; + return total > 0 ? (blocked / total) * 100 : 0; + } - def get_attack_indicators(self, client_id, window_minutes=5): - """Detect rapid repeated attempts that might indicate an attack""" - recent_blocks = [ - event for event in self.suspicious_patterns[client_id] - if time.time() - event['timestamp'] < window_minutes * 60 - ] - return len(recent_blocks) + getAttackIndicators(clientId, windowMinutes = 5) { + // Detect rapid repeated attempts that might indicate an attack + const patterns = this.suspiciousPatterns.get(clientId) || []; + const recentBlocks = patterns.filter(event => // [!code highlight] Filter recent blocked requests + Date.now() - event.timestamp < windowMinutes * 60 * 1000 + ); + return recentBlocks.length; // [!code highlight] Return attack indicator count + } +} ``` +**How metrics collection works:** +- **Request tracking**: Counts all requests and blocked requests per client +- **Pattern detection**: Records timestamps and endpoints for blocked requests +- **Attack indicators**: Identifies rapid repeated attempts within time windows +- **Block rate calculation**: Calculates percentage of requests blocked per client + +{% /tab %} +{% tab label="Alerting Configuration (Prometheus)" %} + ### Alerting Configuration ```yaml {% title="prometheus-alerts.yml" %} @@ -261,15 +518,24 @@ groups: description: "{{ $value }} requests per second being blocked" - alert: SuspiciousRateLimitPattern - expr: rate_limit_block_rate > 80 - for: 1m + expr: rate_limit_block_rate > 80 # [!code highlight] 80% block rate threshold + for: 1m # [!code highlight] Alert after 1 minute labels: - severity: critical + severity: critical # [!code error] Critical security alert annotations: summary: "Possible DDoS or brute force attack" description: "Client {{ $labels.client_id }} has {{ $value }}% blocked rate" ``` +**How alerting works:** +- **HighRateLimitBlocks**: Monitors overall rate of blocked requests across system +- **SuspiciousRateLimitPattern**: Detects clients with abnormally high block rates +- **Threshold-based**: Configurable thresholds trigger security team notifications +- **Context-aware**: Provides client IDs and block rates for investigation + +{% /tab %} +{% /tabs %} + ### Rate Limiting Troubleshooting **Common Issues and Solutions:** @@ -338,27 +604,26 @@ limit_req_zone $binary_remote_addr_internal zone=internal:10m rate=1000r/m; ## Frequently Asked Questions ### Why is rate limiting important for API security? -Rate limiting prevents denial-of-service attacks, brute-force authentication attempts, and data scraping. It ensures fair resource usage among legitimate users while blocking malicious automation. Without rate limits, a single bad actor can overwhelm your API infrastructure. +Rate limiting prevents denial-of-service attacks, brute-force authentication attempts, and data scraping. It ensures fair resource usage among legitimate users while blocking malicious automation. Without rate limits, a single bad actor can overwhelm your API infrastructure. See the [Facebook phone number scraping incident](#attack-example-facebook-phone-number-scraping-2019) for a real-world example. ### What's the difference between rate limiting and throttling? Rate limiting sets hard limits on request volume (e.g., 100 requests per minute), rejecting excess requests with 429 status codes. Throttling typically involves slowing down or queuing requests rather than rejecting them outright. Rate limiting is more common for APIs as it provides clearer client feedback. ### Should rate limits be per-IP, per-user, or both? -Implement multiple layers: per-IP limits prevent DDoS attacks from single sources, per-user limits enforce fair usage policies, and per-API-key limits support tiered service levels. Combine all three for comprehensive protection against different attack patterns. +Implement multiple layers: per-IP limits prevent DDoS attacks from single sources, per-user limits enforce fair usage policies, and per-API-key limits support tiered service levels. Combine all three for comprehensive protection against different attack patterns. See [advanced rate limiting patterns](#advanced-rate-limiting-patterns) for implementation guidance. ### How do I handle legitimate traffic spikes? -Use token bucket algorithms that allow controlled bursts within overall rate limits. Consider implementing adaptive rate limiting that adjusts limits based on server health. For predictable spikes, provide rate limit increase APIs or temporary exemption mechanisms for verified clients. +Use [token bucket algorithms](#rate-limiting-implementation-approaches) that allow controlled bursts within overall rate limits. Consider implementing adaptive rate limiting that adjusts limits based on server health. For predictable spikes, provide rate limit increase APIs or temporary exemption mechanisms for verified clients. ### What rate limiting algorithm should I choose? -- **Token Bucket**: Best for APIs needing burst flexibility -- **Sliding Window**: Most accurate but memory intensive -- **Fixed Window**: Simple but allows boundary condition abuse -- **Sliding Window Log**: Precise but computationally expensive +- **[Token Bucket](#rate-limiting-implementation-approaches)**: Best for APIs needing burst flexibility +- **[Sliding Window](#rate-limiting-implementation-approaches)**: Most accurate but memory intensive +- **[Fixed Window](#rate-limiting-implementation-approaches)**: Simple but allows boundary condition abuse -Choose based on your accuracy requirements, traffic patterns, and implementation complexity tolerance. +Choose based on your accuracy requirements, traffic patterns, and implementation complexity tolerance. See our [implementation approaches](#rate-limiting-implementation-approaches) for detailed comparisons. ### How do I communicate rate limits to API consumers? -Document limits in OpenAPI specifications using `x-rateLimit` extensions, include rate limit headers in responses (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `Retry-After`), provide clear error messages with 429 responses, and maintain public documentation about your rate limiting policies. +Document limits in [OpenAPI specifications using x-rateLimit extensions](#documenting-rate-limits-in-openapi), include rate limit headers in responses (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `Retry-After`), provide clear error messages with 429 responses, and maintain public documentation about your rate limiting policies. ## Rate Limiting Strategy Framework @@ -382,74 +647,80 @@ Document limits in OpenAPI specifications using `x-rateLimit` extensions, includ ### Rate Limit Testing Strategy -```python -# Rate limit testing framework -import asyncio -import aiohttp -import time - -async def test_rate_limit(url, requests_count, window_seconds): - """Test rate limiting behavior""" - start_time = time.time() - successful_requests = 0 - blocked_requests = 0 +```javascript +// Rate limit testing framework +async function testRateLimit(url, requestsCount, windowSeconds) { + /** + * Test rate limiting behavior + * @param {string} url - API endpoint to test + * @param {number} requestsCount - Number of concurrent requests to send + * @param {number} windowSeconds - Expected rate limit window + */ + const startTime = Date.now(); + let successfulRequests = 0; + let blockedRequests = 0; - async with aiohttp.ClientSession() as session: - tasks = [] - for i in range(requests_count): - tasks.append(make_request(session, url)) - - responses = await asyncio.gather(*tasks, return_exceptions=True) + // Create array of request promises + const requests = Array.from({ length: requestsCount }, () => makeRequest(url)); + + // Execute all requests concurrently + const responses = await Promise.allSettled(requests); + + // Analyze responses + for (const result of responses) { + if (result.status === 'rejected') { + console.warn('Request failed:', result.reason.message); + continue; + } - for response in responses: - if isinstance(response, Exception): - continue - if response.status == 200: - successful_requests += 1 - elif response.status == 429: - blocked_requests += 1 + const response = result.value; + if (response.status === 200) { + successfulRequests++; + } else if (response.status === 429) { + blockedRequests++; + } + } - elapsed = time.time() - start_time - print(f"Rate limit test results:") - print(f"Successful: {successful_requests}, Blocked: {blocked_requests}") - print(f"Effective rate: {successful_requests/elapsed:.2f} req/sec") - -async def make_request(session, url): - try: - async with session.get(url) as response: - return response - except Exception as e: - return e -``` - -## Resources and Next Steps + const elapsed = (Date.now() - startTime) / 1000; // Convert to seconds + console.log('Rate limit test results:'); + console.log(`Successful: ${successfulRequests}, Blocked: ${blockedRequests}`); + console.log(`Effective rate: ${(successfulRequests / elapsed).toFixed(2)} req/sec`); + + return { + successful: successfulRequests, + blocked: blockedRequests, + total: requestsCount, + elapsedSeconds: elapsed, + effectiveRate: successfulRequests / elapsed + }; +} -### Essential Reading -- [OWASP API Security Top 10](https://owasp.org/www-project-api-security/) - Comprehensive guide including unrestricted resource consumption (API4:2023) and business logic abuse (API6:2023) -- [RFC 6585](https://tools.ietf.org/html/rfc6585) - HTTP status code 429 (Too Many Requests) specification -- [Rate Limiting Algorithms](https://en.wikipedia.org/wiki/Rate_limiting) - Technical overview of different rate limiting approaches +async function makeRequest(url) { + try { + const response = await fetch(url, { + method: 'GET', + headers: { + 'User-Agent': 'rate-limit-tester/1.0' + } + }); + return response; + } catch (error) { + throw new Error(`Request failed: ${error.message}`); + } +} -### Implementation Tools -- [Redis](https://redis.io/) - In-memory data store commonly used for distributed rate limiting -- [Kong Rate Limiting Plugin](https://docs.konghq.com/hub/kong-inc/rate-limiting/) - Enterprise-grade API gateway rate limiting -- [nginx limit_req_zone](https://nginx.org/en/docs/http/ngx_http_limit_req_module.html) - High-performance rate limiting at the reverse proxy level +// Example usage: +// await testRateLimit('https://api.example.com/users', 50, 60); +``` -### Monitoring and Analytics -- [Prometheus](https://prometheus.io/) - Metrics collection and alerting for rate limiting monitoring -- [Grafana](https://grafana.com/) - Visualization dashboards for rate limiting metrics -- [Elastic Stack](https://www.elastic.co/elastic-stack/) - Log analysis and pattern detection for abuse identification +## Resources and Next Steps -### Load Testing Tools -- [hey](https://github.com/rakyll/hey) - Simple load testing tool for rate limit verification -- [Apache Bench (ab)](https://httpd.apache.org/docs/2.4/programs/ab.html) - Basic HTTP server benchmarking -- [JMeter](https://jmeter.apache.org/) - Comprehensive performance testing with rate limiting scenarios +### Essential Standards +- OWASP API Security Top 10 - Comprehensive guide including unrestricted resource consumption (API4:2023) and business logic abuse (API6:2023) +- RFC 6585 - HTTP status code 429 (Too Many Requests) specification ### Related Security Topics - [API Input Validation and Injection Prevention](api-input-validation-injection-prevention) - Protect APIs from malicious data - [Authentication and Authorization with OpenAPI](authentication-authorization-openapi) - Implement secure access control - [API TLS Encryption and HTTPS Best Practices](api-tls-encryption-https-best-practices) - Secure data in transit -- [API Security by Design: Complete Guide](/learn/security) - Overview of all API security domains - ---- - -**Next Steps:** Now that you have rate limiting protection in place, learn about [Authentication and Authorization with OpenAPI](authentication-authorization-openapi) to implement comprehensive access control for your APIs. \ No newline at end of file +- [API Security by Design: Complete Guide](/learn/security) - Overview of all API security domains \ No newline at end of file diff --git a/learn/security/api-tls-encryption-https-best-practices.md b/learn/security/api-tls-encryption-https-best-practices.md index 91b254aa..49cb225f 100644 --- a/learn/security/api-tls-encryption-https-best-practices.md +++ b/learn/security/api-tls-encryption-https-best-practices.md @@ -15,12 +15,26 @@ seo: When a client and an API exchange information, that data travels across the internet, a public network. Without protection, this data gets intercepted and read by malicious actors. This is where encryption comes in. **In this guide, you'll learn:** -- How TLS 1.3 provides secure communication for APIs -- OpenAPI server URL security contracts and enforcement -- Certificate management and cipher suite selection -- Mutual TLS (mTLS) for service-to-service communication -- Real-world lessons from the Heartbleed vulnerability -- Automated governance for transport security +- [How TLS 1.3 provides secure communication](#tls-13-the-modern-standard) for APIs +- [OpenAPI server URL security contracts](#enforcing-https-in-your-api-specification) and enforcement +- [Certificate management and TLS configuration](#tls-configuration-examples) examples +- [Mutual TLS (mTLS) for service-to-service communication](#mutual-tls-mtls-two-way-authentication) +- [Real-world lessons from the Heartbleed vulnerability](#attack-example-heartbleed-tls-library-vulnerability-2014) +- [Automated governance for transport security](#automated-governance-enforcement) + +--- + +## Quick Start Guide + +Ready to implement secure TLS encryption? Follow these steps: + +1. **Upgrade to TLS 1.3:** Implement [modern TLS 1.3](#tls-13-the-modern-standard) with strong cipher suites and disable legacy protocols +2. **Configure your server:** Choose your technology stack from our [configuration examples](#tls-configuration-examples) (Nginx or Express.js) +3. **Enforce HTTPS in specs:** Update [OpenAPI server URLs](#enforcing-https-in-your-api-specification) to use HTTPS only with automated governance +4. **Set up monitoring:** Implement [certificate monitoring](#tls-monitoring-and-troubleshooting) to track expiration dates and TLS configuration +5. **Consider mTLS:** For service-to-service communication, evaluate [mutual TLS](#mutual-tls-mtls-two-way-authentication) for cryptographic client authentication + +**Next Steps:** Now that you have secure transport with TLS, learn about [API Input Validation and Injection Prevention](api-input-validation-injection-prevention) to protect your APIs from malicious data inputs. --- @@ -114,15 +128,25 @@ testssl.sh --fast https://api.example.com The security contract for encrypted transit begins within the `servers` object of your OpenAPI specification. Every URL defined here must use the `https://` scheme—this isn't just documentation, it's a formal declaration of your API's secure endpoints. -**OpenAPI Servers Declaration:** +**OpenAPI HTTPS Enforcement** + ```yaml {% title="openapi.yaml" %} +# CRITICAL SECURITY: Only HTTPS servers in production OpenAPI specs # [!code error] servers: - - url: https://api.production.com/v1 + - url: https://api.production.com/v1 # [!code warning] ESSENTIAL: HTTPS only for production description: Production Server - - url: https://api.staging.com/v1 + - url: https://api.staging.com/v1 # [!code warning] ESSENTIAL: HTTPS only for staging description: Staging Server + # Never include HTTP servers in production specs # [!code highlight] DANGEROUS: HTTP servers are vulnerable + # - url: http://api.example.com/v1 # [!code error] NEVER DO THIS: Allows man-in-the-middle attacks ``` +**Security Benefits**: +- **Prevents man-in-the-middle attacks** by encrypting all API traffic +- **Protects sensitive data** (API keys, user credentials, personal information) in transit +- **Enables modern web features** that require secure contexts (Service Workers, etc.) +- **Improves SEO and user trust** with browser security indicators + ### Automated Governance Enforcement Modern API governance tools can enforce HTTPS usage through automated validation rules. When integrated into your CI/CD pipeline, automated governance creates security gates. If a developer attempts to commit an OpenAPI file with insecure server URLs, the pipeline fails with a clear error message, preventing insecure configurations from ever reaching production. @@ -131,53 +155,110 @@ Modern API governance tools can enforce HTTPS usage through automated validation ## TLS Configuration Examples -Authoritative sources like the [Mozilla SSL Configuration Generator](https://ssl-config.mozilla.org/) provide excellent, up-to-date templates for secure server configurations across different platforms and security requirements. +Choose your server configuration based on your technology stack. Authoritative sources like the [Mozilla SSL Configuration Generator](https://ssl-config.mozilla.org/) provide excellent, up-to-date templates for secure server configurations. + +{% tabs %} + {% tab label="Nginx Configuration" %} + +### Production Nginx TLS Configuration -**Nginx Configuration:** -```nginx +```nginx {% title="nginx.conf - Production TLS Security Configuration" %} server { - listen 443 ssl http2; - server_name api.example.com; + # STEP 1: Enable HTTPS with HTTP/2 for performance and security # [!code highlight] + listen 443 ssl http2; # Port 443 = HTTPS, http2 = faster + more secure + server_name api.example.com; # Your API domain - must match certificate CN/SAN - # TLS 1.3 only - ssl_protocols TLSv1.3; + # STEP 2: Force TLS 1.3 only - disables ALL vulnerable older versions # [!code highlight] + ssl_protocols TLSv1.3; # [!code error] CRITICAL: Blocks SSL, TLS 1.0, 1.1, 1.2 vulnerabilities - # Strong cipher suites + # STEP 3: Define strong cipher suites (TLS 1.3 has built-in secure ciphers) # [!code highlight] + # These are the only ciphers clients can negotiate - all are AEAD (authenticated encryption) ssl_ciphers TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256; - # HSTS header + # STEP 4: Security headers - prevent client-side attacks # [!code highlight] + # HSTS: Forces browsers to use HTTPS for ALL future requests (even if user types http://) add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; - # Certificate files - ssl_certificate /path/to/certificate.crt; - ssl_certificate_key /path/to/private.key; + # Additional security headers for defense in depth + add_header X-Frame-Options DENY always; # Prevent clickjacking + add_header X-Content-Type-Options nosniff always; # Prevent MIME confusion attacks + add_header Referrer-Policy "strict-origin-when-cross-origin" always; # Limit referrer leakage + + # STEP 5: TLS Certificate configuration - THE MOST CRITICAL PART # [!code highlight] + ssl_certificate /path/to/certificate.crt; # Public certificate (safe to share) + ssl_certificate_key /path/to/private.key; # [!code error] CRITICAL: PRIVATE KEY - never share, restrict access! + + # STEP 6: Certificate security best practices # [!code highlight] + ssl_certificate_transparency on; # Enable CT logging for transparency + ssl_stapling on; # OCSP stapling - faster cert validation + ssl_stapling_verify on; # Verify OCSP responses + ssl_trusted_certificate /path/to/chain.pem; # Certificate chain for OCSP validation + + # STEP 7: Performance optimizations that also improve security # [!code highlight] + ssl_session_cache shared:SSL:10m; # Session resumption (avoids full handshake) + ssl_session_timeout 10m; # Limit session lifetime + ssl_prefer_server_ciphers off; # Let client choose (TLS 1.3 best practice) + + # Your API routes go here... + location / { + # API backend configuration + } +} + +# STEP 8: Redirect ALL HTTP traffic to HTTPS (never serve HTTP in production) # [!code highlight] +server { + listen 80; # [!code highlight] WARNING: HTTP port - only for redirects! + server_name api.example.com; + return 301 https://$server_name$request_uri; # Permanent redirect to HTTPS } ``` -**Express.js Configuration:** -```javascript +**Critical Configuration Notes**: +- **TLS 1.3 only**: Disables vulnerable older protocols (SSL, TLS 1.0/1.1/1.2) +- **Strong ciphers**: Only allows cryptographically secure cipher suites +- **HTTP/2**: Improves performance while maintaining security +- **HSTS header**: Forces browsers to use HTTPS, prevents downgrade attacks + +{% /tab %} +{% tab label="Express.js Configuration" %} + +### Express.js HTTPS Server with Security Headers + +```javascript {% title="secure-server.js" %} const https = require('https'); const fs = require('fs'); const express = require('express'); const app = express(); -// HSTS middleware +// HSTS middleware - ALWAYS force HTTPS for all future requests // [!code highlight] app.use((req, res, next) => { res.setHeader('Strict-Transport-Security', 'max-age=31536000; includeSubDomains'); next(); }); +// TLS configuration - secure defaults // [!code highlight] const options = { - key: fs.readFileSync('private.key'), - cert: fs.readFileSync('certificate.crt'), - // Force TLS 1.3 - secureProtocol: 'TLSv1_3_method' + key: fs.readFileSync('private.key'), // [!code error] CRITICAL: Keep private key secure! + cert: fs.readFileSync('certificate.crt'), // Certificate file + secureProtocol: 'TLSv1_3_method' // [!code highlight] SECURITY: Force TLS 1.3 only }; -https.createServer(options, app).listen(443); +// Start HTTPS server on port 443 - NEVER use HTTP in production // [!code highlight] +https.createServer(options, app).listen(443, () => { + console.log('Secure API server running on https://localhost:443'); +}); ``` +**Security Implementation Details**: +- **HSTS middleware**: Prevents protocol downgrade attacks by forcing HTTPS +- **TLS 1.3 only**: Disables vulnerable older TLS versions +- **Certificate management**: Loads TLS certificate and private key from secure files +- **Port 443**: Standard HTTPS port for production APIs + +{% /tab %} +{% /tabs %} + ## Attack Example: Heartbleed (TLS library vulnerability, 2014) The Heartbleed bug (CVE-2014-0160) was a critical vulnerability in the OpenSSL library, not the TLS protocol itself. It allowed attackers to read up to 64KB of a server's memory by sending a malformed TLS heartbeat request. The server would respond with not only the small payload sent by the attacker but also adjacent memory contents, which could include session cookies, user credentials, and even the server's private encryption keys. @@ -209,66 +290,95 @@ While standard TLS only authenticates the server to the client, **Mutual TLS (mT - IoT device authentication in distributed systems - High-security financial and healthcare APIs requiring cryptographic identity verification -**OpenAPI mTLS Configuration:** +**OpenAPI mTLS Security Definition** + ```yaml {% title="openapi.yaml" %} components: securitySchemes: mtlsAuth: - type: mutualTLS - description: "Client certificate authentication" + type: mutualTLS # [!code highlight] + description: "Client certificate authentication for zero-trust architecture" # [!code highlight] -# Apply to sensitive operations +# Apply mTLS to sensitive internal operations paths: /internal/payments: post: security: - - mtlsAuth: [] + - mtlsAuth: [] # [!code highlight] summary: "Process payment (internal service only)" + /public/info: + get: + # No mTLS required for public endpoints # [!code highlight] + summary: "Public information endpoint" ``` -**Implementation Example (Nginx):** -```nginx +**mTLS Security Benefits**: +- **Cryptographic authentication**: Both client and server prove identity with certificates +- **Zero-trust architecture**: No implicit trust based on network location +- **Non-repudiation**: Certificate-based proof of communication participants + +**mTLS Nginx Configuration** + +```nginx {% title="nginx-mtls.conf" %} server { listen 443 ssl http2; - # Server certificate - ssl_certificate /path/to/server.crt; - ssl_certificate_key /path/to/server.key; + # Server certificate (authenticates server to client) + ssl_certificate /path/to/server.crt; # Public certificate for server identity + ssl_certificate_key /path/to/server.key; # Private key (keep secure!) - # Require client certificates - ssl_verify_client on; - ssl_client_certificate /path/to/ca.crt; + # Client certificate verification (authenticates client to server) + ssl_verify_client on; # Require valid client certificates + ssl_client_certificate /path/to/ca.crt; # CA that signed client certificates - # Pass client certificate info to backend - proxy_set_header X-Client-Cert $ssl_client_cert; - proxy_set_header X-Client-Verify $ssl_client_verify; + # Pass client certificate details to application + proxy_set_header X-Client-Cert $ssl_client_cert; # Full client certificate + proxy_set_header X-Client-Verify $ssl_client_verify; # Verification status + proxy_set_header X-Client-DN $ssl_client_s_dn; # Client Distinguished Name } ``` +**mTLS Flow**: Client presents certificate → Nginx validates against CA → Application receives verified client identity → Both parties authenticated cryptographically + > **mTLS Best Practice**: Use mTLS for service-to-service communication and regular TLS + [JWT/OAuth2](authentication-authorization-openapi) for client-to-server communication. ## TLS Monitoring and Troubleshooting +Choose your monitoring approach based on your infrastructure: + +{% tabs %} + {% tab label="Certificate Monitoring (Prometheus)" %} + ### Certificate Monitoring + ```yaml {% title="prometheus.yml" %} groups: - name: tls_alerts rules: - alert: TLSCertificateExpiringSoon - expr: probe_ssl_earliest_cert_expiry - time() < 86400 * 30 + expr: probe_ssl_earliest_cert_expiry - time() < 86400 * 30 # [!code highlight] 30-day warning labels: severity: warning annotations: summary: "TLS certificate expires in less than 30 days" - alert: WeakTLSVersion - expr: probe_tls_version_info{version!="TLS 1.3"} == 1 + expr: probe_tls_version_info{version!="TLS 1.3"} == 1 # [!code highlight] TLS version check labels: severity: critical annotations: summary: "Weak TLS version detected" ``` +**How certificate monitoring works:** +- **Expiration alerts**: Warns 30 days before certificate expiry to allow renewal time +- **TLS version monitoring**: Detects servers using outdated TLS versions +- **Automated scanning**: Regularly probes endpoints to verify TLS configuration +- **Alert routing**: Sends notifications to security and ops teams for immediate action + +{% /tab %} +{% tab label="Troubleshooting Steps" %} + ### Common TLS Troubleshooting Steps **Certificate Issues:** @@ -294,16 +404,24 @@ echo | openssl s_client -servername api.example.com -connect api.example.com:443 openssl x509 -noout -dates ``` +**Common issues and solutions:** +- **Certificate chain issues**: Use `openssl s_client -showcerts` to verify intermediate certificates +- **TLS version problems**: Check server configuration restricts to TLS 1.3 only +- **HSTS warnings**: Add `Strict-Transport-Security` header to prevent downgrade attacks + +{% /tab %} +{% /tabs %} + ## Frequently Asked Questions ### Why can't I use HTTP for internal APIs? -Even internal networks can be compromised. Using HTTPS everywhere (zero-trust approach) protects against insider threats, lateral movement attacks, and accidental data exposure. The performance overhead of TLS is minimal with modern hardware and HTTP/2. +Even internal networks can be compromised. Using HTTPS everywhere (zero-trust approach) protects against insider threats, lateral movement attacks, and accidental data exposure. The performance overhead of [TLS 1.3](#tls-13-the-modern-standard) is minimal with modern hardware and HTTP/2. See [OpenAPI HTTPS enforcement](#enforcing-https-in-your-api-specification) for implementation guidance. ### How often should I rotate TLS certificates? -Most organizations use certificates with 1-year validity and rotate them every 6-12 months. Automated certificate management tools like Let's Encrypt or cloud provider certificate services can handle this automatically. +Most organizations use certificates with 1-year validity and rotate them every 6-12 months. Automated certificate management tools like Let's Encrypt or cloud provider certificate services can handle this automatically. Implement [certificate monitoring](#tls-monitoring-and-troubleshooting) to track expiration dates. ### What's the difference between TLS and SSL? -SSL (Secure Sockets Layer) is the predecessor to TLS. SSL versions are deprecated and insecure. When people say "SSL certificate" or "SSL/TLS," they're usually referring to modern TLS. Always use TLS 1.2 or preferably TLS 1.3. +SSL (Secure Sockets Layer) is the predecessor to TLS. SSL versions are deprecated and insecure. When people say "SSL certificate" or "SSL/TLS," they're usually referring to modern TLS. Always use [TLS 1.2 or preferably TLS 1.3](#tls-13-the-modern-standard) as shown in our [configuration examples](#tls-configuration-examples). ### Should I implement certificate pinning for API clients? Certificate pinning can improve security by preventing man-in-the-middle attacks, but it adds operational complexity. Consider it for high-security applications, but ensure you have a robust certificate rotation and backup pin management process. @@ -324,8 +442,4 @@ Certificate pinning can improve security by preventing man-in-the-middle attacks - [API Input Validation and Injection Prevention](api-input-validation-injection-prevention) - Protect APIs from malicious data - [Authentication and Authorization with OpenAPI](authentication-authorization-openapi) - Implement secure access control - [API Rate Limiting and Abuse Prevention](api-rate-limiting-abuse-prevention) - Prevent DoS attacks and brute force attempts -- [API Security by Design: Complete Guide](/learn/security) - Overview of all API security domains - ---- - -**Next Steps:** Now that you have secure transport with TLS, learn about [API Input Validation and Injection Prevention](api-input-validation-injection-prevention) to protect your APIs from malicious data inputs. \ No newline at end of file +- [API Security by Design: Complete Guide](/learn/security) - Overview of all API security domains \ No newline at end of file diff --git a/learn/security/authentication-authorization-openapi.md b/learn/security/authentication-authorization-openapi.md index 2d1d3c23..3fce8928 100644 --- a/learn/security/authentication-authorization-openapi.md +++ b/learn/security/authentication-authorization-openapi.md @@ -6,6 +6,8 @@ seo: description: Implement secure access control using OpenAPI security schemes and modern authentication patterns. --- +# Authentication and Authorization with OpenAPI + --- ## Key Takeaways @@ -15,11 +17,25 @@ Authentication and authorization form the foundation of API access control. Whil In this guide, we'll explore how to use OpenAPI 3.1 security schemes to define robust access control patterns that integrate seamlessly with automated governance and modern authentication providers. **We'll cover how to:** -- Define JWT Bearer token authentication in OpenAPI specifications -- Implement OAuth2 with granular scope-based authorization -- Enforce security requirements through automated governance -- Configure API gateways from OpenAPI security definitions -- Monitor and troubleshoot authentication and authorization failures +- [Define authentication methods (JWT, OAuth2, API Keys, mTLS)](#authentication-methods) in OpenAPI specifications +- [Implement advanced authorization patterns](#advanced-authorization-patterns) with granular permissions +- [Enforce security requirements through automated governance](#automated-governance-for-access-control) +- [Configure API gateways from OpenAPI security definitions](#api-gateway-integration) +- [Monitor and troubleshoot authentication and authorization failures](#authentication-and-authorization-monitoring) + +--- + +## Quick Start Guide + +Ready to implement authentication and authorization? Start here: + +1. **Choose your authentication method:** Review [Authentication Methods](#authentication-methods) and select JWT Bearer, OAuth2, API Keys, or mTLS based on your needs +2. **Set up governance:** Implement [automated governance rules](#automated-governance-for-access-control) to prevent accidentally public endpoints +3. **Configure your gateway:** Use [API gateway integration](#api-gateway-integration) to automatically enforce your OpenAPI security definitions +4. **Add monitoring:** Set up [authentication and authorization monitoring](#authentication-and-authorization-monitoring) to track security violations +5. **Plan for issues:** Review [troubleshooting common issues](#troubleshooting-common-issues) and implement [best practices](#best-practices-summary) + +**Next Steps:** Now that you have authentication and authorization in place, explore the complete [API Security by Design guide](/learn/security) to learn about other essential security domains like TLS encryption, input validation, and rate limiting. --- @@ -72,18 +88,18 @@ sequenceDiagram ### Common Authentication Patterns -**API Keys:** +**[API Keys](#authentication-methods):** - Simple, stateless authentication - Often used for service-to-service communication - Limited authorization capabilities (typically binary: access or no access) -**JWT Bearer Tokens:** +**[JWT Bearer Tokens](#authentication-methods):** - Self-contained tokens with embedded claims - Support fine-grained authorization through scopes and claims - Stateless validation (no database lookup required) - Industry standard for modern APIs -**OAuth2 with PKCE:** +**[OAuth2 with PKCE](#authentication-methods):** - Delegated authorization framework - Supports multiple grant types and client types - Built-in scope-based authorization @@ -96,6 +112,13 @@ OpenAPI 3.1 provides a robust framework for defining access control through two 1. **`components.securitySchemes`**: Defines *how* clients can authenticate (JWT Bearer, OAuth2, API Keys) 2. **`security`**: Specifies *that* an endpoint is secured and by which mechanism(s) +## Authentication Methods + +Choose the authentication method that best fits your use case: + +{% tabs %} + {% tab label="JWT Bearer Token" %} + ### JWT Bearer Token Authentication JWT (JSON Web Token) Bearer authentication is the most common pattern for modern APIs. The token contains encoded claims about the user and can be validated without database lookups. @@ -105,89 +128,236 @@ components: securitySchemes: bearerAuth: type: http - scheme: bearer - bearerFormat: JWT + scheme: bearer # [!code highlight] Standard Bearer token scheme + bearerFormat: JWT # [!code highlight] Specify JWT format description: "Enter JWT with 'Bearer ' prefix" -# Apply globally to all operations +# Apply globally to all operations # [!code highlight] security: - - bearerAuth: [] + - bearerAuth: [] # [!code highlight] Require authentication for all endpoints ``` +**What this configuration does:** + +- **`type: http`** - Uses standard HTTP authentication (as opposed to API keys or OAuth2 flows) +- **`scheme: bearer`** - Specifies Bearer token authentication, where tokens are sent in the `Authorization: Bearer ` header +- **`bearerFormat: JWT`** - Documents that tokens must be valid JWTs (helps with API documentation and client generation) +- **`security: - bearerAuth: []`** - Applies this authentication requirement to all endpoints globally (individual endpoints can override this) + +This approach ensures every API request includes a valid JWT token, preventing anonymous access to protected resources. + **JWT Token Structure:** -```javascript -// Header +```javascript {% title="JWT Token Anatomy - 3 Parts Separated by Dots" %} +// PART 1: HEADER - Defines how the token is secured // [!code highlight] { - "alg": "RS256", - "typ": "JWT" + "alg": "RS256", // CRITICAL: Use RS256, not HS256 (prevents key confusion attacks) + "typ": "JWT", // Token type declaration (required for JWT processing) + "kid": "key-123" // Key ID helps API find correct public key for verification } -// Payload (Claims) +// PART 2: PAYLOAD - Contains user identity and permissions (NEVER put secrets here!) // [!code highlight] { - "sub": "user123", - "iss": "https://auth.example.com", - "aud": "api.example.com", - "exp": 1640995200, - "iat": 1640991600, - "scopes": ["users:read", "orders:write"] + // Standard Claims (RFC 7519) - These provide security guarantees + "sub": "user123", // Subject: Who this token represents + "iss": "https://auth.example.com", // Issuer: MUST be HTTPS URL you trust + "aud": ["api.example.com", "admin.example.com"], // Audience: APIs that accept this token + "exp": 1640995200, // Expiration: REQUIRED - limits blast radius if stolen + "nbf": 1640991600, // Not Before: Token invalid before this time + "iat": 1640991600, // Issued At: When token was created + "jti": "unique-token-id", // JWT ID: Unique identifier (helps with revocation) + + // Custom Claims - Your application-specific data + "scopes": ["users:read", "orders:write"], // Permissions: What user can do + "role": "customer", // Role-based access control + "email": "user@example.com", // PII: Consider privacy implications + "premium": true // Feature flags or user attributes } -// Signature (RS256) +// PART 3: SIGNATURE - Cryptographic proof token wasn't tampered with // [!code highlight] RSASHA256( - base64UrlEncode(header) + "." + + base64UrlEncode(header) + "." + // Header and payload concatenated base64UrlEncode(payload), - private_key + private_key // NEVER expose this key - stay with auth server only! ) + +// Security Notes: // [!code highlight] +// 1. JWT is NOT encrypted - anyone can read header/payload (use JWE if needed) // [!code highlight] +// 2. Signature prevents tampering but doesn't hide content // [!code highlight] +// 3. Short expiration times (15-60 minutes) limit security exposure // [!code highlight] +// 4. Always validate iss, aud, exp claims before trusting token // [!code highlight] ``` +**Understanding each JWT component:** + +**Header:** +- **`"alg": "RS256"`** - Specifies RSA SHA-256 signature algorithm, which uses public/private key pairs for security. This prevents token tampering since only the authorization server has the private key to sign tokens. +- **`"typ": "JWT"`** - Declares this is a JWT token (helps parsers know how to handle it) + +**Payload (Claims):** +- **`"sub": "user123"`** - Subject claim identifies the user this token represents. Your API uses this to know *who* is making the request. +- **`"iss": "https://auth.example.com"`** - Issuer claim identifies which authorization server created this token. Your API should validate this matches your trusted auth server. +- **`"aud": "api.example.com"`** - Audience claim specifies which API this token is intended for. Prevents token reuse across different services. +- **`"exp": 1640995200"`** - Expiration timestamp (Unix time). Tokens automatically become invalid after this time, limiting damage if compromised. +- **`"iat": 1640991600"`** - Issued at timestamp. Helps with token lifecycle tracking and debugging. +- **`"scopes": ["users:read", "orders:write"]`** - Custom claim listing what permissions this user has. Your authorization logic checks these scopes. + +**Signature:** +- Created by signing the encoded header and payload with the authorization server's private key +- Your API validates signatures using the corresponding public key +- If signature verification fails, the token is invalid (likely tampered with or forged) + +{% /tab %} +{% tab label="OAuth2 with Scopes" %} + ### OAuth2 with Scope-Based Authorization OAuth2 provides the most flexible authorization framework, supporting fine-grained permissions through scopes and multiple authentication flows. -```yaml {% title="openapi.yaml" %} +```yaml {% title="openapi.yaml - OAuth2 with Security Best Practices" %} components: securitySchemes: oauth2Auth: type: oauth2 - description: "OAuth2 Authorization Code Flow with PKCE" + # CRITICAL: Always use Authorization Code + PKCE for security + description: "OAuth2 Authorization Code Flow with PKCE - prevents CSRF and injection attacks" flows: authorizationCode: - authorizationUrl: https://auth.example.com/authorize - tokenUrl: https://auth.example.com/token + # STEP 1: Authorization URL - where users consent to permissions + authorizationUrl: https://auth.example.com/authorize # [!code highlight] HTTPS REQUIRED - never use HTTP + + # STEP 2: Token endpoint - where your app exchanges codes for tokens + tokenUrl: https://auth.example.com/token # [!code highlight] HTTPS REQUIRED - never use HTTP + + # STEP 3: Define permission scopes using principle of least privilege scopes: - 'users:read': "Read access to user profiles" - 'users:write': "Modify user profiles" - 'orders:read': "View order history" - 'orders:write': "Create and modify orders" - 'admin:users': "Full user management access" + # User-level permissions (granular access control) + 'users:read': "View user profile information" # [!code focus] Read-only access + 'users:write': "Modify user profile data" # [!code warning] Write access - more sensitive + 'users:delete': "Delete user accounts" # [!code error] High-privilege operation + + # Resource-specific permissions + 'orders:read': "View order history and details" # [!code focus] Customer data access + 'orders:write': "Create and modify orders" # [!code warning] Financial operations + 'orders:refund': "Process order refunds" # [!code error] High-value operations + + # Administrative permissions (highest privilege) + 'admin:users': "Full user management access" # [!code error] Admin-only scope + 'admin:system': "System configuration access" # [!code error] Infrastructure access paths: /users/{userId}: get: summary: "Get user profile" + # STEP 4: Require specific permissions for each operation security: - - oauth2Auth: ['users:read'] # Requires read access + - oauth2Auth: ['users:read'] # [!code highlight] Minimal required scope + parameters: + - name: userId + in: path + required: true + schema: + type: string + format: uuid # [!code focus] Use UUIDs to prevent enumeration attacks responses: '200': description: "User profile data" - '401': - description: "Authentication required" - '403': - description: "Insufficient permissions" + content: + application/json: + schema: + $ref: '#/components/schemas/UserProfile' + '401': # [!code error] No valid token provided + description: "Authentication required - token missing or invalid" + content: + application/json: + schema: + $ref: '#/components/schemas/UnauthorizedError' + '403': # [!code error] Valid token but insufficient permissions + description: "Insufficient permissions - requires users:read scope" + content: + application/json: + schema: + $ref: '#/components/schemas/ForbiddenError' patch: summary: "Update user profile" security: - - oauth2Auth: ['users:write'] # Requires write access + - oauth2Auth: ['users:write'] # [!code warning] Higher privilege required + # STEP 5: Document security requirements clearly + description: | + Updates user profile information. Requires 'users:write' scope. + + **Security Notes:** + - Users can only modify their own profiles unless they have admin:users scope + - Sensitive fields like email changes may require additional verification + - All changes are logged for audit purposes + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/UserProfileUpdate' responses: '200': description: "Profile updated successfully" - '401': + '401': # [!code error] Authentication failure description: "Authentication required" - '403': - description: "Insufficient permissions" + '403': # [!code error] Authorization failure + description: "Insufficient permissions - requires users:write scope" + '422': # [!code warning] Validation errors + description: "Invalid input data" + +# STEP 6: Define common error schemas for consistent security responses +components: + schemas: + UnauthorizedError: + type: object + properties: + error: + type: string + example: "Authentication required" + message: + type: string + example: "Please provide a valid Bearer token" + + ForbiddenError: + type: object + properties: + error: + type: string + example: "Insufficient permissions" + required_scopes: # [!code focus] Help developers understand what's needed + type: array + items: + type: string + example: ["users:write"] ``` +**Breaking down this OAuth2 configuration:** + +**Security Scheme Definition:** +- **`type: oauth2`** - Declares this uses the OAuth2 standard for authorization +- **`authorizationCode`** flow - The most secure OAuth2 flow for web applications, involves redirecting users to the authorization server +- **`authorizationUrl`** - Where users go to grant permissions (must use HTTPS for security) +- **`tokenUrl`** - Where your app exchanges authorization codes for access tokens (must use HTTPS) + +**Scope-Based Permissions:** +- **`'users:read'`** - Allows reading user profile data but not modifying it +- **`'users:write'`** - Allows updating user profiles (typically granted to users for their own profiles) +- **`'orders:read'` & `'orders:write'`** - Separate permissions for order management +- **`'admin:users'`** - Administrative permission that overrides user-level restrictions + +**Endpoint-Level Authorization:** +- **`security: - oauth2Auth: ['users:read']`** - This endpoint requires a valid OAuth2 token with the `users:read` scope +- **Different endpoints require different scopes** - GET operations typically need `read` scopes, while PATCH/POST/DELETE need `write` scopes +- **Response codes `401` vs `403`**: + - `401` = No valid token provided (authentication problem) + - `403` = Valid token but insufficient permissions (authorization problem) + +This pattern allows fine-grained control: a user might have permission to read profiles but not edit them, while administrators have broader access. + +{% /tab %} +{% tab label="API Key" %} + ### API Key Authentication For service-to-service communication and simpler use cases, API keys provide straightforward authentication. @@ -197,8 +367,8 @@ components: securitySchemes: apiKeyAuth: type: apiKey - in: header - name: X-API-Key + in: header # [!code highlight] Header-based API key (preferred) + name: X-API-Key # [!code highlight] Custom header name description: "API key for service authentication" paths: @@ -206,12 +376,35 @@ paths: get: summary: "Internal health check" security: - - apiKeyAuth: [] + - apiKeyAuth: [] # [!code highlight] Require API key authentication responses: '200': description: "Service health status" + '401': + description: "Invalid or missing API key" ``` +**API Key configuration explained:** + +- **`type: apiKey`** - Declares this uses simple API key authentication (as opposed to OAuth2 or JWT) +- **`in: header`** - API key is sent in HTTP headers (more secure than query parameters, which get logged) +- **`name: X-API-Key`** - Specifies the exact header name clients must use: `X-API-Key: your-secret-key-here` +- **`security: - apiKeyAuth: []`** - Requires a valid API key for this endpoint + +**When to use API keys:** +- **Service-to-service communication** - When your API calls another internal service +- **Simple integrations** - Third-party services that don't need complex user permissions +- **Internal tools** - Admin dashboards or monitoring systems + +**Security considerations:** +- API keys identify the *application*, not the *user* (unlike JWT tokens) +- Keys should be long, random strings (at least 32 characters) +- Store keys securely and rotate them regularly +- Never include API keys in client-side code or URLs + +{% /tab %} +{% tab label="Mutual TLS (mTLS)" %} + ### Mutual TLS (mTLS) for Service Authentication For high-security environments and service-to-service communication, [mutual TLS](api-tls-encryption-https-best-practices#mutual-tls-mtls-two-way-authentication) provides cryptographic identity verification. @@ -220,22 +413,32 @@ For high-security environments and service-to-service communication, [mutual TLS components: securitySchemes: mtlsAuth: - type: mutualTLS + type: mutualTLS # [!code highlight] Cryptographic client authentication description: "Client certificate authentication" paths: /internal/payments: post: security: - - mtlsAuth: [] + - mtlsAuth: [] # [!code highlight] Requires valid client certificate summary: "Process payment (internal service only)" responses: '200': description: "Payment processed" - '401': + '401': # [!code highlight] Certificate validation failure description: "Invalid client certificate" ``` +**mTLS configuration explained:** + +- **`type: mutualTLS`** - Requires both server and client to present valid certificates +- **Cryptographic authentication** - More secure than API keys since certificates are harder to forge +- **Best for internal services** - High-security service-to-service communication +- **Zero-trust architecture** - No implicit trust based on network location + +{% /tab %} +{% /tabs %} + ## Automated Governance for Access Control One of the most common API vulnerabilities is the accidentally public endpoint—an operation that should require authentication but doesn't have security requirements defined. Automated governance prevents this by enforcing security rules during development. @@ -302,6 +505,8 @@ paths: description: "Insufficient permissions" ``` +**Next steps:** Once you've implemented automated governance, consider setting up [comprehensive monitoring](#authentication-and-authorization-monitoring) to track security violations and [troubleshooting processes](#troubleshooting-common-issues) to handle authentication failures effectively. + ## Security Definitions as Configuration Defining security schemes in OpenAPI extends beyond documentation—it establishes configuration-as-code that drives consistency across your entire API ecosystem: @@ -384,8 +589,15 @@ class APIClient { } ``` +**Development workflow:** Generated client SDKs like the one above help catch authentication issues early. When problems occur in production, use [monitoring](#authentication-and-authorization-monitoring) and [troubleshooting](#troubleshooting-common-issues) to diagnose and resolve issues quickly. + ## Advanced Authorization Patterns +Choose the authorization pattern that fits your application's complexity: + +{% tabs %} + {% tab label="Role-Based Access Control (RBAC)" %} + ### Role-Based Access Control (RBAC) While OpenAPI doesn't have built-in RBAC support, you can model roles through scopes or custom extensions. @@ -397,15 +609,15 @@ components: type: oauth2 flows: authorizationCode: - authorizationUrl: https://auth.example.com/authorize - tokenUrl: https://auth.example.com/token + authorizationUrl: https://auth.example.com/authorize # [!code highlight] HTTPS required + tokenUrl: https://auth.example.com/token # [!code highlight] HTTPS required scopes: - # Role-based scopes - 'role:admin': "Administrative access to all resources" - 'role:manager': "Management access within assigned teams" - 'role:user': "Standard user access to own resources" + # Role-based scopes # [!code highlight] + 'role:admin': "Administrative access to all resources" # [!code highlight] Admin role + 'role:manager': "Management access within assigned teams" # [!code highlight] Manager role + 'role:user': "Standard user access to own resources" # [!code highlight] User role - # Resource-based scopes + # Resource-based scopes # [!code highlight] 'users:read': "Read user profiles" 'users:write': "Modify user profiles" 'orders:read': "View orders" @@ -416,21 +628,26 @@ paths: get: summary: "List all users (admin only)" security: - - oauth2Auth: ['role:admin'] + - oauth2Auth: ['role:admin'] # [!code highlight] Admin-only endpoint responses: '200': description: "List of all users" + '403': # [!code highlight] Authorization failure + description: "Admin access required" /users/me: get: summary: "Get own profile" security: - - oauth2Auth: ['role:user', 'users:read'] + - oauth2Auth: ['role:user', 'users:read'] # [!code highlight] Multiple scope requirement responses: '200': description: "User's own profile" ``` +{% /tab %} +{% tab label="Context-Dependent Authorization" %} + ### Context-Dependent Authorization Some authorization decisions depend on request context, such as resource ownership or dynamic policies. @@ -441,24 +658,27 @@ paths: get: summary: "Get user's orders" security: - - oauth2Auth: ['orders:read'] + - oauth2Auth: ['orders:read'] # [!code highlight] Base permission required parameters: - name: userId in: path required: true schema: - type: string + type: string # [!code highlight] User ID parameter responses: '200': description: "User's order history" - '403': + '403': # [!code highlight] Resource ownership check description: "Can only access own orders unless admin" - # Custom extension for context-dependent rules + # Custom extension for context-dependent rules # [!code highlight] x-authorization-context: - resource-owner-check: true - admin-override: true + resource-owner-check: true # [!code highlight] Check resource ownership + admin-override: true # [!code highlight] Admin can bypass ownership ``` +{% /tab %} +{% tab label="Fine-Grained Permissions" %} + ### Fine-Grained Permissions For complex applications, you might need very specific permissions that combine multiple factors. @@ -470,30 +690,42 @@ components: type: oauth2 flows: authorizationCode: - authorizationUrl: https://auth.example.com/authorize - tokenUrl: https://auth.example.com/token + authorizationUrl: https://auth.example.com/authorize # [!code highlight] HTTPS required + tokenUrl: https://auth.example.com/token # [!code highlight] HTTPS required scopes: - # Operation + Resource + Condition - 'orders:read:own': "Read own orders" - 'orders:read:team': "Read team orders" - 'orders:read:all': "Read all orders" - 'orders:write:own': "Modify own orders" - 'orders:write:team': "Modify team orders" - 'orders:cancel:all': "Cancel any order" + # Operation + Resource + Condition # [!code highlight] Fine-grained permissions + 'orders:read:own': "Read own orders" # [!code highlight] Own resources only + 'orders:read:team': "Read team orders" # [!code highlight] Team scope + 'orders:read:all': "Read all orders" # [!code highlight] Global read access + 'orders:write:own': "Modify own orders" # [!code highlight] Own resources only + 'orders:write:team': "Modify team orders" # [!code highlight] Team write access + 'orders:cancel:all': "Cancel any order" # [!code highlight] Admin-level permission paths: /orders/{orderId}: patch: summary: "Update order" security: - - oauth2Auth: ['orders:write:own', 'orders:write:team'] + - oauth2Auth: ['orders:write:own', 'orders:write:team'] # [!code highlight] Multiple scope options responses: '200': description: "Order updated" + '403': # [!code highlight] Authorization failure + description: "Insufficient permissions to update order" ``` +{% /tab %} +{% /tabs %} + +**Implementation tip:** Complex authorization patterns require robust [monitoring and troubleshooting](#troubleshooting-common-issues). The patterns above should be complemented with comprehensive logging and [best practices](#best-practices-summary) for production deployment. + ## Authentication and Authorization Monitoring +Choose your monitoring approach based on your technology stack: + +{% tabs %} + {% tab label="Authentication Monitoring (JS)" %} + ### Token Validation Metrics Monitor authentication success and failure patterns to detect potential attacks and system issues. @@ -508,35 +740,35 @@ const authMetrics = { }; app.use('/api', (req, res, next) => { - const token = req.headers.authorization?.replace('Bearer ', ''); + const token = req.headers.authorization?.replace('Bearer ', ''); // [!code highlight] Extract Bearer token if (!token) { - authMetrics.failed_auths++; + authMetrics.failed_auths++; // [!code highlight] Track failed attempts return res.status(401).json({ error: 'Bearer token required' }); } try { - const decoded = jwt.verify(token, publicKey, { - algorithms: ['RS256'], - audience: 'api.example.com', - issuer: 'https://auth.example.com' + const decoded = jwt.verify(token, publicKey, { // [!code highlight] Verify with public key + algorithms: ['RS256'], // [!code highlight] Only allow RS256 algorithm + audience: 'api.example.com', // [!code highlight] Verify intended audience + issuer: 'https://auth.example.com' // [!code highlight] Verify trusted issuer }); - // Check token expiration + // Check token expiration // [!code highlight] if (decoded.exp < Date.now() / 1000) { - authMetrics.expired_tokens++; + authMetrics.expired_tokens++; // [!code highlight] Track expired tokens return res.status(401).json({ error: 'Token expired' }); } - authMetrics.successful_auths++; - req.user = decoded; + authMetrics.successful_auths++; // [!code highlight] Track successful auths + req.user = decoded; // [!code highlight] Attach user to request next(); } catch (error) { if (error.name === 'JsonWebTokenError') { - authMetrics.invalid_signatures++; + authMetrics.invalid_signatures++; // [!code error] Track signature failures } else { - authMetrics.failed_auths++; + authMetrics.failed_auths++; // [!code error] Track other failures } return res.status(401).json({ error: 'Invalid token' }); @@ -544,42 +776,127 @@ app.use('/api', (req, res, next) => { }); ``` +**How this authentication monitoring works:** + +**Token Extraction:** +- **`req.headers.authorization?.replace('Bearer ', '')`** - Safely extracts the JWT token from the `Authorization: Bearer ` header +- The `?` optional chaining prevents errors if the header is missing + +**Token Validation Process:** +1. **`jwt.verify(token, publicKey, {...})`** - Uses the public key to verify the token signature wasn't tampered with +2. **`algorithms: ['RS256']`** - Only accepts RSA SHA-256 signatures (prevents algorithm confusion attacks) +3. **`audience` & `issuer` validation** - Ensures the token is intended for your API and came from your trusted auth server +4. **Expiration check** - Even if signature is valid, reject tokens past their expiration time + +**Security Metrics Collection:** +- **`successful_auths`** - Count of valid authentications (helps with usage analytics) +- **`failed_auths`** - Missing or invalid tokens (spikes might indicate attacks) +- **`expired_tokens`** - Tokens past expiration (helps tune token lifetimes) +- **`invalid_signatures`** - Tampered or forged tokens (critical security indicator) + +**What to watch for:** +- **High `invalid_signatures`** - Possible token forgery attempts +- **Many `expired_tokens`** - Token lifetimes might be too short, causing poor user experience +- **Sudden spikes in `failed_auths`** - Potential brute force or credential stuffing attacks + +{% /tab %} +{% tab label="Authorization Monitoring (JavaScript)" %} + ### Authorization Failure Analysis Track authorization failures to identify potential privilege escalation attempts or misconfigured permissions. -```python -# Python middleware for authorization monitoring -import logging -from collections import defaultdict - -class AuthorizationMonitor: - def __init__(self): - self.permission_denials = defaultdict(int) - self.scope_violations = defaultdict(int) +```javascript +// Express.js middleware for authorization monitoring +class AuthorizationMonitor { + constructor() { + this.permissionDenials = new Map(); // [!code highlight] Track denied requests + this.scopeViolations = new Map(); // [!code highlight] Track scope failures + } - def check_scopes(self, required_scopes, user_scopes, endpoint): - missing_scopes = set(required_scopes) - set(user_scopes) + checkScopes(requiredScopes, userScopes, endpoint) { + const requiredSet = new Set(requiredScopes); + const userSet = new Set(userScopes); + const missingScopes = [...requiredSet].filter(scope => !userSet.has(scope)); // [!code highlight] Compare scopes - if missing_scopes: - self.scope_violations[endpoint] += 1 - logging.warning(f"Scope violation at {endpoint}", extra={ - 'required_scopes': required_scopes, - 'user_scopes': user_scopes, - 'missing_scopes': list(missing_scopes), - 'user_id': getattr(g, 'user_id', 'unknown') - }) - return False + if (missingScopes.length > 0) { + // Initialize counters if endpoint is new + if (!this.scopeViolations.has(endpoint)) { + this.scopeViolations.set(endpoint, 0); + } + + this.scopeViolations.set(endpoint, this.scopeViolations.get(endpoint) + 1); // [!code error] Track security violation + + console.warn(`Scope violation at ${endpoint}`, { // [!code error] Log security event + requiredScopes, + userScopes, + missingScopes, + userId: 'unknown' // Would typically come from req.user + }); + + return false; // [!code error] Deny access + } - return True + return true; // [!code highlight] Allow access + } - def get_violation_report(self): + getViolationReport() { return { - 'permission_denials': dict(self.permission_denials), - 'scope_violations': dict(self.scope_violations) + permissionDenials: Object.fromEntries(this.permissionDenials), + scopeViolations: Object.fromEntries(this.scopeViolations) // [!code highlight] Security metrics + }; + } +} + +// Express.js middleware usage example +const authMonitor = new AuthorizationMonitor(); + +function requireScopes(requiredScopes) { + return (req, res, next) => { + const userScopes = req.user?.scopes || []; + const endpoint = req.route.path; + + if (authMonitor.checkScopes(requiredScopes, userScopes, endpoint)) { + next(); // User has required scopes + } else { + res.status(403).json({ + error: 'Insufficient permissions', + required_scopes: requiredScopes + }); } + }; +} ``` +**How this authorization monitoring works:** + +**Scope-Based Authorization:** +- **`[...requiredSet].filter(scope => !userSet.has(scope))`** - Uses array filter to find missing permissions (e.g., endpoint needs `['orders:write']` but user only has `['orders:read']`) +- **`missingScopes`** - If this array has length > 0, the user lacks required permissions + +**Security Tracking:** +- **`permissionDenials`** - Counts authorization failures per endpoint (helps identify which resources are most targeted) +- **`scopeViolations`** - Tracks specific permission mismatches (helps identify privilege escalation attempts) +- **`new Map()`** - Provides efficient key-value storage for endpoint counters + +**Structured Logging:** +- **`console.warn()`** - Records security events with structured data for analysis +- **Object context** - Includes metadata like: + - Which scopes were required vs. provided + - Which specific permissions were missing + - User ID for tracking repeat offenders + - Endpoint being accessed + +**Security Analysis:** +- **High violation counts on specific endpoints** - May indicate targeted attacks +- **Users repeatedly failing scope checks** - Possible compromised accounts or privilege escalation attempts +- **Missing scopes patterns** - Could reveal permission misconfiguration (e.g., users consistently missing `read` permissions might indicate overly restrictive defaults) + +This monitoring helps distinguish between legitimate access denials (user simply doesn't have permission) and suspicious activity (repeated attempts to access unauthorized resources). + +{% /tab %} +{% /tabs %} + ### Security Event Logging Implement comprehensive logging for security events to support incident response and compliance requirements. @@ -604,12 +921,18 @@ security_events: fields: [user_id, token_issued_at, token_expired_at, timestamp] ``` +**Security operations:** When monitoring detects issues, use the structured logs above with the [troubleshooting guide below](#troubleshooting-common-issues) to quickly diagnose and resolve authentication and authorization problems. + ## Troubleshooting Common Issues ### Authentication Problems -**Missing or Invalid Bearer Token:** -```bash +{% tabs %} +{% tab label="Missing or Invalid Bearer Token" %} + +**Error occurs when:** Client sends request without Bearer token or provides malformed token. + +```bash {% title="Testing Unauthenticated Access" %} # Test unauthenticated access (should fail with 401) curl -i https://api.example.com/users/me @@ -619,8 +942,23 @@ curl -i https://api.example.com/users/me # {"error": "Bearer token required"} ``` -**Invalid Token Signature:** -```bash +**Common causes:** +- Client forgot to include `Authorization` header +- Malformed header format (missing "Bearer " prefix) +- Empty or null token value +- Token contains invalid characters + +**How to fix:** +- Ensure clients include the header: `Authorization: Bearer ` +- Validate token format before sending requests +- Check your authentication middleware configuration + +{% /tab %} +{% tab label="Invalid Token Signature" %} + +**Error occurs when:** JWT token's signature doesn't match expected signature, indicating tampering or wrong issuer. + +```bash {% title="Testing Invalid Token Signature" %} # Test with invalid token (should fail with 401) curl -H "Authorization: Bearer invalid_token" \ https://api.example.com/users/me @@ -630,8 +968,24 @@ curl -H "Authorization: Bearer invalid_token" \ # {"error": "Invalid token signature"} ``` -**Expired Token:** -```bash +**Common causes:** +- Token was manually modified or corrupted +- Wrong signing key used to verify the token +- Token was issued by a different authorization server +- Key rotation issues (old key used to verify new token) + +**How to fix:** +- Verify your JWT signing key configuration +- Check key rotation procedures +- Ensure tokens are only issued by trusted authorization servers +- Never modify JWT tokens after they're created + +{% /tab %} +{% tab label="Expired Token" %} + +**Error occurs when:** JWT token has passed its expiration time (`exp` claim), which is a security best practice. + +```bash {% title="Testing Expired Token" %} # Test with expired token curl -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9..." \ https://api.example.com/users/me @@ -641,10 +995,30 @@ curl -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9..." \ # {"error": "Token expired"} ``` +**Common causes:** +- Token has passed its `exp` (expiration) time +- Client cached an old token without refreshing +- Token lifetime is too short for your use case +- Time synchronization issues between servers + +**How to fix:** +- Implement token refresh logic in your clients +- Use refresh tokens to obtain new access tokens +- Adjust token lifetime based on security vs. usability needs +- Ensure server clocks are synchronized (use NTP) +- Clear expired tokens from client storage + +{% /tab %} +{% /tabs %} + ### Authorization Problems -**Insufficient Scopes:** -```bash +{% tabs %} +{% tab label="Insufficient Scopes" %} + +**Problem:** User has valid token but lacks required permissions/scopes for the operation. + +```bash {% title="Testing Scope Enforcement" %} # Test scope enforcement (readonly token trying to write) curl -H "Authorization: Bearer readonly_token" \ -X POST \ @@ -657,14 +1031,30 @@ curl -H "Authorization: Bearer readonly_token" \ # {"error": "Insufficient permissions", "required_scopes": ["users:write"]} ``` -**Missing Security Requirements:** -```yaml +**Common causes:** +- Token has read-only scopes but endpoint requires write access +- User role doesn't include necessary permissions +- Scope names don't match between token and OpenAPI spec +- Token was issued for different resource/service + +**How to fix:** +- Check required scopes in your OpenAPI security definitions +- Verify user has been granted appropriate permissions +- Ensure scope names are consistent across auth server and API +- Request tokens with broader scopes if user is authorized + +{% /tab %} +{% tab label="Missing Security Requirements" %} + +**Problem:** OpenAPI specification doesn't specify security requirements for sensitive endpoints. + +```yaml {% title="Common OpenAPI Security Bug" %} # Common issue: forgetting security on sensitive endpoints paths: /admin/users: delete: summary: "Delete all users" - # BUG: Missing security requirement! + # BUG: Missing security requirement! # [!code error] # security: # - oauth2Auth: ['admin:users'] responses: @@ -672,18 +1062,48 @@ paths: description: "All users deleted" ``` -### Configuration Mismatches +**Common causes:** +- Developer forgot to add `security:` property to endpoint +- Copy-pasted endpoint from public API without adding security +- Global security was removed but individual endpoints not updated +- New endpoints added without security review + +**How to fix:** +- Add explicit security requirements to all protected endpoints +- Use linting rules to catch missing security definitions +- Implement code review processes for new endpoints +- Consider setting global security as default with explicit overrides -**Gateway Config Doesn't Match OpenAPI:** -```bash +{% /tab %} +{% tab label="Configuration Mismatches" %} + +**Problem:** API gateway configuration doesn't match OpenAPI security specifications. + +```bash {% title="Testing Gateway Configuration Sync" %} # Verify gateway is enforcing the same rules as OpenAPI spec curl -H "Authorization: Bearer user_token" \ -X DELETE \ https://api.example.com/admin/users -# If this succeeds, gateway config is out of sync with OpenAPI +# If this succeeds when it should fail, gateway config is out of sync ``` +**Common causes:** +- Gateway config was updated manually but not synced with OpenAPI +- Deployment pipeline doesn't update gateway from OpenAPI spec +- Multiple versions of API spec with different security requirements +- Gateway caching old configuration after spec changes + +**How to fix:** +- Automate gateway configuration from OpenAPI specifications +- Implement configuration drift detection between spec and gateway +- Use infrastructure-as-code to manage gateway settings +- Test security enforcement as part of deployment pipeline +- Clear gateway cache after specification updates + +{% /tab %} +{% /tabs %} + ### Debugging Checklist 1. **Verify token format and claims:** @@ -756,16 +1176,16 @@ curl -H "Authorization: Bearer user_token" \ Authentication verifies *who* the user is (like checking an ID card), while authorization determines *what* they can do (like checking permissions). Authentication happens first and provides identity, while authorization uses that identity to make access decisions for each request. ### Should I use JWT or OAuth2 for my API? -JWT is a token format, while OAuth2 is an authorization framework. They work together: OAuth2 defines how to obtain tokens, and JWT defines the token format. Use OAuth2 with JWT tokens for user-facing applications, and consider simpler JWT Bearer authentication for service-to-service communication. +JWT is a token format, while OAuth2 is an authorization framework. They work together: OAuth2 defines how to obtain tokens, and JWT defines the token format. Use OAuth2 with JWT tokens for user-facing applications, and consider simpler JWT Bearer authentication for service-to-service communication. See [Authentication Methods](#authentication-methods) for detailed implementation examples. ### How do I implement fine-grained permissions with OpenAPI? -Use OAuth2 scopes to define specific permissions like `users:read`, `orders:write`, or `admin:users`. You can also model roles through scopes (e.g., `role:admin`) or use custom extensions for complex authorization logic that depends on request context. +Use OAuth2 scopes to define specific permissions like `users:read`, `orders:write`, or `admin:users`. You can also model roles through scopes (e.g., `role:admin`) or use [advanced authorization patterns](#advanced-authorization-patterns) for complex authorization logic that depends on request context. ### What happens if I forget to add security requirements to an endpoint? -The endpoint becomes accidentally public, which is one of the most common API vulnerabilities. Automated governance rules can prevent this by failing builds when write operations (POST, PUT, PATCH, DELETE) don't have security requirements defined. +The endpoint becomes accidentally public, which is one of the most common API vulnerabilities. [Automated governance rules](#automated-governance-for-access-control) can prevent this by failing builds when write operations (POST, PUT, PATCH, DELETE) don't have security requirements defined. ### How do I handle authorization that depends on resource ownership? -OpenAPI security schemes handle authentication and basic authorization (scopes/roles), but context-dependent authorization (like "users can only access their own resources") typically requires custom logic in your application. Document these requirements using custom extensions like `x-authorization-context`. +OpenAPI security schemes handle authentication and basic authorization (scopes/roles), but context-dependent authorization (like "users can only access their own resources") typically requires custom logic in your application. See [Advanced Authorization Patterns](#advanced-authorization-patterns) for examples of documenting these requirements using custom extensions like `x-authorization-context`. ## Resources @@ -790,8 +1210,4 @@ OpenAPI security schemes handle authentication and basic authorization (scopes/r - [API TLS Encryption and HTTPS Best Practices](api-tls-encryption-https-best-practices) - Secure data in transit with mTLS - [API Input Validation and Injection Prevention](api-input-validation-injection-prevention) - Protect APIs from malicious data - [API Rate Limiting and Abuse Prevention](api-rate-limiting-abuse-prevention) - Prevent brute force attacks on auth endpoints -- [API Security by Design: Complete Guide](/learn/security) - Overview of all API security domains - ---- - -**Next Steps:** Now that you have authentication and authorization in place, explore the complete [API Security by Design guide](/learn/security) to learn about other essential security domains like TLS encryption, input validation, and rate limiting. \ No newline at end of file +- [API Security by Design: Complete Guide](/learn/security) - Overview of all API security domains \ No newline at end of file diff --git a/learn/security/automated-security-validation-walkthrough.md b/learn/security/automated-security-validation-walkthrough.md index b0f6d081..7dd4b378 100644 --- a/learn/security/automated-security-validation-walkthrough.md +++ b/learn/security/automated-security-validation-walkthrough.md @@ -1,30 +1,32 @@ --- title: "Automated API Security Validation - Interactive Walkthrough" -description: "Learn to implement OWASP API Security Top 10 2023 rules using interactive Redocly security validation configurations with step-by-step guidance." +description: "Explore validation approaches that can help identify some common API security issues, with examples using validation rule configurations." seo: title: "Automated API Security Validation - Interactive Walkthrough" - description: "Learn to implement OWASP API Security Top 10 2023 rules using interactive Redocly security validation configurations with step-by-step guidance." + description: "Explore validation approaches that can help identify some common API security issues, with examples using validation rule configurations." --- # Automated API Security Validation - Interactive Walkthrough -*Transform your API security from manual reviews to automated enforcement using production-ready validation rules.* +*Learn how validation rules can complement your existing security practices by catching common issues during development.* --- ## What You'll Learn -This interactive walkthrough guides you through implementing **automated security validation** that enforces the **OWASP API Security Top 10 2023** using Redocly's validation engine. By the end, you'll have a complete security ruleset that prevents vulnerabilities before they reach production. +This walkthrough demonstrates one approach to implementing **automated security validation** that can help identify some common API security issues from the **OWASP API Security Top 10 2023** using validation rules. This complements other essential security practices like [TLS encryption](api-tls-encryption-https-best-practices), [input validation](api-input-validation-injection-prevention), [rate limiting](api-rate-limiting-abuse-prevention), and [access control](authentication-authorization-openapi). This is just one part of a comprehensive security strategy. -**You'll master:** -- Setting up comprehensive security validation rules -- Automating OWASP API Security Top 10 2023 compliance -- Implementing custom security validation functions -- Integrating security checks into CI/CD pipelines -- Troubleshooting common validation issues +**You'll explore:** +- Setting up basic security validation rules for OpenAPI specifications +- Examples of how validation can catch [common security issues](api-input-validation-injection-prevention#attack-prevention-strategies) like mass assignment and injection attacks +- Custom validation function patterns you might adapt for your needs +- Options for integrating validation checks into development workflows +- Common troubleshooting scenarios when working with validation tools --- + + + +## Security Validation Foundation + +### Basic Security Configuration + +Essential security rules for getting started with API validation: + +- **Core Security Rules**: Ensures [security schemes are defined](authentication-authorization-openapi#authentication-methods) +- **Response Validation**: Requires proper HTTP response codes +- **Built-in Protections**: Leverages built-in security checks + +This starter configuration is perfect for teams new to automated security validation. + +### Example API Specification + +An example OpenAPI specification demonstrates proper security implementation following validation best practices: + +**Security Best Practices:** +- [HTTPS-only server URLs](api-tls-encryption-https-best-practices#enforcing-https-in-your-api-specification) +- UUID-based IDs to prevent enumeration +- [Comprehensive security schemes with JWT/OAuth2](authentication-authorization-openapi#authentication-methods) +- [Proper input validation with string length limits](api-input-validation-injection-prevention#key-security-constraints) +- [Rate limiting headers in all responses](api-rate-limiting-abuse-prevention#documenting-rate-limits-in-openapi) +- Complete error response definitions +- [`additionalProperties: false` to prevent mass assignment](api-input-validation-injection-prevention#attack-prevention-strategies) + +Use this as a reference when implementing your own secure APIs. --- ## Implementation Strategy -Implementing automated security validation is an iterative process. Here's a recommended approach: +If you decide to use validation rules in your workflow, consider a gradual approach: -**Phase 1: Foundation (Weeks 1-2)** -- Implement basic built-in rules -- Set up HTTPS enforcement and basic authentication checks -- Integrate into CI/CD pipeline with warning-level severity +**Phase 1: Foundation (Example timeline: Weeks 1-2)** +- Start with basic built-in rules +- Try [HTTPS enforcement](api-tls-encryption-https-best-practices#enforcing-https-in-your-api-specification) and [basic authentication checks](authentication-authorization-openapi#authentication-methods) +- Consider integrating into CI/CD pipeline with warning-level severity -**Phase 2: Core Security (Weeks 3-4)** -- Add input validation and resource consumption rules -- Implement mass assignment prevention -- Escalate critical rules to error-level severity +**Phase 2: Core Security (Example timeline: Weeks 3-4)** +- Explore [input validation](api-input-validation-injection-prevention#schema-based-validation-as-security-contract) and [resource consumption rules](api-input-validation-injection-prevention#key-security-constraints) +- Evaluate [mass assignment prevention](api-input-validation-injection-prevention#attack-prevention-strategies) patterns +- Consider escalating critical rules to error-level severity based on your team's needs --- ## Next Steps and Resources -### **Immediate Actions** -1. **Download the configuration files** using the code walkthrough above -2. **Start with basic approach** if you're new to API security validation -3. **Test in development** before enforcing in production -4. **Customize rules** based on your specific security requirements +### **Suggested Next Steps** +1. **Review the example configurations** in the code walkthrough above +2. **Consider starting small** if you're new to API security validation +3. **Test thoroughly in development** before using in production environments +4. **Adapt patterns** based on your specific security needs and organizational context ### **Integration with Security Articles** This validation walkthrough complements our other security guides: -- **[TLS Encryption Best Practices](api-tls-encryption-https-best-practices)** - Implement the HTTPS enforcement rules -- **[Input Validation Guide](api-input-validation-injection-prevention)** - Apply the resource consumption and schema validation rules -- **[Rate Limiting Guide](api-rate-limiting-abuse-prevention)** - Use the rate limiting validation rules -- **[Authentication Guide](authentication-authorization-openapi)** - Implement the authentication and authorization rules +- **[TLS Encryption Best Practices](api-tls-encryption-https-best-practices)** - Learn about HTTPS enforcement approaches +- **[Input Validation Guide](api-input-validation-injection-prevention)** - Explore schema validation and input security patterns +- **[Rate Limiting Guide](api-rate-limiting-abuse-prevention)** - Understand rate limiting implementation options +- **[Authentication Guide](authentication-authorization-openapi)** - Review authentication and authorization security practices --- -**🔐 Security Note**: This walkthrough provides comprehensive coverage of OWASP API Security Top 10 2023. For production deployment, review each rule's severity level and customize based on your organization's risk tolerance and compliance requirements. +**🔐 Security Note**: This walkthrough demonstrates some validation approaches that can help identify common API security issues. Validation rules are just one layer in a comprehensive security strategy that should also include [proper TLS configuration](api-tls-encryption-https-best-practices), [robust input validation](api-input-validation-injection-prevention), [rate limiting](api-rate-limiting-abuse-prevention), and [strong access controls](authentication-authorization-openapi). Always review and test any rules thoroughly before using them in production, and customize based on your organization's specific security requirements and risk tolerance. diff --git a/learn/security/index.md b/learn/security/index.md index d5b8113c..d2e2f773 100644 --- a/learn/security/index.md +++ b/learn/security/index.md @@ -64,7 +64,7 @@ graph TD Each security domain requires specific knowledge and implementation techniques. Choose the guide that matches your current focus: -### API TLS Encryption and HTTPS Best Practices +### API TLS Encryption and HTTPS Best Practices **What you'll learn:** Protect data in transit with proper TLS configuration, certificate management, and HTTPS enforcement. **Key topics:** @@ -78,7 +78,7 @@ Each security domain requires specific knowledge and implementation techniques. --- -### API Input Validation and Injection Prevention +### API Input Validation and Injection Prevention **What you'll learn:** Stop injection attacks using OpenAPI schema validation and automated governance rules. **Key topics:** @@ -92,7 +92,7 @@ Each security domain requires specific knowledge and implementation techniques. --- -### API Rate Limiting and Abuse Prevention +### API Rate Limiting and Abuse Prevention **What you'll learn:** Prevent DoS attacks, brute force attempts, and business logic abuse through strategic rate limiting. **Key topics:** @@ -106,7 +106,7 @@ Each security domain requires specific knowledge and implementation techniques. --- -### Authentication and Authorization with OpenAPI +### Authentication and Authorization with OpenAPI **What you'll learn:** Implement secure access control using OpenAPI security schemes and modern authentication patterns. **Key topics:** @@ -232,15 +232,15 @@ Authentication verifies *who* the user is (like checking an ID card), while auth ## Resources ### Security Standards and Guidelines -- [OWASP API Security Top 10](https://owasp.org/www-project-api-security/) - Comprehensive vulnerability guide including injection attacks (API3:2023), resource consumption (API4:2023), and business logic abuse (API6:2023) -- [NIST SP 800-52 Rev. 2](https://csrc.nist.gov/publications/detail/sp/800-52/rev-2/final) - Official guidelines for secure TLS implementation and configuration requirements -- [IETF RFC 8446](https://tools.ietf.org/html/rfc8446) - TLS 1.3 protocol specification and security requirements +- OWASP API Security Top 10 - Comprehensive vulnerability guide including injection attacks (API3:2023), resource consumption (API4:2023), and business logic abuse (API6:2023) +- NIST SP 800-52 Rev. 2 - Official guidelines for secure TLS implementation and configuration requirements +- IETF RFC 8446 - TLS 1.3 protocol specification and security requirements ### Practical Implementation Tools -- [Mozilla SSL Configuration Generator](https://ssl-config.mozilla.org/) - Generate secure, up-to-date TLS configurations for various web servers and security levels -- [OpenAPI Generator](https://openapi-generator.tech/) - Code generation tool for creating secure client SDKs and server stubs from OpenAPI specifications -- [OpenAPI Specification](https://spec.openapis.org/oas/v3.1.0) - Official OpenAPI 3.1 specification including security scheme definitions +- Mozilla SSL Configuration Generator - Generate secure, up-to-date TLS configurations for various web servers and security levels +- OpenAPI Generator - Code generation tool for creating secure client SDKs and server stubs from OpenAPI specifications +- OpenAPI Specification - Official OpenAPI 3.1 specification including security scheme definitions ### DevSecOps and API Governance -- [OWASP API Security Project](https://owasp.org/www-project-api-security/) - Community-driven API security best practices and threat modeling -- [OpenAPI Security Schemes](https://spec.openapis.org/oas/v3.1.0#security-scheme-object) - Official specification for defining authentication and authorization in OpenAPI \ No newline at end of file +- OWASP API Security Project - Community-driven API security best practices and threat modeling +- OpenAPI Security Schemes - Official specification for defining authentication and authorization in OpenAPI \ No newline at end of file From d5bdd356d4c1d4846dc85e3eb2660e32833d1375 Mon Sep 17 00:00:00 2001 From: Matt Williams Date: Tue, 30 Sep 2025 11:23:19 -0500 Subject: [PATCH 11/27] Fix security articles sidebar display - Changed 'pages:' to 'items:' in sidebars.yaml to match Redocly syntax - All security articles now display correctly in left navigation menu - Fixed sidebar configuration for API Security Fundamentals group --- learn/security/sidebars.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/learn/security/sidebars.yaml b/learn/security/sidebars.yaml index 260b0ef3..5c3caed6 100644 --- a/learn/security/sidebars.yaml +++ b/learn/security/sidebars.yaml @@ -1,6 +1,6 @@ - page: ./index.md - group: API Security Fundamentals - pages: + items: - page: ./api-tls-encryption-https-best-practices.md - page: ./api-input-validation-injection-prevention.md - page: ./api-rate-limiting-abuse-prevention.md From 22df426aa3be9713c6e8967801d6f8fe785940a1 Mon Sep 17 00:00:00 2001 From: Matt Williams Date: Tue, 30 Sep 2025 11:31:14 -0500 Subject: [PATCH 12/27] Remove consolidated security article and update title - Delete api-design-first-security-guide.md (replaced by focused individual articles) - Remove from sidebars.yaml navigation - Update main landing page title to 'Framework and Fundamentals' instead of 'Complete Guide' - Cleaner navigation with 5 focused security articles + landing page + walkthrough --- .../api-design-first-security-guide.md | 1010 ----------------- ...ated-security-validation-walkthrough-v2.md | 122 -- ...tomated-security-validation-walkthrough.md | 62 - learn/security/index.md | 10 +- learn/security/sidebars.yaml | 13 +- learn/security/test-simple-walkthrough.md | 20 - 6 files changed, 14 insertions(+), 1223 deletions(-) delete mode 100644 learn/security/api-design-first-security-guide.md delete mode 100644 learn/security/automated-security-validation-walkthrough-v2.md delete mode 100644 learn/security/test-simple-walkthrough.md diff --git a/learn/security/api-design-first-security-guide.md b/learn/security/api-design-first-security-guide.md deleted file mode 100644 index cdcff339..00000000 --- a/learn/security/api-design-first-security-guide.md +++ /dev/null @@ -1,1010 +0,0 @@ -# Secure APIs by Design: A Guide to TLS, Validation & Rate Limiting with OpenAPI - -_Build secure APIs from the ground up using OpenAPI security contracts and automated governance._ - ---- - -## Key Takeaways - -Many teams discover security vulnerabilities after they're already in production, but it doesn't have to be that way! - -In this guide, we'll walk though how to turn your OpenAPI specification into a security contract that actually gets enforced. We'll give some tips and tricks on setting up TLS encryption, implementing input validation, defining rate limiting policies, and configuring access control. By the time you're done, you'll know how to catch some security issues during the design phase instead of scrambling to fix them once they're in production. - -**We'll cover how to:** -- Transform your OpenAPI specs into executable security policies -- Automate security enforcement in your CI/CD pipeline -- Reduce vulnerability discovery time (from months to minutes in some cases) -- Build APIs that are secure by design upfront - ---- - -## From Reactive Patching to Proactive API Security - -High-profile data breaches frequently trace back to insecure APIs, exposing a fundamental flaw in traditional security approaches. The conventional method—identifying and patching vulnerabilities in production—is reactive, costly, and ultimately inadequate. In its typical form, this paradigm treats security as an afterthought. - -Shifting security practices to the left in the development lifecycle, known as the "shift-left" imperative, addresses this by integrating security into the earliest stages of design and development. This proactive model prevents vulnerabilities from being introduced in the first place, rather than attempting to remediate them under pressure in production environments. - -### OpenAPI as Your Security Contract - -The core of this strategy is treating your OpenAPI specification not merely as documentation, but as an executable security contract. This contract declaratively defines a set of security requirements, constraints, and policies before any application code is written. It becomes the single source of truth that dictates how an API must behave to be considered secure, effectively implementing a "policy-as-code" approach for APIs. - -However, a contract, much like a law, is only as strong as its enforcement. This is where automated governance and linting tools provide value by transforming your contract into dynamic, automated guardrails that validate security requirements at every stage of development. When integrated into a Continuous Integration/Continuous Deployment (CI/CD) pipeline, this automated governance acts as a gatekeeper, failing builds that violate the security contract and requiring fixes before deployment. - -*OpenAPI specifications are validated by automated governance engines in CI/CD pipelines, failing builds for security violations and requiring fixes before deployment.* - -## Building Secure API Infrastructure: The Technical Foundation - -Building secure APIs doesn't have to feel like playing whack-a-mole with vulnerabilities. Once you shift from reactive patching to proactive design, you'll wonder why you ever did it any other way. Let's explore how to make security an automatic part of your API development process. - -Let's look at 4 key areas: - -1. **TLS Encryption** - Protecting data in transit with enforced HTTPS -2. **Input Validation** - Rejecting malicious data through schema contracts -3. **Rate Limiting** - Preventing abuse with documented policies -4. **Access Control** - Defining authentication and authorization schemes - -Where these areas are codified in your OpenAPI specification and enforced through automated governance, they provide a foundation for APIs that are secure by design - something we very much endorse! - -```mermaid -graph TD - A["🏛️ Secure API Foundation"] --> B["🔐 TLS Encryption
Data in Transit"] - A --> C["✅ Input Validation
Schema Contracts"] - A --> D["⚡ Rate Limiting
Abuse Prevention"] - A --> E["🔑 Access Control
Auth & Authorization"] - - B --> F["• HTTPS Enforcement
• Certificate Management
• Strong Cipher Suites"] - C --> G["• JSON Schema Rules
• Type Validation
• Length Constraints"] - D --> H["• x-rateLimit Extensions
• 429 Response Headers
• Multi-tier Limits"] - E --> I["• Security Schemes
• JWT/OAuth2
• Scope Management"] - - J["📄 OpenAPI 3.1
Specification"] --> A - K["⚙️ Automated
Governance"] --> A - - style A fill:#e8f5e8 - style B fill:#e3f2fd - style C fill:#fff3e0 - style D fill:#fce4ec - style E fill:#f1f8e9 - style J fill:#e1f5fe - style K fill:#f3e5f5 -``` - -*Architecture diagram showing the four essential areas of API security (TLS encryption, input validation, rate limiting, access control) supported by OpenAPI specifications and automated governance tools.* - -## Security Governance Principles - -Before diving into each security area, it's important to understand how automated governance can enforce security best practices. Modern API governance tools allow you to define custom rules that validate your OpenAPI specifications against security standards. - -### Key Security Validation Areas - -**Transport Security:** -- Enforce HTTPS-only server URLs -- Prevent example.com or placeholder domains in production specs -- Validate proper TLS configuration requirements - -**Input Validation:** -- Require `maxLength` constraints on all string properties -- Mandate `minimum` and `maximum` bounds for numeric fields -- Enforce `additionalProperties: false` to prevent mass assignment vulnerabilities - -**Rate Limiting:** -- Require rate limiting policies on authentication endpoints -- Validate that sensitive operations have documented throttling -- Ensure consistent rate limiting standards across APIs - -**Access Control:** -- Mandate security definitions on all write operations (POST, PUT, PATCH, DELETE) -- Validate that authentication schemes are properly documented -- Prevent accidentally public endpoints - -These governance principles can be implemented using various API linting and validation tools. Each section below explains the security concepts behind these requirements and shows implementation examples. - -## Understanding Design-Time vs Runtime Security - -It's important to understand that OpenAPI-based security governance operates at **design-time**, not runtime. This governance approach excels at preventing configuration errors, missing security controls, and specification inconsistencies before they reach production. That said, it cannot prevent runtime vulnerabilities in the underlying implementation. - -### API Security Implementation Timeline - -```mermaid -timeline - title API Security Implementation Timeline - - section Design Phase - OpenAPI Spec : Security schemes defined - : Input validation rules - : Rate limiting policies - - section Build Phase - Code Generation : Security middleware - : Validation logic - CI/CD Pipeline : Governance checks - : Security linting - - section Runtime Phase - Production : TLS termination - : Authentication - : Rate limiting - : Input validation - Monitoring : Attack detection - : Performance metrics -``` - -*Timeline showing how API security spans from design-time specification through build automation to runtime enforcement, with different security controls applied at each phase.* - -**Design-time security governance prevents:** -- Accidentally public endpoints (missing security requirements) -- Insecure server configurations (HTTP instead of HTTPS) -- Missing input validation constraints -- Inconsistent rate limiting policies -- Data leakage through unused components - -**Runtime security still requires:** -- Patch management for frameworks and libraries (like the Heartbleed OpenSSL vulnerability) -- Secure coding practices and parameterized queries -- Infrastructure security monitoring and alerting -- Penetration testing and vulnerability scanning - -True "secure by design" requires both: design-time contracts enforced through OpenAPI governance *and* runtime security posture management as part of a comprehensive DevSecOps practice. - -## TLS Encryption: Protecting Data in Transit with OpenAPI - -When a client and an API exchange information, that data travels across the internet, a public network. Without protection, this data gets intercepted and read by malicious actors. This is where encryption comes in. - -> **The Banking Vault Principle**: When banks transfer large sums between branches, they don't send cash in regular envelopes. They use armored vehicles with multiple security layers. TLS encryption works similarly — it creates a secure transport layer that protects your API data during transit, even across untrusted networks. - -**Encryption in transit** works similarly, creating a secure, private tunnel for API data as it moves between the client and the server. - -### TLS 1.3: The Modern Standard - -This secure tunnel is primarily established using **Transport Layer Security (TLS) version 1.3**, as specified in [IETF RFC 8446](https://tools.ietf.org/html/rfc8446). [NIST SP 800-52 Rev. 2](https://csrc.nist.gov/publications/detail/sp/800-52/rev-2/final) guidelines for TLS implementations unequivocally mandate TLS 1.3 for modern systems, as older protocols—including all versions of SSL, TLS 1.0, and TLS 1.1—are deprecated and considered insecure due to known vulnerabilities. - -When a client connects to an API over `https://`, it initiates a "TLS handshake." During this handshake, the client and server perform crucial steps: - -1. **Authentication:** The server presents its TLS certificate to the client to prove its identity, ensuring the client is talking to the legitimate server and not an impostor. -2. **Agreement on Encryption:** They agree on a set of cryptographic algorithms (a "cipher suite") to use for the session. -3. **Key Exchange:** They securely generate and exchange unique session keys that will be used to encrypt and decrypt all data for the remainder of the conversation. - -We're not going to get all the way into it in this article, but here is what the handshake looks like: - -### TLS Handshake Process - -```mermaid -sequenceDiagram - participant C as Client - participant S as Server - - Note over C,S: TLS Handshake Process - - C->>S: 1. Client Hello (Supported cipher suites) - - S->>C: 2. Server Hello + Certificate - Note right of S: Server presents TLS certificate to prove identity - - C->>C: 3. Certificate Validation - Note left of C: Client verifies server certificate is trusted - - C->>S: 4. Cipher Suite Selection - Note over C,S: Both agree on cryptographic algorithms - - C->>S: 5. Key Exchange - S->>C: 6. Key Exchange Complete - Note over C,S: Generate and exchange unique session keys - - Note over C,S: 🔒 Secure Communication Begins - - C->>S: Encrypted API Request - S->>C: Encrypted API Response - -``` - -*Sequence diagram illustrating the TLS handshake process between client and server, showing certificate validation, cipher suite selection, and secure key exchange that ensures encrypted API communication.* - -### TLS Security Guarantees - -TLS, when done right, provides three essential security guarantees: - -* **Confidentiality:** It encrypts the data, preventing eavesdroppers from reading it. -* **Integrity:** It ensures that the data has not been altered or tampered with during transit. -* **Authentication:** It verifies the identity of the server, protecting against man-in-the-middle attacks. - -This is why secure APIs always use URLs that start with `https://` instead of `http://`. The 's' stands for 'secure' and indicates that the connection is protected by TLS encryption. - -### TLS Implementation Best Practices - -In our production environments, we've learned that telling teams to "use HTTPS" without specifics sometimes leads to misconfigured TLS and a false sense of security. Proper TLS implementation requires: - -* **Enforcing Strong Cipher Suites**: Configure servers to only negotiate cryptographic algorithms that are considered secure, disabling weak or obsolete ciphers -* **Proper Certificate Management**: Use certificates from trusted Certificate Authorities (CAs), ensure they are not expired, and implement robust processes for certificate issuance, renewal, and revocation -* **Protection Against Man-in-the-Middle (MiTM) Attacks**: Implement HTTP Strict Transport Security (HSTS) to instruct browsers to only communicate over HTTPS, preventing protocol downgrade attacks - -#### Common TLS misconfigurations - -* Weak or legacy protocols enabled (SSL, TLS 1.0/1.1) — disable them explicitly -* Missing HSTS header — add Strict-Transport-Security with long max-age -* Mixed content or accidental HTTP endpoints — redirect to HTTPS at the edge -* Expiring certificates — monitor expiry and automate renewal - -Quick checks: - -```bash -# Verify protocol and cipher suites -openssl s_client -connect api.example.com:443 -tls1_3 -cipher 'TLS_AES_256_GCM_SHA384' < /dev/null | grep -E 'Protocol|Cipher' - -# Scan for common TLS issues -testssl.sh --fast https://api.example.com -``` - -> Expert insight: "Treat TLS as a product with owners and SLAs. We track TLS health on dashboards the same way we track latency and errors." - -### Enforcing HTTPS in Your API Specification - -The security contract for encrypted transit begins within the `servers` object of your OpenAPI specification. Every URL defined here must use the `https://` scheme—this isn't just documentation, it's a formal declaration of your API's secure endpoints. - -**OpenAPI Servers Declaration:** -```yaml {% title="openapi.yaml" %} -servers: - - url: https://api.production.com/v1 - description: Production Server - - url: https://api.staging.com/v1 - description: Staging Server -``` - -**Automated Governance Enforcement:** - -The [Security Governance Principles](#security-governance-principles) section shows how modern API governance tools can enforce HTTPS usage and other security controls through automated validation rules. - -When integrated into your CI/CD pipeline, automated governance creates security gates. If a developer attempts to commit an OpenAPI file with insecure server URLs, the pipeline fails with a clear error message, preventing insecure configurations from ever reaching production. - -*Automated governance tools fail CI/CD builds when OpenAPI specifications use HTTP instead of HTTPS, requiring developers to fix security violations before deployment.* - -### TLS Configuration Examples - -Authoritative sources like the [Mozilla SSL Configuration Generator](https://ssl-config.mozilla.org/) provide excellent, up-to-date templates for secure server configurations across different platforms and security requirements. - -**Nginx Configuration:** -```nginx -server { - listen 443 ssl http2; - server_name api.example.com; - - # TLS 1.3 only - ssl_protocols TLSv1.3; - - # Strong cipher suites - ssl_ciphers TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256; - - # HSTS header - add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; - - # Certificate files - ssl_certificate /path/to/certificate.crt; - ssl_certificate_key /path/to/private.key; -} -``` - -**Express.js Configuration:** -```javascript -const https = require('https'); -const fs = require('fs'); -const express = require('express'); - -const app = express(); - -// HSTS middleware -app.use((req, res, next) => { - res.setHeader('Strict-Transport-Security', 'max-age=31536000; includeSubDomains'); - next(); -}); - -const options = { - key: fs.readFileSync('private.key'), - cert: fs.readFileSync('certificate.crt'), - // Force TLS 1.3 - secureProtocol: 'TLSv1_3_method' -}; - -https.createServer(options, app).listen(443); -``` - -### Attack Example: Heartbleed (TLS library vulnerability, 2014) - -The Heartbleed bug (CVE-2014-0160) was a critical vulnerability in the OpenSSL library, not the TLS protocol itself. It allowed attackers to read up to 64KB of a server's memory by sending a malformed TLS heartbeat request. The server would respond with not only the small payload sent by the attacker but also adjacent memory contents, which could include session cookies, user credentials, and even the server's private encryption keys. - -This incident demonstrates a crucial point: security is multi-layered. While an OpenAPI specification can enforce the *intent* of using secure transport (https://), it cannot prevent a runtime vulnerability in the underlying software stack. As mentioned earlier, true "secure by design" requires both design-time governance via OpenAPI linting and runtime security posture management, including diligent vulnerability scanning and patch management. - -```mermaid -sequenceDiagram - participant A as Attacker - participant S as Vulnerable Server (OpenSSL) - - A->>S: TLS handshake - A->>S: Malformed Heartbeat Request (len >> data) - S-->>A: Memory contents leak (keys, session cookies) - A->>S: Follow-on requests using stolen secrets -``` - -*Sequence diagram showing the Heartbleed attack: malformed TLS heartbeat requests cause vulnerable OpenSSL servers to leak memory contents including encryption keys and session data.* - -Why this matters: TLS is only as strong as its implementation. Monitoring and rapid patching for library CVEs are part of infrastructure security. - -### Mutual TLS (mTLS): Two-Way Authentication - -While standard TLS only authenticates the server to the client, **Mutual TLS (mTLS)** requires both parties to authenticate each other using certificates. This provides stronger security for high-trust scenarios and is essential for implementing zero-trust architecture principles. - -**mTLS Use Cases:** -- Microservice communication in zero-trust architectures where no network segment is inherently trusted -- API-to-API authentication between organizations implementing defense-in-depth strategies -- IoT device authentication in distributed systems -- High-security financial and healthcare APIs requiring cryptographic identity verification - -**OpenAPI mTLS Configuration:** -```yaml {% title="openapi.yaml" %} -components: - securitySchemes: - mtlsAuth: - type: mutualTLS - description: "Client certificate authentication" - -# Apply to sensitive operations -paths: - /internal/payments: - post: - security: - - mtlsAuth: [] - summary: "Process payment (internal service only)" -``` - -**Implementation Example (Nginx):** -```nginx -server { - listen 443 ssl http2; - - # Server certificate - ssl_certificate /path/to/server.crt; - ssl_certificate_key /path/to/server.key; - - # Require client certificates - ssl_verify_client on; - ssl_client_certificate /path/to/ca.crt; - - # Pass client certificate info to backend - proxy_set_header X-Client-Cert $ssl_client_cert; - proxy_set_header X-Client-Verify $ssl_client_verify; -} -``` - -> **mTLS Best Practice**: Use mTLS for service-to-service communication and regular TLS + JWT/OAuth2 for client-to-server communication. - ---- - -## Input Validation: Preventing Injection Attacks with Schema-Based Security - -APIs are designed to accept data as input. However, an API should never blindly trust the data it receives from a client. The process of rigorously checking all incoming data is called data validation. NIST defines data validation as "The process of determining that data...is acceptable according to a predefined set of tests and the results of those tests." - -### The Restaurant Waiter Analogy - -> **The Restaurant Waiter**: The API is the waiter, and its documentation (or schema) is the menu. The menu explicitly states what can be ordered and in what format (e.g., "Steak - medium rare"). If a customer tries to order something not on the menu, like "a bicycle," or provides an invalid option, like "a million steaks," a competent waiter will immediately reject the order at the table before it ever reaches the kitchen. This is data validation. - -### Technical Implementation of Data Validation - -In technical terms, data validation is the practice of checking all incoming data from a client to ensure it conforms to the expected format, type, range, and other constraints before it is processed by the application's business logic. - -For example, if an API endpoint expects a user's age, validation rules should ensure the input is an integer and falls within a reasonable range (e.g., 0-130). - -Proper data validation is a critical defense against a wide range of attacks, notably **Injection flaws**. An injection attack occurs when a malicious actor sends executable code disguised as data. - -If the API fails to validate the input and passes it directly to a database or the operating system, that malicious code could be executed. By strictly validating that all inputs are what they are supposed to be, an API can reject malicious payloads before they can do any harm. - -### SQL Injection Prevention - -For interactions with a database, the gold standard for preventing SQL injection attacks is the use of parameterized queries, also known as prepared statements. - -A parameterized query forces a separation between the SQL command (the code) and the user-supplied data, making it impossible for an attacker to alter the logic of the query. - -**Vulnerable Code (Never Do This):** -```javascript -// DANGEROUS: Directly interpolating user input # [!code error] -const userId = req.query.user_id; -const query = `SELECT * FROM users WHERE id = ${userId}`; // [!code --] -const result = await db.query(query); // [!code --] -``` - -**Secure Code (Use Parameterized Queries):** -```javascript -// SAFE: Using parameterized queries # [!code ++] -const userId = req.query.user_id; -const query = "SELECT * FROM users WHERE id = $1"; // [!code ++] -const result = await db.query(query, [userId]); // [!code ++] -``` - -### Schema-Based Validation as Security Contract - -OpenAPI 3.1 provides a comprehensive vocabulary for defining strict validation rules by leveraging JSON Schema Draft 2020-12. By codifying these rules directly in your API specification, validation becomes core to your API's design. - -**Secure Schema Example:** -```yaml {% title="openapi.yaml" %} -components: - schemas: - NewUser: - type: object - additionalProperties: false # [!code highlight] Prevent mass assignment (OWASP API3:2023) - required: - - username - - email - - password - - age - properties: - username: - type: string - minLength: 4 - maxLength: 20 # [!code highlight] Prevent resource exhaustion (OWASP API4:2023) - pattern: "^[a-zA-Z0-9]+$" # [!code highlight] Prevent injection attacks - email: - type: string - maxLength: 254 # [!code highlight] Prevent resource exhaustion (OWASP API4:2023) - format: email # [!code highlight] Built-in email validation - password: - type: string - minLength: 12 # [!code highlight] Strong password requirement - maxLength: 128 - age: - type: integer - minimum: 18 # [!code highlight] Age verification - maximum: 130 # [!code highlight] Prevent integer overflow attacks - role: - type: string - enum: ["user", "viewer"] # [!code highlight] Enforce allow-list approach - default: "user" -``` - -**Automated Governance for Validation:** - -The [Security Governance Principles](#security-governance-principles) section outlines how automated governance tools can enforce input validation rules that require string length bounds, numeric ranges, and prevent mass assignment vulnerabilities. - -This governance approach transforms security reviews. Instead of manually checking many properties for missing `maxLength` constraints, automated linting tools handle baseline validation so security teams can focus on strategic concerns like business logic and context-dependent risks. - -### Key Security Constraints - -The most critical schema constraints for API security focus on preventing resource exhaustion and injection attacks: - -- **`maxLength`**: Required on all strings to prevent memory exhaustion attacks -- **`maximum/minimum`**: Required on all numbers to prevent integer overflow vulnerabilities -- **`additionalProperties: false`**: Essential for preventing mass assignment attacks -- **`pattern`**: Use restrictive regex patterns to block injection payloads - -These constraints can be automatically enforced by governance rules as outlined in the [Security Governance Principles](#security-governance-principles) section, ensuring no schema can bypass these fundamental protections. - -### Common Validation Patterns - -{% table %} -* Input Type -* Validation Rules -* Example ---- -* Email -* RFC 5322 format -* `user@example.com` ---- -* Phone -* E.164 format -* `+1234567890` ---- -* URL -* Valid URL scheme -* `https://example.com` ---- -* UUID -* Standard UUID format -* `123e4567-e89b-12d3-a456-426614174000` ---- -* Date -* ISO 8601 format -* `2025-01-20T10:30:00Z` ---- -* Password -* Minimum complexity -* 8+ chars, mixed case, numbers, symbols -{% /table %} - -#### Validation troubleshooting and common pitfalls - -* Missing bounds (no `maxLength`, no numeric ranges) — leads to resource exhaustion -* Overly permissive regex patterns — allow unwanted characters and injection payloads -* Validating at the wrong layer — front-end only, or after DB calls -* Accepting undeclared properties — enables mass assignment - -Quick fixes: - -```yaml {% title="JSON Schema example" %} -type: object -additionalProperties: false -properties: - name: - type: string - minLength: 1 - maxLength: 100 - pattern: "^[a-zA-Z\\s]+$" - age: - type: integer - minimum: 0 - maximum: 130 -``` - -> API Security Best Practice: "Blocking PRs that add new string fields without `maxLength` constraints is one of the most cost-effective security guardrails you can implement." - -### Attack Example: Equifax (OGNL injection via Apache Struts, 2017) - -The 2017 Equifax data breach was the result of a catastrophic input validation failure in the Apache Struts framework (CVE-2017-5638). The vulnerability allowed attackers to perform remote code execution by sending a specially crafted `Content-Type` header. The Struts framework failed to properly sanitize this header value, interpreting it as an Object-Graph Navigation Language (OGNL) expression and executing it. This gave attackers a direct shell on the server, which they used to access sensitive databases and exfiltrate the personal data of over 140 million people. - -This incident underscores the critical importance of validating all inputs, including HTTP headers, against a strict allow-list or pattern. A strong schema-based validation approach, enforced by governance, can block entire classes of injection attacks before they ever reach vulnerable application code. - -```mermaid -sequenceDiagram - participant A as Attacker - participant W as WAF (misconfigured) - participant S as Struts App (vulnerable) - participant DB as Database - - A->>W: HTTP request with malicious Content-Type header - W-->>S: Pass-through (no block) - A->>S: OGNL payload evaluated - S->>S: Remote code execution - S->>DB: Query PII at scale - DB-->>A: Exfiltrated records (PII) -``` - -*Sequence diagram illustrating the Equifax breach: attacker exploited Apache Struts vulnerability through OGNL injection in Content-Type headers, bypassing WAF and executing code to steal personal data.* - -Why this matters: Strong schema validation, input allow-lists, and patch hygiene block entire classes of injection attacks. - ---- - -## Rate Limiting: Preventing DoS and Abuse with API Policies - -A single client, whether intentionally malicious or simply due to a bug in its code, can send a massive number of requests to an API in a short period. This can overwhelm the server, degrading performance for all other users or even causing the service to crash. Rate limiting is the primary defense against this scenario. - -### The Library Card Analogy - -> **The Library Card**: A library card allows a patron to check out a maximum of ten books per month. Once that limit is reached, the system will not allow any more checkouts until the next month begins, regardless of how many times the patron asks. - -**Rate limiting** applies this same principle to an API. It establishes a policy that restricts the number of requests a single client can make within a specific time window (e.g., 100 requests per minute). - -### Documenting Rate Limits in OpenAPI - -While OpenAPI 3.1 doesn't include native rate-limiting objects, extension properties (prefixed with `x-`) provide a standard mechanism. The best practice is defining custom `x-rateLimit` extensions at the operation level. - -**Note:** Rate limits are typically dynamic in production environments, with different limits for different clients based on service tiers, contracts, or usage patterns. The OpenAPI specification documents the baseline policy, while implementation systems apply client-specific variations: - -```yaml {% title="openapi.yaml" %} -paths: - /auth/login: - post: - summary: User Login - tags: [Authentication] - # Define rate-limiting policy for this sensitive endpoint - x-rateLimit: - limit: 5 - window: "1m" - scope: "ip_address" - description: "Limits login attempts to 5 per minute per IP to prevent brute-force attacks." - responses: - '200': - description: "Successful login." - # Document the 429 response with proper headers - '429': - description: "Too Many Requests. Rate limit exceeded." - headers: - Retry-After: - schema: - type: integer - description: "Seconds to wait before making a new request." - X-RateLimit-Limit: - schema: - type: integer - description: "Maximum requests permitted in the window." - X-RateLimit-Remaining: - schema: - type: integer - description: "Requests remaining in current window." -``` - -**Automated Governance for Rate Limiting:** - -API governance tools can enforce rules that ensure authentication endpoints always have rate limiting policies defined. - -This approach provides dual benefits: modern API documentation tools automatically display rate limiting extensions in generated documentation, making policies transparent to API consumers, while governance rules ensure sensitive endpoints never lack rate-limiting policies. - -### Why Rate Limiting Is Critical - -Rate limiting is a critical control for both security and reliability, directly mitigating several OWASP API Security Top 10 risks: - -1. **Security:** It thwarts Denial-of-Service (DoS) attacks by preventing traffic floods, addressing OWASP API4:2023 - Unrestricted Resource Consumption. It also makes brute-force attacks against authentication endpoints much slower and less effective, reducing the risk of credential stuffing attacks. -2. **Business Logic Abuse:** It helps mitigate abuse by preventing bots from scraping data or manipulating business flows, addressing OWASP API6:2023 - Unrestricted Access to Sensitive Business Flows. -3. **Reliability and Fair Usage:** It ensures that the API remains stable and responsive for all users by preventing any single client from monopolizing server resources. - -### Rate Limiting Implementation Approaches - -**Common Algorithm Types:** -- **Token Bucket**: Allows burst traffic within limits, refills at steady rate -- **Sliding Window**: Precise per-window enforcement with distributed request tracking -- **Fixed Window**: Simple per-timeframe limits, prone to boundary conditions - -**Multi-tier Strategy:** -```yaml {% title="API Gateway configuration" %} -rate_limits: - global: - requests_per_minute: 1000 - requests_per_hour: 10000 - by_endpoint: - "/auth/*": - requests_per_minute: 5 - requests_per_hour: 20 - "/api/data": - requests_per_minute: 100 -``` - -### Advanced Rate Limiting Techniques - -**Multi-tier Rate Limiting:** -```yaml {% title="Kong configuration" %} -plugins: -- name: rate-limiting - config: - minute: 100 # 100 requests per minute per IP - hour: 1000 # 1000 requests per hour per IP - policy: redis # Use Redis for distributed rate limiting - fault_tolerant: true - hide_client_headers: false - -# Per-endpoint overrides -- name: rate-limiting - route: auth-endpoints - config: - minute: 5 # Stricter limits for auth endpoints - hour: 20 -``` - -**Client-side Exponential Backoff:** -```javascript -class APIClient { - async makeRequest(url, options, retries = 3) { - try { - const response = await fetch(url, options); - - if (response.status === 429) { - const retryAfter = response.headers.get('Retry-After'); - const delay = retryAfter ? parseInt(retryAfter) * 1000 : - Math.pow(2, 4 - retries) * 1000; // Exponential backoff - - if (retries > 0) { - await new Promise(resolve => setTimeout(resolve, delay)); - return this.makeRequest(url, options, retries - 1); - } - - throw new Error('Rate limit exceeded'); - } - - return response; - } catch (error) { - throw error; - } - } -} -``` - -As a complementary practice, the client-side responsibility of implementing exponential backoff should also be noted. When an API client receives a rate-limiting error (e.g., HTTP 429 Too Many Requests), it should wait for an exponentially increasing period of time between retries. This prevents clients from overwhelming the server and helps the system recover gracefully from load spikes. - -> **Tip:** Combine per-IP and per-account quotas and require exponential backoff on clients. - -### Attack Example: Facebook phone number scraping (2019 dataset) - -In 2019, malicious actors exploited a vulnerability in Facebook's contact importer feature to scrape the personal data of over 530 million users. The API endpoint itself was not technically "broken"—it performed its intended function of matching phone numbers to user profiles. The vulnerability was the absence of adequate rate limiting and business rule enforcement. Attackers used automated scripts to submit massive lists of phone numbers, and the API dutifully returned the corresponding user profiles, allowing them to build a massive database of personal information. - -This incident highlights a different type of API attacks, moving from exploiting technical flaws to abusing business logic at scale. It elevates rate limiting from an infrastructure protection mechanism to a also being a tool for enforcing business rules. The `x-rateLimit` extension in OpenAPI is a form of declarative security policy. - -```mermaid -sequenceDiagram - participant B as Botnet/Script - participant API as Contact Import API - - loop Enumerate phone numbers - B->>API: Batch upload numbers - API-->>B: Matched user IDs/profile data - end - Note over B,API: Missing per-account/IP limits and anomaly detection -``` - -*Sequence diagram showing how attackers used Facebook's contact import API to scrape phone numbers at scale, exploiting missing rate limits and velocity checks to harvest personal data.* - -Why this matters: Rate limiting, velocity checks, and behavior analytics are core defenses against scraping and credential-stuffing at scale. - ---- - -### Defining Security Schemes in OpenAPI - -OpenAPI 3.1 provides a robust framework for defining access control through two primary constructs: - -1. **`components.securitySchemes`**: Defines *how* clients can authenticate (JWT Bearer, OAuth2, API Keys) -2. **`security`**: Specifies *that* an endpoint is secured and by which mechanism(s) - -#### Authentication vs Authorization Flow - -```mermaid -sequenceDiagram - participant U as User - participant A as API Gateway - participant Auth as Auth Service - participant API as API Endpoint - - Note over U,API: Authentication Phase - U->>A: 1. Request with credentials - A->>Auth: 2. Verify identity - Auth->>A: 3. Identity confirmed + token - A->>U: 4. Return access token - - Note over U,API: Authorization Phase - U->>A: 5. API request + token - A->>A: 6. Validate token - A->>A: 7. Check permissions/scopes - - alt Authorized - A->>API: 8. Forward request - API->>A: 9. Response - A->>U: 10. Return response - else Unauthorized - A->>U: 11. 403 Forbidden - end -``` - -*Sequence diagram showing the two-phase process: authentication verifies who the user is, while authorization determines what they can do. Both phases are essential for secure API access control.* - -**JWT Bearer Token Example:** -```yaml {% title="openapi.yaml" %} -components: - securitySchemes: - bearerAuth: - type: http - scheme: bearer - bearerFormat: JWT - description: "Enter JWT with 'Bearer ' prefix" - -# Apply globally to all operations -security: - - bearerAuth: [] -``` - -**OAuth2 with Scopes Example:** -```yaml {% title="openapi.yaml" %} -components: - securitySchemes: - oauth2Auth: - type: oauth2 - description: "OAuth2 Authorization Code Flow with PKCE" - flows: - authorizationCode: - authorizationUrl: https://auth.example.com/authorize - tokenUrl: https://auth.example.com/token - scopes: - 'users:read': "Read access to user profiles" - 'users:write': "Modify user profiles" - -paths: - /users/{userId}: - patch: - summary: "Update user profile" - security: - - oauth2Auth: ['users:write'] # Requires specific scope -``` - -### Automated Governance for Access Control - -Access control enforcement can be handled through custom governance rules that ensure all write operations have security requirements defined. - -When automated linting runs, any endpoint without a corresponding `security` block causes the build to fail, preventing the most common API vulnerability: the unintentionally public endpoint. - -### Security Definitions as Configuration - -Defining security schemes in OpenAPI extends beyond documentation—it establishes configuration-as-code that drives consistency across your entire API ecosystem: - -- **API Gateways** (Kong, Apigee) import OpenAPI files and automatically configure JWT validation based on `securitySchemes` -- **Code generators** create boilerplate authentication handling -- **Testing tools** automate authenticated requests -- **API documentation tools** render appropriate interactive UI for each scheme type - -This unified approach ensures the security policy defined in design is the same policy implemented, documented, tested, and enforced in production. - -#### Access control troubleshooting and common pitfalls - -* Missing security definitions — endpoints accidentally left public -* Overly broad scopes — `admin` scope used everywhere instead of granular permissions -* Security schemes not enforced — gateway config doesn't match OpenAPI definition -* Bearer tokens without validation — accepting any JWT without signature verification - -Quick checks: - -```bash -# Test unauthenticated access (should fail) -curl -i https://api.example.com/users/me - -# Test with invalid token (should fail) -curl -H "Authorization: Bearer invalid" https://api.example.com/users/me - -# Test scope enforcement -curl -H "Authorization: Bearer readonly_token" -X POST https://api.example.com/users -``` - -> Key insight: "Requiring security definitions on all write operations has prevented more breaches than any other single control. Automated enforcement of authentication requirements on mutation operations should be non-negotiable in your CI pipeline." - -#### Rate limiting troubleshooting and common pitfalls - -* Counting the wrong thing — per-IP only; add per-account and per-token limits -* Same limits for every endpoint — tighten auth and write endpoints separately -* No Retry-After header — clients can't back off predictably -* Stateless limits in distributed systems — use Redis or gateway-native stores - -Quick checks: - -```bash -# Observe 429 behavior and headers -curl -i https://api.example.com/login | grep -E 'HTTP/|Retry-After' - -# Simulate burst to verify buckets/windows -hey -z 10s -q 50 -c 50 https://api.example.com/api/resource -``` - -> Another insight: "Rate limiting on auth endpoints is non-negotiable. We set 5/min per IP and per account, and alert when bypass attempts appear." - -## Monitoring and Observability - -### TLS Monitoring -```yaml {% title="prometheus.yml" %} -groups: -- name: tls_alerts - rules: - - alert: TLSCertificateExpiringSoon - expr: probe_ssl_earliest_cert_expiry - time() < 86400 * 30 - labels: - severity: warning - annotations: - summary: "TLS certificate expires in less than 30 days" - - - alert: WeakTLSVersion - expr: probe_tls_version_info{version!="TLS 1.3"} == 1 - labels: - severity: critical - annotations: - summary: "Weak TLS version detected" -``` - -### Validation Monitoring -```javascript -// Log validation failures for analysis -app.use((req, res, next) => { - const originalSend = res.send; - - res.send = function(data) { - if (res.statusCode === 400 && req.validationErrors) { - logger.warn('Validation failure', { - endpoint: req.path, - errors: req.validationErrors, - clientIP: req.ip, - userAgent: req.get('User-Agent') - }); - } - - originalSend.call(this, data); - }; - - next(); -}); -``` - -### Rate Limiting Monitoring -```javascript -// Track rate limiting metrics -class RateLimitMetrics { - constructor() { - this.blockedRequests = new Map(); - this.totalRequests = new Map(); - } - - recordRequest(clientId, blocked = false) { - // Initialize counters if client is new - if (!this.totalRequests.has(clientId)) { - this.totalRequests.set(clientId, 0); - this.blockedRequests.set(clientId, 0); - } - - this.totalRequests.set(clientId, this.totalRequests.get(clientId) + 1); - if (blocked) { - this.blockedRequests.set(clientId, this.blockedRequests.get(clientId) + 1); - } - } - - getBlockRate(clientId) { - const total = this.totalRequests.get(clientId) || 0; - const blocked = this.blockedRequests.get(clientId) || 0; - return total > 0 ? (blocked / total) * 100 : 0; - } -} -``` - -## API Security Maturity Model - -Implementing comprehensive API security is a journey. Organizations typically progress through distinct maturity levels as they build more sophisticated security practices: - -```mermaid -graph TD - A[Level 0: Basic] --> B[Level 1: Structured] --> C[Level 2: Automated] --> D[Level 3: Proactive] - - A --> A1[Manual reviews
Basic HTTPS
Simple auth] - B --> B1[OpenAPI specs
Schema validation
Rate limiting] - C --> C1[Automated governance
CI/CD integration
Policy enforcement] - D --> D1[Threat modeling
Zero-trust architecture
Continuous monitoring] - - style A fill:#ffcdd2 - style B fill:#fff59d - style C fill:#c8e6c9 - style D fill:#a5d6a7 -``` - -*API security maturity progression showing the evolution from basic manual practices to proactive, automated security governance with comprehensive threat detection and prevention.* - -**Level 0 - Basic Security:** -- Manual code reviews for obvious security issues -- HTTPS enabled but not enforced through specifications -- Basic authentication (API keys or simple passwords) -- Ad-hoc security practices without consistent standards - -**Level 1 - Structured Security:** -- OpenAPI specifications document all APIs with security requirements -- Schema-based input validation prevents basic injection attacks -- Rate limiting implemented on authentication and sensitive endpoints -- Consistent security patterns across API teams - -**Level 2 - Automated Security:** -- Automated governance tools enforce security standards in CI/CD pipelines -- Security policies defined as code and validated automatically -- Breaking changes to security configurations fail builds -- Security metrics tracked and monitored systematically - -**Level 3 - Proactive Security:** -- Comprehensive threat modeling integrated into the design process -- Zero-trust architecture with mutual TLS for service-to-service communication -- Continuous security monitoring with behavioral analysis and anomaly detection -- Security feedback loops drive iterative improvements to governance policies - -Most organizations find that advancing one level at a time provides the most sustainable improvement path. The techniques covered in this guide primarily support progression from Level 0 to Level 2, with Level 3 requiring additional infrastructure and organizational maturity. - -## Frequently Asked Questions - -### What is design-first API security? -Design-first API security means defining security requirements in your OpenAPI specification before writing code, then using automated governance tools to enforce those requirements throughout the development lifecycle. This prevents vulnerabilities from reaching production rather than patching them after discovery. - -### How does OpenAPI prevent injection attacks? -OpenAPI specifications define precise data schemas with type validation, format constraints, and length limits. When enforced by governance tools, these schemas automatically reject malformed inputs that could contain injection payloads, stopping attacks before they reach your application logic. - -### Why is rate limiting important for API security? -Rate limiting prevents denial-of-service attacks, brute-force authentication attempts, and data scraping. It ensures fair resource usage among legitimate users while blocking malicious automation. Without rate limits, a single bad actor can overwhelm your API infrastructure. - -### Can I implement all four security areas with just OpenAPI? -Yes, OpenAPI 3.1 supports all four security areas: TLS enforcement through server URLs, input validation via JSON schemas, rate limiting through extensions like `x-rateLimit`, and access control via security schemes. Combined with governance automation, your specification becomes an executable security contract. - -### What's the difference between authentication and authorization in APIs? -Authentication verifies *who* the user is (like checking an ID card), while authorization determines *what* they can do (like checking permissions). Both are essential for API security, and OpenAPI provides security schemes to define and enforce both concepts through your specification. - -## Resources - -### Security Standards and Guidelines -- [OWASP API Security Top 10](https://owasp.org/www-project-api-security/) - Comprehensive vulnerability guide including injection attacks (API3:2023), resource consumption (API4:2023), and business logic abuse (API6:2023) -- [NIST SP 800-52 Rev. 2](https://csrc.nist.gov/publications/detail/sp/800-52/rev-2/final) - Official guidelines for secure TLS implementation and configuration requirements -- [IETF RFC 8446](https://tools.ietf.org/html/rfc8446) - TLS 1.3 protocol specification and security requirements - -### Practical Implementation Tools -- [Mozilla SSL Configuration Generator](https://ssl-config.mozilla.org/) - Generate secure, up-to-date TLS configurations for various web servers and security levels -- [OpenAPI Generator](https://openapi-generator.tech/) - Code generation tool for creating secure client SDKs and server stubs from OpenAPI specifications -- [OpenAPI Specification](https://spec.openapis.org/oas/v3.1.0) - Official OpenAPI 3.1 specification including security scheme definitions - -### DevSecOps and API Governance -- [OWASP API Security Project](https://owasp.org/www-project-api-security/) - Community-driven API security best practices and threat modeling -- [OpenAPI Security Schemes](https://spec.openapis.org/oas/v3.1.0#security-scheme-object) - Official specification for defining authentication and authorization in OpenAPI diff --git a/learn/security/automated-security-validation-walkthrough-v2.md b/learn/security/automated-security-validation-walkthrough-v2.md deleted file mode 100644 index df55e09d..00000000 --- a/learn/security/automated-security-validation-walkthrough-v2.md +++ /dev/null @@ -1,122 +0,0 @@ ---- -title: "Automated API Security Validation - Interactive Walkthrough" -description: "Learn to implement OWASP API Security Top 10 2023 rules using interactive Redocly security validation configurations with step-by-step guidance." -seo: - title: "Automated API Security Validation - Interactive Walkthrough" - description: "Learn to implement OWASP API Security Top 10 2023 rules using interactive Redocly security validation configurations with step-by-step guidance." ---- - -# Automated API Security Validation - Interactive Walkthrough - -*Transform your API security from manual reviews to automated enforcement using production-ready validation rules.* - ---- - -## What You'll Learn - -This interactive walkthrough guides you through implementing **automated security validation** that enforces the **OWASP API Security Top 10 2023** using Redocly's validation engine. By the end, you'll have a complete security ruleset that prevents vulnerabilities before they reach production. - -**You'll master:** -- Setting up comprehensive security validation rules -- Automating OWASP API Security Top 10 2023 compliance -- Implementing custom security validation functions -- Integrating security checks into CI/CD pipelines -- Troubleshooting common validation issues - ---- - -{% code-walkthrough - filesets=[ - { - "files": ["./_filesets/basic-security.yaml"], - "when": { - "config": "basic" - } - }, - { - "files": ["./_filesets/example-api.yaml"], - "when": { - "config": "example" - } - } - ] - filters={ - "config": { - "label": "Configuration Type", - "items": [ - {"value": "basic"}, - {"value": "example"} - ] - } - } -%} - -## Getting Started - -{% step id="basic-rules" heading="Basic Security Rules" when={"config": "basic"} %} - -Start with these essential security validation rules that provide the foundation for API security: - -- **Security schemes required**: Ensures all operations have proper authentication -- **HTTPS enforcement**: Prevents insecure HTTP connections -- **Input validation**: Requires proper constraints on strings and arrays -- **Response validation**: Ensures proper error response definitions - -This basic configuration is perfect for teams getting started with automated security validation. - -{% /step %} - -{% step id="api-spec" heading="Example API Specification" when={"config": "example"} %} - -This example OpenAPI specification demonstrates security best practices: - -**Key Security Features:** -- HTTPS-only server URLs prevent man-in-the-middle attacks -- UUID-based IDs prevent object-level authorization vulnerabilities -- JWT authentication with proper bearer token handling -- Comprehensive input validation with length limits and patterns -- Rate limiting headers in all responses -- Complete error response definitions (400, 401, 403, 404, 422, 429, 500) -- `additionalProperties: false` prevents mass assignment attacks - -Use this as a reference when building your own secure APIs. - -{% /step %} - -{% /code-walkthrough %} - ---- - -## Implementation Strategy - -Implementing automated security validation is an iterative process. Here's a recommended approach: - -**Phase 1: Foundation (Week 1)** -- Implement basic built-in rules from the configuration above -- Test in development environment -- Set up CI/CD integration with warning-level severity - -**Phase 2: Enhancement (Week 2)** -- Add custom security rules based on your API requirements -- Escalate critical rules to error-level severity -- Train team on validation rule interpretation - ---- - -## Next Steps and Resources - -### **Quick Start Actions** -1. **Download the basic configuration** using the walkthrough above -2. **Test with your OpenAPI specification** in development -3. **Integrate into CI/CD pipeline** to catch issues early -4. **Customize rules** based on your specific security requirements - -### **Related Security Guides** -- **[TLS Encryption Best Practices](api-tls-encryption-https-best-practices)** - HTTPS implementation -- **[Input Validation Guide](api-input-validation-injection-prevention)** - Prevent injection attacks -- **[Rate Limiting Guide](api-rate-limiting-abuse-prevention)** - Prevent abuse and DoS -- **[Authentication Guide](authentication-authorization-openapi)** - Secure access control - ---- - -**🔐 Security Note**: This walkthrough covers essential OWASP API Security Top 10 2023 practices. For production deployment, review and customize rules based on your organization's specific security requirements and risk tolerance. diff --git a/learn/security/automated-security-validation-walkthrough.md b/learn/security/automated-security-validation-walkthrough.md index 7dd4b378..9b651eeb 100644 --- a/learn/security/automated-security-validation-walkthrough.md +++ b/learn/security/automated-security-validation-walkthrough.md @@ -25,68 +25,6 @@ This walkthrough demonstrates one approach to implementing **automated security --- - - - ## Security Validation Foundation ### Basic Security Configuration diff --git a/learn/security/index.md b/learn/security/index.md index d2e2f773..44201d36 100644 --- a/learn/security/index.md +++ b/learn/security/index.md @@ -1,4 +1,12 @@ -# API Security by Design: Complete Guide +--- +title: API Security by Design: Framework and Fundamentals +description: Build secure APIs from the ground up using OpenAPI security contracts and automated governance. +seo: + title: API Security by Design: Framework and Fundamentals + description: Build secure APIs from the ground up using OpenAPI security contracts and automated governance. +--- + +# API Security by Design: Framework and Fundamentals _Build secure APIs from the ground up using OpenAPI security contracts and automated governance._ diff --git a/learn/security/sidebars.yaml b/learn/security/sidebars.yaml index 5c3caed6..e7233848 100644 --- a/learn/security/sidebars.yaml +++ b/learn/security/sidebars.yaml @@ -1,9 +1,6 @@ - page: ./index.md -- group: API Security Fundamentals - items: - - page: ./api-tls-encryption-https-best-practices.md - - page: ./api-input-validation-injection-prevention.md - - page: ./api-rate-limiting-abuse-prevention.md - - page: ./authentication-authorization-openapi.md - - page: ./automated-security-validation-walkthrough.md - - page: ./api-design-first-security-guide.md +- page: ./api-tls-encryption-https-best-practices.md +- page: ./api-input-validation-injection-prevention.md +- page: ./api-rate-limiting-abuse-prevention.md +- page: ./authentication-authorization-openapi.md +- page: ./automated-security-validation-walkthrough.md diff --git a/learn/security/test-simple-walkthrough.md b/learn/security/test-simple-walkthrough.md deleted file mode 100644 index 115cb96f..00000000 --- a/learn/security/test-simple-walkthrough.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -title: "Simple Test Walkthrough" -description: "Test basic walkthrough functionality" ---- - -# Simple Test Walkthrough - -{% code-walkthrough - filesets=[ - { "files": ["./_filesets/basic-security.yaml"] } - ] -%} - -## Basic Configuration - -{% step id="test-step" heading="Test Step" %} -This is a simple test step to verify walkthrough functionality. -{% /step %} - -{% /code-walkthrough %} From 1e08d887be32f53c88f894f220bd2d8dc0635379 Mon Sep 17 00:00:00 2001 From: Matt Williams Date: Tue, 30 Sep 2025 11:31:56 -0500 Subject: [PATCH 13/27] Remove automated security validation walkthrough - Delete automated-security-validation-walkthrough.md (temporarily removed) - Update sidebars.yaml to remove walkthrough from navigation - Final security learning center now has 5 focused articles + landing page --- ...tomated-security-validation-walkthrough.md | 91 ------------------- learn/security/sidebars.yaml | 1 - 2 files changed, 92 deletions(-) delete mode 100644 learn/security/automated-security-validation-walkthrough.md diff --git a/learn/security/automated-security-validation-walkthrough.md b/learn/security/automated-security-validation-walkthrough.md deleted file mode 100644 index 9b651eeb..00000000 --- a/learn/security/automated-security-validation-walkthrough.md +++ /dev/null @@ -1,91 +0,0 @@ ---- -title: "Automated API Security Validation - Interactive Walkthrough" -description: "Explore validation approaches that can help identify some common API security issues, with examples using validation rule configurations." -seo: - title: "Automated API Security Validation - Interactive Walkthrough" - description: "Explore validation approaches that can help identify some common API security issues, with examples using validation rule configurations." ---- - -# Automated API Security Validation - Interactive Walkthrough - -*Learn how validation rules can complement your existing security practices by catching common issues during development.* - ---- - -## What You'll Learn - -This walkthrough demonstrates one approach to implementing **automated security validation** that can help identify some common API security issues from the **OWASP API Security Top 10 2023** using validation rules. This complements other essential security practices like [TLS encryption](api-tls-encryption-https-best-practices), [input validation](api-input-validation-injection-prevention), [rate limiting](api-rate-limiting-abuse-prevention), and [access control](authentication-authorization-openapi). This is just one part of a comprehensive security strategy. - -**You'll explore:** -- Setting up basic security validation rules for OpenAPI specifications -- Examples of how validation can catch [common security issues](api-input-validation-injection-prevention#attack-prevention-strategies) like mass assignment and injection attacks -- Custom validation function patterns you might adapt for your needs -- Options for integrating validation checks into development workflows -- Common troubleshooting scenarios when working with validation tools - ---- - -## Security Validation Foundation - -### Basic Security Configuration - -Essential security rules for getting started with API validation: - -- **Core Security Rules**: Ensures [security schemes are defined](authentication-authorization-openapi#authentication-methods) -- **Response Validation**: Requires proper HTTP response codes -- **Built-in Protections**: Leverages built-in security checks - -This starter configuration is perfect for teams new to automated security validation. - -### Example API Specification - -An example OpenAPI specification demonstrates proper security implementation following validation best practices: - -**Security Best Practices:** -- [HTTPS-only server URLs](api-tls-encryption-https-best-practices#enforcing-https-in-your-api-specification) -- UUID-based IDs to prevent enumeration -- [Comprehensive security schemes with JWT/OAuth2](authentication-authorization-openapi#authentication-methods) -- [Proper input validation with string length limits](api-input-validation-injection-prevention#key-security-constraints) -- [Rate limiting headers in all responses](api-rate-limiting-abuse-prevention#documenting-rate-limits-in-openapi) -- Complete error response definitions -- [`additionalProperties: false` to prevent mass assignment](api-input-validation-injection-prevention#attack-prevention-strategies) - -Use this as a reference when implementing your own secure APIs. - ---- - -## Implementation Strategy - -If you decide to use validation rules in your workflow, consider a gradual approach: - -**Phase 1: Foundation (Example timeline: Weeks 1-2)** -- Start with basic built-in rules -- Try [HTTPS enforcement](api-tls-encryption-https-best-practices#enforcing-https-in-your-api-specification) and [basic authentication checks](authentication-authorization-openapi#authentication-methods) -- Consider integrating into CI/CD pipeline with warning-level severity - -**Phase 2: Core Security (Example timeline: Weeks 3-4)** -- Explore [input validation](api-input-validation-injection-prevention#schema-based-validation-as-security-contract) and [resource consumption rules](api-input-validation-injection-prevention#key-security-constraints) -- Evaluate [mass assignment prevention](api-input-validation-injection-prevention#attack-prevention-strategies) patterns -- Consider escalating critical rules to error-level severity based on your team's needs - ---- - -## Next Steps and Resources - -### **Suggested Next Steps** -1. **Review the example configurations** in the code walkthrough above -2. **Consider starting small** if you're new to API security validation -3. **Test thoroughly in development** before using in production environments -4. **Adapt patterns** based on your specific security needs and organizational context - -### **Integration with Security Articles** -This validation walkthrough complements our other security guides: - -- **[TLS Encryption Best Practices](api-tls-encryption-https-best-practices)** - Learn about HTTPS enforcement approaches -- **[Input Validation Guide](api-input-validation-injection-prevention)** - Explore schema validation and input security patterns -- **[Rate Limiting Guide](api-rate-limiting-abuse-prevention)** - Understand rate limiting implementation options -- **[Authentication Guide](authentication-authorization-openapi)** - Review authentication and authorization security practices - ---- - -**🔐 Security Note**: This walkthrough demonstrates some validation approaches that can help identify common API security issues. Validation rules are just one layer in a comprehensive security strategy that should also include [proper TLS configuration](api-tls-encryption-https-best-practices), [robust input validation](api-input-validation-injection-prevention), [rate limiting](api-rate-limiting-abuse-prevention), and [strong access controls](authentication-authorization-openapi). Always review and test any rules thoroughly before using them in production, and customize based on your organization's specific security requirements and risk tolerance. diff --git a/learn/security/sidebars.yaml b/learn/security/sidebars.yaml index e7233848..c97575e2 100644 --- a/learn/security/sidebars.yaml +++ b/learn/security/sidebars.yaml @@ -3,4 +3,3 @@ - page: ./api-input-validation-injection-prevention.md - page: ./api-rate-limiting-abuse-prevention.md - page: ./authentication-authorization-openapi.md -- page: ./automated-security-validation-walkthrough.md From e94f7c46c26a6ca67c702bef7ec6974d1cfcb697 Mon Sep 17 00:00:00 2001 From: Matt Williams Date: Tue, 30 Sep 2025 11:37:09 -0500 Subject: [PATCH 14/27] Create security learning center foundation structure - Landing page with updated 'Framework and Fundamentals' title - Complete sidebar navigation structure - Placeholder stub articles with proper frontmatter and outlines - No broken links - all navigation functional - Ready for individual article content PRs Stubs created for: - TLS Encryption and HTTPS Best Practices - Input Validation and Injection Prevention - Rate Limiting and Abuse Prevention - Authentication and Authorization with OpenAPI --- ...i-input-validation-injection-prevention.md | 614 +-------- .../api-rate-limiting-abuse-prevention.md | 720 +--------- ...api-tls-encryption-https-best-practices.md | 439 +----- .../authentication-authorization-openapi.md | 1207 +---------------- 4 files changed, 37 insertions(+), 2943 deletions(-) diff --git a/learn/security/api-input-validation-injection-prevention.md b/learn/security/api-input-validation-injection-prevention.md index 52a5f9aa..eea94964 100644 --- a/learn/security/api-input-validation-injection-prevention.md +++ b/learn/security/api-input-validation-injection-prevention.md @@ -6,613 +6,19 @@ seo: description: Prevent API injection attacks and mass assignment vulnerabilities using OpenAPI schema validation and automated governance. --- -# Input Validation and Injection Prevention with OpenAPI +# Input Validation and Injection Prevention ---- - -## Key Takeaways - -APIs are designed to accept data as input. However, an API should never blindly trust the data it receives from a client. The process of rigorously checking all incoming data is called data validation. - -**In this guide, you'll learn:** -- [How to implement schema-based validation](#schema-based-validation-as-security-contract) as a security contract -- [JSON Schema security constraints and validation patterns](#key-security-constraints) -- [Attack prevention techniques](#attack-prevention-strategies) for SQL injection, OGNL injection, and mass assignment -- [Real-world lessons from the Equifax breach](#attack-example-equifax-ognl-injection-via-apache-struts-2017) -- [Automated validation governance and linting rules](#automated-governance-for-validation) -- [Input validation monitoring and troubleshooting](#input-validation-monitoring) - ---- - -## Quick Start Guide - -Ready to implement secure input validation? Follow these steps: - -1. **Define validation rules:** Start with [schema-based validation](#schema-based-validation-as-security-contract) to create security contracts in your OpenAPI specifications -2. **Implement attack prevention:** Set up [SQL injection and mass assignment protection](#attack-prevention-strategies) using parameterized queries and `additionalProperties: false` -3. **Add governance rules:** Configure [automated governance](#automated-governance-for-validation) to prevent accidentally unvalidated endpoints -4. **Set up monitoring:** Implement [validation monitoring](#input-validation-monitoring) to detect attack attempts and track security metrics -5. **Handle edge cases:** Use [advanced validation techniques](#advanced-validation-techniques) for custom formats and contextual rules - -**Next Steps:** Now that you have input validation covered, learn about [API Rate Limiting and Abuse Prevention](api-rate-limiting-abuse-prevention) to protect your APIs from denial-of-service attacks and business logic abuse. - ---- - -## The Restaurant Waiter Principle - -> **The Restaurant Waiter**: The API is the waiter, and its documentation (or schema) is the menu. The menu explicitly states what can be ordered and in what format (e.g., "Steak - medium rare"). If a customer tries to order something not on the menu, like "a bicycle," or provides an invalid option, like "a million steaks," a competent waiter will immediately reject the order at the table before it ever reaches the kitchen. This is data validation. - -## Technical Implementation of Data Validation - -In technical terms, data validation is the practice of checking all incoming data from a client to ensure it conforms to the expected format, type, range, and other constraints before it is processed by the application's business logic. - -For example, if an API endpoint expects a user's age, validation rules should ensure the input is an integer and falls within a reasonable range (e.g., 0-130). - -Proper data validation is a critical defense against a wide range of attacks, notably **Injection flaws**. An injection attack occurs when a malicious actor sends executable code disguised as data. - -If the API fails to validate the input and passes it directly to a database or the operating system, that malicious code could be executed. By strictly validating that all inputs are what they are supposed to be, an API can reject malicious payloads before they can do any harm. - -## Attack Prevention Strategies - -Choose the appropriate prevention strategy based on the attack vector you're protecting against: - -{% tabs %} - {% tab label="SQL Injection Prevention" %} - -### SQL Injection Prevention - -For interactions with a database, the gold standard for preventing SQL injection attacks is the use of parameterized queries, also known as prepared statements. - -A parameterized query forces a separation between the SQL command (the code) and the user-supplied data, making it impossible for an attacker to alter the logic of the query. - -**Before vs After: Preventing SQL Injection** - -```javascript {% title="Secure Database Query Implementation" %} -// Step 1: Receive user input from request (potentially malicious) -const userId = req.query.user_id; // Could contain: "1; DROP TABLE users;--" - -// VULNERABLE APPROACH - NEVER DO THIS # [!code error] -// Problem: Direct string interpolation allows malicious code injection -const vulnerableQuery = `SELECT * FROM users WHERE id = ${userId}`; // Creates: SELECT * FROM users WHERE id = 1; DROP TABLE users;-- -// The database sees this as TWO commands: a SELECT and a DROP TABLE -const vulnerableResult = await db.query(vulnerableQuery); // Executes both commands - deletes entire table! - -// SECURE APPROACH - ALWAYS USE PARAMETERIZED QUERIES # [!code highlight] -// Solution: SQL structure and data are separated at database level -const secureQuery = "SELECT * FROM users WHERE id = $1"; // SQL structure defined first -const secureResult = await db.query(secureQuery, [userId]); // Data bound separately as parameter - -// Why this works: # [!code highlight] -// - Database parses SQL structure before receiving user data # [!code highlight] -// - User input is treated as literal data, never as executable code # [!code highlight] -// - Even "1; DROP TABLE users;--" becomes a harmless literal string value # [!code highlight] - -// Full Express.js route example: -app.get('/users/:id', async (req, res) => { - try { - const userId = req.params.id; - const result = await db.query('SELECT * FROM users WHERE id = $1', [userId]); - res.json(result.rows[0] || { error: 'User not found' }); - } catch (error) { - console.error('Database error:', error); - res.status(500).json({ error: 'Internal server error' }); - } -}); -``` - -**How SQL injection prevention works:** -- **Parameterized queries**: The SQL structure is defined separately from user data -- **Data binding**: User input is bound to parameters after the SQL structure is parsed -- **No code injection**: Even malicious input like `1 OR 1=1; DROP TABLE users;` is treated as literal data -- **Database driver security**: Modern database drivers automatically escape parameter values - -{% /tab %} -{% tab label="Mass Assignment Prevention" %} - -### Mass Assignment Attack Prevention - -Mass assignment attacks occur when an application accepts more input parameters than expected, allowing attackers to modify fields they shouldn't have access to. The `additionalProperties: false` constraint is essential for preventing these attacks. - -**Mass Assignment Prevention: Before vs After** - -```yaml {% title="Securing Against Mass Assignment (OWASP API3:2023)" %} -NewUser: - type: object - # CRITICAL SECURITY SETTING: additionalProperties defaults to true - DANGEROUS! # [!code error] - # Without this setting, attackers can inject ANY extra fields into requests # [!code highlight] - additionalProperties: false # [!code error] ESSENTIAL: Blocks mass assignment - REQUIRED for security - - # STEP 1: Define ONLY the fields that should be accepted # [!code highlight] - properties: - name: - type: string - minLength: 1 # Prevent empty names - maxLength: 100 # Prevent buffer overflow attacks - pattern: "^[a-zA-Z\\s]+$" # Allow only letters and spaces - email: - type: string - format: email # Built-in email validation prevents malformed input - maxLength: 254 # Prevent resource exhaustion (RFC 5321 limit) - - # STEP 2: Require critical fields to prevent incomplete records # [!code highlight] - required: # These fields MUST be provided - - name # User identification required - - email # Contact method required - -# What this prevents: # [!code highlight] -# Malicious request: {"name": "John", "email": "john@test.com", "isAdmin": true, "balance": 999999} # [!code highlight] -# Result: isAdmin and balance fields are BLOCKED and ignored # [!code highlight] -``` - -**How mass assignment prevention works:** -- **`additionalProperties: false`**: Rejects any properties not explicitly defined in the schema -- **Explicit allow-listing**: Only defined properties are accepted, unknown fields are blocked -- **Field-level validation**: Each allowed property has its own validation constraints -- **Attack surface reduction**: Prevents unauthorized modification of sensitive fields like `isAdmin`, `balance`, or `role` - -**What this prevents**: -```json {% title="Malicious Request Example" %} -// This attack payload is blocked with additionalProperties: false -{ - "name": "John Doe", - "email": "john@example.com", - "isAdmin": true, // [!code error] Blocked - not in schema - "balance": 1000000 // [!code error] Blocked - not in schema -} -``` - -{% /tab %} -{% /tabs %} - -## Schema-Based Validation as Security Contract - -OpenAPI 3.1 provides a comprehensive vocabulary for defining strict validation rules by leveraging JSON Schema Draft 2020-12. By codifying these rules directly in your API specification, validation becomes core to your API's design. - -**Secure API Schema with Input Validation** - -```yaml {% title="openapi.yaml - Comprehensive Security Validation Schema" %} -components: - schemas: - NewUser: - type: object - # STEP 1: CRITICAL MASS ASSIGNMENT PROTECTION - blocks OWASP API3:2023 # [!code error] - additionalProperties: false # [!code error] ESSENTIAL: Prevents attackers from injecting extra fields - - # STEP 2: Define required fields to prevent incomplete records # [!code highlight] - required: - - username # User identification - mandatory - - email # Contact method - mandatory - - password # Authentication credential - mandatory - - age # Legal compliance (COPPA, etc.) - - properties: - # STEP 3: Username validation - prevent enumeration and injection # [!code highlight] - username: - type: string - minLength: 4 # Prevent too-short usernames (harder to guess) - maxLength: 20 # OWASP API4:2023: Prevent resource exhaustion - pattern: "^[a-zA-Z0-9_-]+$" # Allow-list only safe characters (blocks XSS, injection) - description: "Alphanumeric characters, underscores, and hyphens only" - example: "john_doe123" - - # STEP 4: Email validation - prevent malformed addresses and attacks # [!code highlight] - email: - type: string - minLength: 5 # Shortest valid email: "a@b.c" - maxLength: 254 # RFC 5321 limit - prevents buffer overflow - format: email # Built-in validation (RFC 5322 format) - description: "Must be a valid email address according to RFC 5322" - example: "user@example.com" - - # STEP 5: Password constraints - security + usability balance # [!code highlight] - password: - type: string - minLength: 12 # NIST recommends 12+ chars for user passwords - maxLength: 128 # Allow long passphrases but prevent DoS - description: | - Password requirements: - - Minimum 12 characters (strong security baseline) - - Maximum 128 characters (prevents resource exhaustion) - - No composition requirements (per NIST 800-63B) - example: "MySecurePassphrase123!" - writeOnly: true # [!code error] CRITICAL: NEVER return passwords in responses - - # STEP 6: Age validation - legal compliance and reasonableness checks # [!code highlight] - age: - type: integer - minimum: 13 # COPPA compliance (US law for child privacy) - maximum: 130 # Prevent integer overflow attacks - description: "User age in years (COPPA compliance requires 13+)" - example: 25 - - # STEP 7: Role-based access control with allow-list approach # [!code highlight] - role: - type: string - enum: ["user", "premium", "moderator"] # [!code error] CRITICAL: Allow-list prevents privilege escalation - default: "user" # Secure default (least privilege) - description: "User role determines access permissions" - - # STEP 8: Optional fields with validation (shows pattern for expansion) # [!code highlight] - profile: - type: object - additionalProperties: false # [!code highlight] Nested objects also need mass assignment protection - properties: - firstName: - type: string - minLength: 1 - maxLength: 50 # Reasonable limits prevent storage abuse - pattern: "^[\\p{L}\\s'-]+$" # Unicode letters, spaces, hyphens, apostrophes - description: "First name (supports international characters)" - lastName: - type: string - minLength: 1 - maxLength: 50 - pattern: "^[\\p{L}\\s'-]+$" - description: "Last name (supports international characters)" - bio: - type: string - maxLength: 500 # Prevent excessive text storage - description: "User biography (plain text only)" - - # STEP 9: Contact preferences with validation # [!code highlight] - preferences: - type: object - additionalProperties: false # [!code highlight] Every nested object needs this protection - properties: - newsletter: - type: boolean - default: false # Privacy-friendly default (opt-in) - description: "Subscribe to newsletter (GDPR compliant opt-in)" - notifications: - type: array - maxItems: 10 # [!code error] CRITICAL: Prevent array abuse/DoS attacks - uniqueItems: true # No duplicate notification types - items: - type: string - enum: ["email", "sms", "push", "in-app"] # Allow-list notification channels - description: "Preferred notification channels" - -# STEP 10: Common validation patterns for reuse # [!code highlight] -ValidationPattern: - # Phone number with international support - PhoneNumber: - type: string - pattern: "^\\+[1-9]\\d{1,14}$" # [!code highlight] SECURITY: E.164 format prevents malformed numbers - maxLength: 15 # International standard maximum - example: "+1234567890" - - # URL validation for security - SecureUrl: - type: string - format: uri # Basic URI validation - pattern: "^https://.*" # [!code error] CRITICAL: FORCE HTTPS - no HTTP allowed - maxLength: 2048 # Prevent excessively long URLs - example: "https://example.com" -``` - -**Key Security Controls**: -- **`additionalProperties: false`** blocks mass assignment attacks -- **Length constraints** prevent buffer overflow and resource exhaustion -- **Pattern validation** blocks injection attempts and malformed data -- **Enum restrictions** enforce allow-lists instead of dangerous validation bypass - -### Automated Governance for Validation - -Modern API governance tools can enforce input validation rules that require string length bounds, numeric ranges, and prevent mass assignment vulnerabilities. - -This governance approach transforms security reviews. Instead of manually checking many properties for missing `maxLength` constraints, automated linting tools handle baseline validation so security teams can focus on strategic concerns like business logic and context-dependent risks. - -> **🚀 Interactive Implementation**: Learn to set up comprehensive input validation with our [Automated Security Validation Walkthrough](automated-security-validation-walkthrough), which includes production-ready rules for OWASP API Security Top 10 2023 compliance. +*This comprehensive guide is coming soon and will cover:* -## Key Security Constraints +## What You'll Learn -The most critical schema constraints for API security focus on preventing resource exhaustion and injection attacks: +- **SQL Injection Prevention**: Parameterized queries and input sanitization +- **Mass Assignment Protection**: Schema-based validation and field filtering +- **OpenAPI Validation**: Schema constraints and automated enforcement +- **OWASP API Security**: Addressing Top 10 injection vulnerabilities +- **Real-World Examples**: Code samples in Node.js with security patterns +- **Automated Governance**: CI/CD validation rules and policy enforcement -- **`maxLength`**: Required on all strings to prevent memory exhaustion attacks -- **`maximum/minimum`**: Required on all numbers to prevent integer overflow vulnerabilities -- **`additionalProperties: false`**: Essential for preventing mass assignment attacks -- **`pattern`**: Use restrictive regex patterns to block injection payloads - -These constraints can be automatically enforced by governance rules, ensuring no schema can bypass these fundamental protections. - -## Common Validation Patterns - -{% table %} -* Input Type -* Validation Rules -* Example ---- -* Email -* RFC 5322 format -* `user@example.com` ---- -* Phone -* E.164 format -* `+1234567890` ---- -* URL -* Valid URL scheme -* `https://example.com` ---- -* UUID -* Standard UUID format -* `123e4567-e89b-12d3-a456-426614174000` --- -* Date -* ISO 8601 format -* `2025-01-20T10:30:00Z` ---- -* Password -* Minimum complexity -* 8+ chars, mixed case, numbers, symbols -{% /table %} - -### Validation troubleshooting and common pitfalls - -* Missing bounds (no `maxLength`, no numeric ranges) — leads to resource exhaustion -* Overly permissive regex patterns — allow unwanted characters and injection payloads -* Validating at the wrong layer — front-end only, or after DB calls -* Accepting undeclared properties — enables mass assignment - -Quick fixes: - -```yaml {% title="JSON Schema example" %} -type: object -additionalProperties: false -properties: - name: - type: string - minLength: 1 - maxLength: 100 - pattern: "^[a-zA-Z\\s]+$" - age: - type: integer - minimum: 0 - maximum: 130 -``` - -> API Security Best Practice: "Blocking PRs that add new string fields without `maxLength` constraints is one of the most cost-effective security guardrails you can implement." - -## Attack Example: Equifax (OGNL injection via Apache Struts, 2017) - -The 2017 Equifax data breach was the result of a catastrophic input validation failure in the Apache Struts framework (CVE-2017-5638). The vulnerability allowed attackers to perform remote code execution by sending a specially crafted `Content-Type` header. The Struts framework failed to properly sanitize this header value, interpreting it as an Object-Graph Navigation Language (OGNL) expression and executing it. This gave attackers a direct shell on the server, which they used to access sensitive databases and exfiltrate the personal data of over 140 million people. - -This incident underscores the critical importance of validating all inputs, including HTTP headers, against a strict allow-list or pattern. A strong schema-based validation approach, enforced by governance, can block entire classes of injection attacks before they ever reach vulnerable application code. - -```mermaid -sequenceDiagram - participant A as Attacker - participant W as WAF (misconfigured) - participant S as Struts App (vulnerable) - participant DB as Database - - A->>W: HTTP request with malicious Content-Type header - W-->>S: Pass-through (no block) - A->>S: OGNL payload evaluated - S->>S: Remote code execution - S->>DB: Query PII at scale - DB-->>A: Exfiltrated records (PII) -``` - -*Sequence diagram illustrating the Equifax breach: attacker exploited Apache Struts vulnerability through OGNL injection in Content-Type headers, bypassing WAF and executing code to steal personal data.* - -Why this matters: Strong schema validation, input allow-lists, and patch hygiene block entire classes of injection attacks. - -**Security operations:** When schema validation and [attack prevention strategies](#attack-prevention-strategies) are in place, implement [monitoring](#input-validation-monitoring) to detect attempted breaches and [advanced validation techniques](#advanced-validation-techniques) for complex scenarios. - -## Input Validation Monitoring - -Choose your monitoring approach based on your security operations needs: - -{% tabs %} - {% tab label="Validation Logging (JavaScript)" %} - -### Validation Failure Logging - -**Express.js Middleware for Security Monitoring** - -```javascript {% title="validation-logger.js" %} -// Middleware to log validation failures for security analysis -app.use((req, res, next) => { - const originalSend = res.send; - - res.send = function(data) { - // Track validation failures for potential attack patterns - if (res.statusCode === 400 && req.validationErrors) { // [!code highlight] - logger.warn('Validation failure', { // [!code highlight] - endpoint: req.path, // [!code highlight] Track which endpoints are targeted - errors: req.validationErrors, // [!code highlight] Log specific validation failures - clientIP: req.ip, // [!code highlight] Track source IPs for analysis - userAgent: req.get('User-Agent') // [!code highlight] Detect automated attacks - }); - } - - originalSend.call(this, data); - }; - - next(); -}); -``` - -**How validation logging works:** -- **Middleware interception**: Captures all responses before they're sent to clients -- **Status code filtering**: Only logs when `statusCode === 400` (validation failures) -- **Structured logging**: Records endpoint, errors, IP, and user agent for security analysis -- **Attack pattern detection**: Unusual spikes or repeated failures from same IPs indicate potential attacks - -**Why this matters**: Logging validation failures helps detect attack patterns, frequent probe attempts, and potential security issues before they escalate. Monitor these logs for unusual spikes or repeated failures from the same IP addresses. - -{% /tab %} -{% tab label="Validation Metrics (JavaScript)" %} - -### Validation Metrics - -```javascript -// Track validation patterns for security analysis -class ValidationMetrics { - constructor() { - this.validationFailures = new Map(); // [!code highlight] Count failures by type - this.attackPatterns = new Map(); // [!code highlight] Track potential attacks - } - - recordFailure(endpoint, field, errorType) { - const key = `${endpoint}:${field}:${errorType}`; - - // Initialize counter if key doesn't exist - if (!this.validationFailures.has(key)) { - this.validationFailures.set(key, 0); - } - this.validationFailures.set(key, this.validationFailures.get(key) + 1); // [!code highlight] Increment failure counter - - // Detect potential attack patterns // [!code highlight] - const attackTypes = ['pattern_violation', 'length_exceeded', 'additional_property']; - if (attackTypes.includes(errorType)) { - if (!this.attackPatterns.has(endpoint)) { - this.attackPatterns.set(endpoint, 0); - } - this.attackPatterns.set(endpoint, this.attackPatterns.get(endpoint) + 1); // [!code highlight] Flag suspicious activity - } - } - - getAttackSummary() { - return Object.fromEntries(this.attackPatterns); // [!code highlight] Return attack metrics - } - - // Additional utility method for comprehensive metrics - getFailureReport() { - return { - totalFailures: this.validationFailures.size, - attackPatterns: this.getAttackSummary(), - topFailureTypes: Object.fromEntries(this.validationFailures) - }; - } -} - -// Usage in Express.js validation middleware -const validationMetrics = new ValidationMetrics(); - -function trackValidationError(req, field, errorType) { - const endpoint = req.route?.path || req.path; - validationMetrics.recordFailure(endpoint, field, errorType); - - // Log for immediate monitoring - console.warn('Validation failure tracked', { - endpoint, - field, - errorType, - ip: req.ip, - userAgent: req.get('User-Agent') - }); -} -``` - -**How validation metrics work:** -- **Failure tracking**: Counts validation failures by endpoint, field, and error type -- **Pattern detection**: Identifies suspicious error types that often indicate attacks -- **Attack scoring**: Tracks which endpoints receive the most attack attempts -- **Metrics export**: Provides data for security dashboards and alerting systems - -**Key metrics to monitor:** -- **`pattern_violation`**: Input doesn't match expected format (possible injection attempt) -- **`length_exceeded`**: Input too long (buffer overflow or DoS attempt) -- **`additional_property`**: Extra fields in request (mass assignment attack) - -{% /tab %} -{% /tabs %} - -## Advanced Validation Techniques - -### Custom Format Validators -```javascript -// Custom OpenAPI format validators -const customFormats = { - 'safe-html': { - validate: (value) => { - // Strip dangerous HTML tags and attributes - const clean = DOMPurify.sanitize(value, { - ALLOWED_TAGS: ['p', 'br', 'strong', 'em'], - ALLOWED_ATTR: [] - }); - return clean === value; - } - }, - 'sql-safe': { - validate: (value) => { - // Block SQL injection patterns - const sqlPatterns = /('|(\\x27)|(\\x2D\\x2D)|(%27)|(%2D%2D))/i; - return !sqlPatterns.test(value); - } - } -}; - -// Use in OpenAPI schema -const schema = { - type: "string", - format: "safe-html", - maxLength: 1000 -}; -``` - -### Contextual Validation Rules -```yaml {% title="openapi.yaml" %} -# Different validation rules based on context -components: - schemas: - PublicProfile: - type: object - additionalProperties: false - properties: - displayName: - type: string - maxLength: 50 - pattern: "^[a-zA-Z0-9\\s._-]+$" # More restrictive for public display - - InternalUser: - type: object - additionalProperties: false - properties: - displayName: - type: string - maxLength: 100 - pattern: "^[\\w\\s._@-]+$" # Less restrictive for internal use -``` - -## Frequently Asked Questions - -### How does OpenAPI validation prevent injection attacks? -OpenAPI specifications define precise data schemas with type validation, format constraints, and length limits. When enforced by [automated governance](#automated-governance-for-validation), these schemas automatically reject malformed inputs that could contain injection payloads, stopping attacks before they reach your application logic. See [Schema-Based Validation as Security Contract](#schema-based-validation-as-security-contract) for implementation details. - -### What's the difference between client-side and server-side validation? -Client-side validation improves user experience by providing immediate feedback, but it can be bypassed by attackers. Server-side validation is the critical security control—never trust data from the client. Always validate on the server even if you also validate on the client. Review our [attack prevention strategies](#attack-prevention-strategies) to understand why server-side validation is essential. - -### Should I validate HTTP headers and query parameters? -Yes! The [Equifax breach](#attack-example-equifax-ognl-injection-via-apache-struts-2017) occurred through a malicious `Content-Type` header. All inputs—including headers, query parameters, path parameters, and request bodies—should be validated against strict schemas. Don't assume any input is safe. - -### How do I handle file uploads securely? -File uploads require special attention: validate file types using content inspection (not just extensions), enforce size limits, scan for malware, store files outside the web root, and use content-disposition headers to prevent execution. Consider using dedicated file storage services with [advanced validation techniques](#advanced-validation-techniques). - -### What's the performance impact of extensive validation? -Modern validation libraries are highly optimized. The security benefit far outweighs the minimal performance cost. Consider caching compiled schemas and using efficient validation libraries like `ajv` for JavaScript or `jsonschema` for Python. Implement [validation monitoring](#input-validation-monitoring) to track performance impacts. - -## Resources and Next Steps - -### Essential Reading -- [OWASP API Security Top 10](https://owasp.org/www-project-api-security/) - Comprehensive vulnerability guide including injection attacks (API3:2023) and resource consumption (API4:2023) -- [JSON Schema Specification](https://json-schema.org/specification.html) - Complete reference for OpenAPI validation capabilities -- [OpenAPI Data Types](https://spec.openapis.org/oas/v3.1.0#data-types) - Official OpenAPI data type and format specifications - -### Implementation Tools -- [AJV JSON Schema Validator](https://ajv.js.org/) - Fast JSON Schema validation for JavaScript/Node.js -- [Joi Validation](https://joi.dev/) - Object schema validation library with expressive API -- [Cerberus](https://docs.python-cerberus.org/) - Lightweight, extensible data validation library for Python - -### Security Testing Tools -- [OWASP ZAP](https://owasp.org/www-project-zap/) - Security testing proxy for finding injection vulnerabilities -- [Postman Security Testing](https://learning.postman.com/docs/writing-scripts/test-scripts/) - API security test automation -- [Burp Suite](https://portswigger.net/burp) - Web application security testing platform -### Related Security Topics -- [API TLS Encryption and HTTPS Best Practices](api-tls-encryption-https-best-practices) - Secure data in transit -- [API Rate Limiting and Abuse Prevention](api-rate-limiting-abuse-prevention) - Prevent DoS attacks and abuse -- [Authentication and Authorization with OpenAPI](authentication-authorization-openapi) - Implement secure access control -- [API Security by Design: Complete Guide](/learn/security) - Overview of all API security domains \ No newline at end of file +*This article is currently under review and will be available soon. Return to the [API Security Framework and Fundamentals](.) to explore other security topics.* diff --git a/learn/security/api-rate-limiting-abuse-prevention.md b/learn/security/api-rate-limiting-abuse-prevention.md index 823b7624..b97ceced 100644 --- a/learn/security/api-rate-limiting-abuse-prevention.md +++ b/learn/security/api-rate-limiting-abuse-prevention.md @@ -8,719 +8,17 @@ seo: # Rate Limiting and Abuse Prevention for APIs ---- - -## Key Takeaways - -A single client, whether intentionally malicious or simply due to a bug in its code, can send a massive number of requests to an API in a short period. This can overwhelm the server, degrading performance for all other users or even causing the service to crash. Rate limiting is the primary defense against this scenario. - -**In this guide, you'll learn:** -- [How to implement rate limiting](#documenting-rate-limits-in-openapi) as a security and reliability control -- [OpenAPI x-rateLimit extensions](#documenting-rate-limits-in-openapi) and documentation strategies -- [Rate limiting algorithms and implementation patterns](#rate-limiting-implementation-approaches) -- [Client-side exponential backoff](#client-side-exponential-backoff) and error handling -- [Real-world lessons from the Facebook phone number scraping incident](#attack-example-facebook-phone-number-scraping-2019) -- [Advanced techniques and monitoring approaches](#rate-limiting-monitoring-and-observability) - ---- - -## Quick Start Guide - -Ready to implement effective rate limiting? Follow these steps: +*This comprehensive guide is coming soon and will cover:* -1. **Document rate limits:** Add [OpenAPI x-rateLimit extensions](#documenting-rate-limits-in-openapi) to your API specifications -2. **Choose an algorithm:** Select from [Token Bucket, Sliding Window, or Fixed Window](#rate-limiting-implementation-approaches) based on your needs -3. **Implement multi-tier limits:** Set up global, per-endpoint, and per-client [rate limiting configurations](#advanced-rate-limiting-techniques) -4. **Set up monitoring:** Implement [metrics collection and alerting](#rate-limiting-monitoring-and-observability) to detect attacks -5. **Test and tune:** Use the [implementation strategy framework](#rate-limiting-strategy-framework) to prioritize critical endpoints and validate limits +## What You'll Learn -**Next Steps:** Now that you have rate limiting protection in place, learn about [Authentication and Authorization with OpenAPI](authentication-authorization-openapi) to implement comprehensive access control for your APIs. +- **Rate Limiting Algorithms**: Token bucket, sliding window, and fixed window approaches +- **OpenAPI Documentation**: x-rateLimit extensions and client communication +- **Multi-Tier Protection**: Global, per-endpoint, and per-client rate limiting +- **Abuse Detection**: Pattern recognition and automated response strategies +- **Real-World Examples**: Implementation patterns in Node.js and Redis +- **Monitoring & Observability**: Metrics collection and alerting strategies --- -## The Library Card Principle - -> **The Library Card**: A library card allows a patron to check out a maximum of ten books per month. Once that limit is reached, the system will not allow any more checkouts until the next month begins, regardless of how many times the patron asks. - -**Rate limiting** applies this same principle to an API. It establishes a policy that restricts the number of requests a single client can make within a specific time window (e.g., 100 requests per minute). - -## Why Rate Limiting Is Critical for API Security - -Rate limiting is a critical control for both security and reliability, directly mitigating several OWASP API Security Top 10 risks: - -1. **Security:** It thwarts Denial-of-Service (DoS) attacks by preventing traffic floods, addressing OWASP API4:2023 - Unrestricted Resource Consumption. It also makes brute-force attacks against [authentication endpoints](authentication-authorization-openapi) much slower and less effective, reducing the risk of credential stuffing attacks. - -2. **Business Logic Abuse:** It helps mitigate abuse by preventing bots from scraping data or manipulating business flows, addressing OWASP API6:2023 - Unrestricted Access to Sensitive Business Flows. - -3. **Reliability and Fair Usage:** It ensures that the API remains stable and responsive for all users by preventing any single client from monopolizing server resources. - -## Documenting Rate Limits in OpenAPI - -While OpenAPI 3.1 doesn't include native rate-limiting objects, extension properties (prefixed with `x-`) provide a standard mechanism. The best practice is defining custom `x-rateLimit` extensions at the operation level. - -**Note:** Rate limits are typically dynamic in production environments, with different limits for different clients based on service tiers, contracts, or usage patterns. The OpenAPI specification documents the baseline policy, while implementation systems apply client-specific variations. - -```yaml {% title="openapi.yaml" %} -paths: - /auth/login: - post: - summary: User Login - tags: [Authentication] - # Define rate-limiting policy for this sensitive endpoint # [!code highlight] - x-rateLimit: - limit: 5 # [!code highlight] Strict limit for auth endpoints - window: "1m" # [!code highlight] Short time window - scope: "ip_address" # [!code highlight] IP-based rate limiting - description: "Limits login attempts to 5 per minute per IP to prevent brute-force attacks." - responses: - '200': - description: "Successful login." - # Document the 429 response with proper headers # [!code highlight] - '429': - description: "Too Many Requests. Rate limit exceeded." - headers: - Retry-After: # [!code highlight] Required for proper client behavior - schema: - type: integer - description: "Seconds to wait before making a new request." - X-RateLimit-Limit: # [!code highlight] Inform clients of limits - schema: - type: integer - description: "Maximum requests permitted in the window." - X-RateLimit-Remaining: # [!code highlight] Help clients pace requests - schema: - type: integer - description: "Requests remaining in current window." -``` - -### Automated Governance for Rate Limiting - -API governance tools can enforce rules that ensure [authentication endpoints](authentication-authorization-openapi) always have rate limiting policies defined. - -This approach provides dual benefits: modern API documentation tools automatically display rate limiting extensions in generated documentation, making policies transparent to API consumers, while governance rules ensure sensitive endpoints never lack rate-limiting policies. - -> **🔧 Implementation Guide**: See our [Automated Security Validation Walkthrough](automated-security-validation-walkthrough) for step-by-step instructions on implementing rate limiting validation rules, including 429 response validation and header consistency checks. - -## Rate Limiting Implementation Approaches - -Choose the rate limiting algorithm that best fits your traffic patterns and precision requirements: - -{% tabs %} - {% tab label="Token Bucket" %} - -### Token Bucket Algorithm - -**Best for:** APIs that need to handle legitimate traffic spikes - -**How it works:** -- Tokens are added to a bucket at a steady rate (refill rate) -- Each request consumes one token from the bucket -- If bucket is empty, requests are rejected or queued -- Allows burst traffic up to bucket capacity - -**Pros:** -- **Flexible burst handling**: Accommodates legitimate traffic spikes -- **Smooth long-term limiting**: Maintains steady average rate -- **User-friendly**: Doesn't penalize users for occasional bursts - -**Cons:** -- **Implementation complexity**: Requires token state management -- **Memory overhead**: Need to track bucket state per client -- **Distributed challenges**: Synchronizing token state across servers - -**Implementation example:** -```javascript {% title="token-bucket.js - Secure Rate Limiting Algorithm" %} -class TokenBucket { - constructor(capacity, refillRate) { - // STEP 1: Initialize bucket parameters - this.capacity = capacity; // Max burst size (e.g., 100 requests) - this.tokens = capacity; // Start with full bucket (allows immediate bursts) - this.refillRate = refillRate; // Steady rate (e.g., 10 requests/second) - this.lastRefill = Date.now(); // Track when we last added tokens - } - - // STEP 2: Process incoming request - the main security enforcement point - consume(tokens = 1) { - // First, add any tokens we've earned since last request - this.refill(); // CRITICAL: Always refill before checking - - // STEP 3: Security decision - allow or block the request - if (this.tokens >= tokens) { - this.tokens -= tokens; // Consume tokens for this request - return true; // ✅ REQUEST ALLOWED - user under limit - } - - // STEP 4: Rate limit exceeded - implement security response - console.warn(`Rate limit exceeded. Tokens available: ${this.tokens}, requested: ${tokens}`); - return false; // ❌ BLOCK REQUEST - user over limit - } - - // STEP 5: Token refill logic - implements the "steady rate" behavior - refill() { - const now = Date.now(); - const timePassed = (now - this.lastRefill) / 1000; // Convert to seconds - - // Calculate tokens earned: time × rate - const tokensToAdd = Math.floor(timePassed * this.refillRate); // Floor prevents fractional tokens - - if (tokensToAdd > 0) { - // Add tokens but never exceed capacity (prevents bucket overflow) - this.tokens = Math.min(this.capacity, this.tokens + tokensToAdd); - this.lastRefill = now; // Update timestamp for next calculation - - console.debug(`Added ${tokensToAdd} tokens. Current: ${this.tokens}/${this.capacity}`); - } - } - - // STEP 6: Utility methods for monitoring and debugging - getStatus() { - this.refill(); // Ensure current state - return { - tokens: this.tokens, // Available tokens right now - capacity: this.capacity, // Maximum burst size - utilizationPercent: ((this.capacity - this.tokens) / this.capacity * 100).toFixed(1) - }; - } -} - -// EXAMPLE USAGE: Protect login endpoint from brute force -const loginRateLimit = new TokenBucket(5, 0.1); // 5 attempts, refill 1 every 10 seconds - -// In your API endpoint: -app.post('/auth/login', (req, res) => { - const clientId = req.ip || req.headers['x-client-id']; // Identify the client - - if (!loginRateLimit.consume()) { - return res.status(429).json({ // HTTP 429 = Too Many Requests - error: 'Rate limit exceeded', - retryAfter: Math.ceil((1 / loginRateLimit.refillRate)) // Tell client when to retry - }); - } - - // Process login attempt... // Only reached if under rate limit -}); -``` - - {% /tab %} - {% tab label="Sliding Window" %} - -### Sliding Window Algorithm - -**Best for:** APIs requiring exact rate limiting precision - -**How it works:** -- Tracks exact timestamps of requests within a rolling time window -- Continuously slides the window forward with each request -- Provides most accurate rate limiting without boundary conditions - -**Pros:** -- **Maximum accuracy**: No boundary condition exploits -- **Precise enforcement**: Exact request counting within time windows -- **Fair distribution**: Prevents gaming of window boundaries - -**Cons:** -- **Memory intensive**: Stores timestamp for each request -- **Complex implementation**: Requires efficient data structures -- **Distributed complexity**: Hard to synchronize across multiple servers - -**Implementation example:** -```javascript {% title="sliding-window.js" %} -class SlidingWindowRateLimit { - constructor(maxRequests, windowSeconds) { - this.maxRequests = maxRequests; // [!code highlight] Maximum requests allowed - this.windowSeconds = windowSeconds; // [!code highlight] Time window in seconds - this.requests = []; // [!code highlight] Store request timestamps - } - - isAllowed() { - const now = Date.now(); - const windowMs = this.windowSeconds * 1000; - - // Remove requests outside current window // [!code highlight] - while (this.requests.length > 0 && this.requests[0] <= now - windowMs) { - this.requests.shift(); // [!code highlight] Clean old timestamps - } - - // Check if we're under the limit - if (this.requests.length < this.maxRequests) { - this.requests.push(now); // [!code highlight] Record this request - return true; // [!code highlight] Request allowed - } - - return false; // [!code error] Rate limit exceeded - } - - // Utility method to get current status - getStatus() { - const now = Date.now(); - const windowMs = this.windowSeconds * 1000; - - // Clean old requests first - while (this.requests.length > 0 && this.requests[0] <= now - windowMs) { - this.requests.shift(); - } - - return { - currentRequests: this.requests.length, - maxRequests: this.maxRequests, - remaining: this.maxRequests - this.requests.length, - windowSeconds: this.windowSeconds - }; - } -} -``` - - {% /tab %} - {% tab label="Fixed Window" %} - -### Fixed Window Algorithm - -**Best for:** Simple use cases with easy implementation requirements - -**How it works:** -- Divides time into fixed intervals (e.g., per minute, per hour) -- Counts requests within each fixed window -- Resets counter at the start of each new window - -**Pros:** -- **Simple implementation**: Easy to understand and code -- **Low memory usage**: Only need counter per time window -- **Distributed-friendly**: Easy to implement with shared counters - -**Cons:** -- **Boundary condition abuse**: 2x rate limit possible at window edges -- **Traffic spikes**: All requests could arrive at start of window -- **Less user-friendly**: Sudden cutoffs can impact user experience - -**Implementation example:** -```javascript {% title="fixed-window.js" %} -class FixedWindowRateLimit { - constructor(maxRequests, windowMs) { - this.maxRequests = maxRequests; // [!code highlight] Maximum requests per window - this.windowMs = windowMs; // [!code highlight] Window duration in milliseconds - this.counter = new Map(); // [!code highlight] Request counters by client - this.windowStart = new Map(); // [!code highlight] Window start times - } - - isAllowed(clientId) { - const now = Date.now(); - const windowStart = this.windowStart.get(clientId); - - // Check if we're in a new window // [!code highlight] - if (!windowStart || (now - windowStart) >= this.windowMs) { - this.windowStart.set(clientId, now); // [!code highlight] Start new window - this.counter.set(clientId, 1); // [!code highlight] Reset counter - return true; // [!code highlight] Request allowed - } - - // Check current window limit - const currentCount = this.counter.get(clientId) || 0; - if (currentCount < this.maxRequests) { - this.counter.set(clientId, currentCount + 1); // [!code highlight] Increment counter - return true; // [!code highlight] Request allowed - } - - return false; // [!code error] Rate limit exceeded - } - - // Utility method to get window status for a client - getWindowStatus(clientId) { - const now = Date.now(); - const windowStart = this.windowStart.get(clientId); - const currentCount = this.counter.get(clientId) || 0; - - if (!windowStart) { - return { - requests: 0, - maxRequests: this.maxRequests, - remaining: this.maxRequests, - timeUntilReset: this.windowMs - }; - } - - const timeElapsed = now - windowStart; - const timeUntilReset = Math.max(0, this.windowMs - timeElapsed); - - return { - requests: currentCount, - maxRequests: this.maxRequests, - remaining: Math.max(0, this.maxRequests - currentCount), - timeUntilReset - }; - } -} -``` - - {% /tab %} -{% /tabs %} - -## Advanced Rate Limiting Techniques - -### Multi-tier Rate Limiting Configuration - -```yaml {% title="Kong configuration" %} -plugins: -- name: rate-limiting - config: - minute: 100 # 100 requests per minute per IP - hour: 1000 # 1000 requests per hour per IP - policy: redis # Use Redis for distributed rate limiting - fault_tolerant: true - hide_client_headers: false - -# Per-endpoint overrides -- name: rate-limiting - route: auth-endpoints - config: - minute: 5 # Stricter limits for auth endpoints - hour: 20 - policy: redis -``` - -### Client-side Exponential Backoff - -```javascript -class APIClient { - async makeRequest(url, options, retries = 3) { - try { - const response = await fetch(url, options); - - if (response.status === 429) { - const retryAfter = response.headers.get('Retry-After'); - const delay = retryAfter ? parseInt(retryAfter) * 1000 : - Math.pow(2, 4 - retries) * 1000; // Exponential backoff - - if (retries > 0) { - await new Promise(resolve => setTimeout(resolve, delay)); - return this.makeRequest(url, options, retries - 1); - } - - throw new Error('Rate limit exceeded'); - } - - return response; - } catch (error) { - throw error; - } - } -} -``` - -As a complementary practice, the client-side responsibility of implementing exponential backoff should also be noted. When an API client receives a rate-limiting error (e.g., HTTP 429 Too Many Requests), it should wait for an exponentially increasing period of time between retries. This prevents clients from overwhelming the server and helps the system recover gracefully from load spikes. - -> **Tip:** Combine per-IP and per-account quotas and require exponential backoff on clients. - -## Attack Example: Facebook Phone Number Scraping (2019) - -In 2019, malicious actors exploited a vulnerability in Facebook's contact importer feature to scrape the personal data of over 530 million users. The API endpoint itself was not technically "broken"—it performed its intended function of matching phone numbers to user profiles. The vulnerability was the absence of adequate rate limiting and business rule enforcement. - -Attackers used automated scripts to submit massive lists of phone numbers, and the API dutifully returned the corresponding user profiles, allowing them to build a massive database of personal information. - -This incident highlights a different type of API attack, moving from exploiting technical flaws to abusing business logic at scale. It elevates rate limiting from an infrastructure protection mechanism to also being a tool for enforcing business rules. The `x-rateLimit` extension in OpenAPI is a form of declarative security policy. - -```mermaid -sequenceDiagram - participant B as Botnet/Script - participant API as Contact Import API - - loop Enumerate phone numbers - B->>API: Batch upload numbers - API-->>B: Matched user IDs/profile data - end - Note over B,API: Missing per-account/IP limits and anomaly detection -``` - -*Sequence diagram showing how attackers used Facebook's contact import API to scrape phone numbers at scale, exploiting missing rate limits and velocity checks to harvest personal data.* - -Why this matters: Rate limiting, velocity checks, and behavior analytics are core defenses against scraping and credential-stuffing at scale. - -## Rate Limiting Monitoring and Observability - -Choose your monitoring approach based on your security operations needs: - -{% tabs %} - {% tab label="Metrics Collection (JavaScript)" %} - -### Rate Limiting Metrics Collection - -```javascript -// Track rate limiting metrics for security analysis -class RateLimitMetrics { - constructor() { - this.blockedRequests = new Map(); // [!code highlight] Count blocked requests by client - this.totalRequests = new Map(); // [!code highlight] Count total requests by client - this.suspiciousPatterns = new Map(); // [!code highlight] Track attack patterns - } - - recordRequest(clientId, blocked = false, endpoint = null) { - // Initialize counters if client is new - if (!this.totalRequests.has(clientId)) { - this.totalRequests.set(clientId, 0); - this.blockedRequests.set(clientId, 0); - this.suspiciousPatterns.set(clientId, []); - } - - this.totalRequests.set(clientId, this.totalRequests.get(clientId) + 1); // [!code highlight] Increment request counter - - if (blocked) { - this.blockedRequests.set(clientId, this.blockedRequests.get(clientId) + 1); // [!code highlight] Track blocked request - - // Track suspicious patterns // [!code highlight] - const patterns = this.suspiciousPatterns.get(clientId); - patterns.push({ - timestamp: Date.now(), // [!code highlight] When attack occurred - endpoint: endpoint, // [!code highlight] Which endpoint targeted - blocked: true // [!code highlight] Request was blocked - }); - this.suspiciousPatterns.set(clientId, patterns); - } - } - - getBlockRate(clientId) { - const total = this.totalRequests.get(clientId) || 0; - const blocked = this.blockedRequests.get(clientId) || 0; - return total > 0 ? (blocked / total) * 100 : 0; - } - - getAttackIndicators(clientId, windowMinutes = 5) { - // Detect rapid repeated attempts that might indicate an attack - const patterns = this.suspiciousPatterns.get(clientId) || []; - const recentBlocks = patterns.filter(event => // [!code highlight] Filter recent blocked requests - Date.now() - event.timestamp < windowMinutes * 60 * 1000 - ); - return recentBlocks.length; // [!code highlight] Return attack indicator count - } -} -``` - -**How metrics collection works:** -- **Request tracking**: Counts all requests and blocked requests per client -- **Pattern detection**: Records timestamps and endpoints for blocked requests -- **Attack indicators**: Identifies rapid repeated attempts within time windows -- **Block rate calculation**: Calculates percentage of requests blocked per client - -{% /tab %} -{% tab label="Alerting Configuration (Prometheus)" %} - -### Alerting Configuration - -```yaml {% title="prometheus-alerts.yml" %} -groups: -- name: rate_limiting_alerts - rules: - - alert: HighRateLimitBlocks - expr: rate(rate_limit_blocked_total[5m]) > 10 - for: 2m - labels: - severity: warning - annotations: - summary: "High rate of blocked requests detected" - description: "{{ $value }} requests per second being blocked" - - - alert: SuspiciousRateLimitPattern - expr: rate_limit_block_rate > 80 # [!code highlight] 80% block rate threshold - for: 1m # [!code highlight] Alert after 1 minute - labels: - severity: critical # [!code error] Critical security alert - annotations: - summary: "Possible DDoS or brute force attack" - description: "Client {{ $labels.client_id }} has {{ $value }}% blocked rate" -``` - -**How alerting works:** -- **HighRateLimitBlocks**: Monitors overall rate of blocked requests across system -- **SuspiciousRateLimitPattern**: Detects clients with abnormally high block rates -- **Threshold-based**: Configurable thresholds trigger security team notifications -- **Context-aware**: Provides client IDs and block rates for investigation - -{% /tab %} -{% /tabs %} - -### Rate Limiting Troubleshooting - -**Common Issues and Solutions:** - -* **Counting the wrong thing** — per-IP only; add per-account and per-token limits -* **Same limits for every endpoint** — tighten auth and write endpoints separately -* **No Retry-After header** — clients can't back off predictably -* **Stateless limits in distributed systems** — use Redis or gateway-native stores -* **Legitimate bursts blocked** — implement token bucket algorithm for flexibility - -**Quick Diagnostic Commands:** - -```bash -# Observe 429 behavior and headers -curl -i https://api.example.com/login | grep -E 'HTTP/|Retry-After|X-RateLimit' - -# Simulate burst to verify rate limiting -hey -z 10s -q 50 -c 50 https://api.example.com/api/resource - -# Test different client patterns -for i in {1..10}; do - curl -H "Authorization: Bearer $TOKEN" https://api.example.com/api/data - sleep 1 -done -``` - -### Advanced Rate Limiting Patterns - -**Adaptive Rate Limiting:** -```javascript -// Adjust limits based on server health -class AdaptiveRateLimit { - constructor() { - this.baseLimit = 100; - this.currentLimit = 100; - this.healthThreshold = 0.8; - } - - adjustLimit(serverLoad, errorRate) { - if (serverLoad > this.healthThreshold || errorRate > 0.1) { - this.currentLimit = Math.max(10, this.currentLimit * 0.8); - } else if (serverLoad < 0.5 && errorRate < 0.01) { - this.currentLimit = Math.min(this.baseLimit, this.currentLimit * 1.1); - } - } -} -``` - -**Geographic Rate Limiting:** -```yaml {% title="nginx-rate-limit.conf" %} -# Different limits based on geographic regions -geo $rate_limit_zone { - default $binary_remote_addr; - # More restrictive limits for high-risk regions - ~^192\.168\. $binary_remote_addr_strict; - ~^10\. $binary_remote_addr_internal; -} - -limit_req_zone $rate_limit_zone zone=general:10m rate=100r/m; -limit_req_zone $binary_remote_addr_strict zone=restricted:10m rate=20r/m; -limit_req_zone $binary_remote_addr_internal zone=internal:10m rate=1000r/m; -``` - -> Rate Limiting Best Practice: "Rate limiting on auth endpoints is non-negotiable. We set 5/min per IP and per account, and alert when bypass attempts appear." - -## Frequently Asked Questions - -### Why is rate limiting important for API security? -Rate limiting prevents denial-of-service attacks, brute-force authentication attempts, and data scraping. It ensures fair resource usage among legitimate users while blocking malicious automation. Without rate limits, a single bad actor can overwhelm your API infrastructure. See the [Facebook phone number scraping incident](#attack-example-facebook-phone-number-scraping-2019) for a real-world example. - -### What's the difference between rate limiting and throttling? -Rate limiting sets hard limits on request volume (e.g., 100 requests per minute), rejecting excess requests with 429 status codes. Throttling typically involves slowing down or queuing requests rather than rejecting them outright. Rate limiting is more common for APIs as it provides clearer client feedback. - -### Should rate limits be per-IP, per-user, or both? -Implement multiple layers: per-IP limits prevent DDoS attacks from single sources, per-user limits enforce fair usage policies, and per-API-key limits support tiered service levels. Combine all three for comprehensive protection against different attack patterns. See [advanced rate limiting patterns](#advanced-rate-limiting-patterns) for implementation guidance. - -### How do I handle legitimate traffic spikes? -Use [token bucket algorithms](#rate-limiting-implementation-approaches) that allow controlled bursts within overall rate limits. Consider implementing adaptive rate limiting that adjusts limits based on server health. For predictable spikes, provide rate limit increase APIs or temporary exemption mechanisms for verified clients. - -### What rate limiting algorithm should I choose? -- **[Token Bucket](#rate-limiting-implementation-approaches)**: Best for APIs needing burst flexibility -- **[Sliding Window](#rate-limiting-implementation-approaches)**: Most accurate but memory intensive -- **[Fixed Window](#rate-limiting-implementation-approaches)**: Simple but allows boundary condition abuse - -Choose based on your accuracy requirements, traffic patterns, and implementation complexity tolerance. See our [implementation approaches](#rate-limiting-implementation-approaches) for detailed comparisons. - -### How do I communicate rate limits to API consumers? -Document limits in [OpenAPI specifications using x-rateLimit extensions](#documenting-rate-limits-in-openapi), include rate limit headers in responses (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `Retry-After`), provide clear error messages with 429 responses, and maintain public documentation about your rate limiting policies. - -## Rate Limiting Strategy Framework - -### Implementation Priority - -1. **Critical Endpoints First** - - Authentication endpoints: 5-10 requests per minute per IP - - Password reset: 3 requests per hour per email - - Account creation: 5 requests per hour per IP - - Payment processing: Strict limits based on business rules - -2. **Resource-Intensive Operations** - - Search endpoints: Higher limits but monitor query complexity - - File uploads: Size-based and frequency-based limits - - Data export: Very restrictive limits with queuing - -3. **General API Access** - - Read operations: Generous limits for good user experience - - Write operations: More restrictive than reads - - Administrative endpoints: Very restrictive with strong authentication - -### Rate Limit Testing Strategy - -```javascript -// Rate limit testing framework -async function testRateLimit(url, requestsCount, windowSeconds) { - /** - * Test rate limiting behavior - * @param {string} url - API endpoint to test - * @param {number} requestsCount - Number of concurrent requests to send - * @param {number} windowSeconds - Expected rate limit window - */ - const startTime = Date.now(); - let successfulRequests = 0; - let blockedRequests = 0; - - // Create array of request promises - const requests = Array.from({ length: requestsCount }, () => makeRequest(url)); - - // Execute all requests concurrently - const responses = await Promise.allSettled(requests); - - // Analyze responses - for (const result of responses) { - if (result.status === 'rejected') { - console.warn('Request failed:', result.reason.message); - continue; - } - - const response = result.value; - if (response.status === 200) { - successfulRequests++; - } else if (response.status === 429) { - blockedRequests++; - } - } - - const elapsed = (Date.now() - startTime) / 1000; // Convert to seconds - console.log('Rate limit test results:'); - console.log(`Successful: ${successfulRequests}, Blocked: ${blockedRequests}`); - console.log(`Effective rate: ${(successfulRequests / elapsed).toFixed(2)} req/sec`); - - return { - successful: successfulRequests, - blocked: blockedRequests, - total: requestsCount, - elapsedSeconds: elapsed, - effectiveRate: successfulRequests / elapsed - }; -} - -async function makeRequest(url) { - try { - const response = await fetch(url, { - method: 'GET', - headers: { - 'User-Agent': 'rate-limit-tester/1.0' - } - }); - return response; - } catch (error) { - throw new Error(`Request failed: ${error.message}`); - } -} - -// Example usage: -// await testRateLimit('https://api.example.com/users', 50, 60); -``` - -## Resources and Next Steps - -### Essential Standards -- OWASP API Security Top 10 - Comprehensive guide including unrestricted resource consumption (API4:2023) and business logic abuse (API6:2023) -- RFC 6585 - HTTP status code 429 (Too Many Requests) specification - -### Related Security Topics -- [API Input Validation and Injection Prevention](api-input-validation-injection-prevention) - Protect APIs from malicious data -- [Authentication and Authorization with OpenAPI](authentication-authorization-openapi) - Implement secure access control -- [API TLS Encryption and HTTPS Best Practices](api-tls-encryption-https-best-practices) - Secure data in transit -- [API Security by Design: Complete Guide](/learn/security) - Overview of all API security domains \ No newline at end of file +*This article is currently under review and will be available soon. Return to the [API Security Framework and Fundamentals](.) to explore other security topics.* diff --git a/learn/security/api-tls-encryption-https-best-practices.md b/learn/security/api-tls-encryption-https-best-practices.md index 49cb225f..1d12fcf3 100644 --- a/learn/security/api-tls-encryption-https-best-practices.md +++ b/learn/security/api-tls-encryption-https-best-practices.md @@ -8,438 +8,17 @@ seo: # TLS Encryption and HTTPS Best Practices for APIs ---- - -## Key Takeaways +*This comprehensive guide is coming soon and will cover:* -When a client and an API exchange information, that data travels across the internet, a public network. Without protection, this data gets intercepted and read by malicious actors. This is where encryption comes in. +## What You'll Learn -**In this guide, you'll learn:** -- [How TLS 1.3 provides secure communication](#tls-13-the-modern-standard) for APIs -- [OpenAPI server URL security contracts](#enforcing-https-in-your-api-specification) and enforcement -- [Certificate management and TLS configuration](#tls-configuration-examples) examples -- [Mutual TLS (mTLS) for service-to-service communication](#mutual-tls-mtls-two-way-authentication) -- [Real-world lessons from the Heartbleed vulnerability](#attack-example-heartbleed-tls-library-vulnerability-2014) -- [Automated governance for transport security](#automated-governance-enforcement) +- **TLS 1.3 Configuration**: Modern encryption standards and cipher suite selection +- **Certificate Management**: Best practices for SSL/TLS certificate lifecycle +- **OpenAPI Security Contracts**: Enforcing HTTPS-only APIs through specifications +- **Mutual TLS (mTLS)**: Service-to-service cryptographic authentication +- **Real-World Examples**: Configuration examples for Nginx and Express.js +- **Automated Governance**: CI/CD integration for transport security validation --- -## Quick Start Guide - -Ready to implement secure TLS encryption? Follow these steps: - -1. **Upgrade to TLS 1.3:** Implement [modern TLS 1.3](#tls-13-the-modern-standard) with strong cipher suites and disable legacy protocols -2. **Configure your server:** Choose your technology stack from our [configuration examples](#tls-configuration-examples) (Nginx or Express.js) -3. **Enforce HTTPS in specs:** Update [OpenAPI server URLs](#enforcing-https-in-your-api-specification) to use HTTPS only with automated governance -4. **Set up monitoring:** Implement [certificate monitoring](#tls-monitoring-and-troubleshooting) to track expiration dates and TLS configuration -5. **Consider mTLS:** For service-to-service communication, evaluate [mutual TLS](#mutual-tls-mtls-two-way-authentication) for cryptographic client authentication - -**Next Steps:** Now that you have secure transport with TLS, learn about [API Input Validation and Injection Prevention](api-input-validation-injection-prevention) to protect your APIs from malicious data inputs. - ---- - -## The Banking Vault Principle - -> **The Banking Vault Principle**: When banks transfer large sums between branches, they don't send cash in regular envelopes. They use armored vehicles with multiple security layers. TLS encryption works similarly — it creates a secure transport layer that protects your API data during transit, even across untrusted networks. - -**Encryption in transit** works similarly, creating a secure, private tunnel for API data as it moves between the client and the server. - -## TLS 1.3: The Modern Standard - -This secure tunnel is primarily established using **Transport Layer Security (TLS) version 1.3**, as specified in [IETF RFC 8446](https://tools.ietf.org/html/rfc8446). [NIST SP 800-52 Rev. 2](https://csrc.nist.gov/publications/detail/sp/800-52/rev-2/final) guidelines for TLS implementations unequivocally mandate TLS 1.3 for modern systems, as older protocols—including all versions of SSL, TLS 1.0, and TLS 1.1—are deprecated and considered insecure due to known vulnerabilities. - -When a client connects to an API over `https://`, it initiates a "TLS handshake." During this handshake, the client and server perform crucial steps: - -1. **Authentication:** The server presents its TLS certificate to the client to prove its identity, ensuring the client is talking to the legitimate server and not an impostor. -2. **Agreement on Encryption:** They agree on a set of cryptographic algorithms (a "cipher suite") to use for the session. -3. **Key Exchange:** They securely generate and exchange unique session keys that will be used to encrypt and decrypt all data for the remainder of the conversation. - -### TLS Handshake Process - -```mermaid -sequenceDiagram - participant C as Client - participant S as Server - - Note over C,S: TLS Handshake Process - - C->>S: 1. Client Hello (Supported cipher suites) - - S->>C: 2. Server Hello + Certificate - Note right of S: Server presents TLS certificate to prove identity - - C->>C: 3. Certificate Validation - Note left of C: Client verifies server certificate is trusted - - C->>S: 4. Cipher Suite Selection - Note over C,S: Both agree on cryptographic algorithms - - C->>S: 5. Key Exchange - S->>C: 6. Key Exchange Complete - Note over C,S: Generate and exchange unique session keys - - Note over C,S: 🔒 Secure Communication Begins - - C->>S: Encrypted API Request - S->>C: Encrypted API Response - -``` - -*Sequence diagram illustrating the TLS handshake process between client and server, showing certificate validation, cipher suite selection, and secure key exchange that ensures encrypted API communication.* - -## TLS Security Guarantees - -TLS, when done right, provides three essential security guarantees: - -* **Confidentiality:** It encrypts the data, preventing eavesdroppers from reading it. -* **Integrity:** It ensures that the data has not been altered or tampered with during transit. -* **Authentication:** It verifies the identity of the server, protecting against man-in-the-middle attacks. - -This is why secure APIs always use URLs that start with `https://` instead of `http://`. The 's' stands for 'secure' and indicates that the connection is protected by TLS encryption. - -## TLS Implementation Best Practices - -In production environments, telling teams to "use HTTPS" without specifics sometimes leads to misconfigured TLS and a false sense of security. Proper TLS implementation requires: - -* **Enforcing Strong Cipher Suites**: Configure servers to only negotiate cryptographic algorithms that are considered secure, disabling weak or obsolete ciphers -* **Proper Certificate Management**: Use certificates from trusted Certificate Authorities (CAs), ensure they are not expired, and implement robust processes for certificate issuance, renewal, and revocation -* **Protection Against Man-in-the-Middle (MiTM) Attacks**: Implement HTTP Strict Transport Security (HSTS) to instruct browsers to only communicate over HTTPS, preventing protocol downgrade attacks - -### Common TLS misconfigurations - -* Weak or legacy protocols enabled (SSL, TLS 1.0/1.1) — disable them explicitly -* Missing HSTS header — add Strict-Transport-Security with long max-age -* Mixed content or accidental HTTP endpoints — redirect to HTTPS at the edge -* Expiring certificates — monitor expiry and automate renewal - -Quick checks: - -```bash -# Verify protocol and cipher suites -openssl s_client -connect api.example.com:443 -tls1_3 -cipher 'TLS_AES_256_GCM_SHA384' < /dev/null | grep -E 'Protocol|Cipher' - -# Scan for common TLS issues -testssl.sh --fast https://api.example.com -``` - -> Expert insight: "Treat TLS as a product with owners and SLAs. We track TLS health on dashboards the same way we track latency and errors." - -## Enforcing HTTPS in Your API Specification - -The security contract for encrypted transit begins within the `servers` object of your OpenAPI specification. Every URL defined here must use the `https://` scheme—this isn't just documentation, it's a formal declaration of your API's secure endpoints. - -**OpenAPI HTTPS Enforcement** - -```yaml {% title="openapi.yaml" %} -# CRITICAL SECURITY: Only HTTPS servers in production OpenAPI specs # [!code error] -servers: - - url: https://api.production.com/v1 # [!code warning] ESSENTIAL: HTTPS only for production - description: Production Server - - url: https://api.staging.com/v1 # [!code warning] ESSENTIAL: HTTPS only for staging - description: Staging Server - # Never include HTTP servers in production specs # [!code highlight] DANGEROUS: HTTP servers are vulnerable - # - url: http://api.example.com/v1 # [!code error] NEVER DO THIS: Allows man-in-the-middle attacks -``` - -**Security Benefits**: -- **Prevents man-in-the-middle attacks** by encrypting all API traffic -- **Protects sensitive data** (API keys, user credentials, personal information) in transit -- **Enables modern web features** that require secure contexts (Service Workers, etc.) -- **Improves SEO and user trust** with browser security indicators - -### Automated Governance Enforcement - -Modern API governance tools can enforce HTTPS usage through automated validation rules. When integrated into your CI/CD pipeline, automated governance creates security gates. If a developer attempts to commit an OpenAPI file with insecure server URLs, the pipeline fails with a clear error message, preventing insecure configurations from ever reaching production. - -*Automated governance tools fail CI/CD builds when OpenAPI specifications use HTTP instead of HTTPS, requiring developers to fix security violations before deployment.* - -## TLS Configuration Examples - -Choose your server configuration based on your technology stack. Authoritative sources like the [Mozilla SSL Configuration Generator](https://ssl-config.mozilla.org/) provide excellent, up-to-date templates for secure server configurations. - -{% tabs %} - {% tab label="Nginx Configuration" %} - -### Production Nginx TLS Configuration - -```nginx {% title="nginx.conf - Production TLS Security Configuration" %} -server { - # STEP 1: Enable HTTPS with HTTP/2 for performance and security # [!code highlight] - listen 443 ssl http2; # Port 443 = HTTPS, http2 = faster + more secure - server_name api.example.com; # Your API domain - must match certificate CN/SAN - - # STEP 2: Force TLS 1.3 only - disables ALL vulnerable older versions # [!code highlight] - ssl_protocols TLSv1.3; # [!code error] CRITICAL: Blocks SSL, TLS 1.0, 1.1, 1.2 vulnerabilities - - # STEP 3: Define strong cipher suites (TLS 1.3 has built-in secure ciphers) # [!code highlight] - # These are the only ciphers clients can negotiate - all are AEAD (authenticated encryption) - ssl_ciphers TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256; - - # STEP 4: Security headers - prevent client-side attacks # [!code highlight] - # HSTS: Forces browsers to use HTTPS for ALL future requests (even if user types http://) - add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; - - # Additional security headers for defense in depth - add_header X-Frame-Options DENY always; # Prevent clickjacking - add_header X-Content-Type-Options nosniff always; # Prevent MIME confusion attacks - add_header Referrer-Policy "strict-origin-when-cross-origin" always; # Limit referrer leakage - - # STEP 5: TLS Certificate configuration - THE MOST CRITICAL PART # [!code highlight] - ssl_certificate /path/to/certificate.crt; # Public certificate (safe to share) - ssl_certificate_key /path/to/private.key; # [!code error] CRITICAL: PRIVATE KEY - never share, restrict access! - - # STEP 6: Certificate security best practices # [!code highlight] - ssl_certificate_transparency on; # Enable CT logging for transparency - ssl_stapling on; # OCSP stapling - faster cert validation - ssl_stapling_verify on; # Verify OCSP responses - ssl_trusted_certificate /path/to/chain.pem; # Certificate chain for OCSP validation - - # STEP 7: Performance optimizations that also improve security # [!code highlight] - ssl_session_cache shared:SSL:10m; # Session resumption (avoids full handshake) - ssl_session_timeout 10m; # Limit session lifetime - ssl_prefer_server_ciphers off; # Let client choose (TLS 1.3 best practice) - - # Your API routes go here... - location / { - # API backend configuration - } -} - -# STEP 8: Redirect ALL HTTP traffic to HTTPS (never serve HTTP in production) # [!code highlight] -server { - listen 80; # [!code highlight] WARNING: HTTP port - only for redirects! - server_name api.example.com; - return 301 https://$server_name$request_uri; # Permanent redirect to HTTPS -} -``` - -**Critical Configuration Notes**: -- **TLS 1.3 only**: Disables vulnerable older protocols (SSL, TLS 1.0/1.1/1.2) -- **Strong ciphers**: Only allows cryptographically secure cipher suites -- **HTTP/2**: Improves performance while maintaining security -- **HSTS header**: Forces browsers to use HTTPS, prevents downgrade attacks - -{% /tab %} -{% tab label="Express.js Configuration" %} - -### Express.js HTTPS Server with Security Headers - -```javascript {% title="secure-server.js" %} -const https = require('https'); -const fs = require('fs'); -const express = require('express'); - -const app = express(); - -// HSTS middleware - ALWAYS force HTTPS for all future requests // [!code highlight] -app.use((req, res, next) => { - res.setHeader('Strict-Transport-Security', 'max-age=31536000; includeSubDomains'); - next(); -}); - -// TLS configuration - secure defaults // [!code highlight] -const options = { - key: fs.readFileSync('private.key'), // [!code error] CRITICAL: Keep private key secure! - cert: fs.readFileSync('certificate.crt'), // Certificate file - secureProtocol: 'TLSv1_3_method' // [!code highlight] SECURITY: Force TLS 1.3 only -}; - -// Start HTTPS server on port 443 - NEVER use HTTP in production // [!code highlight] -https.createServer(options, app).listen(443, () => { - console.log('Secure API server running on https://localhost:443'); -}); -``` - -**Security Implementation Details**: -- **HSTS middleware**: Prevents protocol downgrade attacks by forcing HTTPS -- **TLS 1.3 only**: Disables vulnerable older TLS versions -- **Certificate management**: Loads TLS certificate and private key from secure files -- **Port 443**: Standard HTTPS port for production APIs - -{% /tab %} -{% /tabs %} - -## Attack Example: Heartbleed (TLS library vulnerability, 2014) - -The Heartbleed bug (CVE-2014-0160) was a critical vulnerability in the OpenSSL library, not the TLS protocol itself. It allowed attackers to read up to 64KB of a server's memory by sending a malformed TLS heartbeat request. The server would respond with not only the small payload sent by the attacker but also adjacent memory contents, which could include session cookies, user credentials, and even the server's private encryption keys. - -This incident demonstrates a crucial point: security is multi-layered. While an OpenAPI specification can enforce the *intent* of using secure transport (https://), it cannot prevent a runtime vulnerability in the underlying software stack. True "secure by design" requires both design-time governance via OpenAPI linting and runtime security posture management, including diligent vulnerability scanning and patch management. - -```mermaid -sequenceDiagram - participant A as Attacker - participant S as Vulnerable Server (OpenSSL) - - A->>S: TLS handshake - A->>S: Malformed Heartbeat Request (len >> data) - S-->>A: Memory contents leak (keys, session cookies) - A->>S: Follow-on requests using stolen secrets -``` - -*Sequence diagram showing the Heartbleed attack: malformed TLS heartbeat requests cause vulnerable OpenSSL servers to leak memory contents including encryption keys and session data.* - -Why this matters: TLS is only as strong as its implementation. Monitoring and rapid patching for library CVEs are part of infrastructure security. - -## Mutual TLS (mTLS): Two-Way Authentication - -While standard TLS only authenticates the server to the client, **Mutual TLS (mTLS)** requires both parties to authenticate each other using certificates. This provides stronger security for high-trust scenarios and is essential for implementing zero-trust architecture principles. - -**mTLS Use Cases:** -- Microservice communication in zero-trust architectures where no network segment is inherently trusted -- API-to-API authentication between organizations implementing defense-in-depth strategies -- IoT device authentication in distributed systems -- High-security financial and healthcare APIs requiring cryptographic identity verification - -**OpenAPI mTLS Security Definition** - -```yaml {% title="openapi.yaml" %} -components: - securitySchemes: - mtlsAuth: - type: mutualTLS # [!code highlight] - description: "Client certificate authentication for zero-trust architecture" # [!code highlight] - -# Apply mTLS to sensitive internal operations -paths: - /internal/payments: - post: - security: - - mtlsAuth: [] # [!code highlight] - summary: "Process payment (internal service only)" - /public/info: - get: - # No mTLS required for public endpoints # [!code highlight] - summary: "Public information endpoint" -``` - -**mTLS Security Benefits**: -- **Cryptographic authentication**: Both client and server prove identity with certificates -- **Zero-trust architecture**: No implicit trust based on network location -- **Non-repudiation**: Certificate-based proof of communication participants - -**mTLS Nginx Configuration** - -```nginx {% title="nginx-mtls.conf" %} -server { - listen 443 ssl http2; - - # Server certificate (authenticates server to client) - ssl_certificate /path/to/server.crt; # Public certificate for server identity - ssl_certificate_key /path/to/server.key; # Private key (keep secure!) - - # Client certificate verification (authenticates client to server) - ssl_verify_client on; # Require valid client certificates - ssl_client_certificate /path/to/ca.crt; # CA that signed client certificates - - # Pass client certificate details to application - proxy_set_header X-Client-Cert $ssl_client_cert; # Full client certificate - proxy_set_header X-Client-Verify $ssl_client_verify; # Verification status - proxy_set_header X-Client-DN $ssl_client_s_dn; # Client Distinguished Name -} -``` - -**mTLS Flow**: Client presents certificate → Nginx validates against CA → Application receives verified client identity → Both parties authenticated cryptographically - -> **mTLS Best Practice**: Use mTLS for service-to-service communication and regular TLS + [JWT/OAuth2](authentication-authorization-openapi) for client-to-server communication. - -## TLS Monitoring and Troubleshooting - -Choose your monitoring approach based on your infrastructure: - -{% tabs %} - {% tab label="Certificate Monitoring (Prometheus)" %} - -### Certificate Monitoring - -```yaml {% title="prometheus.yml" %} -groups: -- name: tls_alerts - rules: - - alert: TLSCertificateExpiringSoon - expr: probe_ssl_earliest_cert_expiry - time() < 86400 * 30 # [!code highlight] 30-day warning - labels: - severity: warning - annotations: - summary: "TLS certificate expires in less than 30 days" - - - alert: WeakTLSVersion - expr: probe_tls_version_info{version!="TLS 1.3"} == 1 # [!code highlight] TLS version check - labels: - severity: critical - annotations: - summary: "Weak TLS version detected" -``` - -**How certificate monitoring works:** -- **Expiration alerts**: Warns 30 days before certificate expiry to allow renewal time -- **TLS version monitoring**: Detects servers using outdated TLS versions -- **Automated scanning**: Regularly probes endpoints to verify TLS configuration -- **Alert routing**: Sends notifications to security and ops teams for immediate action - -{% /tab %} -{% tab label="Troubleshooting Steps" %} - -### Common TLS Troubleshooting Steps - -**Certificate Issues:** -- Expired certificates — monitor expiry dates and automate renewal -- Certificate chain problems — verify intermediate certificates are included -- Certificate-hostname mismatch — ensure certificate covers all domains used - -**Configuration Issues:** -- Weak cipher suites — disable deprecated algorithms and enable only strong ciphers -- Missing HSTS headers — add Strict-Transport-Security to prevent downgrade attacks -- Mixed content warnings — ensure all resources load over HTTPS - -**Quick Verification Commands:** -```bash -# Test TLS connection and certificate -curl -vI https://api.example.com 2>&1 | grep -E 'SSL|TLS|certificate' - -# Verify certificate chain -openssl s_client -showcerts -connect api.example.com:443 < /dev/null - -# Check certificate expiry -echo | openssl s_client -servername api.example.com -connect api.example.com:443 2>/dev/null | \ -openssl x509 -noout -dates -``` - -**Common issues and solutions:** -- **Certificate chain issues**: Use `openssl s_client -showcerts` to verify intermediate certificates -- **TLS version problems**: Check server configuration restricts to TLS 1.3 only -- **HSTS warnings**: Add `Strict-Transport-Security` header to prevent downgrade attacks - -{% /tab %} -{% /tabs %} - -## Frequently Asked Questions - -### Why can't I use HTTP for internal APIs? -Even internal networks can be compromised. Using HTTPS everywhere (zero-trust approach) protects against insider threats, lateral movement attacks, and accidental data exposure. The performance overhead of [TLS 1.3](#tls-13-the-modern-standard) is minimal with modern hardware and HTTP/2. See [OpenAPI HTTPS enforcement](#enforcing-https-in-your-api-specification) for implementation guidance. - -### How often should I rotate TLS certificates? -Most organizations use certificates with 1-year validity and rotate them every 6-12 months. Automated certificate management tools like Let's Encrypt or cloud provider certificate services can handle this automatically. Implement [certificate monitoring](#tls-monitoring-and-troubleshooting) to track expiration dates. - -### What's the difference between TLS and SSL? -SSL (Secure Sockets Layer) is the predecessor to TLS. SSL versions are deprecated and insecure. When people say "SSL certificate" or "SSL/TLS," they're usually referring to modern TLS. Always use [TLS 1.2 or preferably TLS 1.3](#tls-13-the-modern-standard) as shown in our [configuration examples](#tls-configuration-examples). - -### Should I implement certificate pinning for API clients? -Certificate pinning can improve security by preventing man-in-the-middle attacks, but it adds operational complexity. Consider it for high-security applications, but ensure you have a robust certificate rotation and backup pin management process. - -## Resources and Next Steps - -### Essential Reading -- [IETF RFC 8446](https://tools.ietf.org/html/rfc8446) - TLS 1.3 protocol specification and security requirements -- [NIST SP 800-52 Rev. 2](https://csrc.nist.gov/publications/detail/sp/800-52/rev-2/final) - Official guidelines for secure TLS implementation -- [Mozilla SSL Configuration Generator](https://ssl-config.mozilla.org/) - Generate secure TLS configurations for various platforms - -### Implementation Tools -- [Let's Encrypt](https://letsencrypt.org/) - Free, automated certificate authority for TLS certificates -- [testssl.sh](https://testssl.sh/) - Command-line tool for testing TLS/SSL implementations -- [SSL Labs Server Test](https://www.ssllabs.com/ssltest/) - Online tool for testing TLS configuration - -### Related Security Topics -- [API Input Validation and Injection Prevention](api-input-validation-injection-prevention) - Protect APIs from malicious data -- [Authentication and Authorization with OpenAPI](authentication-authorization-openapi) - Implement secure access control -- [API Rate Limiting and Abuse Prevention](api-rate-limiting-abuse-prevention) - Prevent DoS attacks and brute force attempts -- [API Security by Design: Complete Guide](/learn/security) - Overview of all API security domains \ No newline at end of file +*This article is currently under review and will be available soon. Return to the [API Security Framework and Fundamentals](.) to explore other security topics.* diff --git a/learn/security/authentication-authorization-openapi.md b/learn/security/authentication-authorization-openapi.md index 3fce8928..4e2c5e6b 100644 --- a/learn/security/authentication-authorization-openapi.md +++ b/learn/security/authentication-authorization-openapi.md @@ -8,1206 +8,17 @@ seo: # Authentication and Authorization with OpenAPI ---- - -## Key Takeaways +*This comprehensive guide is coming soon and will cover:* -Authentication and authorization form the foundation of API access control. While often used interchangeably, these concepts serve distinct purposes: authentication verifies *who* the user is, while authorization determines *what* they can do. Modern APIs require both layers to prevent unauthorized access and enforce business rules. +## What You'll Learn -In this guide, we'll explore how to use OpenAPI 3.1 security schemes to define robust access control patterns that integrate seamlessly with automated governance and modern authentication providers. - -**We'll cover how to:** -- [Define authentication methods (JWT, OAuth2, API Keys, mTLS)](#authentication-methods) in OpenAPI specifications -- [Implement advanced authorization patterns](#advanced-authorization-patterns) with granular permissions -- [Enforce security requirements through automated governance](#automated-governance-for-access-control) -- [Configure API gateways from OpenAPI security definitions](#api-gateway-integration) -- [Monitor and troubleshoot authentication and authorization failures](#authentication-and-authorization-monitoring) +- **Authentication Methods**: JWT, OAuth2, API Keys, and Mutual TLS patterns +- **Authorization Strategies**: RBAC, scope-based access, and fine-grained permissions +- **OpenAPI Security Schemes**: Specification-driven access control definitions +- **Token Management**: Validation, expiration, and refresh strategies +- **Real-World Examples**: Implementation patterns with detailed code samples +- **Monitoring & Observability**: Auth failure analysis and security metrics --- -## Quick Start Guide - -Ready to implement authentication and authorization? Start here: - -1. **Choose your authentication method:** Review [Authentication Methods](#authentication-methods) and select JWT Bearer, OAuth2, API Keys, or mTLS based on your needs -2. **Set up governance:** Implement [automated governance rules](#automated-governance-for-access-control) to prevent accidentally public endpoints -3. **Configure your gateway:** Use [API gateway integration](#api-gateway-integration) to automatically enforce your OpenAPI security definitions -4. **Add monitoring:** Set up [authentication and authorization monitoring](#authentication-and-authorization-monitoring) to track security violations -5. **Plan for issues:** Review [troubleshooting common issues](#troubleshooting-common-issues) and implement [best practices](#best-practices-summary) - -**Next Steps:** Now that you have authentication and authorization in place, explore the complete [API Security by Design guide](/learn/security) to learn about other essential security domains like TLS encryption, input validation, and rate limiting. - ---- - -## Understanding Authentication vs Authorization - -The distinction between authentication and authorization is fundamental to API security design. Understanding this difference helps you implement the right controls at the right layers. - -### The Two-Phase Security Process - -```mermaid -sequenceDiagram - participant U as User - participant A as API Gateway - participant Auth as Auth Service - participant API as API Endpoint - - Note over U,API: Authentication Phase - U->>A: 1. Request with credentials - A->>Auth: 2. Verify identity - Auth->>A: 3. Identity confirmed + token - A->>U: 4. Return access token - - Note over U,API: Authorization Phase - U->>A: 5. API request + token - A->>A: 6. Validate token - A->>A: 7. Check permissions/scopes - - alt Authorized - A->>API: 8. Forward request - API->>A: 9. Response - A->>U: 10. Return response - else Unauthorized - A->>U: 11. 403 Forbidden - end -``` - -*Sequence diagram showing the two-phase process: authentication verifies who the user is, while authorization determines what they can do. Both phases are essential for secure API access control.* - -**Authentication (Who are you?):** -- Verifies the identity of the caller -- Typically involves credentials like passwords, API keys, or certificates -- Results in a token or session that proves identity -- Usually happens once per session or token lifetime - -**Authorization (What can you do?):** -- Determines what resources and operations the authenticated user can access -- Based on permissions, roles, scopes, or policies -- Evaluated for each request to protected resources -- Can be fine-grained (specific endpoints) or coarse-grained (broad permissions) - -### Common Authentication Patterns - -**[API Keys](#authentication-methods):** -- Simple, stateless authentication -- Often used for service-to-service communication -- Limited authorization capabilities (typically binary: access or no access) - -**[JWT Bearer Tokens](#authentication-methods):** -- Self-contained tokens with embedded claims -- Support fine-grained authorization through scopes and claims -- Stateless validation (no database lookup required) -- Industry standard for modern APIs - -**[OAuth2 with PKCE](#authentication-methods):** -- Delegated authorization framework -- Supports multiple grant types and client types -- Built-in scope-based authorization -- Recommended for user-facing applications - -## Defining Security Schemes in OpenAPI - -OpenAPI 3.1 provides a robust framework for defining access control through two primary constructs: - -1. **`components.securitySchemes`**: Defines *how* clients can authenticate (JWT Bearer, OAuth2, API Keys) -2. **`security`**: Specifies *that* an endpoint is secured and by which mechanism(s) - -## Authentication Methods - -Choose the authentication method that best fits your use case: - -{% tabs %} - {% tab label="JWT Bearer Token" %} - -### JWT Bearer Token Authentication - -JWT (JSON Web Token) Bearer authentication is the most common pattern for modern APIs. The token contains encoded claims about the user and can be validated without database lookups. - -```yaml {% title="openapi.yaml" %} -components: - securitySchemes: - bearerAuth: - type: http - scheme: bearer # [!code highlight] Standard Bearer token scheme - bearerFormat: JWT # [!code highlight] Specify JWT format - description: "Enter JWT with 'Bearer ' prefix" - -# Apply globally to all operations # [!code highlight] -security: - - bearerAuth: [] # [!code highlight] Require authentication for all endpoints -``` - -**What this configuration does:** - -- **`type: http`** - Uses standard HTTP authentication (as opposed to API keys or OAuth2 flows) -- **`scheme: bearer`** - Specifies Bearer token authentication, where tokens are sent in the `Authorization: Bearer ` header -- **`bearerFormat: JWT`** - Documents that tokens must be valid JWTs (helps with API documentation and client generation) -- **`security: - bearerAuth: []`** - Applies this authentication requirement to all endpoints globally (individual endpoints can override this) - -This approach ensures every API request includes a valid JWT token, preventing anonymous access to protected resources. - -**JWT Token Structure:** -```javascript {% title="JWT Token Anatomy - 3 Parts Separated by Dots" %} -// PART 1: HEADER - Defines how the token is secured // [!code highlight] -{ - "alg": "RS256", // CRITICAL: Use RS256, not HS256 (prevents key confusion attacks) - "typ": "JWT", // Token type declaration (required for JWT processing) - "kid": "key-123" // Key ID helps API find correct public key for verification -} - -// PART 2: PAYLOAD - Contains user identity and permissions (NEVER put secrets here!) // [!code highlight] -{ - // Standard Claims (RFC 7519) - These provide security guarantees - "sub": "user123", // Subject: Who this token represents - "iss": "https://auth.example.com", // Issuer: MUST be HTTPS URL you trust - "aud": ["api.example.com", "admin.example.com"], // Audience: APIs that accept this token - "exp": 1640995200, // Expiration: REQUIRED - limits blast radius if stolen - "nbf": 1640991600, // Not Before: Token invalid before this time - "iat": 1640991600, // Issued At: When token was created - "jti": "unique-token-id", // JWT ID: Unique identifier (helps with revocation) - - // Custom Claims - Your application-specific data - "scopes": ["users:read", "orders:write"], // Permissions: What user can do - "role": "customer", // Role-based access control - "email": "user@example.com", // PII: Consider privacy implications - "premium": true // Feature flags or user attributes -} - -// PART 3: SIGNATURE - Cryptographic proof token wasn't tampered with // [!code highlight] -RSASHA256( - base64UrlEncode(header) + "." + // Header and payload concatenated - base64UrlEncode(payload), - private_key // NEVER expose this key - stay with auth server only! -) - -// Security Notes: // [!code highlight] -// 1. JWT is NOT encrypted - anyone can read header/payload (use JWE if needed) // [!code highlight] -// 2. Signature prevents tampering but doesn't hide content // [!code highlight] -// 3. Short expiration times (15-60 minutes) limit security exposure // [!code highlight] -// 4. Always validate iss, aud, exp claims before trusting token // [!code highlight] -``` - -**Understanding each JWT component:** - -**Header:** -- **`"alg": "RS256"`** - Specifies RSA SHA-256 signature algorithm, which uses public/private key pairs for security. This prevents token tampering since only the authorization server has the private key to sign tokens. -- **`"typ": "JWT"`** - Declares this is a JWT token (helps parsers know how to handle it) - -**Payload (Claims):** -- **`"sub": "user123"`** - Subject claim identifies the user this token represents. Your API uses this to know *who* is making the request. -- **`"iss": "https://auth.example.com"`** - Issuer claim identifies which authorization server created this token. Your API should validate this matches your trusted auth server. -- **`"aud": "api.example.com"`** - Audience claim specifies which API this token is intended for. Prevents token reuse across different services. -- **`"exp": 1640995200"`** - Expiration timestamp (Unix time). Tokens automatically become invalid after this time, limiting damage if compromised. -- **`"iat": 1640991600"`** - Issued at timestamp. Helps with token lifecycle tracking and debugging. -- **`"scopes": ["users:read", "orders:write"]`** - Custom claim listing what permissions this user has. Your authorization logic checks these scopes. - -**Signature:** -- Created by signing the encoded header and payload with the authorization server's private key -- Your API validates signatures using the corresponding public key -- If signature verification fails, the token is invalid (likely tampered with or forged) - -{% /tab %} -{% tab label="OAuth2 with Scopes" %} - -### OAuth2 with Scope-Based Authorization - -OAuth2 provides the most flexible authorization framework, supporting fine-grained permissions through scopes and multiple authentication flows. - -```yaml {% title="openapi.yaml - OAuth2 with Security Best Practices" %} -components: - securitySchemes: - oauth2Auth: - type: oauth2 - # CRITICAL: Always use Authorization Code + PKCE for security - description: "OAuth2 Authorization Code Flow with PKCE - prevents CSRF and injection attacks" - flows: - authorizationCode: - # STEP 1: Authorization URL - where users consent to permissions - authorizationUrl: https://auth.example.com/authorize # [!code highlight] HTTPS REQUIRED - never use HTTP - - # STEP 2: Token endpoint - where your app exchanges codes for tokens - tokenUrl: https://auth.example.com/token # [!code highlight] HTTPS REQUIRED - never use HTTP - - # STEP 3: Define permission scopes using principle of least privilege - scopes: - # User-level permissions (granular access control) - 'users:read': "View user profile information" # [!code focus] Read-only access - 'users:write': "Modify user profile data" # [!code warning] Write access - more sensitive - 'users:delete': "Delete user accounts" # [!code error] High-privilege operation - - # Resource-specific permissions - 'orders:read': "View order history and details" # [!code focus] Customer data access - 'orders:write': "Create and modify orders" # [!code warning] Financial operations - 'orders:refund': "Process order refunds" # [!code error] High-value operations - - # Administrative permissions (highest privilege) - 'admin:users': "Full user management access" # [!code error] Admin-only scope - 'admin:system': "System configuration access" # [!code error] Infrastructure access - -paths: - /users/{userId}: - get: - summary: "Get user profile" - # STEP 4: Require specific permissions for each operation - security: - - oauth2Auth: ['users:read'] # [!code highlight] Minimal required scope - parameters: - - name: userId - in: path - required: true - schema: - type: string - format: uuid # [!code focus] Use UUIDs to prevent enumeration attacks - responses: - '200': - description: "User profile data" - content: - application/json: - schema: - $ref: '#/components/schemas/UserProfile' - '401': # [!code error] No valid token provided - description: "Authentication required - token missing or invalid" - content: - application/json: - schema: - $ref: '#/components/schemas/UnauthorizedError' - '403': # [!code error] Valid token but insufficient permissions - description: "Insufficient permissions - requires users:read scope" - content: - application/json: - schema: - $ref: '#/components/schemas/ForbiddenError' - - patch: - summary: "Update user profile" - security: - - oauth2Auth: ['users:write'] # [!code warning] Higher privilege required - # STEP 5: Document security requirements clearly - description: | - Updates user profile information. Requires 'users:write' scope. - - **Security Notes:** - - Users can only modify their own profiles unless they have admin:users scope - - Sensitive fields like email changes may require additional verification - - All changes are logged for audit purposes - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/UserProfileUpdate' - responses: - '200': - description: "Profile updated successfully" - '401': # [!code error] Authentication failure - description: "Authentication required" - '403': # [!code error] Authorization failure - description: "Insufficient permissions - requires users:write scope" - '422': # [!code warning] Validation errors - description: "Invalid input data" - -# STEP 6: Define common error schemas for consistent security responses -components: - schemas: - UnauthorizedError: - type: object - properties: - error: - type: string - example: "Authentication required" - message: - type: string - example: "Please provide a valid Bearer token" - - ForbiddenError: - type: object - properties: - error: - type: string - example: "Insufficient permissions" - required_scopes: # [!code focus] Help developers understand what's needed - type: array - items: - type: string - example: ["users:write"] -``` - -**Breaking down this OAuth2 configuration:** - -**Security Scheme Definition:** -- **`type: oauth2`** - Declares this uses the OAuth2 standard for authorization -- **`authorizationCode`** flow - The most secure OAuth2 flow for web applications, involves redirecting users to the authorization server -- **`authorizationUrl`** - Where users go to grant permissions (must use HTTPS for security) -- **`tokenUrl`** - Where your app exchanges authorization codes for access tokens (must use HTTPS) - -**Scope-Based Permissions:** -- **`'users:read'`** - Allows reading user profile data but not modifying it -- **`'users:write'`** - Allows updating user profiles (typically granted to users for their own profiles) -- **`'orders:read'` & `'orders:write'`** - Separate permissions for order management -- **`'admin:users'`** - Administrative permission that overrides user-level restrictions - -**Endpoint-Level Authorization:** -- **`security: - oauth2Auth: ['users:read']`** - This endpoint requires a valid OAuth2 token with the `users:read` scope -- **Different endpoints require different scopes** - GET operations typically need `read` scopes, while PATCH/POST/DELETE need `write` scopes -- **Response codes `401` vs `403`**: - - `401` = No valid token provided (authentication problem) - - `403` = Valid token but insufficient permissions (authorization problem) - -This pattern allows fine-grained control: a user might have permission to read profiles but not edit them, while administrators have broader access. - -{% /tab %} -{% tab label="API Key" %} - -### API Key Authentication - -For service-to-service communication and simpler use cases, API keys provide straightforward authentication. - -```yaml {% title="openapi.yaml" %} -components: - securitySchemes: - apiKeyAuth: - type: apiKey - in: header # [!code highlight] Header-based API key (preferred) - name: X-API-Key # [!code highlight] Custom header name - description: "API key for service authentication" - -paths: - /internal/health: - get: - summary: "Internal health check" - security: - - apiKeyAuth: [] # [!code highlight] Require API key authentication - responses: - '200': - description: "Service health status" - '401': - description: "Invalid or missing API key" -``` - -**API Key configuration explained:** - -- **`type: apiKey`** - Declares this uses simple API key authentication (as opposed to OAuth2 or JWT) -- **`in: header`** - API key is sent in HTTP headers (more secure than query parameters, which get logged) -- **`name: X-API-Key`** - Specifies the exact header name clients must use: `X-API-Key: your-secret-key-here` -- **`security: - apiKeyAuth: []`** - Requires a valid API key for this endpoint - -**When to use API keys:** -- **Service-to-service communication** - When your API calls another internal service -- **Simple integrations** - Third-party services that don't need complex user permissions -- **Internal tools** - Admin dashboards or monitoring systems - -**Security considerations:** -- API keys identify the *application*, not the *user* (unlike JWT tokens) -- Keys should be long, random strings (at least 32 characters) -- Store keys securely and rotate them regularly -- Never include API keys in client-side code or URLs - -{% /tab %} -{% tab label="Mutual TLS (mTLS)" %} - -### Mutual TLS (mTLS) for Service Authentication - -For high-security environments and service-to-service communication, [mutual TLS](api-tls-encryption-https-best-practices#mutual-tls-mtls-two-way-authentication) provides cryptographic identity verification. - -```yaml {% title="openapi.yaml" %} -components: - securitySchemes: - mtlsAuth: - type: mutualTLS # [!code highlight] Cryptographic client authentication - description: "Client certificate authentication" - -paths: - /internal/payments: - post: - security: - - mtlsAuth: [] # [!code highlight] Requires valid client certificate - summary: "Process payment (internal service only)" - responses: - '200': - description: "Payment processed" - '401': # [!code highlight] Certificate validation failure - description: "Invalid client certificate" -``` - -**mTLS configuration explained:** - -- **`type: mutualTLS`** - Requires both server and client to present valid certificates -- **Cryptographic authentication** - More secure than API keys since certificates are harder to forge -- **Best for internal services** - High-security service-to-service communication -- **Zero-trust architecture** - No implicit trust based on network location - -{% /tab %} -{% /tabs %} - -## Automated Governance for Access Control - -One of the most common API vulnerabilities is the accidentally public endpoint—an operation that should require authentication but doesn't have security requirements defined. Automated governance prevents this by enforcing security rules during development. - -### Security Governance Rules - -**Mandatory Authentication on Write Operations:** -```yaml {% title="governance-rules.yaml" %} -rules: - require-auth-on-mutations: - description: "All write operations must have security requirements" - severity: error - given: "$.paths[*][*]" - when: - function: enumerated - functionOptions: - values: ["post", "put", "patch", "delete"] - then: - field: "security" - function: truthy -``` - -**Validate Security Scheme Definitions:** -```yaml {% title="governance-rules.yaml" %} -rules: - security-schemes-defined: - description: "All security references must have corresponding definitions" - severity: error - given: "$.paths[*][*].security[*]" - then: - function: defined-security-scheme -``` - -When these rules run in your CI/CD pipeline, any endpoint without proper security definitions causes the build to fail, preventing accidentally public endpoints from reaching production. - -### Implementation Example - -**Before Governance (Vulnerable):** -```yaml -paths: - /users/{userId}: - delete: - summary: "Delete user account" - # Missing security requirement - accidentally public! - responses: - '204': - description: "User deleted" -``` - -**After Governance (Secure):** -```yaml -paths: - /users/{userId}: - delete: - summary: "Delete user account" - security: - - oauth2Auth: ['admin:users'] # Required by governance rules - responses: - '204': - description: "User deleted" - '401': - description: "Authentication required" - '403': - description: "Insufficient permissions" -``` - -**Next steps:** Once you've implemented automated governance, consider setting up [comprehensive monitoring](#authentication-and-authorization-monitoring) to track security violations and [troubleshooting processes](#troubleshooting-common-issues) to handle authentication failures effectively. - -## Security Definitions as Configuration - -Defining security schemes in OpenAPI extends beyond documentation—it establishes configuration-as-code that drives consistency across your entire API ecosystem: - -### API Gateway Integration - -Modern API gateways can import OpenAPI specifications and automatically configure authentication and authorization based on your security definitions. - -**Kong Gateway Configuration:** -```yaml {% title="kong.yaml" %} -# Generated from OpenAPI securitySchemes -plugins: -- name: jwt - config: - key_claim_name: iss - secret_is_base64: false - claims_to_verify: - - exp - - iat - run_on_preflight: false - -# Generated from OAuth2 scopes -- name: openapi-validator - config: - validate_request_body: true - validate_response_body: false - api_spec: "/path/to/openapi.yaml" -``` - -**AWS API Gateway Integration:** -```yaml {% title="serverless.yml" %} -functions: - getUserProfile: - handler: users.getProfile - events: - - http: - path: users/{userId} - method: get - # Generated from OpenAPI security requirements - authorizer: - name: jwtAuthorizer - scopes: - - users:read -``` - -### Code Generation - -OpenAPI security schemes enable automated generation of authentication handling in client SDKs and server stubs. - -**Generated Client SDK (TypeScript):** -```typescript -// Auto-generated from OpenAPI security schemes -class APIClient { - private bearerToken?: string; - - setBearerToken(token: string) { - this.bearerToken = token; - } - - async getUserProfile(userId: string): Promise { - const headers: Record = {}; - - // Auto-added based on security requirements - if (this.bearerToken) { - headers['Authorization'] = `Bearer ${this.bearerToken}`; - } - - const response = await fetch(`/users/${userId}`, { headers }); - - if (response.status === 401) { - throw new AuthenticationError('Bearer token required'); - } - - if (response.status === 403) { - throw new AuthorizationError('Insufficient permissions'); - } - - return response.json(); - } -} -``` - -**Development workflow:** Generated client SDKs like the one above help catch authentication issues early. When problems occur in production, use [monitoring](#authentication-and-authorization-monitoring) and [troubleshooting](#troubleshooting-common-issues) to diagnose and resolve issues quickly. - -## Advanced Authorization Patterns - -Choose the authorization pattern that fits your application's complexity: - -{% tabs %} - {% tab label="Role-Based Access Control (RBAC)" %} - -### Role-Based Access Control (RBAC) - -While OpenAPI doesn't have built-in RBAC support, you can model roles through scopes or custom extensions. - -```yaml {% title="openapi.yaml" %} -components: - securitySchemes: - oauth2Auth: - type: oauth2 - flows: - authorizationCode: - authorizationUrl: https://auth.example.com/authorize # [!code highlight] HTTPS required - tokenUrl: https://auth.example.com/token # [!code highlight] HTTPS required - scopes: - # Role-based scopes # [!code highlight] - 'role:admin': "Administrative access to all resources" # [!code highlight] Admin role - 'role:manager': "Management access within assigned teams" # [!code highlight] Manager role - 'role:user': "Standard user access to own resources" # [!code highlight] User role - - # Resource-based scopes # [!code highlight] - 'users:read': "Read user profiles" - 'users:write': "Modify user profiles" - 'orders:read': "View orders" - 'orders:write': "Create and modify orders" - -paths: - /admin/users: - get: - summary: "List all users (admin only)" - security: - - oauth2Auth: ['role:admin'] # [!code highlight] Admin-only endpoint - responses: - '200': - description: "List of all users" - '403': # [!code highlight] Authorization failure - description: "Admin access required" - - /users/me: - get: - summary: "Get own profile" - security: - - oauth2Auth: ['role:user', 'users:read'] # [!code highlight] Multiple scope requirement - responses: - '200': - description: "User's own profile" -``` - -{% /tab %} -{% tab label="Context-Dependent Authorization" %} - -### Context-Dependent Authorization - -Some authorization decisions depend on request context, such as resource ownership or dynamic policies. - -```yaml {% title="openapi.yaml" %} -paths: - /users/{userId}/orders: - get: - summary: "Get user's orders" - security: - - oauth2Auth: ['orders:read'] # [!code highlight] Base permission required - parameters: - - name: userId - in: path - required: true - schema: - type: string # [!code highlight] User ID parameter - responses: - '200': - description: "User's order history" - '403': # [!code highlight] Resource ownership check - description: "Can only access own orders unless admin" - # Custom extension for context-dependent rules # [!code highlight] - x-authorization-context: - resource-owner-check: true # [!code highlight] Check resource ownership - admin-override: true # [!code highlight] Admin can bypass ownership -``` - -{% /tab %} -{% tab label="Fine-Grained Permissions" %} - -### Fine-Grained Permissions - -For complex applications, you might need very specific permissions that combine multiple factors. - -```yaml {% title="openapi.yaml" %} -components: - securitySchemes: - oauth2Auth: - type: oauth2 - flows: - authorizationCode: - authorizationUrl: https://auth.example.com/authorize # [!code highlight] HTTPS required - tokenUrl: https://auth.example.com/token # [!code highlight] HTTPS required - scopes: - # Operation + Resource + Condition # [!code highlight] Fine-grained permissions - 'orders:read:own': "Read own orders" # [!code highlight] Own resources only - 'orders:read:team': "Read team orders" # [!code highlight] Team scope - 'orders:read:all': "Read all orders" # [!code highlight] Global read access - 'orders:write:own': "Modify own orders" # [!code highlight] Own resources only - 'orders:write:team': "Modify team orders" # [!code highlight] Team write access - 'orders:cancel:all': "Cancel any order" # [!code highlight] Admin-level permission - -paths: - /orders/{orderId}: - patch: - summary: "Update order" - security: - - oauth2Auth: ['orders:write:own', 'orders:write:team'] # [!code highlight] Multiple scope options - responses: - '200': - description: "Order updated" - '403': # [!code highlight] Authorization failure - description: "Insufficient permissions to update order" -``` - -{% /tab %} -{% /tabs %} - -**Implementation tip:** Complex authorization patterns require robust [monitoring and troubleshooting](#troubleshooting-common-issues). The patterns above should be complemented with comprehensive logging and [best practices](#best-practices-summary) for production deployment. - -## Authentication and Authorization Monitoring - -Choose your monitoring approach based on your technology stack: - -{% tabs %} - {% tab label="Authentication Monitoring (JS)" %} - -### Token Validation Metrics - -Monitor authentication success and failure patterns to detect potential attacks and system issues. - -```javascript -// Express.js middleware for auth monitoring -const authMetrics = { - successful_auths: 0, - failed_auths: 0, - expired_tokens: 0, - invalid_signatures: 0 -}; - -app.use('/api', (req, res, next) => { - const token = req.headers.authorization?.replace('Bearer ', ''); // [!code highlight] Extract Bearer token - - if (!token) { - authMetrics.failed_auths++; // [!code highlight] Track failed attempts - return res.status(401).json({ error: 'Bearer token required' }); - } - - try { - const decoded = jwt.verify(token, publicKey, { // [!code highlight] Verify with public key - algorithms: ['RS256'], // [!code highlight] Only allow RS256 algorithm - audience: 'api.example.com', // [!code highlight] Verify intended audience - issuer: 'https://auth.example.com' // [!code highlight] Verify trusted issuer - }); - - // Check token expiration // [!code highlight] - if (decoded.exp < Date.now() / 1000) { - authMetrics.expired_tokens++; // [!code highlight] Track expired tokens - return res.status(401).json({ error: 'Token expired' }); - } - - authMetrics.successful_auths++; // [!code highlight] Track successful auths - req.user = decoded; // [!code highlight] Attach user to request - next(); - - } catch (error) { - if (error.name === 'JsonWebTokenError') { - authMetrics.invalid_signatures++; // [!code error] Track signature failures - } else { - authMetrics.failed_auths++; // [!code error] Track other failures - } - - return res.status(401).json({ error: 'Invalid token' }); - } -}); -``` - -**How this authentication monitoring works:** - -**Token Extraction:** -- **`req.headers.authorization?.replace('Bearer ', '')`** - Safely extracts the JWT token from the `Authorization: Bearer ` header -- The `?` optional chaining prevents errors if the header is missing - -**Token Validation Process:** -1. **`jwt.verify(token, publicKey, {...})`** - Uses the public key to verify the token signature wasn't tampered with -2. **`algorithms: ['RS256']`** - Only accepts RSA SHA-256 signatures (prevents algorithm confusion attacks) -3. **`audience` & `issuer` validation** - Ensures the token is intended for your API and came from your trusted auth server -4. **Expiration check** - Even if signature is valid, reject tokens past their expiration time - -**Security Metrics Collection:** -- **`successful_auths`** - Count of valid authentications (helps with usage analytics) -- **`failed_auths`** - Missing or invalid tokens (spikes might indicate attacks) -- **`expired_tokens`** - Tokens past expiration (helps tune token lifetimes) -- **`invalid_signatures`** - Tampered or forged tokens (critical security indicator) - -**What to watch for:** -- **High `invalid_signatures`** - Possible token forgery attempts -- **Many `expired_tokens`** - Token lifetimes might be too short, causing poor user experience -- **Sudden spikes in `failed_auths`** - Potential brute force or credential stuffing attacks - -{% /tab %} -{% tab label="Authorization Monitoring (JavaScript)" %} - -### Authorization Failure Analysis - -Track authorization failures to identify potential privilege escalation attempts or misconfigured permissions. - -```javascript -// Express.js middleware for authorization monitoring -class AuthorizationMonitor { - constructor() { - this.permissionDenials = new Map(); // [!code highlight] Track denied requests - this.scopeViolations = new Map(); // [!code highlight] Track scope failures - } - - checkScopes(requiredScopes, userScopes, endpoint) { - const requiredSet = new Set(requiredScopes); - const userSet = new Set(userScopes); - const missingScopes = [...requiredSet].filter(scope => !userSet.has(scope)); // [!code highlight] Compare scopes - - if (missingScopes.length > 0) { - // Initialize counters if endpoint is new - if (!this.scopeViolations.has(endpoint)) { - this.scopeViolations.set(endpoint, 0); - } - - this.scopeViolations.set(endpoint, this.scopeViolations.get(endpoint) + 1); // [!code error] Track security violation - - console.warn(`Scope violation at ${endpoint}`, { // [!code error] Log security event - requiredScopes, - userScopes, - missingScopes, - userId: 'unknown' // Would typically come from req.user - }); - - return false; // [!code error] Deny access - } - - return true; // [!code highlight] Allow access - } - - getViolationReport() { - return { - permissionDenials: Object.fromEntries(this.permissionDenials), - scopeViolations: Object.fromEntries(this.scopeViolations) // [!code highlight] Security metrics - }; - } -} - -// Express.js middleware usage example -const authMonitor = new AuthorizationMonitor(); - -function requireScopes(requiredScopes) { - return (req, res, next) => { - const userScopes = req.user?.scopes || []; - const endpoint = req.route.path; - - if (authMonitor.checkScopes(requiredScopes, userScopes, endpoint)) { - next(); // User has required scopes - } else { - res.status(403).json({ - error: 'Insufficient permissions', - required_scopes: requiredScopes - }); - } - }; -} -``` - -**How this authorization monitoring works:** - -**Scope-Based Authorization:** -- **`[...requiredSet].filter(scope => !userSet.has(scope))`** - Uses array filter to find missing permissions (e.g., endpoint needs `['orders:write']` but user only has `['orders:read']`) -- **`missingScopes`** - If this array has length > 0, the user lacks required permissions - -**Security Tracking:** -- **`permissionDenials`** - Counts authorization failures per endpoint (helps identify which resources are most targeted) -- **`scopeViolations`** - Tracks specific permission mismatches (helps identify privilege escalation attempts) -- **`new Map()`** - Provides efficient key-value storage for endpoint counters - -**Structured Logging:** -- **`console.warn()`** - Records security events with structured data for analysis -- **Object context** - Includes metadata like: - - Which scopes were required vs. provided - - Which specific permissions were missing - - User ID for tracking repeat offenders - - Endpoint being accessed - -**Security Analysis:** -- **High violation counts on specific endpoints** - May indicate targeted attacks -- **Users repeatedly failing scope checks** - Possible compromised accounts or privilege escalation attempts -- **Missing scopes patterns** - Could reveal permission misconfiguration (e.g., users consistently missing `read` permissions might indicate overly restrictive defaults) - -This monitoring helps distinguish between legitimate access denials (user simply doesn't have permission) and suspicious activity (repeated attempts to access unauthorized resources). - -{% /tab %} -{% /tabs %} - -### Security Event Logging - -Implement comprehensive logging for security events to support incident response and compliance requirements. - -```yaml {% title="logging-config.yaml" %} -# Structured logging for security events -security_events: - authentication_success: - level: INFO - fields: [user_id, client_ip, user_agent, timestamp] - - authentication_failure: - level: WARN - fields: [client_ip, user_agent, failure_reason, timestamp] - - authorization_failure: - level: WARN - fields: [user_id, endpoint, required_scopes, user_scopes, timestamp] - - token_expiration: - level: INFO - fields: [user_id, token_issued_at, token_expired_at, timestamp] -``` - -**Security operations:** When monitoring detects issues, use the structured logs above with the [troubleshooting guide below](#troubleshooting-common-issues) to quickly diagnose and resolve authentication and authorization problems. - -## Troubleshooting Common Issues - -### Authentication Problems - -{% tabs %} -{% tab label="Missing or Invalid Bearer Token" %} - -**Error occurs when:** Client sends request without Bearer token or provides malformed token. - -```bash {% title="Testing Unauthenticated Access" %} -# Test unauthenticated access (should fail with 401) -curl -i https://api.example.com/users/me - -# Expected response: -# HTTP/1.1 401 Unauthorized -# Content-Type: application/json -# {"error": "Bearer token required"} -``` - -**Common causes:** -- Client forgot to include `Authorization` header -- Malformed header format (missing "Bearer " prefix) -- Empty or null token value -- Token contains invalid characters - -**How to fix:** -- Ensure clients include the header: `Authorization: Bearer ` -- Validate token format before sending requests -- Check your authentication middleware configuration - -{% /tab %} -{% tab label="Invalid Token Signature" %} - -**Error occurs when:** JWT token's signature doesn't match expected signature, indicating tampering or wrong issuer. - -```bash {% title="Testing Invalid Token Signature" %} -# Test with invalid token (should fail with 401) -curl -H "Authorization: Bearer invalid_token" \ - https://api.example.com/users/me - -# Expected response: -# HTTP/1.1 401 Unauthorized -# {"error": "Invalid token signature"} -``` - -**Common causes:** -- Token was manually modified or corrupted -- Wrong signing key used to verify the token -- Token was issued by a different authorization server -- Key rotation issues (old key used to verify new token) - -**How to fix:** -- Verify your JWT signing key configuration -- Check key rotation procedures -- Ensure tokens are only issued by trusted authorization servers -- Never modify JWT tokens after they're created - -{% /tab %} -{% tab label="Expired Token" %} - -**Error occurs when:** JWT token has passed its expiration time (`exp` claim), which is a security best practice. - -```bash {% title="Testing Expired Token" %} -# Test with expired token -curl -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9..." \ - https://api.example.com/users/me - -# Expected response: -# HTTP/1.1 401 Unauthorized -# {"error": "Token expired"} -``` - -**Common causes:** -- Token has passed its `exp` (expiration) time -- Client cached an old token without refreshing -- Token lifetime is too short for your use case -- Time synchronization issues between servers - -**How to fix:** -- Implement token refresh logic in your clients -- Use refresh tokens to obtain new access tokens -- Adjust token lifetime based on security vs. usability needs -- Ensure server clocks are synchronized (use NTP) -- Clear expired tokens from client storage - -{% /tab %} -{% /tabs %} - -### Authorization Problems - -{% tabs %} -{% tab label="Insufficient Scopes" %} - -**Problem:** User has valid token but lacks required permissions/scopes for the operation. - -```bash {% title="Testing Scope Enforcement" %} -# Test scope enforcement (readonly token trying to write) -curl -H "Authorization: Bearer readonly_token" \ - -X POST \ - -H "Content-Type: application/json" \ - -d '{"name": "test"}' \ - https://api.example.com/users - -# Expected response: -# HTTP/1.1 403 Forbidden -# {"error": "Insufficient permissions", "required_scopes": ["users:write"]} -``` - -**Common causes:** -- Token has read-only scopes but endpoint requires write access -- User role doesn't include necessary permissions -- Scope names don't match between token and OpenAPI spec -- Token was issued for different resource/service - -**How to fix:** -- Check required scopes in your OpenAPI security definitions -- Verify user has been granted appropriate permissions -- Ensure scope names are consistent across auth server and API -- Request tokens with broader scopes if user is authorized - -{% /tab %} -{% tab label="Missing Security Requirements" %} - -**Problem:** OpenAPI specification doesn't specify security requirements for sensitive endpoints. - -```yaml {% title="Common OpenAPI Security Bug" %} -# Common issue: forgetting security on sensitive endpoints -paths: - /admin/users: - delete: - summary: "Delete all users" - # BUG: Missing security requirement! # [!code error] - # security: - # - oauth2Auth: ['admin:users'] - responses: - '204': - description: "All users deleted" -``` - -**Common causes:** -- Developer forgot to add `security:` property to endpoint -- Copy-pasted endpoint from public API without adding security -- Global security was removed but individual endpoints not updated -- New endpoints added without security review - -**How to fix:** -- Add explicit security requirements to all protected endpoints -- Use linting rules to catch missing security definitions -- Implement code review processes for new endpoints -- Consider setting global security as default with explicit overrides - -{% /tab %} -{% tab label="Configuration Mismatches" %} - -**Problem:** API gateway configuration doesn't match OpenAPI security specifications. - -```bash {% title="Testing Gateway Configuration Sync" %} -# Verify gateway is enforcing the same rules as OpenAPI spec -curl -H "Authorization: Bearer user_token" \ - -X DELETE \ - https://api.example.com/admin/users - -# If this succeeds when it should fail, gateway config is out of sync -``` - -**Common causes:** -- Gateway config was updated manually but not synced with OpenAPI -- Deployment pipeline doesn't update gateway from OpenAPI spec -- Multiple versions of API spec with different security requirements -- Gateway caching old configuration after spec changes - -**How to fix:** -- Automate gateway configuration from OpenAPI specifications -- Implement configuration drift detection between spec and gateway -- Use infrastructure-as-code to manage gateway settings -- Test security enforcement as part of deployment pipeline -- Clear gateway cache after specification updates - -{% /tab %} -{% /tabs %} - -### Debugging Checklist - -1. **Verify token format and claims:** - ```bash - # Decode JWT to inspect claims (don't use in production) - echo "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9..." | base64 -d - ``` - -2. **Check security scheme definitions:** - ```yaml - # Ensure all referenced security schemes are defined - components: - securitySchemes: - oauth2Auth: # Must match security references - type: oauth2 - # ... configuration - ``` - -3. **Validate scope requirements:** - ```yaml - # Ensure required scopes exist in security scheme - security: - - oauth2Auth: ['users:write'] # Must be defined in scopes - ``` - -4. **Test authentication flow:** - ```bash - # Full OAuth2 flow test - # 1. Get authorization code - open "https://auth.example.com/authorize?response_type=code&client_id=..." - - # 2. Exchange code for token - curl -X POST https://auth.example.com/token \ - -d "grant_type=authorization_code&code=..." - - # 3. Use token for API access - curl -H "Authorization: Bearer access_token" \ - https://api.example.com/users/me - ``` - -## Best Practices Summary - -### Security Scheme Design -- Use JWT Bearer tokens for stateless authentication -- Implement OAuth2 with PKCE for user-facing applications -- Define granular scopes that map to business operations -- Use mTLS for high-trust service-to-service communication - -### Governance and Automation -- Require security definitions on all write operations -- Validate that all security references have corresponding definitions -- Fail builds when security requirements are missing -- Generate gateway configurations from OpenAPI security schemes - -### Monitoring and Observability -- Track authentication success/failure rates -- Monitor authorization violations by endpoint -- Log security events with sufficient context for incident response -- Set up alerts for unusual authentication patterns - -### Implementation -- Generate client SDKs with built-in authentication handling -- Use OpenAPI security schemes to configure API gateways -- Implement proper error responses (401 vs 403) -- Test authentication and authorization scenarios in CI/CD - -## Frequently Asked Questions - -### What's the difference between authentication and authorization? -Authentication verifies *who* the user is (like checking an ID card), while authorization determines *what* they can do (like checking permissions). Authentication happens first and provides identity, while authorization uses that identity to make access decisions for each request. - -### Should I use JWT or OAuth2 for my API? -JWT is a token format, while OAuth2 is an authorization framework. They work together: OAuth2 defines how to obtain tokens, and JWT defines the token format. Use OAuth2 with JWT tokens for user-facing applications, and consider simpler JWT Bearer authentication for service-to-service communication. See [Authentication Methods](#authentication-methods) for detailed implementation examples. - -### How do I implement fine-grained permissions with OpenAPI? -Use OAuth2 scopes to define specific permissions like `users:read`, `orders:write`, or `admin:users`. You can also model roles through scopes (e.g., `role:admin`) or use [advanced authorization patterns](#advanced-authorization-patterns) for complex authorization logic that depends on request context. - -### What happens if I forget to add security requirements to an endpoint? -The endpoint becomes accidentally public, which is one of the most common API vulnerabilities. [Automated governance rules](#automated-governance-for-access-control) can prevent this by failing builds when write operations (POST, PUT, PATCH, DELETE) don't have security requirements defined. - -### How do I handle authorization that depends on resource ownership? -OpenAPI security schemes handle authentication and basic authorization (scopes/roles), but context-dependent authorization (like "users can only access their own resources") typically requires custom logic in your application. See [Advanced Authorization Patterns](#advanced-authorization-patterns) for examples of documenting these requirements using custom extensions like `x-authorization-context`. - -## Resources - -### Standards and Specifications -- [OpenAPI Security Schemes](https://spec.openapis.org/oas/v3.1.0#security-scheme-object) - Official specification for defining authentication and authorization -- [JWT RFC 7519](https://tools.ietf.org/html/rfc7519) - JSON Web Token standard for secure information transmission -- [OAuth2 RFC 6749](https://tools.ietf.org/html/rfc6749) - Authorization framework for delegated access -- [OAuth2 PKCE RFC 7636](https://tools.ietf.org/html/rfc7636) - Proof Key for Code Exchange extension for public clients - -### Implementation Tools -- [Auth0](https://auth0.com/) - Managed authentication and authorization platform with OpenAPI integration -- [Keycloak](https://www.keycloak.org/) - Open-source identity and access management with OAuth2/JWT support -- [Kong](https://konghq.com/) - API gateway with native OpenAPI security scheme support -- [AWS API Gateway](https://aws.amazon.com/api-gateway/) - Managed API gateway with built-in authentication and authorization - -### Security Best Practices -- [OWASP API Security Top 10](https://owasp.org/www-project-api-security/) - Including API1:2023 (Broken Object Level Authorization) and API2:2023 (Broken Authentication) -- [NIST Digital Identity Guidelines](https://pages.nist.gov/800-63-3/) - Comprehensive guidance on authentication and identity verification -- [OAuth2 Security Best Practices](https://tools.ietf.org/html/draft-ietf-oauth-security-topics) - Latest security recommendations for OAuth2 implementations - -### Related Security Topics -- [API TLS Encryption and HTTPS Best Practices](api-tls-encryption-https-best-practices) - Secure data in transit with mTLS -- [API Input Validation and Injection Prevention](api-input-validation-injection-prevention) - Protect APIs from malicious data -- [API Rate Limiting and Abuse Prevention](api-rate-limiting-abuse-prevention) - Prevent brute force attacks on auth endpoints -- [API Security by Design: Complete Guide](/learn/security) - Overview of all API security domains \ No newline at end of file +*This article is currently under review and will be available soon. Return to the [API Security Framework and Fundamentals](.) to explore other security topics.* From f7ad61f2dc02bffa7cd94c5d9d1e0deae769d8a5 Mon Sep 17 00:00:00 2001 From: Matt Williams Date: Tue, 30 Sep 2025 11:37:58 -0500 Subject: [PATCH 15/27] Add Authentication and Authorization with OpenAPI article - Comprehensive guide with JWT, OAuth2, API Key, and mTLS patterns - Role-Based Access Control (RBAC) implementation strategies - OpenAPI security scheme definitions and validation - Context-dependent authorization examples - Token management and validation patterns - Node.js implementation examples with detailed explanations - Tabbed organization for different auth methods - Quick Start Guide and internal linking structure --- ...i-input-validation-injection-prevention.md | 618 --------------- .../api-rate-limiting-abuse-prevention.md | 726 ------------------ ...api-tls-encryption-https-best-practices.md | 445 ----------- 3 files changed, 1789 deletions(-) delete mode 100644 learn/security/api-input-validation-injection-prevention.md delete mode 100644 learn/security/api-rate-limiting-abuse-prevention.md delete mode 100644 learn/security/api-tls-encryption-https-best-practices.md diff --git a/learn/security/api-input-validation-injection-prevention.md b/learn/security/api-input-validation-injection-prevention.md deleted file mode 100644 index 52a5f9aa..00000000 --- a/learn/security/api-input-validation-injection-prevention.md +++ /dev/null @@ -1,618 +0,0 @@ ---- -title: Input Validation and Injection Prevention -description: Prevent API injection attacks and mass assignment vulnerabilities using OpenAPI schema validation and automated governance. -seo: - title: Input Validation and Injection Prevention - description: Prevent API injection attacks and mass assignment vulnerabilities using OpenAPI schema validation and automated governance. ---- - -# Input Validation and Injection Prevention with OpenAPI - ---- - -## Key Takeaways - -APIs are designed to accept data as input. However, an API should never blindly trust the data it receives from a client. The process of rigorously checking all incoming data is called data validation. - -**In this guide, you'll learn:** -- [How to implement schema-based validation](#schema-based-validation-as-security-contract) as a security contract -- [JSON Schema security constraints and validation patterns](#key-security-constraints) -- [Attack prevention techniques](#attack-prevention-strategies) for SQL injection, OGNL injection, and mass assignment -- [Real-world lessons from the Equifax breach](#attack-example-equifax-ognl-injection-via-apache-struts-2017) -- [Automated validation governance and linting rules](#automated-governance-for-validation) -- [Input validation monitoring and troubleshooting](#input-validation-monitoring) - ---- - -## Quick Start Guide - -Ready to implement secure input validation? Follow these steps: - -1. **Define validation rules:** Start with [schema-based validation](#schema-based-validation-as-security-contract) to create security contracts in your OpenAPI specifications -2. **Implement attack prevention:** Set up [SQL injection and mass assignment protection](#attack-prevention-strategies) using parameterized queries and `additionalProperties: false` -3. **Add governance rules:** Configure [automated governance](#automated-governance-for-validation) to prevent accidentally unvalidated endpoints -4. **Set up monitoring:** Implement [validation monitoring](#input-validation-monitoring) to detect attack attempts and track security metrics -5. **Handle edge cases:** Use [advanced validation techniques](#advanced-validation-techniques) for custom formats and contextual rules - -**Next Steps:** Now that you have input validation covered, learn about [API Rate Limiting and Abuse Prevention](api-rate-limiting-abuse-prevention) to protect your APIs from denial-of-service attacks and business logic abuse. - ---- - -## The Restaurant Waiter Principle - -> **The Restaurant Waiter**: The API is the waiter, and its documentation (or schema) is the menu. The menu explicitly states what can be ordered and in what format (e.g., "Steak - medium rare"). If a customer tries to order something not on the menu, like "a bicycle," or provides an invalid option, like "a million steaks," a competent waiter will immediately reject the order at the table before it ever reaches the kitchen. This is data validation. - -## Technical Implementation of Data Validation - -In technical terms, data validation is the practice of checking all incoming data from a client to ensure it conforms to the expected format, type, range, and other constraints before it is processed by the application's business logic. - -For example, if an API endpoint expects a user's age, validation rules should ensure the input is an integer and falls within a reasonable range (e.g., 0-130). - -Proper data validation is a critical defense against a wide range of attacks, notably **Injection flaws**. An injection attack occurs when a malicious actor sends executable code disguised as data. - -If the API fails to validate the input and passes it directly to a database or the operating system, that malicious code could be executed. By strictly validating that all inputs are what they are supposed to be, an API can reject malicious payloads before they can do any harm. - -## Attack Prevention Strategies - -Choose the appropriate prevention strategy based on the attack vector you're protecting against: - -{% tabs %} - {% tab label="SQL Injection Prevention" %} - -### SQL Injection Prevention - -For interactions with a database, the gold standard for preventing SQL injection attacks is the use of parameterized queries, also known as prepared statements. - -A parameterized query forces a separation between the SQL command (the code) and the user-supplied data, making it impossible for an attacker to alter the logic of the query. - -**Before vs After: Preventing SQL Injection** - -```javascript {% title="Secure Database Query Implementation" %} -// Step 1: Receive user input from request (potentially malicious) -const userId = req.query.user_id; // Could contain: "1; DROP TABLE users;--" - -// VULNERABLE APPROACH - NEVER DO THIS # [!code error] -// Problem: Direct string interpolation allows malicious code injection -const vulnerableQuery = `SELECT * FROM users WHERE id = ${userId}`; // Creates: SELECT * FROM users WHERE id = 1; DROP TABLE users;-- -// The database sees this as TWO commands: a SELECT and a DROP TABLE -const vulnerableResult = await db.query(vulnerableQuery); // Executes both commands - deletes entire table! - -// SECURE APPROACH - ALWAYS USE PARAMETERIZED QUERIES # [!code highlight] -// Solution: SQL structure and data are separated at database level -const secureQuery = "SELECT * FROM users WHERE id = $1"; // SQL structure defined first -const secureResult = await db.query(secureQuery, [userId]); // Data bound separately as parameter - -// Why this works: # [!code highlight] -// - Database parses SQL structure before receiving user data # [!code highlight] -// - User input is treated as literal data, never as executable code # [!code highlight] -// - Even "1; DROP TABLE users;--" becomes a harmless literal string value # [!code highlight] - -// Full Express.js route example: -app.get('/users/:id', async (req, res) => { - try { - const userId = req.params.id; - const result = await db.query('SELECT * FROM users WHERE id = $1', [userId]); - res.json(result.rows[0] || { error: 'User not found' }); - } catch (error) { - console.error('Database error:', error); - res.status(500).json({ error: 'Internal server error' }); - } -}); -``` - -**How SQL injection prevention works:** -- **Parameterized queries**: The SQL structure is defined separately from user data -- **Data binding**: User input is bound to parameters after the SQL structure is parsed -- **No code injection**: Even malicious input like `1 OR 1=1; DROP TABLE users;` is treated as literal data -- **Database driver security**: Modern database drivers automatically escape parameter values - -{% /tab %} -{% tab label="Mass Assignment Prevention" %} - -### Mass Assignment Attack Prevention - -Mass assignment attacks occur when an application accepts more input parameters than expected, allowing attackers to modify fields they shouldn't have access to. The `additionalProperties: false` constraint is essential for preventing these attacks. - -**Mass Assignment Prevention: Before vs After** - -```yaml {% title="Securing Against Mass Assignment (OWASP API3:2023)" %} -NewUser: - type: object - # CRITICAL SECURITY SETTING: additionalProperties defaults to true - DANGEROUS! # [!code error] - # Without this setting, attackers can inject ANY extra fields into requests # [!code highlight] - additionalProperties: false # [!code error] ESSENTIAL: Blocks mass assignment - REQUIRED for security - - # STEP 1: Define ONLY the fields that should be accepted # [!code highlight] - properties: - name: - type: string - minLength: 1 # Prevent empty names - maxLength: 100 # Prevent buffer overflow attacks - pattern: "^[a-zA-Z\\s]+$" # Allow only letters and spaces - email: - type: string - format: email # Built-in email validation prevents malformed input - maxLength: 254 # Prevent resource exhaustion (RFC 5321 limit) - - # STEP 2: Require critical fields to prevent incomplete records # [!code highlight] - required: # These fields MUST be provided - - name # User identification required - - email # Contact method required - -# What this prevents: # [!code highlight] -# Malicious request: {"name": "John", "email": "john@test.com", "isAdmin": true, "balance": 999999} # [!code highlight] -# Result: isAdmin and balance fields are BLOCKED and ignored # [!code highlight] -``` - -**How mass assignment prevention works:** -- **`additionalProperties: false`**: Rejects any properties not explicitly defined in the schema -- **Explicit allow-listing**: Only defined properties are accepted, unknown fields are blocked -- **Field-level validation**: Each allowed property has its own validation constraints -- **Attack surface reduction**: Prevents unauthorized modification of sensitive fields like `isAdmin`, `balance`, or `role` - -**What this prevents**: -```json {% title="Malicious Request Example" %} -// This attack payload is blocked with additionalProperties: false -{ - "name": "John Doe", - "email": "john@example.com", - "isAdmin": true, // [!code error] Blocked - not in schema - "balance": 1000000 // [!code error] Blocked - not in schema -} -``` - -{% /tab %} -{% /tabs %} - -## Schema-Based Validation as Security Contract - -OpenAPI 3.1 provides a comprehensive vocabulary for defining strict validation rules by leveraging JSON Schema Draft 2020-12. By codifying these rules directly in your API specification, validation becomes core to your API's design. - -**Secure API Schema with Input Validation** - -```yaml {% title="openapi.yaml - Comprehensive Security Validation Schema" %} -components: - schemas: - NewUser: - type: object - # STEP 1: CRITICAL MASS ASSIGNMENT PROTECTION - blocks OWASP API3:2023 # [!code error] - additionalProperties: false # [!code error] ESSENTIAL: Prevents attackers from injecting extra fields - - # STEP 2: Define required fields to prevent incomplete records # [!code highlight] - required: - - username # User identification - mandatory - - email # Contact method - mandatory - - password # Authentication credential - mandatory - - age # Legal compliance (COPPA, etc.) - - properties: - # STEP 3: Username validation - prevent enumeration and injection # [!code highlight] - username: - type: string - minLength: 4 # Prevent too-short usernames (harder to guess) - maxLength: 20 # OWASP API4:2023: Prevent resource exhaustion - pattern: "^[a-zA-Z0-9_-]+$" # Allow-list only safe characters (blocks XSS, injection) - description: "Alphanumeric characters, underscores, and hyphens only" - example: "john_doe123" - - # STEP 4: Email validation - prevent malformed addresses and attacks # [!code highlight] - email: - type: string - minLength: 5 # Shortest valid email: "a@b.c" - maxLength: 254 # RFC 5321 limit - prevents buffer overflow - format: email # Built-in validation (RFC 5322 format) - description: "Must be a valid email address according to RFC 5322" - example: "user@example.com" - - # STEP 5: Password constraints - security + usability balance # [!code highlight] - password: - type: string - minLength: 12 # NIST recommends 12+ chars for user passwords - maxLength: 128 # Allow long passphrases but prevent DoS - description: | - Password requirements: - - Minimum 12 characters (strong security baseline) - - Maximum 128 characters (prevents resource exhaustion) - - No composition requirements (per NIST 800-63B) - example: "MySecurePassphrase123!" - writeOnly: true # [!code error] CRITICAL: NEVER return passwords in responses - - # STEP 6: Age validation - legal compliance and reasonableness checks # [!code highlight] - age: - type: integer - minimum: 13 # COPPA compliance (US law for child privacy) - maximum: 130 # Prevent integer overflow attacks - description: "User age in years (COPPA compliance requires 13+)" - example: 25 - - # STEP 7: Role-based access control with allow-list approach # [!code highlight] - role: - type: string - enum: ["user", "premium", "moderator"] # [!code error] CRITICAL: Allow-list prevents privilege escalation - default: "user" # Secure default (least privilege) - description: "User role determines access permissions" - - # STEP 8: Optional fields with validation (shows pattern for expansion) # [!code highlight] - profile: - type: object - additionalProperties: false # [!code highlight] Nested objects also need mass assignment protection - properties: - firstName: - type: string - minLength: 1 - maxLength: 50 # Reasonable limits prevent storage abuse - pattern: "^[\\p{L}\\s'-]+$" # Unicode letters, spaces, hyphens, apostrophes - description: "First name (supports international characters)" - lastName: - type: string - minLength: 1 - maxLength: 50 - pattern: "^[\\p{L}\\s'-]+$" - description: "Last name (supports international characters)" - bio: - type: string - maxLength: 500 # Prevent excessive text storage - description: "User biography (plain text only)" - - # STEP 9: Contact preferences with validation # [!code highlight] - preferences: - type: object - additionalProperties: false # [!code highlight] Every nested object needs this protection - properties: - newsletter: - type: boolean - default: false # Privacy-friendly default (opt-in) - description: "Subscribe to newsletter (GDPR compliant opt-in)" - notifications: - type: array - maxItems: 10 # [!code error] CRITICAL: Prevent array abuse/DoS attacks - uniqueItems: true # No duplicate notification types - items: - type: string - enum: ["email", "sms", "push", "in-app"] # Allow-list notification channels - description: "Preferred notification channels" - -# STEP 10: Common validation patterns for reuse # [!code highlight] -ValidationPattern: - # Phone number with international support - PhoneNumber: - type: string - pattern: "^\\+[1-9]\\d{1,14}$" # [!code highlight] SECURITY: E.164 format prevents malformed numbers - maxLength: 15 # International standard maximum - example: "+1234567890" - - # URL validation for security - SecureUrl: - type: string - format: uri # Basic URI validation - pattern: "^https://.*" # [!code error] CRITICAL: FORCE HTTPS - no HTTP allowed - maxLength: 2048 # Prevent excessively long URLs - example: "https://example.com" -``` - -**Key Security Controls**: -- **`additionalProperties: false`** blocks mass assignment attacks -- **Length constraints** prevent buffer overflow and resource exhaustion -- **Pattern validation** blocks injection attempts and malformed data -- **Enum restrictions** enforce allow-lists instead of dangerous validation bypass - -### Automated Governance for Validation - -Modern API governance tools can enforce input validation rules that require string length bounds, numeric ranges, and prevent mass assignment vulnerabilities. - -This governance approach transforms security reviews. Instead of manually checking many properties for missing `maxLength` constraints, automated linting tools handle baseline validation so security teams can focus on strategic concerns like business logic and context-dependent risks. - -> **🚀 Interactive Implementation**: Learn to set up comprehensive input validation with our [Automated Security Validation Walkthrough](automated-security-validation-walkthrough), which includes production-ready rules for OWASP API Security Top 10 2023 compliance. - -## Key Security Constraints - -The most critical schema constraints for API security focus on preventing resource exhaustion and injection attacks: - -- **`maxLength`**: Required on all strings to prevent memory exhaustion attacks -- **`maximum/minimum`**: Required on all numbers to prevent integer overflow vulnerabilities -- **`additionalProperties: false`**: Essential for preventing mass assignment attacks -- **`pattern`**: Use restrictive regex patterns to block injection payloads - -These constraints can be automatically enforced by governance rules, ensuring no schema can bypass these fundamental protections. - -## Common Validation Patterns - -{% table %} -* Input Type -* Validation Rules -* Example ---- -* Email -* RFC 5322 format -* `user@example.com` ---- -* Phone -* E.164 format -* `+1234567890` ---- -* URL -* Valid URL scheme -* `https://example.com` ---- -* UUID -* Standard UUID format -* `123e4567-e89b-12d3-a456-426614174000` ---- -* Date -* ISO 8601 format -* `2025-01-20T10:30:00Z` ---- -* Password -* Minimum complexity -* 8+ chars, mixed case, numbers, symbols -{% /table %} - -### Validation troubleshooting and common pitfalls - -* Missing bounds (no `maxLength`, no numeric ranges) — leads to resource exhaustion -* Overly permissive regex patterns — allow unwanted characters and injection payloads -* Validating at the wrong layer — front-end only, or after DB calls -* Accepting undeclared properties — enables mass assignment - -Quick fixes: - -```yaml {% title="JSON Schema example" %} -type: object -additionalProperties: false -properties: - name: - type: string - minLength: 1 - maxLength: 100 - pattern: "^[a-zA-Z\\s]+$" - age: - type: integer - minimum: 0 - maximum: 130 -``` - -> API Security Best Practice: "Blocking PRs that add new string fields without `maxLength` constraints is one of the most cost-effective security guardrails you can implement." - -## Attack Example: Equifax (OGNL injection via Apache Struts, 2017) - -The 2017 Equifax data breach was the result of a catastrophic input validation failure in the Apache Struts framework (CVE-2017-5638). The vulnerability allowed attackers to perform remote code execution by sending a specially crafted `Content-Type` header. The Struts framework failed to properly sanitize this header value, interpreting it as an Object-Graph Navigation Language (OGNL) expression and executing it. This gave attackers a direct shell on the server, which they used to access sensitive databases and exfiltrate the personal data of over 140 million people. - -This incident underscores the critical importance of validating all inputs, including HTTP headers, against a strict allow-list or pattern. A strong schema-based validation approach, enforced by governance, can block entire classes of injection attacks before they ever reach vulnerable application code. - -```mermaid -sequenceDiagram - participant A as Attacker - participant W as WAF (misconfigured) - participant S as Struts App (vulnerable) - participant DB as Database - - A->>W: HTTP request with malicious Content-Type header - W-->>S: Pass-through (no block) - A->>S: OGNL payload evaluated - S->>S: Remote code execution - S->>DB: Query PII at scale - DB-->>A: Exfiltrated records (PII) -``` - -*Sequence diagram illustrating the Equifax breach: attacker exploited Apache Struts vulnerability through OGNL injection in Content-Type headers, bypassing WAF and executing code to steal personal data.* - -Why this matters: Strong schema validation, input allow-lists, and patch hygiene block entire classes of injection attacks. - -**Security operations:** When schema validation and [attack prevention strategies](#attack-prevention-strategies) are in place, implement [monitoring](#input-validation-monitoring) to detect attempted breaches and [advanced validation techniques](#advanced-validation-techniques) for complex scenarios. - -## Input Validation Monitoring - -Choose your monitoring approach based on your security operations needs: - -{% tabs %} - {% tab label="Validation Logging (JavaScript)" %} - -### Validation Failure Logging - -**Express.js Middleware for Security Monitoring** - -```javascript {% title="validation-logger.js" %} -// Middleware to log validation failures for security analysis -app.use((req, res, next) => { - const originalSend = res.send; - - res.send = function(data) { - // Track validation failures for potential attack patterns - if (res.statusCode === 400 && req.validationErrors) { // [!code highlight] - logger.warn('Validation failure', { // [!code highlight] - endpoint: req.path, // [!code highlight] Track which endpoints are targeted - errors: req.validationErrors, // [!code highlight] Log specific validation failures - clientIP: req.ip, // [!code highlight] Track source IPs for analysis - userAgent: req.get('User-Agent') // [!code highlight] Detect automated attacks - }); - } - - originalSend.call(this, data); - }; - - next(); -}); -``` - -**How validation logging works:** -- **Middleware interception**: Captures all responses before they're sent to clients -- **Status code filtering**: Only logs when `statusCode === 400` (validation failures) -- **Structured logging**: Records endpoint, errors, IP, and user agent for security analysis -- **Attack pattern detection**: Unusual spikes or repeated failures from same IPs indicate potential attacks - -**Why this matters**: Logging validation failures helps detect attack patterns, frequent probe attempts, and potential security issues before they escalate. Monitor these logs for unusual spikes or repeated failures from the same IP addresses. - -{% /tab %} -{% tab label="Validation Metrics (JavaScript)" %} - -### Validation Metrics - -```javascript -// Track validation patterns for security analysis -class ValidationMetrics { - constructor() { - this.validationFailures = new Map(); // [!code highlight] Count failures by type - this.attackPatterns = new Map(); // [!code highlight] Track potential attacks - } - - recordFailure(endpoint, field, errorType) { - const key = `${endpoint}:${field}:${errorType}`; - - // Initialize counter if key doesn't exist - if (!this.validationFailures.has(key)) { - this.validationFailures.set(key, 0); - } - this.validationFailures.set(key, this.validationFailures.get(key) + 1); // [!code highlight] Increment failure counter - - // Detect potential attack patterns // [!code highlight] - const attackTypes = ['pattern_violation', 'length_exceeded', 'additional_property']; - if (attackTypes.includes(errorType)) { - if (!this.attackPatterns.has(endpoint)) { - this.attackPatterns.set(endpoint, 0); - } - this.attackPatterns.set(endpoint, this.attackPatterns.get(endpoint) + 1); // [!code highlight] Flag suspicious activity - } - } - - getAttackSummary() { - return Object.fromEntries(this.attackPatterns); // [!code highlight] Return attack metrics - } - - // Additional utility method for comprehensive metrics - getFailureReport() { - return { - totalFailures: this.validationFailures.size, - attackPatterns: this.getAttackSummary(), - topFailureTypes: Object.fromEntries(this.validationFailures) - }; - } -} - -// Usage in Express.js validation middleware -const validationMetrics = new ValidationMetrics(); - -function trackValidationError(req, field, errorType) { - const endpoint = req.route?.path || req.path; - validationMetrics.recordFailure(endpoint, field, errorType); - - // Log for immediate monitoring - console.warn('Validation failure tracked', { - endpoint, - field, - errorType, - ip: req.ip, - userAgent: req.get('User-Agent') - }); -} -``` - -**How validation metrics work:** -- **Failure tracking**: Counts validation failures by endpoint, field, and error type -- **Pattern detection**: Identifies suspicious error types that often indicate attacks -- **Attack scoring**: Tracks which endpoints receive the most attack attempts -- **Metrics export**: Provides data for security dashboards and alerting systems - -**Key metrics to monitor:** -- **`pattern_violation`**: Input doesn't match expected format (possible injection attempt) -- **`length_exceeded`**: Input too long (buffer overflow or DoS attempt) -- **`additional_property`**: Extra fields in request (mass assignment attack) - -{% /tab %} -{% /tabs %} - -## Advanced Validation Techniques - -### Custom Format Validators -```javascript -// Custom OpenAPI format validators -const customFormats = { - 'safe-html': { - validate: (value) => { - // Strip dangerous HTML tags and attributes - const clean = DOMPurify.sanitize(value, { - ALLOWED_TAGS: ['p', 'br', 'strong', 'em'], - ALLOWED_ATTR: [] - }); - return clean === value; - } - }, - 'sql-safe': { - validate: (value) => { - // Block SQL injection patterns - const sqlPatterns = /('|(\\x27)|(\\x2D\\x2D)|(%27)|(%2D%2D))/i; - return !sqlPatterns.test(value); - } - } -}; - -// Use in OpenAPI schema -const schema = { - type: "string", - format: "safe-html", - maxLength: 1000 -}; -``` - -### Contextual Validation Rules -```yaml {% title="openapi.yaml" %} -# Different validation rules based on context -components: - schemas: - PublicProfile: - type: object - additionalProperties: false - properties: - displayName: - type: string - maxLength: 50 - pattern: "^[a-zA-Z0-9\\s._-]+$" # More restrictive for public display - - InternalUser: - type: object - additionalProperties: false - properties: - displayName: - type: string - maxLength: 100 - pattern: "^[\\w\\s._@-]+$" # Less restrictive for internal use -``` - -## Frequently Asked Questions - -### How does OpenAPI validation prevent injection attacks? -OpenAPI specifications define precise data schemas with type validation, format constraints, and length limits. When enforced by [automated governance](#automated-governance-for-validation), these schemas automatically reject malformed inputs that could contain injection payloads, stopping attacks before they reach your application logic. See [Schema-Based Validation as Security Contract](#schema-based-validation-as-security-contract) for implementation details. - -### What's the difference between client-side and server-side validation? -Client-side validation improves user experience by providing immediate feedback, but it can be bypassed by attackers. Server-side validation is the critical security control—never trust data from the client. Always validate on the server even if you also validate on the client. Review our [attack prevention strategies](#attack-prevention-strategies) to understand why server-side validation is essential. - -### Should I validate HTTP headers and query parameters? -Yes! The [Equifax breach](#attack-example-equifax-ognl-injection-via-apache-struts-2017) occurred through a malicious `Content-Type` header. All inputs—including headers, query parameters, path parameters, and request bodies—should be validated against strict schemas. Don't assume any input is safe. - -### How do I handle file uploads securely? -File uploads require special attention: validate file types using content inspection (not just extensions), enforce size limits, scan for malware, store files outside the web root, and use content-disposition headers to prevent execution. Consider using dedicated file storage services with [advanced validation techniques](#advanced-validation-techniques). - -### What's the performance impact of extensive validation? -Modern validation libraries are highly optimized. The security benefit far outweighs the minimal performance cost. Consider caching compiled schemas and using efficient validation libraries like `ajv` for JavaScript or `jsonschema` for Python. Implement [validation monitoring](#input-validation-monitoring) to track performance impacts. - -## Resources and Next Steps - -### Essential Reading -- [OWASP API Security Top 10](https://owasp.org/www-project-api-security/) - Comprehensive vulnerability guide including injection attacks (API3:2023) and resource consumption (API4:2023) -- [JSON Schema Specification](https://json-schema.org/specification.html) - Complete reference for OpenAPI validation capabilities -- [OpenAPI Data Types](https://spec.openapis.org/oas/v3.1.0#data-types) - Official OpenAPI data type and format specifications - -### Implementation Tools -- [AJV JSON Schema Validator](https://ajv.js.org/) - Fast JSON Schema validation for JavaScript/Node.js -- [Joi Validation](https://joi.dev/) - Object schema validation library with expressive API -- [Cerberus](https://docs.python-cerberus.org/) - Lightweight, extensible data validation library for Python - -### Security Testing Tools -- [OWASP ZAP](https://owasp.org/www-project-zap/) - Security testing proxy for finding injection vulnerabilities -- [Postman Security Testing](https://learning.postman.com/docs/writing-scripts/test-scripts/) - API security test automation -- [Burp Suite](https://portswigger.net/burp) - Web application security testing platform - -### Related Security Topics -- [API TLS Encryption and HTTPS Best Practices](api-tls-encryption-https-best-practices) - Secure data in transit -- [API Rate Limiting and Abuse Prevention](api-rate-limiting-abuse-prevention) - Prevent DoS attacks and abuse -- [Authentication and Authorization with OpenAPI](authentication-authorization-openapi) - Implement secure access control -- [API Security by Design: Complete Guide](/learn/security) - Overview of all API security domains \ No newline at end of file diff --git a/learn/security/api-rate-limiting-abuse-prevention.md b/learn/security/api-rate-limiting-abuse-prevention.md deleted file mode 100644 index 823b7624..00000000 --- a/learn/security/api-rate-limiting-abuse-prevention.md +++ /dev/null @@ -1,726 +0,0 @@ ---- -title: Rate Limiting and Abuse Prevention -description: Implement API rate limiting strategies to prevent DoS attacks, brute force attempts, and business logic abuse. -seo: - title: Rate Limiting and Abuse Prevention - description: Implement API rate limiting strategies to prevent DoS attacks, brute force attempts, and business logic abuse. ---- - -# Rate Limiting and Abuse Prevention for APIs - ---- - -## Key Takeaways - -A single client, whether intentionally malicious or simply due to a bug in its code, can send a massive number of requests to an API in a short period. This can overwhelm the server, degrading performance for all other users or even causing the service to crash. Rate limiting is the primary defense against this scenario. - -**In this guide, you'll learn:** -- [How to implement rate limiting](#documenting-rate-limits-in-openapi) as a security and reliability control -- [OpenAPI x-rateLimit extensions](#documenting-rate-limits-in-openapi) and documentation strategies -- [Rate limiting algorithms and implementation patterns](#rate-limiting-implementation-approaches) -- [Client-side exponential backoff](#client-side-exponential-backoff) and error handling -- [Real-world lessons from the Facebook phone number scraping incident](#attack-example-facebook-phone-number-scraping-2019) -- [Advanced techniques and monitoring approaches](#rate-limiting-monitoring-and-observability) - ---- - -## Quick Start Guide - -Ready to implement effective rate limiting? Follow these steps: - -1. **Document rate limits:** Add [OpenAPI x-rateLimit extensions](#documenting-rate-limits-in-openapi) to your API specifications -2. **Choose an algorithm:** Select from [Token Bucket, Sliding Window, or Fixed Window](#rate-limiting-implementation-approaches) based on your needs -3. **Implement multi-tier limits:** Set up global, per-endpoint, and per-client [rate limiting configurations](#advanced-rate-limiting-techniques) -4. **Set up monitoring:** Implement [metrics collection and alerting](#rate-limiting-monitoring-and-observability) to detect attacks -5. **Test and tune:** Use the [implementation strategy framework](#rate-limiting-strategy-framework) to prioritize critical endpoints and validate limits - -**Next Steps:** Now that you have rate limiting protection in place, learn about [Authentication and Authorization with OpenAPI](authentication-authorization-openapi) to implement comprehensive access control for your APIs. - ---- - -## The Library Card Principle - -> **The Library Card**: A library card allows a patron to check out a maximum of ten books per month. Once that limit is reached, the system will not allow any more checkouts until the next month begins, regardless of how many times the patron asks. - -**Rate limiting** applies this same principle to an API. It establishes a policy that restricts the number of requests a single client can make within a specific time window (e.g., 100 requests per minute). - -## Why Rate Limiting Is Critical for API Security - -Rate limiting is a critical control for both security and reliability, directly mitigating several OWASP API Security Top 10 risks: - -1. **Security:** It thwarts Denial-of-Service (DoS) attacks by preventing traffic floods, addressing OWASP API4:2023 - Unrestricted Resource Consumption. It also makes brute-force attacks against [authentication endpoints](authentication-authorization-openapi) much slower and less effective, reducing the risk of credential stuffing attacks. - -2. **Business Logic Abuse:** It helps mitigate abuse by preventing bots from scraping data or manipulating business flows, addressing OWASP API6:2023 - Unrestricted Access to Sensitive Business Flows. - -3. **Reliability and Fair Usage:** It ensures that the API remains stable and responsive for all users by preventing any single client from monopolizing server resources. - -## Documenting Rate Limits in OpenAPI - -While OpenAPI 3.1 doesn't include native rate-limiting objects, extension properties (prefixed with `x-`) provide a standard mechanism. The best practice is defining custom `x-rateLimit` extensions at the operation level. - -**Note:** Rate limits are typically dynamic in production environments, with different limits for different clients based on service tiers, contracts, or usage patterns. The OpenAPI specification documents the baseline policy, while implementation systems apply client-specific variations. - -```yaml {% title="openapi.yaml" %} -paths: - /auth/login: - post: - summary: User Login - tags: [Authentication] - # Define rate-limiting policy for this sensitive endpoint # [!code highlight] - x-rateLimit: - limit: 5 # [!code highlight] Strict limit for auth endpoints - window: "1m" # [!code highlight] Short time window - scope: "ip_address" # [!code highlight] IP-based rate limiting - description: "Limits login attempts to 5 per minute per IP to prevent brute-force attacks." - responses: - '200': - description: "Successful login." - # Document the 429 response with proper headers # [!code highlight] - '429': - description: "Too Many Requests. Rate limit exceeded." - headers: - Retry-After: # [!code highlight] Required for proper client behavior - schema: - type: integer - description: "Seconds to wait before making a new request." - X-RateLimit-Limit: # [!code highlight] Inform clients of limits - schema: - type: integer - description: "Maximum requests permitted in the window." - X-RateLimit-Remaining: # [!code highlight] Help clients pace requests - schema: - type: integer - description: "Requests remaining in current window." -``` - -### Automated Governance for Rate Limiting - -API governance tools can enforce rules that ensure [authentication endpoints](authentication-authorization-openapi) always have rate limiting policies defined. - -This approach provides dual benefits: modern API documentation tools automatically display rate limiting extensions in generated documentation, making policies transparent to API consumers, while governance rules ensure sensitive endpoints never lack rate-limiting policies. - -> **🔧 Implementation Guide**: See our [Automated Security Validation Walkthrough](automated-security-validation-walkthrough) for step-by-step instructions on implementing rate limiting validation rules, including 429 response validation and header consistency checks. - -## Rate Limiting Implementation Approaches - -Choose the rate limiting algorithm that best fits your traffic patterns and precision requirements: - -{% tabs %} - {% tab label="Token Bucket" %} - -### Token Bucket Algorithm - -**Best for:** APIs that need to handle legitimate traffic spikes - -**How it works:** -- Tokens are added to a bucket at a steady rate (refill rate) -- Each request consumes one token from the bucket -- If bucket is empty, requests are rejected or queued -- Allows burst traffic up to bucket capacity - -**Pros:** -- **Flexible burst handling**: Accommodates legitimate traffic spikes -- **Smooth long-term limiting**: Maintains steady average rate -- **User-friendly**: Doesn't penalize users for occasional bursts - -**Cons:** -- **Implementation complexity**: Requires token state management -- **Memory overhead**: Need to track bucket state per client -- **Distributed challenges**: Synchronizing token state across servers - -**Implementation example:** -```javascript {% title="token-bucket.js - Secure Rate Limiting Algorithm" %} -class TokenBucket { - constructor(capacity, refillRate) { - // STEP 1: Initialize bucket parameters - this.capacity = capacity; // Max burst size (e.g., 100 requests) - this.tokens = capacity; // Start with full bucket (allows immediate bursts) - this.refillRate = refillRate; // Steady rate (e.g., 10 requests/second) - this.lastRefill = Date.now(); // Track when we last added tokens - } - - // STEP 2: Process incoming request - the main security enforcement point - consume(tokens = 1) { - // First, add any tokens we've earned since last request - this.refill(); // CRITICAL: Always refill before checking - - // STEP 3: Security decision - allow or block the request - if (this.tokens >= tokens) { - this.tokens -= tokens; // Consume tokens for this request - return true; // ✅ REQUEST ALLOWED - user under limit - } - - // STEP 4: Rate limit exceeded - implement security response - console.warn(`Rate limit exceeded. Tokens available: ${this.tokens}, requested: ${tokens}`); - return false; // ❌ BLOCK REQUEST - user over limit - } - - // STEP 5: Token refill logic - implements the "steady rate" behavior - refill() { - const now = Date.now(); - const timePassed = (now - this.lastRefill) / 1000; // Convert to seconds - - // Calculate tokens earned: time × rate - const tokensToAdd = Math.floor(timePassed * this.refillRate); // Floor prevents fractional tokens - - if (tokensToAdd > 0) { - // Add tokens but never exceed capacity (prevents bucket overflow) - this.tokens = Math.min(this.capacity, this.tokens + tokensToAdd); - this.lastRefill = now; // Update timestamp for next calculation - - console.debug(`Added ${tokensToAdd} tokens. Current: ${this.tokens}/${this.capacity}`); - } - } - - // STEP 6: Utility methods for monitoring and debugging - getStatus() { - this.refill(); // Ensure current state - return { - tokens: this.tokens, // Available tokens right now - capacity: this.capacity, // Maximum burst size - utilizationPercent: ((this.capacity - this.tokens) / this.capacity * 100).toFixed(1) - }; - } -} - -// EXAMPLE USAGE: Protect login endpoint from brute force -const loginRateLimit = new TokenBucket(5, 0.1); // 5 attempts, refill 1 every 10 seconds - -// In your API endpoint: -app.post('/auth/login', (req, res) => { - const clientId = req.ip || req.headers['x-client-id']; // Identify the client - - if (!loginRateLimit.consume()) { - return res.status(429).json({ // HTTP 429 = Too Many Requests - error: 'Rate limit exceeded', - retryAfter: Math.ceil((1 / loginRateLimit.refillRate)) // Tell client when to retry - }); - } - - // Process login attempt... // Only reached if under rate limit -}); -``` - - {% /tab %} - {% tab label="Sliding Window" %} - -### Sliding Window Algorithm - -**Best for:** APIs requiring exact rate limiting precision - -**How it works:** -- Tracks exact timestamps of requests within a rolling time window -- Continuously slides the window forward with each request -- Provides most accurate rate limiting without boundary conditions - -**Pros:** -- **Maximum accuracy**: No boundary condition exploits -- **Precise enforcement**: Exact request counting within time windows -- **Fair distribution**: Prevents gaming of window boundaries - -**Cons:** -- **Memory intensive**: Stores timestamp for each request -- **Complex implementation**: Requires efficient data structures -- **Distributed complexity**: Hard to synchronize across multiple servers - -**Implementation example:** -```javascript {% title="sliding-window.js" %} -class SlidingWindowRateLimit { - constructor(maxRequests, windowSeconds) { - this.maxRequests = maxRequests; // [!code highlight] Maximum requests allowed - this.windowSeconds = windowSeconds; // [!code highlight] Time window in seconds - this.requests = []; // [!code highlight] Store request timestamps - } - - isAllowed() { - const now = Date.now(); - const windowMs = this.windowSeconds * 1000; - - // Remove requests outside current window // [!code highlight] - while (this.requests.length > 0 && this.requests[0] <= now - windowMs) { - this.requests.shift(); // [!code highlight] Clean old timestamps - } - - // Check if we're under the limit - if (this.requests.length < this.maxRequests) { - this.requests.push(now); // [!code highlight] Record this request - return true; // [!code highlight] Request allowed - } - - return false; // [!code error] Rate limit exceeded - } - - // Utility method to get current status - getStatus() { - const now = Date.now(); - const windowMs = this.windowSeconds * 1000; - - // Clean old requests first - while (this.requests.length > 0 && this.requests[0] <= now - windowMs) { - this.requests.shift(); - } - - return { - currentRequests: this.requests.length, - maxRequests: this.maxRequests, - remaining: this.maxRequests - this.requests.length, - windowSeconds: this.windowSeconds - }; - } -} -``` - - {% /tab %} - {% tab label="Fixed Window" %} - -### Fixed Window Algorithm - -**Best for:** Simple use cases with easy implementation requirements - -**How it works:** -- Divides time into fixed intervals (e.g., per minute, per hour) -- Counts requests within each fixed window -- Resets counter at the start of each new window - -**Pros:** -- **Simple implementation**: Easy to understand and code -- **Low memory usage**: Only need counter per time window -- **Distributed-friendly**: Easy to implement with shared counters - -**Cons:** -- **Boundary condition abuse**: 2x rate limit possible at window edges -- **Traffic spikes**: All requests could arrive at start of window -- **Less user-friendly**: Sudden cutoffs can impact user experience - -**Implementation example:** -```javascript {% title="fixed-window.js" %} -class FixedWindowRateLimit { - constructor(maxRequests, windowMs) { - this.maxRequests = maxRequests; // [!code highlight] Maximum requests per window - this.windowMs = windowMs; // [!code highlight] Window duration in milliseconds - this.counter = new Map(); // [!code highlight] Request counters by client - this.windowStart = new Map(); // [!code highlight] Window start times - } - - isAllowed(clientId) { - const now = Date.now(); - const windowStart = this.windowStart.get(clientId); - - // Check if we're in a new window // [!code highlight] - if (!windowStart || (now - windowStart) >= this.windowMs) { - this.windowStart.set(clientId, now); // [!code highlight] Start new window - this.counter.set(clientId, 1); // [!code highlight] Reset counter - return true; // [!code highlight] Request allowed - } - - // Check current window limit - const currentCount = this.counter.get(clientId) || 0; - if (currentCount < this.maxRequests) { - this.counter.set(clientId, currentCount + 1); // [!code highlight] Increment counter - return true; // [!code highlight] Request allowed - } - - return false; // [!code error] Rate limit exceeded - } - - // Utility method to get window status for a client - getWindowStatus(clientId) { - const now = Date.now(); - const windowStart = this.windowStart.get(clientId); - const currentCount = this.counter.get(clientId) || 0; - - if (!windowStart) { - return { - requests: 0, - maxRequests: this.maxRequests, - remaining: this.maxRequests, - timeUntilReset: this.windowMs - }; - } - - const timeElapsed = now - windowStart; - const timeUntilReset = Math.max(0, this.windowMs - timeElapsed); - - return { - requests: currentCount, - maxRequests: this.maxRequests, - remaining: Math.max(0, this.maxRequests - currentCount), - timeUntilReset - }; - } -} -``` - - {% /tab %} -{% /tabs %} - -## Advanced Rate Limiting Techniques - -### Multi-tier Rate Limiting Configuration - -```yaml {% title="Kong configuration" %} -plugins: -- name: rate-limiting - config: - minute: 100 # 100 requests per minute per IP - hour: 1000 # 1000 requests per hour per IP - policy: redis # Use Redis for distributed rate limiting - fault_tolerant: true - hide_client_headers: false - -# Per-endpoint overrides -- name: rate-limiting - route: auth-endpoints - config: - minute: 5 # Stricter limits for auth endpoints - hour: 20 - policy: redis -``` - -### Client-side Exponential Backoff - -```javascript -class APIClient { - async makeRequest(url, options, retries = 3) { - try { - const response = await fetch(url, options); - - if (response.status === 429) { - const retryAfter = response.headers.get('Retry-After'); - const delay = retryAfter ? parseInt(retryAfter) * 1000 : - Math.pow(2, 4 - retries) * 1000; // Exponential backoff - - if (retries > 0) { - await new Promise(resolve => setTimeout(resolve, delay)); - return this.makeRequest(url, options, retries - 1); - } - - throw new Error('Rate limit exceeded'); - } - - return response; - } catch (error) { - throw error; - } - } -} -``` - -As a complementary practice, the client-side responsibility of implementing exponential backoff should also be noted. When an API client receives a rate-limiting error (e.g., HTTP 429 Too Many Requests), it should wait for an exponentially increasing period of time between retries. This prevents clients from overwhelming the server and helps the system recover gracefully from load spikes. - -> **Tip:** Combine per-IP and per-account quotas and require exponential backoff on clients. - -## Attack Example: Facebook Phone Number Scraping (2019) - -In 2019, malicious actors exploited a vulnerability in Facebook's contact importer feature to scrape the personal data of over 530 million users. The API endpoint itself was not technically "broken"—it performed its intended function of matching phone numbers to user profiles. The vulnerability was the absence of adequate rate limiting and business rule enforcement. - -Attackers used automated scripts to submit massive lists of phone numbers, and the API dutifully returned the corresponding user profiles, allowing them to build a massive database of personal information. - -This incident highlights a different type of API attack, moving from exploiting technical flaws to abusing business logic at scale. It elevates rate limiting from an infrastructure protection mechanism to also being a tool for enforcing business rules. The `x-rateLimit` extension in OpenAPI is a form of declarative security policy. - -```mermaid -sequenceDiagram - participant B as Botnet/Script - participant API as Contact Import API - - loop Enumerate phone numbers - B->>API: Batch upload numbers - API-->>B: Matched user IDs/profile data - end - Note over B,API: Missing per-account/IP limits and anomaly detection -``` - -*Sequence diagram showing how attackers used Facebook's contact import API to scrape phone numbers at scale, exploiting missing rate limits and velocity checks to harvest personal data.* - -Why this matters: Rate limiting, velocity checks, and behavior analytics are core defenses against scraping and credential-stuffing at scale. - -## Rate Limiting Monitoring and Observability - -Choose your monitoring approach based on your security operations needs: - -{% tabs %} - {% tab label="Metrics Collection (JavaScript)" %} - -### Rate Limiting Metrics Collection - -```javascript -// Track rate limiting metrics for security analysis -class RateLimitMetrics { - constructor() { - this.blockedRequests = new Map(); // [!code highlight] Count blocked requests by client - this.totalRequests = new Map(); // [!code highlight] Count total requests by client - this.suspiciousPatterns = new Map(); // [!code highlight] Track attack patterns - } - - recordRequest(clientId, blocked = false, endpoint = null) { - // Initialize counters if client is new - if (!this.totalRequests.has(clientId)) { - this.totalRequests.set(clientId, 0); - this.blockedRequests.set(clientId, 0); - this.suspiciousPatterns.set(clientId, []); - } - - this.totalRequests.set(clientId, this.totalRequests.get(clientId) + 1); // [!code highlight] Increment request counter - - if (blocked) { - this.blockedRequests.set(clientId, this.blockedRequests.get(clientId) + 1); // [!code highlight] Track blocked request - - // Track suspicious patterns // [!code highlight] - const patterns = this.suspiciousPatterns.get(clientId); - patterns.push({ - timestamp: Date.now(), // [!code highlight] When attack occurred - endpoint: endpoint, // [!code highlight] Which endpoint targeted - blocked: true // [!code highlight] Request was blocked - }); - this.suspiciousPatterns.set(clientId, patterns); - } - } - - getBlockRate(clientId) { - const total = this.totalRequests.get(clientId) || 0; - const blocked = this.blockedRequests.get(clientId) || 0; - return total > 0 ? (blocked / total) * 100 : 0; - } - - getAttackIndicators(clientId, windowMinutes = 5) { - // Detect rapid repeated attempts that might indicate an attack - const patterns = this.suspiciousPatterns.get(clientId) || []; - const recentBlocks = patterns.filter(event => // [!code highlight] Filter recent blocked requests - Date.now() - event.timestamp < windowMinutes * 60 * 1000 - ); - return recentBlocks.length; // [!code highlight] Return attack indicator count - } -} -``` - -**How metrics collection works:** -- **Request tracking**: Counts all requests and blocked requests per client -- **Pattern detection**: Records timestamps and endpoints for blocked requests -- **Attack indicators**: Identifies rapid repeated attempts within time windows -- **Block rate calculation**: Calculates percentage of requests blocked per client - -{% /tab %} -{% tab label="Alerting Configuration (Prometheus)" %} - -### Alerting Configuration - -```yaml {% title="prometheus-alerts.yml" %} -groups: -- name: rate_limiting_alerts - rules: - - alert: HighRateLimitBlocks - expr: rate(rate_limit_blocked_total[5m]) > 10 - for: 2m - labels: - severity: warning - annotations: - summary: "High rate of blocked requests detected" - description: "{{ $value }} requests per second being blocked" - - - alert: SuspiciousRateLimitPattern - expr: rate_limit_block_rate > 80 # [!code highlight] 80% block rate threshold - for: 1m # [!code highlight] Alert after 1 minute - labels: - severity: critical # [!code error] Critical security alert - annotations: - summary: "Possible DDoS or brute force attack" - description: "Client {{ $labels.client_id }} has {{ $value }}% blocked rate" -``` - -**How alerting works:** -- **HighRateLimitBlocks**: Monitors overall rate of blocked requests across system -- **SuspiciousRateLimitPattern**: Detects clients with abnormally high block rates -- **Threshold-based**: Configurable thresholds trigger security team notifications -- **Context-aware**: Provides client IDs and block rates for investigation - -{% /tab %} -{% /tabs %} - -### Rate Limiting Troubleshooting - -**Common Issues and Solutions:** - -* **Counting the wrong thing** — per-IP only; add per-account and per-token limits -* **Same limits for every endpoint** — tighten auth and write endpoints separately -* **No Retry-After header** — clients can't back off predictably -* **Stateless limits in distributed systems** — use Redis or gateway-native stores -* **Legitimate bursts blocked** — implement token bucket algorithm for flexibility - -**Quick Diagnostic Commands:** - -```bash -# Observe 429 behavior and headers -curl -i https://api.example.com/login | grep -E 'HTTP/|Retry-After|X-RateLimit' - -# Simulate burst to verify rate limiting -hey -z 10s -q 50 -c 50 https://api.example.com/api/resource - -# Test different client patterns -for i in {1..10}; do - curl -H "Authorization: Bearer $TOKEN" https://api.example.com/api/data - sleep 1 -done -``` - -### Advanced Rate Limiting Patterns - -**Adaptive Rate Limiting:** -```javascript -// Adjust limits based on server health -class AdaptiveRateLimit { - constructor() { - this.baseLimit = 100; - this.currentLimit = 100; - this.healthThreshold = 0.8; - } - - adjustLimit(serverLoad, errorRate) { - if (serverLoad > this.healthThreshold || errorRate > 0.1) { - this.currentLimit = Math.max(10, this.currentLimit * 0.8); - } else if (serverLoad < 0.5 && errorRate < 0.01) { - this.currentLimit = Math.min(this.baseLimit, this.currentLimit * 1.1); - } - } -} -``` - -**Geographic Rate Limiting:** -```yaml {% title="nginx-rate-limit.conf" %} -# Different limits based on geographic regions -geo $rate_limit_zone { - default $binary_remote_addr; - # More restrictive limits for high-risk regions - ~^192\.168\. $binary_remote_addr_strict; - ~^10\. $binary_remote_addr_internal; -} - -limit_req_zone $rate_limit_zone zone=general:10m rate=100r/m; -limit_req_zone $binary_remote_addr_strict zone=restricted:10m rate=20r/m; -limit_req_zone $binary_remote_addr_internal zone=internal:10m rate=1000r/m; -``` - -> Rate Limiting Best Practice: "Rate limiting on auth endpoints is non-negotiable. We set 5/min per IP and per account, and alert when bypass attempts appear." - -## Frequently Asked Questions - -### Why is rate limiting important for API security? -Rate limiting prevents denial-of-service attacks, brute-force authentication attempts, and data scraping. It ensures fair resource usage among legitimate users while blocking malicious automation. Without rate limits, a single bad actor can overwhelm your API infrastructure. See the [Facebook phone number scraping incident](#attack-example-facebook-phone-number-scraping-2019) for a real-world example. - -### What's the difference between rate limiting and throttling? -Rate limiting sets hard limits on request volume (e.g., 100 requests per minute), rejecting excess requests with 429 status codes. Throttling typically involves slowing down or queuing requests rather than rejecting them outright. Rate limiting is more common for APIs as it provides clearer client feedback. - -### Should rate limits be per-IP, per-user, or both? -Implement multiple layers: per-IP limits prevent DDoS attacks from single sources, per-user limits enforce fair usage policies, and per-API-key limits support tiered service levels. Combine all three for comprehensive protection against different attack patterns. See [advanced rate limiting patterns](#advanced-rate-limiting-patterns) for implementation guidance. - -### How do I handle legitimate traffic spikes? -Use [token bucket algorithms](#rate-limiting-implementation-approaches) that allow controlled bursts within overall rate limits. Consider implementing adaptive rate limiting that adjusts limits based on server health. For predictable spikes, provide rate limit increase APIs or temporary exemption mechanisms for verified clients. - -### What rate limiting algorithm should I choose? -- **[Token Bucket](#rate-limiting-implementation-approaches)**: Best for APIs needing burst flexibility -- **[Sliding Window](#rate-limiting-implementation-approaches)**: Most accurate but memory intensive -- **[Fixed Window](#rate-limiting-implementation-approaches)**: Simple but allows boundary condition abuse - -Choose based on your accuracy requirements, traffic patterns, and implementation complexity tolerance. See our [implementation approaches](#rate-limiting-implementation-approaches) for detailed comparisons. - -### How do I communicate rate limits to API consumers? -Document limits in [OpenAPI specifications using x-rateLimit extensions](#documenting-rate-limits-in-openapi), include rate limit headers in responses (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `Retry-After`), provide clear error messages with 429 responses, and maintain public documentation about your rate limiting policies. - -## Rate Limiting Strategy Framework - -### Implementation Priority - -1. **Critical Endpoints First** - - Authentication endpoints: 5-10 requests per minute per IP - - Password reset: 3 requests per hour per email - - Account creation: 5 requests per hour per IP - - Payment processing: Strict limits based on business rules - -2. **Resource-Intensive Operations** - - Search endpoints: Higher limits but monitor query complexity - - File uploads: Size-based and frequency-based limits - - Data export: Very restrictive limits with queuing - -3. **General API Access** - - Read operations: Generous limits for good user experience - - Write operations: More restrictive than reads - - Administrative endpoints: Very restrictive with strong authentication - -### Rate Limit Testing Strategy - -```javascript -// Rate limit testing framework -async function testRateLimit(url, requestsCount, windowSeconds) { - /** - * Test rate limiting behavior - * @param {string} url - API endpoint to test - * @param {number} requestsCount - Number of concurrent requests to send - * @param {number} windowSeconds - Expected rate limit window - */ - const startTime = Date.now(); - let successfulRequests = 0; - let blockedRequests = 0; - - // Create array of request promises - const requests = Array.from({ length: requestsCount }, () => makeRequest(url)); - - // Execute all requests concurrently - const responses = await Promise.allSettled(requests); - - // Analyze responses - for (const result of responses) { - if (result.status === 'rejected') { - console.warn('Request failed:', result.reason.message); - continue; - } - - const response = result.value; - if (response.status === 200) { - successfulRequests++; - } else if (response.status === 429) { - blockedRequests++; - } - } - - const elapsed = (Date.now() - startTime) / 1000; // Convert to seconds - console.log('Rate limit test results:'); - console.log(`Successful: ${successfulRequests}, Blocked: ${blockedRequests}`); - console.log(`Effective rate: ${(successfulRequests / elapsed).toFixed(2)} req/sec`); - - return { - successful: successfulRequests, - blocked: blockedRequests, - total: requestsCount, - elapsedSeconds: elapsed, - effectiveRate: successfulRequests / elapsed - }; -} - -async function makeRequest(url) { - try { - const response = await fetch(url, { - method: 'GET', - headers: { - 'User-Agent': 'rate-limit-tester/1.0' - } - }); - return response; - } catch (error) { - throw new Error(`Request failed: ${error.message}`); - } -} - -// Example usage: -// await testRateLimit('https://api.example.com/users', 50, 60); -``` - -## Resources and Next Steps - -### Essential Standards -- OWASP API Security Top 10 - Comprehensive guide including unrestricted resource consumption (API4:2023) and business logic abuse (API6:2023) -- RFC 6585 - HTTP status code 429 (Too Many Requests) specification - -### Related Security Topics -- [API Input Validation and Injection Prevention](api-input-validation-injection-prevention) - Protect APIs from malicious data -- [Authentication and Authorization with OpenAPI](authentication-authorization-openapi) - Implement secure access control -- [API TLS Encryption and HTTPS Best Practices](api-tls-encryption-https-best-practices) - Secure data in transit -- [API Security by Design: Complete Guide](/learn/security) - Overview of all API security domains \ No newline at end of file diff --git a/learn/security/api-tls-encryption-https-best-practices.md b/learn/security/api-tls-encryption-https-best-practices.md deleted file mode 100644 index 49cb225f..00000000 --- a/learn/security/api-tls-encryption-https-best-practices.md +++ /dev/null @@ -1,445 +0,0 @@ ---- -title: TLS Encryption and HTTPS Best Practices for APIs -description: Protect data in transit with proper TLS configuration, certificate management, and HTTPS enforcement using OpenAPI security contracts. -seo: - title: TLS Encryption and HTTPS Best Practices for APIs - description: Protect data in transit with proper TLS configuration, certificate management, and HTTPS enforcement using OpenAPI security contracts. ---- - -# TLS Encryption and HTTPS Best Practices for APIs - ---- - -## Key Takeaways - -When a client and an API exchange information, that data travels across the internet, a public network. Without protection, this data gets intercepted and read by malicious actors. This is where encryption comes in. - -**In this guide, you'll learn:** -- [How TLS 1.3 provides secure communication](#tls-13-the-modern-standard) for APIs -- [OpenAPI server URL security contracts](#enforcing-https-in-your-api-specification) and enforcement -- [Certificate management and TLS configuration](#tls-configuration-examples) examples -- [Mutual TLS (mTLS) for service-to-service communication](#mutual-tls-mtls-two-way-authentication) -- [Real-world lessons from the Heartbleed vulnerability](#attack-example-heartbleed-tls-library-vulnerability-2014) -- [Automated governance for transport security](#automated-governance-enforcement) - ---- - -## Quick Start Guide - -Ready to implement secure TLS encryption? Follow these steps: - -1. **Upgrade to TLS 1.3:** Implement [modern TLS 1.3](#tls-13-the-modern-standard) with strong cipher suites and disable legacy protocols -2. **Configure your server:** Choose your technology stack from our [configuration examples](#tls-configuration-examples) (Nginx or Express.js) -3. **Enforce HTTPS in specs:** Update [OpenAPI server URLs](#enforcing-https-in-your-api-specification) to use HTTPS only with automated governance -4. **Set up monitoring:** Implement [certificate monitoring](#tls-monitoring-and-troubleshooting) to track expiration dates and TLS configuration -5. **Consider mTLS:** For service-to-service communication, evaluate [mutual TLS](#mutual-tls-mtls-two-way-authentication) for cryptographic client authentication - -**Next Steps:** Now that you have secure transport with TLS, learn about [API Input Validation and Injection Prevention](api-input-validation-injection-prevention) to protect your APIs from malicious data inputs. - ---- - -## The Banking Vault Principle - -> **The Banking Vault Principle**: When banks transfer large sums between branches, they don't send cash in regular envelopes. They use armored vehicles with multiple security layers. TLS encryption works similarly — it creates a secure transport layer that protects your API data during transit, even across untrusted networks. - -**Encryption in transit** works similarly, creating a secure, private tunnel for API data as it moves between the client and the server. - -## TLS 1.3: The Modern Standard - -This secure tunnel is primarily established using **Transport Layer Security (TLS) version 1.3**, as specified in [IETF RFC 8446](https://tools.ietf.org/html/rfc8446). [NIST SP 800-52 Rev. 2](https://csrc.nist.gov/publications/detail/sp/800-52/rev-2/final) guidelines for TLS implementations unequivocally mandate TLS 1.3 for modern systems, as older protocols—including all versions of SSL, TLS 1.0, and TLS 1.1—are deprecated and considered insecure due to known vulnerabilities. - -When a client connects to an API over `https://`, it initiates a "TLS handshake." During this handshake, the client and server perform crucial steps: - -1. **Authentication:** The server presents its TLS certificate to the client to prove its identity, ensuring the client is talking to the legitimate server and not an impostor. -2. **Agreement on Encryption:** They agree on a set of cryptographic algorithms (a "cipher suite") to use for the session. -3. **Key Exchange:** They securely generate and exchange unique session keys that will be used to encrypt and decrypt all data for the remainder of the conversation. - -### TLS Handshake Process - -```mermaid -sequenceDiagram - participant C as Client - participant S as Server - - Note over C,S: TLS Handshake Process - - C->>S: 1. Client Hello (Supported cipher suites) - - S->>C: 2. Server Hello + Certificate - Note right of S: Server presents TLS certificate to prove identity - - C->>C: 3. Certificate Validation - Note left of C: Client verifies server certificate is trusted - - C->>S: 4. Cipher Suite Selection - Note over C,S: Both agree on cryptographic algorithms - - C->>S: 5. Key Exchange - S->>C: 6. Key Exchange Complete - Note over C,S: Generate and exchange unique session keys - - Note over C,S: 🔒 Secure Communication Begins - - C->>S: Encrypted API Request - S->>C: Encrypted API Response - -``` - -*Sequence diagram illustrating the TLS handshake process between client and server, showing certificate validation, cipher suite selection, and secure key exchange that ensures encrypted API communication.* - -## TLS Security Guarantees - -TLS, when done right, provides three essential security guarantees: - -* **Confidentiality:** It encrypts the data, preventing eavesdroppers from reading it. -* **Integrity:** It ensures that the data has not been altered or tampered with during transit. -* **Authentication:** It verifies the identity of the server, protecting against man-in-the-middle attacks. - -This is why secure APIs always use URLs that start with `https://` instead of `http://`. The 's' stands for 'secure' and indicates that the connection is protected by TLS encryption. - -## TLS Implementation Best Practices - -In production environments, telling teams to "use HTTPS" without specifics sometimes leads to misconfigured TLS and a false sense of security. Proper TLS implementation requires: - -* **Enforcing Strong Cipher Suites**: Configure servers to only negotiate cryptographic algorithms that are considered secure, disabling weak or obsolete ciphers -* **Proper Certificate Management**: Use certificates from trusted Certificate Authorities (CAs), ensure they are not expired, and implement robust processes for certificate issuance, renewal, and revocation -* **Protection Against Man-in-the-Middle (MiTM) Attacks**: Implement HTTP Strict Transport Security (HSTS) to instruct browsers to only communicate over HTTPS, preventing protocol downgrade attacks - -### Common TLS misconfigurations - -* Weak or legacy protocols enabled (SSL, TLS 1.0/1.1) — disable them explicitly -* Missing HSTS header — add Strict-Transport-Security with long max-age -* Mixed content or accidental HTTP endpoints — redirect to HTTPS at the edge -* Expiring certificates — monitor expiry and automate renewal - -Quick checks: - -```bash -# Verify protocol and cipher suites -openssl s_client -connect api.example.com:443 -tls1_3 -cipher 'TLS_AES_256_GCM_SHA384' < /dev/null | grep -E 'Protocol|Cipher' - -# Scan for common TLS issues -testssl.sh --fast https://api.example.com -``` - -> Expert insight: "Treat TLS as a product with owners and SLAs. We track TLS health on dashboards the same way we track latency and errors." - -## Enforcing HTTPS in Your API Specification - -The security contract for encrypted transit begins within the `servers` object of your OpenAPI specification. Every URL defined here must use the `https://` scheme—this isn't just documentation, it's a formal declaration of your API's secure endpoints. - -**OpenAPI HTTPS Enforcement** - -```yaml {% title="openapi.yaml" %} -# CRITICAL SECURITY: Only HTTPS servers in production OpenAPI specs # [!code error] -servers: - - url: https://api.production.com/v1 # [!code warning] ESSENTIAL: HTTPS only for production - description: Production Server - - url: https://api.staging.com/v1 # [!code warning] ESSENTIAL: HTTPS only for staging - description: Staging Server - # Never include HTTP servers in production specs # [!code highlight] DANGEROUS: HTTP servers are vulnerable - # - url: http://api.example.com/v1 # [!code error] NEVER DO THIS: Allows man-in-the-middle attacks -``` - -**Security Benefits**: -- **Prevents man-in-the-middle attacks** by encrypting all API traffic -- **Protects sensitive data** (API keys, user credentials, personal information) in transit -- **Enables modern web features** that require secure contexts (Service Workers, etc.) -- **Improves SEO and user trust** with browser security indicators - -### Automated Governance Enforcement - -Modern API governance tools can enforce HTTPS usage through automated validation rules. When integrated into your CI/CD pipeline, automated governance creates security gates. If a developer attempts to commit an OpenAPI file with insecure server URLs, the pipeline fails with a clear error message, preventing insecure configurations from ever reaching production. - -*Automated governance tools fail CI/CD builds when OpenAPI specifications use HTTP instead of HTTPS, requiring developers to fix security violations before deployment.* - -## TLS Configuration Examples - -Choose your server configuration based on your technology stack. Authoritative sources like the [Mozilla SSL Configuration Generator](https://ssl-config.mozilla.org/) provide excellent, up-to-date templates for secure server configurations. - -{% tabs %} - {% tab label="Nginx Configuration" %} - -### Production Nginx TLS Configuration - -```nginx {% title="nginx.conf - Production TLS Security Configuration" %} -server { - # STEP 1: Enable HTTPS with HTTP/2 for performance and security # [!code highlight] - listen 443 ssl http2; # Port 443 = HTTPS, http2 = faster + more secure - server_name api.example.com; # Your API domain - must match certificate CN/SAN - - # STEP 2: Force TLS 1.3 only - disables ALL vulnerable older versions # [!code highlight] - ssl_protocols TLSv1.3; # [!code error] CRITICAL: Blocks SSL, TLS 1.0, 1.1, 1.2 vulnerabilities - - # STEP 3: Define strong cipher suites (TLS 1.3 has built-in secure ciphers) # [!code highlight] - # These are the only ciphers clients can negotiate - all are AEAD (authenticated encryption) - ssl_ciphers TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256; - - # STEP 4: Security headers - prevent client-side attacks # [!code highlight] - # HSTS: Forces browsers to use HTTPS for ALL future requests (even if user types http://) - add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; - - # Additional security headers for defense in depth - add_header X-Frame-Options DENY always; # Prevent clickjacking - add_header X-Content-Type-Options nosniff always; # Prevent MIME confusion attacks - add_header Referrer-Policy "strict-origin-when-cross-origin" always; # Limit referrer leakage - - # STEP 5: TLS Certificate configuration - THE MOST CRITICAL PART # [!code highlight] - ssl_certificate /path/to/certificate.crt; # Public certificate (safe to share) - ssl_certificate_key /path/to/private.key; # [!code error] CRITICAL: PRIVATE KEY - never share, restrict access! - - # STEP 6: Certificate security best practices # [!code highlight] - ssl_certificate_transparency on; # Enable CT logging for transparency - ssl_stapling on; # OCSP stapling - faster cert validation - ssl_stapling_verify on; # Verify OCSP responses - ssl_trusted_certificate /path/to/chain.pem; # Certificate chain for OCSP validation - - # STEP 7: Performance optimizations that also improve security # [!code highlight] - ssl_session_cache shared:SSL:10m; # Session resumption (avoids full handshake) - ssl_session_timeout 10m; # Limit session lifetime - ssl_prefer_server_ciphers off; # Let client choose (TLS 1.3 best practice) - - # Your API routes go here... - location / { - # API backend configuration - } -} - -# STEP 8: Redirect ALL HTTP traffic to HTTPS (never serve HTTP in production) # [!code highlight] -server { - listen 80; # [!code highlight] WARNING: HTTP port - only for redirects! - server_name api.example.com; - return 301 https://$server_name$request_uri; # Permanent redirect to HTTPS -} -``` - -**Critical Configuration Notes**: -- **TLS 1.3 only**: Disables vulnerable older protocols (SSL, TLS 1.0/1.1/1.2) -- **Strong ciphers**: Only allows cryptographically secure cipher suites -- **HTTP/2**: Improves performance while maintaining security -- **HSTS header**: Forces browsers to use HTTPS, prevents downgrade attacks - -{% /tab %} -{% tab label="Express.js Configuration" %} - -### Express.js HTTPS Server with Security Headers - -```javascript {% title="secure-server.js" %} -const https = require('https'); -const fs = require('fs'); -const express = require('express'); - -const app = express(); - -// HSTS middleware - ALWAYS force HTTPS for all future requests // [!code highlight] -app.use((req, res, next) => { - res.setHeader('Strict-Transport-Security', 'max-age=31536000; includeSubDomains'); - next(); -}); - -// TLS configuration - secure defaults // [!code highlight] -const options = { - key: fs.readFileSync('private.key'), // [!code error] CRITICAL: Keep private key secure! - cert: fs.readFileSync('certificate.crt'), // Certificate file - secureProtocol: 'TLSv1_3_method' // [!code highlight] SECURITY: Force TLS 1.3 only -}; - -// Start HTTPS server on port 443 - NEVER use HTTP in production // [!code highlight] -https.createServer(options, app).listen(443, () => { - console.log('Secure API server running on https://localhost:443'); -}); -``` - -**Security Implementation Details**: -- **HSTS middleware**: Prevents protocol downgrade attacks by forcing HTTPS -- **TLS 1.3 only**: Disables vulnerable older TLS versions -- **Certificate management**: Loads TLS certificate and private key from secure files -- **Port 443**: Standard HTTPS port for production APIs - -{% /tab %} -{% /tabs %} - -## Attack Example: Heartbleed (TLS library vulnerability, 2014) - -The Heartbleed bug (CVE-2014-0160) was a critical vulnerability in the OpenSSL library, not the TLS protocol itself. It allowed attackers to read up to 64KB of a server's memory by sending a malformed TLS heartbeat request. The server would respond with not only the small payload sent by the attacker but also adjacent memory contents, which could include session cookies, user credentials, and even the server's private encryption keys. - -This incident demonstrates a crucial point: security is multi-layered. While an OpenAPI specification can enforce the *intent* of using secure transport (https://), it cannot prevent a runtime vulnerability in the underlying software stack. True "secure by design" requires both design-time governance via OpenAPI linting and runtime security posture management, including diligent vulnerability scanning and patch management. - -```mermaid -sequenceDiagram - participant A as Attacker - participant S as Vulnerable Server (OpenSSL) - - A->>S: TLS handshake - A->>S: Malformed Heartbeat Request (len >> data) - S-->>A: Memory contents leak (keys, session cookies) - A->>S: Follow-on requests using stolen secrets -``` - -*Sequence diagram showing the Heartbleed attack: malformed TLS heartbeat requests cause vulnerable OpenSSL servers to leak memory contents including encryption keys and session data.* - -Why this matters: TLS is only as strong as its implementation. Monitoring and rapid patching for library CVEs are part of infrastructure security. - -## Mutual TLS (mTLS): Two-Way Authentication - -While standard TLS only authenticates the server to the client, **Mutual TLS (mTLS)** requires both parties to authenticate each other using certificates. This provides stronger security for high-trust scenarios and is essential for implementing zero-trust architecture principles. - -**mTLS Use Cases:** -- Microservice communication in zero-trust architectures where no network segment is inherently trusted -- API-to-API authentication between organizations implementing defense-in-depth strategies -- IoT device authentication in distributed systems -- High-security financial and healthcare APIs requiring cryptographic identity verification - -**OpenAPI mTLS Security Definition** - -```yaml {% title="openapi.yaml" %} -components: - securitySchemes: - mtlsAuth: - type: mutualTLS # [!code highlight] - description: "Client certificate authentication for zero-trust architecture" # [!code highlight] - -# Apply mTLS to sensitive internal operations -paths: - /internal/payments: - post: - security: - - mtlsAuth: [] # [!code highlight] - summary: "Process payment (internal service only)" - /public/info: - get: - # No mTLS required for public endpoints # [!code highlight] - summary: "Public information endpoint" -``` - -**mTLS Security Benefits**: -- **Cryptographic authentication**: Both client and server prove identity with certificates -- **Zero-trust architecture**: No implicit trust based on network location -- **Non-repudiation**: Certificate-based proof of communication participants - -**mTLS Nginx Configuration** - -```nginx {% title="nginx-mtls.conf" %} -server { - listen 443 ssl http2; - - # Server certificate (authenticates server to client) - ssl_certificate /path/to/server.crt; # Public certificate for server identity - ssl_certificate_key /path/to/server.key; # Private key (keep secure!) - - # Client certificate verification (authenticates client to server) - ssl_verify_client on; # Require valid client certificates - ssl_client_certificate /path/to/ca.crt; # CA that signed client certificates - - # Pass client certificate details to application - proxy_set_header X-Client-Cert $ssl_client_cert; # Full client certificate - proxy_set_header X-Client-Verify $ssl_client_verify; # Verification status - proxy_set_header X-Client-DN $ssl_client_s_dn; # Client Distinguished Name -} -``` - -**mTLS Flow**: Client presents certificate → Nginx validates against CA → Application receives verified client identity → Both parties authenticated cryptographically - -> **mTLS Best Practice**: Use mTLS for service-to-service communication and regular TLS + [JWT/OAuth2](authentication-authorization-openapi) for client-to-server communication. - -## TLS Monitoring and Troubleshooting - -Choose your monitoring approach based on your infrastructure: - -{% tabs %} - {% tab label="Certificate Monitoring (Prometheus)" %} - -### Certificate Monitoring - -```yaml {% title="prometheus.yml" %} -groups: -- name: tls_alerts - rules: - - alert: TLSCertificateExpiringSoon - expr: probe_ssl_earliest_cert_expiry - time() < 86400 * 30 # [!code highlight] 30-day warning - labels: - severity: warning - annotations: - summary: "TLS certificate expires in less than 30 days" - - - alert: WeakTLSVersion - expr: probe_tls_version_info{version!="TLS 1.3"} == 1 # [!code highlight] TLS version check - labels: - severity: critical - annotations: - summary: "Weak TLS version detected" -``` - -**How certificate monitoring works:** -- **Expiration alerts**: Warns 30 days before certificate expiry to allow renewal time -- **TLS version monitoring**: Detects servers using outdated TLS versions -- **Automated scanning**: Regularly probes endpoints to verify TLS configuration -- **Alert routing**: Sends notifications to security and ops teams for immediate action - -{% /tab %} -{% tab label="Troubleshooting Steps" %} - -### Common TLS Troubleshooting Steps - -**Certificate Issues:** -- Expired certificates — monitor expiry dates and automate renewal -- Certificate chain problems — verify intermediate certificates are included -- Certificate-hostname mismatch — ensure certificate covers all domains used - -**Configuration Issues:** -- Weak cipher suites — disable deprecated algorithms and enable only strong ciphers -- Missing HSTS headers — add Strict-Transport-Security to prevent downgrade attacks -- Mixed content warnings — ensure all resources load over HTTPS - -**Quick Verification Commands:** -```bash -# Test TLS connection and certificate -curl -vI https://api.example.com 2>&1 | grep -E 'SSL|TLS|certificate' - -# Verify certificate chain -openssl s_client -showcerts -connect api.example.com:443 < /dev/null - -# Check certificate expiry -echo | openssl s_client -servername api.example.com -connect api.example.com:443 2>/dev/null | \ -openssl x509 -noout -dates -``` - -**Common issues and solutions:** -- **Certificate chain issues**: Use `openssl s_client -showcerts` to verify intermediate certificates -- **TLS version problems**: Check server configuration restricts to TLS 1.3 only -- **HSTS warnings**: Add `Strict-Transport-Security` header to prevent downgrade attacks - -{% /tab %} -{% /tabs %} - -## Frequently Asked Questions - -### Why can't I use HTTP for internal APIs? -Even internal networks can be compromised. Using HTTPS everywhere (zero-trust approach) protects against insider threats, lateral movement attacks, and accidental data exposure. The performance overhead of [TLS 1.3](#tls-13-the-modern-standard) is minimal with modern hardware and HTTP/2. See [OpenAPI HTTPS enforcement](#enforcing-https-in-your-api-specification) for implementation guidance. - -### How often should I rotate TLS certificates? -Most organizations use certificates with 1-year validity and rotate them every 6-12 months. Automated certificate management tools like Let's Encrypt or cloud provider certificate services can handle this automatically. Implement [certificate monitoring](#tls-monitoring-and-troubleshooting) to track expiration dates. - -### What's the difference between TLS and SSL? -SSL (Secure Sockets Layer) is the predecessor to TLS. SSL versions are deprecated and insecure. When people say "SSL certificate" or "SSL/TLS," they're usually referring to modern TLS. Always use [TLS 1.2 or preferably TLS 1.3](#tls-13-the-modern-standard) as shown in our [configuration examples](#tls-configuration-examples). - -### Should I implement certificate pinning for API clients? -Certificate pinning can improve security by preventing man-in-the-middle attacks, but it adds operational complexity. Consider it for high-security applications, but ensure you have a robust certificate rotation and backup pin management process. - -## Resources and Next Steps - -### Essential Reading -- [IETF RFC 8446](https://tools.ietf.org/html/rfc8446) - TLS 1.3 protocol specification and security requirements -- [NIST SP 800-52 Rev. 2](https://csrc.nist.gov/publications/detail/sp/800-52/rev-2/final) - Official guidelines for secure TLS implementation -- [Mozilla SSL Configuration Generator](https://ssl-config.mozilla.org/) - Generate secure TLS configurations for various platforms - -### Implementation Tools -- [Let's Encrypt](https://letsencrypt.org/) - Free, automated certificate authority for TLS certificates -- [testssl.sh](https://testssl.sh/) - Command-line tool for testing TLS/SSL implementations -- [SSL Labs Server Test](https://www.ssllabs.com/ssltest/) - Online tool for testing TLS configuration - -### Related Security Topics -- [API Input Validation and Injection Prevention](api-input-validation-injection-prevention) - Protect APIs from malicious data -- [Authentication and Authorization with OpenAPI](authentication-authorization-openapi) - Implement secure access control -- [API Rate Limiting and Abuse Prevention](api-rate-limiting-abuse-prevention) - Prevent DoS attacks and brute force attempts -- [API Security by Design: Complete Guide](/learn/security) - Overview of all API security domains \ No newline at end of file From 15abbe7ca3c75c5da9c03bb5b67a1d21ffdcea91 Mon Sep 17 00:00:00 2001 From: Matt Williams Date: Tue, 30 Sep 2025 11:45:39 -0500 Subject: [PATCH 16/27] Fix YAML frontmatter - quote title with colon --- learn/security/index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/learn/security/index.md b/learn/security/index.md index 44201d36..20c11e4b 100644 --- a/learn/security/index.md +++ b/learn/security/index.md @@ -1,8 +1,8 @@ --- -title: API Security by Design: Framework and Fundamentals +title: "API Security by Design: Framework and Fundamentals" description: Build secure APIs from the ground up using OpenAPI security contracts and automated governance. seo: - title: API Security by Design: Framework and Fundamentals + title: "API Security by Design: Framework and Fundamentals" description: Build secure APIs from the ground up using OpenAPI security contracts and automated governance. --- From 0eda6a62ef0ad577f4ed04c67d4ccd2efbac8029 Mon Sep 17 00:00:00 2001 From: Matt Williams Date: Tue, 30 Sep 2025 11:45:53 -0500 Subject: [PATCH 17/27] Fix YAML frontmatter - quote title with colon --- learn/security/index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/learn/security/index.md b/learn/security/index.md index 44201d36..20c11e4b 100644 --- a/learn/security/index.md +++ b/learn/security/index.md @@ -1,8 +1,8 @@ --- -title: API Security by Design: Framework and Fundamentals +title: "API Security by Design: Framework and Fundamentals" description: Build secure APIs from the ground up using OpenAPI security contracts and automated governance. seo: - title: API Security by Design: Framework and Fundamentals + title: "API Security by Design: Framework and Fundamentals" description: Build secure APIs from the ground up using OpenAPI security contracts and automated governance. --- From f3de1cacca8e27abc44d6df50c972ebc4f70c4d9 Mon Sep 17 00:00:00 2001 From: Matt Williams Date: Tue, 30 Sep 2025 11:48:42 -0500 Subject: [PATCH 18/27] Add stub articles for other security topics to prevent broken sidebar links --- ...i-input-validation-injection-prevention.md | 24 +++++++++++++++++++ .../api-rate-limiting-abuse-prevention.md | 24 +++++++++++++++++++ ...api-tls-encryption-https-best-practices.md | 24 +++++++++++++++++++ 3 files changed, 72 insertions(+) create mode 100644 learn/security/api-input-validation-injection-prevention.md create mode 100644 learn/security/api-rate-limiting-abuse-prevention.md create mode 100644 learn/security/api-tls-encryption-https-best-practices.md diff --git a/learn/security/api-input-validation-injection-prevention.md b/learn/security/api-input-validation-injection-prevention.md new file mode 100644 index 00000000..eea94964 --- /dev/null +++ b/learn/security/api-input-validation-injection-prevention.md @@ -0,0 +1,24 @@ +--- +title: Input Validation and Injection Prevention +description: Prevent API injection attacks and mass assignment vulnerabilities using OpenAPI schema validation and automated governance. +seo: + title: Input Validation and Injection Prevention + description: Prevent API injection attacks and mass assignment vulnerabilities using OpenAPI schema validation and automated governance. +--- + +# Input Validation and Injection Prevention + +*This comprehensive guide is coming soon and will cover:* + +## What You'll Learn + +- **SQL Injection Prevention**: Parameterized queries and input sanitization +- **Mass Assignment Protection**: Schema-based validation and field filtering +- **OpenAPI Validation**: Schema constraints and automated enforcement +- **OWASP API Security**: Addressing Top 10 injection vulnerabilities +- **Real-World Examples**: Code samples in Node.js with security patterns +- **Automated Governance**: CI/CD validation rules and policy enforcement + +--- + +*This article is currently under review and will be available soon. Return to the [API Security Framework and Fundamentals](.) to explore other security topics.* diff --git a/learn/security/api-rate-limiting-abuse-prevention.md b/learn/security/api-rate-limiting-abuse-prevention.md new file mode 100644 index 00000000..b97ceced --- /dev/null +++ b/learn/security/api-rate-limiting-abuse-prevention.md @@ -0,0 +1,24 @@ +--- +title: Rate Limiting and Abuse Prevention +description: Implement API rate limiting strategies to prevent DoS attacks, brute force attempts, and business logic abuse. +seo: + title: Rate Limiting and Abuse Prevention + description: Implement API rate limiting strategies to prevent DoS attacks, brute force attempts, and business logic abuse. +--- + +# Rate Limiting and Abuse Prevention for APIs + +*This comprehensive guide is coming soon and will cover:* + +## What You'll Learn + +- **Rate Limiting Algorithms**: Token bucket, sliding window, and fixed window approaches +- **OpenAPI Documentation**: x-rateLimit extensions and client communication +- **Multi-Tier Protection**: Global, per-endpoint, and per-client rate limiting +- **Abuse Detection**: Pattern recognition and automated response strategies +- **Real-World Examples**: Implementation patterns in Node.js and Redis +- **Monitoring & Observability**: Metrics collection and alerting strategies + +--- + +*This article is currently under review and will be available soon. Return to the [API Security Framework and Fundamentals](.) to explore other security topics.* diff --git a/learn/security/api-tls-encryption-https-best-practices.md b/learn/security/api-tls-encryption-https-best-practices.md new file mode 100644 index 00000000..1d12fcf3 --- /dev/null +++ b/learn/security/api-tls-encryption-https-best-practices.md @@ -0,0 +1,24 @@ +--- +title: TLS Encryption and HTTPS Best Practices for APIs +description: Protect data in transit with proper TLS configuration, certificate management, and HTTPS enforcement using OpenAPI security contracts. +seo: + title: TLS Encryption and HTTPS Best Practices for APIs + description: Protect data in transit with proper TLS configuration, certificate management, and HTTPS enforcement using OpenAPI security contracts. +--- + +# TLS Encryption and HTTPS Best Practices for APIs + +*This comprehensive guide is coming soon and will cover:* + +## What You'll Learn + +- **TLS 1.3 Configuration**: Modern encryption standards and cipher suite selection +- **Certificate Management**: Best practices for SSL/TLS certificate lifecycle +- **OpenAPI Security Contracts**: Enforcing HTTPS-only APIs through specifications +- **Mutual TLS (mTLS)**: Service-to-service cryptographic authentication +- **Real-World Examples**: Configuration examples for Nginx and Express.js +- **Automated Governance**: CI/CD integration for transport security validation + +--- + +*This article is currently under review and will be available soon. Return to the [API Security Framework and Fundamentals](.) to explore other security topics.* From c88dcb203a92084ab6408953de602f815ea63294 Mon Sep 17 00:00:00 2001 From: Matt Williams Date: Tue, 30 Sep 2025 12:09:31 -0500 Subject: [PATCH 19/27] Add security validation reference files for future review - Add redocly.yaml: Production-ready security validation configuration (505 lines) - Add security-functions.ts: TypeScript custom security validation functions (239 lines) - Files placed in _filesets directory for review purposes only (not linked in navigation) - Includes 4 advanced validation functions: checkOperationSecurity, validateAdminSecurity, validateOAuthScopes, validateRateLimitConsistency --- learn/security/_filesets/redocly.yaml | 505 ++++++++++++++++++ .../security/_filesets/security-functions.ts | 239 +++++++++ 2 files changed, 744 insertions(+) create mode 100644 learn/security/_filesets/redocly.yaml create mode 100644 learn/security/_filesets/security-functions.ts diff --git a/learn/security/_filesets/redocly.yaml b/learn/security/_filesets/redocly.yaml new file mode 100644 index 00000000..e83beb0d --- /dev/null +++ b/learn/security/_filesets/redocly.yaml @@ -0,0 +1,505 @@ +# Redocly Security Ruleset +# Based on OWASP API Security Top 10 2023 +# https://owasp.org/www-project-api-security/ + +plugins: + - './security-functions.js' + + +# Enable built-in security rules +rules: + # Built-in Redocly security rules + security-defined: error + operation-4xx-response: error + operation-2xx-response: error + no-unresolved-refs: error + + # ========================================== + # API1:2023 - Broken Object Level Authorization + # ========================================== + + # Prevent numeric IDs that can be easily guessed + rule/no-numeric-ids: + subject: + type: Schema + property: type + filterInParentKeys: [path] + where: + - subject: + type: Parameter + property: name + assertions: + pattern: /(^id$|_id$|Id$|-id$)/ + assertions: + enum: [string] + message: "Use random IDs that cannot be guessed (UUIDs are preferred). Avoid integer IDs in path parameters." + severity: error + + # Ensure ID parameters use appropriate formats + rule/id-format-required: + subject: + type: Schema + property: format + filterInParentKeys: [path] + where: + - subject: + type: Parameter + property: name + assertions: + pattern: /(^id$|_id$|Id$|-id$)/ + assertions: + enum: [uuid, uri, password] + message: "ID parameters should specify a secure format like 'uuid'." + severity: warn + + # ========================================== + # API2:2023 - Broken Authentication + # ========================================== + + # Enforce HTTPS for all server URLs + rule/https-server-urls: + subject: + type: Server + property: url + assertions: + pattern: /^https:/ + message: "Server URLs must use HTTPS protocol. HTTP is insecure and exposes data to interception." + severity: error + + # Prevent HTTP Basic authentication + rule/no-http-basic-auth: + subject: + type: SecurityScheme + property: scheme + where: + - subject: + type: SecurityScheme + property: type + assertions: + const: http + assertions: + notPattern: /^basic$/i + message: "HTTP Basic authentication is insecure. Use OAuth 2.0, API keys in headers, or other secure methods." + severity: error + + # Prevent API keys in URL (query/path) + rule/no-api-keys-in-url: + subject: + type: SecurityScheme + property: in + where: + - subject: + type: SecurityScheme + property: type + assertions: + const: apiKey + assertions: + enum: [header, cookie] + message: "API keys must not be in URL (query or path parameters). Use headers or cookies instead." + severity: error + + # Prevent credentials in parameter names + rule/no-credentials-in-parameters: + subject: + type: Parameter + property: name + filterInParentKeys: [query, path] + assertions: + notPattern: /(secret|token|access.?token|refresh.?token|id.?token|password|api.?key|credential)/i + message: "Parameter names must not contain credential-related terms. Use secure authentication headers instead." + severity: error + + # Ensure write operations are protected + rule/write-operations-secured: + subject: + type: Operation + property: security + filterInParentKeys: [post, put, patch, delete] + assertions: + defined: true + nonEmpty: true + message: "Write operations (POST, PUT, PATCH, DELETE) must be protected by security schemes." + severity: error + + # JWT bearer format security schemes should reference RFC8725 + rule/jwt-rfc8725-compliance: + subject: + type: SecurityScheme + property: description + where: + - subject: + type: SecurityScheme + property: bearerFormat + assertions: + pattern: /jwt/i + assertions: + pattern: /RFC\s*8725/i + message: "JWT security schemes must reference RFC8725 compliance in description for security best practices." + severity: error + + # Advanced cross-operation security validation (requires custom functions) + rule/comprehensive-security-check: + subject: + type: Root + assertions: + security/checkOperationSecurity: + methods: [post, put, patch, delete] + nullable: false + message: "All write operations must have properly configured security schemes" + severity: error + + # ========================================== + # API3:2023 - Broken Object Property Level Authorization + # ========================================== + + # Prevent unconstrained additionalProperties + rule/no-additional-properties: + subject: + type: Schema + property: additionalProperties + where: + - subject: + type: Schema + property: type + assertions: + const: object + assertions: + const: false + message: "Objects should not allow additionalProperties. Set to false to prevent mass assignment vulnerabilities." + severity: warn + + # Require maxProperties when additionalProperties is not false + rule/constrained-additional-properties: + subject: + type: Schema + property: maxProperties + where: + - subject: + type: Schema + property: type + assertions: + const: object + - subject: + type: Schema + property: additionalProperties + assertions: + defined: true + notPattern: /^false$/ + assertions: + defined: true + message: "Objects with additionalProperties should define maxProperties to limit resource consumption." + severity: warn + + # ========================================== + # API4:2023 - Unrestricted Resource Consumption + # ========================================== + + # Require rate limiting headers in responses + rule/rate-limit-headers-present: + subject: + type: Header + where: + - subject: + type: Response + filterInParentKeys: ["200", "201", "202", "204", "400", "401", "403", "404", "422", "429"] + assertions: + defined: true + assertions: + pattern: /^(RateLimit|RateLimit-Limit|X-RateLimit-Limit|X-Rate-Limit-Limit)$/i + message: "2XX and 4XX responses should include rate limiting headers (RateLimit, RateLimit-Limit, X-RateLimit-Limit, or X-Rate-Limit-Limit)." + severity: warn + + # Require 429 Too Many Requests response + rule/require-429-response: + subject: + type: Responses + property: "429" + assertions: + defined: true + message: "Operations should define a 429 (Too Many Requests) response for rate limiting." + severity: warn + + # Retry-After header required for 429 responses + rule/retry-after-header-429: + subject: + type: Header + where: + - subject: + type: Response + filterInParentKeys: ["429"] + assertions: + defined: true + assertions: + pattern: /^Retry-After$/i + message: "429 responses must include a Retry-After header to indicate when clients can retry." + severity: error + + # Array schemas must specify maxItems + rule/array-max-items: + subject: + type: Schema + property: maxItems + where: + - subject: + type: Schema + property: type + assertions: + const: array + assertions: + defined: true + message: "Array schemas must specify maxItems to prevent resource exhaustion attacks." + severity: error + + # String schemas must have length constraints + rule/string-length-limit: + subject: + type: Schema + where: + - subject: + type: Schema + property: type + assertions: + const: string + assertions: + requireAny: + - maxLength + - enum + - const + - pattern + message: "String schemas must specify maxLength, enum, const, or pattern to limit resource consumption." + severity: error + + # Integer schemas must have min/max constraints + rule/integer-constraints: + subject: + type: Schema + where: + - subject: + type: Schema + property: type + assertions: + const: integer + assertions: + required: [minimum, maximum] + message: "Integer schemas must specify minimum and maximum values to prevent resource exhaustion." + severity: error + + # Integer schemas should specify format + rule/integer-format: + subject: + type: Schema + property: format + where: + - subject: + type: Schema + property: type + assertions: + const: integer + assertions: + enum: [int32, int64] + message: "Integer schemas should specify format (int32 or int64) for precise validation." + severity: warn + + # Advanced rate limiting consistency validation (requires custom functions) + rule/rate-limit-consistency: + subject: + type: Root + assertions: + security/validateRateLimitConsistency: + requiredHeaders: [RateLimit, X-RateLimit-Limit, X-Rate-Limit-Limit] + message: "Rate limiting configurations should be consistent across operations" + severity: warn + + # ========================================== + # API5:2023 - Broken Function Level Authorization + # ========================================== + + # Administrative endpoints should have stricter security + rule/admin-endpoints-secured: + subject: + type: Operation + property: security + where: + - subject: + type: PathItem + assertions: + pattern: /(admin|manage|control|configure)/i + assertions: + defined: true + nonEmpty: true + message: "Administrative endpoints must have defined security schemes with appropriate authorization levels." + severity: error + + # Advanced admin security isolation validation (requires custom functions) + rule/admin-security-isolation: + subject: + type: Root + assertions: + security/validateAdminSecurity: + adminUrlPattern: "/admin" + message: "Administrative endpoints must use different security schemes than regular operations" + severity: error + + # Advanced OAuth scope validation (requires custom functions) + rule/oauth-scope-validation: + subject: + type: Root + assertions: + security/validateOAuthScopes: + adminOperations: [delete, post, put, patch] + requiredAdminScopes: [admin, write, manage] + adminPathPatterns: ["/admin", "/manage", "/config", "/system"] + message: "OAuth scopes must be appropriate for operation sensitivity" + severity: error + + # ========================================== + # API7:2023 - Server Side Request Forgery + # ========================================== + + # Warn about URL parameters that might lead to SSRF + rule/ssrf-url-parameters: + subject: + type: Parameter + property: name + assertions: + notPattern: /(callback|redirect|url|uri|endpoint|webhook|fetch|proxy)/i + message: "URL-related parameters may be vulnerable to Server Side Request Forgery. Ensure proper validation and allowlisting." + severity: warn + + # ========================================== + # API8:2023 - Security Misconfiguration + # ========================================== + + # Require CORS headers in responses + rule/cors-access-control-allow-origin: + subject: + type: Header + where: + - subject: + type: Response + assertions: + defined: true + assertions: + pattern: /^Access-Control-Allow-Origin$/i + message: "Responses should define CORS headers (Access-Control-Allow-Origin) to control cross-origin access." + severity: warn + + # Require error response schemas (400, 401, 403, 500) + rule/error-responses-defined: + subject: + type: Responses + assertions: + requireAny: ["400", "401", "403", "422", "4XX"] + message: "Operations should define appropriate error responses (400, 401, 403, 422, or 4XX) with proper schemas." + severity: warn + + # Require 401 unauthorized responses for secured operations + rule/unauthorized-response-required: + subject: + type: Responses + property: "401" + where: + - subject: + type: Operation + property: security + assertions: + defined: true + assertions: + defined: true + message: "Secured operations should define 401 (Unauthorized) responses." + severity: warn + + # Require 500 server error responses + rule/server-error-response: + subject: + type: Responses + property: "500" + assertions: + defined: true + message: "Operations should define 500 (Internal Server Error) responses to handle server errors gracefully." + severity: warn + + # ========================================== + # API9:2023 - Improper Inventory Management + # ========================================== + + # Server objects should declare internal/external audience + rule/server-audience-declaration: + subject: + type: Server + property: x-internal + assertions: + defined: true + enum: ['true', 'false'] + message: "Servers should declare their intended audience using x-internal (true for internal, false for external)." + severity: error + + # Server descriptions should indicate environment + rule/server-environment-declaration: + subject: + type: Server + property: description + assertions: + pattern: /(local|dev|development|test|testing|stage|staging|prod|production|live|sandbox)/i + message: "Server descriptions should clearly indicate the environment (development, testing, staging, production)." + severity: error + + # API version should be clearly defined + rule/api-version-defined: + subject: + type: Info + property: version + assertions: + defined: true + pattern: /^\d+\.\d+\.\d+/ + message: "API version should be clearly defined using semantic versioning (e.g., 1.0.0)." + severity: error + + # ========================================== + # Additional Security Rules + # ========================================== + + # Prevent sensitive data in examples + rule/no-sensitive-data-in-examples: + subject: + type: Schema + property: example + assertions: + notPattern: /(password|secret|token|key|credential|ssn|social.?security|credit.?card|api.?key)/i + message: "Examples should not contain sensitive data like passwords, tokens, or personal information." + severity: warn + + # Ensure request bodies have proper content types + rule/secure-content-types: + subject: + type: MediaType + where: + - subject: + type: RequestBody + assertions: + defined: true + assertions: + enum: + - application/json + - application/xml + - application/x-www-form-urlencoded + - multipart/form-data + - text/plain + message: "Use secure and well-defined content types. Avoid allowing arbitrary content types." + severity: warn + + # Prevent overly broad schemas + rule/no-empty-schemas: + subject: + type: Schema + assertions: + requireAny: + - type + - properties + - items + - allOf + - anyOf + - oneOf + - $ref + message: "Schemas should not be empty. Define proper constraints to prevent accepting arbitrary data." + severity: error diff --git a/learn/security/_filesets/security-functions.ts b/learn/security/_filesets/security-functions.ts new file mode 100644 index 00000000..9e91d6ae --- /dev/null +++ b/learn/security/_filesets/security-functions.ts @@ -0,0 +1,239 @@ +// Custom security validation functions for Redocly +// These implement the advanced security checks from the Spectral OWASP ruleset + +export default function securityPlugin() { + return { + id: 'security', + assertions: { + // Validates that operations have appropriate security based on HTTP method + checkOperationSecurity: (openapi, options, ctx) => { + const errors = []; + const { methods = [], nullable = false } = options; + const { paths, security: globalSecurity } = openapi; + + if (!paths || typeof paths !== 'object') { + return errors; + } + + // Iterate through all operations + for (const [pathKey, pathItem] of Object.entries(paths)) { + if (!pathItem || typeof pathItem !== 'object') continue; + + const httpMethods = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']; + + for (const method of httpMethods) { + const operation = pathItem[method]; + if (!operation || typeof operation !== 'object') continue; + + // Skip if method not in configured methods list + if (methods.length > 0 && !methods.includes(method)) continue; + + let operationSecurity = operation.security; + + // Fall back to global security if operation security not defined + if (operationSecurity === undefined) { + operationSecurity = globalSecurity; + } + + // Check if security is properly defined + if (!operationSecurity || operationSecurity.length === 0) { + errors.push({ + message: `${method.toUpperCase()} operation at ${pathKey} has no security scheme defined`, + location: ctx.baseLocation.child(['paths', pathKey, method, 'security']), + }); + continue; + } + + // Validate each security requirement + if (Array.isArray(operationSecurity)) { + for (const [idx, securityEntry] of operationSecurity.entries()) { + if (typeof securityEntry !== 'object') continue; + + const securitySchemeIds = Object.keys(securityEntry); + if (securitySchemeIds.length === 0 && !nullable) { + errors.push({ + message: `${method.toUpperCase()} operation at ${pathKey} has empty security requirement at index ${idx}`, + location: ctx.baseLocation.child(['paths', pathKey, method, 'security', idx]), + }); + } + } + } + } + } + + return errors; + }, + + // Ensures admin endpoints use different security schemes than regular endpoints + validateAdminSecurity: (openapi, options, ctx) => { + const errors = []; + const { adminUrlPattern = '/admin' } = options; + const { paths } = openapi; + + if (!paths || typeof paths !== 'object') { + return errors; + } + + const nonAdminSecurityHashes = new Set(); + const adminSecurityEntries = []; + + // First pass: collect all security configurations + for (const [pathKey, pathItem] of Object.entries(paths)) { + if (!pathItem || typeof pathItem !== 'object') continue; + + const httpMethods = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']; + + for (const method of httpMethods) { + const operation = pathItem[method]; + if (!operation || typeof operation !== 'object') continue; + + const operationSecurity = operation.security; + if (!operationSecurity || !Array.isArray(operationSecurity)) continue; + + // Create hash of security configuration for comparison + const securityHash = JSON.stringify(operationSecurity); + + if (pathKey.includes(adminUrlPattern)) { + adminSecurityEntries.push({ + path: pathKey, + method, + hash: securityHash, + location: ctx.baseLocation.child(['paths', pathKey, method, 'security']), + }); + } else { + nonAdminSecurityHashes.add(securityHash); + } + } + } + + // Second pass: validate admin endpoints use unique security + for (const adminEntry of adminSecurityEntries) { + if (nonAdminSecurityHashes.has(adminEntry.hash)) { + errors.push({ + message: `Admin endpoint ${adminEntry.path} (${adminEntry.method.toUpperCase()}) uses the same security scheme as non-admin endpoints. Admin operations should have stricter authentication.`, + location: adminEntry.location, + }); + } + } + + return errors; + }, + + // Validates OAuth scopes are appropriate for operation sensitivity + validateOAuthScopes: (openapi, options, ctx) => { + const errors = []; + const { + adminOperations = ['delete', 'post', 'put', 'patch'], + requiredAdminScopes = ['admin', 'write', 'manage'], + adminPathPatterns = ['/admin', '/manage', '/config'] + } = options; + + const { paths, components } = openapi; + + if (!paths || !components?.securitySchemes) { + return errors; + } + + // Find OAuth2 security schemes + const oauthSchemes = Object.entries(components.securitySchemes) + .filter(([_, scheme]) => scheme.type === 'oauth2') + .map(([name, _]) => name); + + if (oauthSchemes.length === 0) return errors; + + for (const [pathKey, pathItem] of Object.entries(paths)) { + if (!pathItem || typeof pathItem !== 'object') continue; + + const isAdminPath = adminPathPatterns.some(pattern => pathKey.includes(pattern)); + + for (const method of adminOperations) { + const operation = pathItem[method]; + if (!operation || typeof operation !== 'object') continue; + + const operationSecurity = operation.security; + if (!operationSecurity || !Array.isArray(operationSecurity)) continue; + + // Check if this operation uses OAuth and has appropriate scopes + for (const securityReq of operationSecurity) { + for (const [schemeName, scopes] of Object.entries(securityReq)) { + if (oauthSchemes.includes(schemeName)) { + const hasAdminScope = requiredAdminScopes.some(scope => + Array.isArray(scopes) && scopes.includes(scope) + ); + + if ((isAdminPath || adminOperations.includes(method)) && !hasAdminScope) { + errors.push({ + message: `${method.toUpperCase()} operation at ${pathKey} should require admin scopes (${requiredAdminScopes.join(', ')}) for sensitive operations`, + location: ctx.baseLocation.child(['paths', pathKey, method, 'security']), + }); + } + } + } + } + } + } + + return errors; + }, + + // Validates rate limiting configuration consistency + validateRateLimitConsistency: (openapi, options, ctx) => { + const errors = []; + const { requiredHeaders = ['RateLimit', 'X-RateLimit-Limit'] } = options; + const { paths } = openapi; + + if (!paths || typeof paths !== 'object') { + return errors; + } + + const rateLimitConfigs = new Map(); + + // Collect all rate limiting configurations + for (const [pathKey, pathItem] of Object.entries(paths)) { + if (!pathItem || typeof pathItem !== 'object') continue; + + const httpMethods = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options']; + + for (const method of httpMethods) { + const operation = pathItem[method]; + if (!operation?.responses) continue; + + for (const [statusCode, response] of Object.entries(operation.responses)) { + if (!statusCode.match(/^[24]/)) continue; // Only 2xx and 4xx responses + + const headers = response.headers || {}; + const hasRateLimit = requiredHeaders.some(header => headers[header]); + + if (hasRateLimit) { + const config = requiredHeaders + .filter(header => headers[header]) + .map(header => ({ header, schema: headers[header] })); + + const configKey = `${pathKey}:${method}`; + rateLimitConfigs.set(configKey, config); + } + } + } + } + + // Validate consistency across operations + const configValues = Array.from(rateLimitConfigs.values()); + if (configValues.length > 1) { + const firstConfig = JSON.stringify(configValues[0]); + + for (const [pathMethod, config] of rateLimitConfigs.entries()) { + if (JSON.stringify(config) !== firstConfig) { + const [path, method] = pathMethod.split(':'); + errors.push({ + message: `Rate limiting configuration at ${path} (${method.toUpperCase()}) differs from other operations. Consider using consistent rate limiting headers across your API.`, + location: ctx.baseLocation.child(['paths', path, method, 'responses']), + }); + } + } + } + + return errors; + } + }, + }; +} From 63248a6e35fb8aef4769b5d78b3ea5a8140c5e0d Mon Sep 17 00:00:00 2001 From: Matt Williams Date: Tue, 7 Oct 2025 14:02:52 -0500 Subject: [PATCH 20/27] Fix: Comment out plugin reference in _filesets redocly.yaml This is a reference file for review purposes only and should not attempt to load plugins during build. --- learn/security/_filesets/redocly.yaml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/learn/security/_filesets/redocly.yaml b/learn/security/_filesets/redocly.yaml index e83beb0d..4c8d1c11 100644 --- a/learn/security/_filesets/redocly.yaml +++ b/learn/security/_filesets/redocly.yaml @@ -2,8 +2,10 @@ # Based on OWASP API Security Top 10 2023 # https://owasp.org/www-project-api-security/ -plugins: - - './security-functions.js' +# NOTE: This is a reference file for review purposes only +# Plugin reference commented out to prevent build errors +# plugins: +# - './security-functions.js' # Enable built-in security rules From be2eaca348b26b337b9bcade25ab5fb638482e5c Mon Sep 17 00:00:00 2001 From: Matt Williams Date: Tue, 7 Oct 2025 15:27:06 -0500 Subject: [PATCH 21/27] Fix: Apply sentence casing to all headings per reviewer feedback - Changed all headings from title case to sentence case - Addresses @adamaltman review comment on PR #109 --- learn/security/index.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/learn/security/index.md b/learn/security/index.md index 20c11e4b..60a4a736 100644 --- a/learn/security/index.md +++ b/learn/security/index.md @@ -12,7 +12,7 @@ _Build secure APIs from the ground up using OpenAPI security contracts and autom --- -## Key Takeaways +## Key takeaways Many teams discover security vulnerabilities after they're already in production, but it doesn't have to be that way! @@ -26,19 +26,19 @@ This comprehensive guide shows you how to turn your OpenAPI specification into a --- -## From Reactive Patching to Proactive API Security +## From reactive patching to proactive API security High-profile data breaches frequently trace back to insecure APIs, exposing a fundamental flaw in traditional security approaches. The conventional method—identifying and patching vulnerabilities in production—is reactive, costly, and ultimately inadequate. In its typical form, this paradigm treats security as an afterthought. Shifting security practices to the left in the development lifecycle, known as the "shift-left" imperative, addresses this by integrating security into the earliest stages of design and development. This proactive model prevents vulnerabilities from being introduced in the first place, rather than attempting to remediate them under pressure in production environments. -### OpenAPI as Your Security Contract +### OpenAPI as your security contract The core of this strategy is treating your OpenAPI specification not merely as documentation, but as an executable security contract. This contract declaratively defines a set of security requirements, constraints, and policies before any application code is written. It becomes the single source of truth that dictates how an API must behave to be considered secure, effectively implementing a "policy-as-code" approach for APIs. However, a contract, much like a law, is only as strong as its enforcement. This is where automated governance and linting tools provide value by transforming your contract into dynamic, automated guardrails that validate security requirements at every stage of development. When integrated into a Continuous Integration/Continuous Deployment (CI/CD) pipeline, this automated governance acts as a gatekeeper, failing builds that violate the security contract and requiring fixes before deployment. -## The Four Pillars of API Security +## The four pillars of API security Building secure APIs doesn't have to feel like playing whack-a-mole with vulnerabilities. Once you shift from reactive patching to proactive design, you'll wonder why you ever did it any other way. Let's explore how to make security an automatic part of your API development process. @@ -68,7 +68,7 @@ graph TD *Architecture diagram showing the four essential areas of API security (TLS encryption, input validation, rate limiting, access control) supported by OpenAPI specifications and automated governance tools.* -## Deep Dive Guides +## Deep dive guides Each security domain requires specific knowledge and implementation techniques. Choose the guide that matches your current focus: @@ -126,11 +126,11 @@ Each security domain requires specific knowledge and implementation techniques. **Perfect for:** Identity and access management teams, full-stack developers, and security engineers -## Understanding Design-Time vs Runtime Security +## Understanding design-time vs runtime security It's important to understand that OpenAPI-based security governance operates at **design-time**, not runtime. This governance approach excels at preventing configuration errors, missing security controls, and specification inconsistencies before they reach production. That said, it cannot prevent runtime vulnerabilities in the underlying implementation. -### API Security Implementation Timeline +### API security implementation timeline ```mermaid timeline @@ -173,7 +173,7 @@ timeline True "secure by design" requires both: design-time contracts enforced through OpenAPI governance *and* runtime security posture management as part of a comprehensive DevSecOps practice. -## API Security Maturity Model +## API security maturity model Implementing comprehensive API security is a journey. Organizations typically progress through distinct maturity levels as they build more sophisticated security practices: @@ -220,7 +220,7 @@ graph TD Most organizations find that advancing one level at a time provides the most sustainable improvement path. The techniques covered in this guide primarily support progression from Level 0 to Level 2, with Level 3 requiring additional infrastructure and organizational maturity. -## Frequently Asked Questions +## Frequently asked questions ### What is design-first API security? Design-first API security means defining security requirements in your OpenAPI specification before writing code, then using automated governance tools to enforce those requirements throughout the development lifecycle. This prevents vulnerabilities from reaching production rather than patching them after discovery. @@ -239,16 +239,16 @@ Authentication verifies *who* the user is (like checking an ID card), while auth ## Resources -### Security Standards and Guidelines +### Security standards and guidelines - OWASP API Security Top 10 - Comprehensive vulnerability guide including injection attacks (API3:2023), resource consumption (API4:2023), and business logic abuse (API6:2023) - NIST SP 800-52 Rev. 2 - Official guidelines for secure TLS implementation and configuration requirements - IETF RFC 8446 - TLS 1.3 protocol specification and security requirements -### Practical Implementation Tools +### Practical implementation tools - Mozilla SSL Configuration Generator - Generate secure, up-to-date TLS configurations for various web servers and security levels - OpenAPI Generator - Code generation tool for creating secure client SDKs and server stubs from OpenAPI specifications - OpenAPI Specification - Official OpenAPI 3.1 specification including security scheme definitions -### DevSecOps and API Governance +### DevSecOps and API governance - OWASP API Security Project - Community-driven API security best practices and threat modeling - OpenAPI Security Schemes - Official specification for defining authentication and authorization in OpenAPI \ No newline at end of file From a3102ca6ac6cbc287fe97e3b599d788b0505ee2d Mon Sep 17 00:00:00 2001 From: Matt Williams Date: Tue, 7 Oct 2025 15:32:12 -0500 Subject: [PATCH 22/27] Fix: Apply sentence casing to all headings per reviewer feedback - Changed all headings from title case to sentence case - Addresses @adamaltman review comment on PR #109 --- .../authentication-authorization-openapi.md | 68 +++++++++---------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/learn/security/authentication-authorization-openapi.md b/learn/security/authentication-authorization-openapi.md index 3fce8928..b6473f90 100644 --- a/learn/security/authentication-authorization-openapi.md +++ b/learn/security/authentication-authorization-openapi.md @@ -10,7 +10,7 @@ seo: --- -## Key Takeaways +## Key takeaways Authentication and authorization form the foundation of API access control. While often used interchangeably, these concepts serve distinct purposes: authentication verifies *who* the user is, while authorization determines *what* they can do. Modern APIs require both layers to prevent unauthorized access and enforce business rules. @@ -25,7 +25,7 @@ In this guide, we'll explore how to use OpenAPI 3.1 security schemes to define r --- -## Quick Start Guide +## Quick start guide Ready to implement authentication and authorization? Start here: @@ -39,11 +39,11 @@ Ready to implement authentication and authorization? Start here: --- -## Understanding Authentication vs Authorization +## Understanding authentication vs authorization The distinction between authentication and authorization is fundamental to API security design. Understanding this difference helps you implement the right controls at the right layers. -### The Two-Phase Security Process +### The two-phase security process ```mermaid sequenceDiagram @@ -86,7 +86,7 @@ sequenceDiagram - Evaluated for each request to protected resources - Can be fine-grained (specific endpoints) or coarse-grained (broad permissions) -### Common Authentication Patterns +### Common authentication patterns **[API Keys](#authentication-methods):** - Simple, stateless authentication @@ -105,21 +105,21 @@ sequenceDiagram - Built-in scope-based authorization - Recommended for user-facing applications -## Defining Security Schemes in OpenAPI +## Defining security schemes in OpenAPI OpenAPI 3.1 provides a robust framework for defining access control through two primary constructs: 1. **`components.securitySchemes`**: Defines *how* clients can authenticate (JWT Bearer, OAuth2, API Keys) 2. **`security`**: Specifies *that* an endpoint is secured and by which mechanism(s) -## Authentication Methods +## Authentication methods Choose the authentication method that best fits your use case: {% tabs %} {% tab label="JWT Bearer Token" %} -### JWT Bearer Token Authentication +### JWT bearer token authentication JWT (JSON Web Token) Bearer authentication is the most common pattern for modern APIs. The token contains encoded claims about the user and can be validated without database lookups. @@ -209,7 +209,7 @@ RSASHA256( {% /tab %} {% tab label="OAuth2 with Scopes" %} -### OAuth2 with Scope-Based Authorization +### OAuth2 with scope-based authorization OAuth2 provides the most flexible authorization framework, supporting fine-grained permissions through scopes and multiple authentication flows. @@ -358,7 +358,7 @@ This pattern allows fine-grained control: a user might have permission to read p {% /tab %} {% tab label="API Key" %} -### API Key Authentication +### API key authentication For service-to-service communication and simpler use cases, API keys provide straightforward authentication. @@ -405,7 +405,7 @@ paths: {% /tab %} {% tab label="Mutual TLS (mTLS)" %} -### Mutual TLS (mTLS) for Service Authentication +### Mutual TLS (mTLS) for service authentication For high-security environments and service-to-service communication, [mutual TLS](api-tls-encryption-https-best-practices#mutual-tls-mtls-two-way-authentication) provides cryptographic identity verification. @@ -439,11 +439,11 @@ paths: {% /tab %} {% /tabs %} -## Automated Governance for Access Control +## Automated governance for access control One of the most common API vulnerabilities is the accidentally public endpoint—an operation that should require authentication but doesn't have security requirements defined. Automated governance prevents this by enforcing security rules during development. -### Security Governance Rules +### Security governance rules **Mandatory Authentication on Write Operations:** ```yaml {% title="governance-rules.yaml" %} @@ -474,7 +474,7 @@ rules: When these rules run in your CI/CD pipeline, any endpoint without proper security definitions causes the build to fail, preventing accidentally public endpoints from reaching production. -### Implementation Example +### Implementation example **Before Governance (Vulnerable):** ```yaml @@ -507,11 +507,11 @@ paths: **Next steps:** Once you've implemented automated governance, consider setting up [comprehensive monitoring](#authentication-and-authorization-monitoring) to track security violations and [troubleshooting processes](#troubleshooting-common-issues) to handle authentication failures effectively. -## Security Definitions as Configuration +## Security definitions as configuration Defining security schemes in OpenAPI extends beyond documentation—it establishes configuration-as-code that drives consistency across your entire API ecosystem: -### API Gateway Integration +### API gateway integration Modern API gateways can import OpenAPI specifications and automatically configure authentication and authorization based on your security definitions. @@ -552,7 +552,7 @@ functions: - users:read ``` -### Code Generation +### Code generation OpenAPI security schemes enable automated generation of authentication handling in client SDKs and server stubs. @@ -591,14 +591,14 @@ class APIClient { **Development workflow:** Generated client SDKs like the one above help catch authentication issues early. When problems occur in production, use [monitoring](#authentication-and-authorization-monitoring) and [troubleshooting](#troubleshooting-common-issues) to diagnose and resolve issues quickly. -## Advanced Authorization Patterns +## Advanced authorization patterns Choose the authorization pattern that fits your application's complexity: {% tabs %} {% tab label="Role-Based Access Control (RBAC)" %} -### Role-Based Access Control (RBAC) +### Role-based access control (RBAC) While OpenAPI doesn't have built-in RBAC support, you can model roles through scopes or custom extensions. @@ -648,7 +648,7 @@ paths: {% /tab %} {% tab label="Context-Dependent Authorization" %} -### Context-Dependent Authorization +### Context-dependent authorization Some authorization decisions depend on request context, such as resource ownership or dynamic policies. @@ -679,7 +679,7 @@ paths: {% /tab %} {% tab label="Fine-Grained Permissions" %} -### Fine-Grained Permissions +### Fine-grained permissions For complex applications, you might need very specific permissions that combine multiple factors. @@ -719,14 +719,14 @@ paths: **Implementation tip:** Complex authorization patterns require robust [monitoring and troubleshooting](#troubleshooting-common-issues). The patterns above should be complemented with comprehensive logging and [best practices](#best-practices-summary) for production deployment. -## Authentication and Authorization Monitoring +## Authentication and authorization monitoring Choose your monitoring approach based on your technology stack: {% tabs %} {% tab label="Authentication Monitoring (JS)" %} -### Token Validation Metrics +### Token validation metrics Monitor authentication success and failure patterns to detect potential attacks and system issues. @@ -802,7 +802,7 @@ app.use('/api', (req, res, next) => { {% /tab %} {% tab label="Authorization Monitoring (JavaScript)" %} -### Authorization Failure Analysis +### Authorization failure analysis Track authorization failures to identify potential privilege escalation attempts or misconfigured permissions. @@ -897,7 +897,7 @@ This monitoring helps distinguish between legitimate access denials (user simply {% /tab %} {% /tabs %} -### Security Event Logging +### Security event logging Implement comprehensive logging for security events to support incident response and compliance requirements. @@ -923,9 +923,9 @@ security_events: **Security operations:** When monitoring detects issues, use the structured logs above with the [troubleshooting guide below](#troubleshooting-common-issues) to quickly diagnose and resolve authentication and authorization problems. -## Troubleshooting Common Issues +## Troubleshooting common issues -### Authentication Problems +### Authentication problems {% tabs %} {% tab label="Missing or Invalid Bearer Token" %} @@ -1011,7 +1011,7 @@ curl -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9..." \ {% /tab %} {% /tabs %} -### Authorization Problems +### Authorization problems {% tabs %} {% tab label="Insufficient Scopes" %} @@ -1104,7 +1104,7 @@ curl -H "Authorization: Bearer user_token" \ {% /tab %} {% /tabs %} -### Debugging Checklist +### Debugging checklist 1. **Verify token format and claims:** ```bash @@ -1144,21 +1144,21 @@ curl -H "Authorization: Bearer user_token" \ https://api.example.com/users/me ``` -## Best Practices Summary +## Best practices summary -### Security Scheme Design +### Security scheme design - Use JWT Bearer tokens for stateless authentication - Implement OAuth2 with PKCE for user-facing applications - Define granular scopes that map to business operations - Use mTLS for high-trust service-to-service communication -### Governance and Automation +### Governance and automation - Require security definitions on all write operations - Validate that all security references have corresponding definitions - Fail builds when security requirements are missing - Generate gateway configurations from OpenAPI security schemes -### Monitoring and Observability +### Monitoring and observability - Track authentication success/failure rates - Monitor authorization violations by endpoint - Log security events with sufficient context for incident response @@ -1170,7 +1170,7 @@ curl -H "Authorization: Bearer user_token" \ - Implement proper error responses (401 vs 403) - Test authentication and authorization scenarios in CI/CD -## Frequently Asked Questions +## Frequently asked questions ### What's the difference between authentication and authorization? Authentication verifies *who* the user is (like checking an ID card), while authorization determines *what* they can do (like checking permissions). Authentication happens first and provides identity, while authorization uses that identity to make access decisions for each request. From 5527d575c087f985f959ad0fd5b1566364feb00b Mon Sep 17 00:00:00 2001 From: Matt Williams Date: Tue, 7 Oct 2025 15:35:02 -0500 Subject: [PATCH 23/27] Fix: Comment out custom security plugin rules in _filesets - Commented out rules that use custom security plugin functions - Prevents 'Plugin security isn't found' error during build - Rules require security-functions.js plugin which is not available --- learn/security/_filesets/redocly.yaml | 74 ++++++++++++++------------- 1 file changed, 39 insertions(+), 35 deletions(-) diff --git a/learn/security/_filesets/redocly.yaml b/learn/security/_filesets/redocly.yaml index 4c8d1c11..6f5b13ce 100644 --- a/learn/security/_filesets/redocly.yaml +++ b/learn/security/_filesets/redocly.yaml @@ -140,15 +140,16 @@ rules: severity: error # Advanced cross-operation security validation (requires custom functions) - rule/comprehensive-security-check: - subject: - type: Root - assertions: - security/checkOperationSecurity: - methods: [post, put, patch, delete] - nullable: false - message: "All write operations must have properly configured security schemes" - severity: error + # NOTE: Commented out - requires security plugin + # rule/comprehensive-security-check: + # subject: + # type: Root + # assertions: + # security/checkOperationSecurity: + # methods: [post, put, patch, delete] + # nullable: false + # message: "All write operations must have properly configured security schemes" + # severity: error # ========================================== # API3:2023 - Broken Object Property Level Authorization @@ -303,14 +304,15 @@ rules: severity: warn # Advanced rate limiting consistency validation (requires custom functions) - rule/rate-limit-consistency: - subject: - type: Root - assertions: - security/validateRateLimitConsistency: - requiredHeaders: [RateLimit, X-RateLimit-Limit, X-Rate-Limit-Limit] - message: "Rate limiting configurations should be consistent across operations" - severity: warn + # NOTE: Commented out - requires security plugin + # rule/rate-limit-consistency: + # subject: + # type: Root + # assertions: + # security/validateRateLimitConsistency: + # requiredHeaders: [RateLimit, X-RateLimit-Limit, X-Rate-Limit-Limit] + # message: "Rate limiting configurations should be consistent across operations" + # severity: warn # ========================================== # API5:2023 - Broken Function Level Authorization @@ -333,26 +335,28 @@ rules: severity: error # Advanced admin security isolation validation (requires custom functions) - rule/admin-security-isolation: - subject: - type: Root - assertions: - security/validateAdminSecurity: - adminUrlPattern: "/admin" - message: "Administrative endpoints must use different security schemes than regular operations" - severity: error + # NOTE: Commented out - requires security plugin + # rule/admin-security-isolation: + # subject: + # type: Root + # assertions: + # security/validateAdminSecurity: + # adminUrlPattern: "/admin" + # message: "Administrative endpoints must use different security schemes than regular operations" + # severity: error # Advanced OAuth scope validation (requires custom functions) - rule/oauth-scope-validation: - subject: - type: Root - assertions: - security/validateOAuthScopes: - adminOperations: [delete, post, put, patch] - requiredAdminScopes: [admin, write, manage] - adminPathPatterns: ["/admin", "/manage", "/config", "/system"] - message: "OAuth scopes must be appropriate for operation sensitivity" - severity: error + # NOTE: Commented out - requires security plugin + # rule/oauth-scope-validation: + # subject: + # type: Root + # assertions: + # security/validateOAuthScopes: + # adminOperations: [delete, post, put, patch] + # requiredAdminScopes: [admin, write, manage] + # adminPathPatterns: ["/admin", "/manage", "/config", "/system"] + # message: "OAuth scopes must be appropriate for operation sensitivity" + # severity: error # ========================================== # API7:2023 - Server Side Request Forgery From 0cf98fa7a0622d6721cee326fb210f71ac36deba Mon Sep 17 00:00:00 2001 From: Matt Williams Date: Tue, 7 Oct 2025 15:39:36 -0500 Subject: [PATCH 24/27] Remove _filesets folder and references from learn/security - Deleted learn/security/_filesets/ directory containing redocly.yaml and security-functions.ts - Removed _filesets reference from root redocly.yaml ignore list - Files were for reference only and no longer needed --- learn/security/_filesets/redocly.yaml | 511 ------------------ .../security/_filesets/security-functions.ts | 239 -------- redocly.yaml | 1 - 3 files changed, 751 deletions(-) delete mode 100644 learn/security/_filesets/redocly.yaml delete mode 100644 learn/security/_filesets/security-functions.ts diff --git a/learn/security/_filesets/redocly.yaml b/learn/security/_filesets/redocly.yaml deleted file mode 100644 index 6f5b13ce..00000000 --- a/learn/security/_filesets/redocly.yaml +++ /dev/null @@ -1,511 +0,0 @@ -# Redocly Security Ruleset -# Based on OWASP API Security Top 10 2023 -# https://owasp.org/www-project-api-security/ - -# NOTE: This is a reference file for review purposes only -# Plugin reference commented out to prevent build errors -# plugins: -# - './security-functions.js' - - -# Enable built-in security rules -rules: - # Built-in Redocly security rules - security-defined: error - operation-4xx-response: error - operation-2xx-response: error - no-unresolved-refs: error - - # ========================================== - # API1:2023 - Broken Object Level Authorization - # ========================================== - - # Prevent numeric IDs that can be easily guessed - rule/no-numeric-ids: - subject: - type: Schema - property: type - filterInParentKeys: [path] - where: - - subject: - type: Parameter - property: name - assertions: - pattern: /(^id$|_id$|Id$|-id$)/ - assertions: - enum: [string] - message: "Use random IDs that cannot be guessed (UUIDs are preferred). Avoid integer IDs in path parameters." - severity: error - - # Ensure ID parameters use appropriate formats - rule/id-format-required: - subject: - type: Schema - property: format - filterInParentKeys: [path] - where: - - subject: - type: Parameter - property: name - assertions: - pattern: /(^id$|_id$|Id$|-id$)/ - assertions: - enum: [uuid, uri, password] - message: "ID parameters should specify a secure format like 'uuid'." - severity: warn - - # ========================================== - # API2:2023 - Broken Authentication - # ========================================== - - # Enforce HTTPS for all server URLs - rule/https-server-urls: - subject: - type: Server - property: url - assertions: - pattern: /^https:/ - message: "Server URLs must use HTTPS protocol. HTTP is insecure and exposes data to interception." - severity: error - - # Prevent HTTP Basic authentication - rule/no-http-basic-auth: - subject: - type: SecurityScheme - property: scheme - where: - - subject: - type: SecurityScheme - property: type - assertions: - const: http - assertions: - notPattern: /^basic$/i - message: "HTTP Basic authentication is insecure. Use OAuth 2.0, API keys in headers, or other secure methods." - severity: error - - # Prevent API keys in URL (query/path) - rule/no-api-keys-in-url: - subject: - type: SecurityScheme - property: in - where: - - subject: - type: SecurityScheme - property: type - assertions: - const: apiKey - assertions: - enum: [header, cookie] - message: "API keys must not be in URL (query or path parameters). Use headers or cookies instead." - severity: error - - # Prevent credentials in parameter names - rule/no-credentials-in-parameters: - subject: - type: Parameter - property: name - filterInParentKeys: [query, path] - assertions: - notPattern: /(secret|token|access.?token|refresh.?token|id.?token|password|api.?key|credential)/i - message: "Parameter names must not contain credential-related terms. Use secure authentication headers instead." - severity: error - - # Ensure write operations are protected - rule/write-operations-secured: - subject: - type: Operation - property: security - filterInParentKeys: [post, put, patch, delete] - assertions: - defined: true - nonEmpty: true - message: "Write operations (POST, PUT, PATCH, DELETE) must be protected by security schemes." - severity: error - - # JWT bearer format security schemes should reference RFC8725 - rule/jwt-rfc8725-compliance: - subject: - type: SecurityScheme - property: description - where: - - subject: - type: SecurityScheme - property: bearerFormat - assertions: - pattern: /jwt/i - assertions: - pattern: /RFC\s*8725/i - message: "JWT security schemes must reference RFC8725 compliance in description for security best practices." - severity: error - - # Advanced cross-operation security validation (requires custom functions) - # NOTE: Commented out - requires security plugin - # rule/comprehensive-security-check: - # subject: - # type: Root - # assertions: - # security/checkOperationSecurity: - # methods: [post, put, patch, delete] - # nullable: false - # message: "All write operations must have properly configured security schemes" - # severity: error - - # ========================================== - # API3:2023 - Broken Object Property Level Authorization - # ========================================== - - # Prevent unconstrained additionalProperties - rule/no-additional-properties: - subject: - type: Schema - property: additionalProperties - where: - - subject: - type: Schema - property: type - assertions: - const: object - assertions: - const: false - message: "Objects should not allow additionalProperties. Set to false to prevent mass assignment vulnerabilities." - severity: warn - - # Require maxProperties when additionalProperties is not false - rule/constrained-additional-properties: - subject: - type: Schema - property: maxProperties - where: - - subject: - type: Schema - property: type - assertions: - const: object - - subject: - type: Schema - property: additionalProperties - assertions: - defined: true - notPattern: /^false$/ - assertions: - defined: true - message: "Objects with additionalProperties should define maxProperties to limit resource consumption." - severity: warn - - # ========================================== - # API4:2023 - Unrestricted Resource Consumption - # ========================================== - - # Require rate limiting headers in responses - rule/rate-limit-headers-present: - subject: - type: Header - where: - - subject: - type: Response - filterInParentKeys: ["200", "201", "202", "204", "400", "401", "403", "404", "422", "429"] - assertions: - defined: true - assertions: - pattern: /^(RateLimit|RateLimit-Limit|X-RateLimit-Limit|X-Rate-Limit-Limit)$/i - message: "2XX and 4XX responses should include rate limiting headers (RateLimit, RateLimit-Limit, X-RateLimit-Limit, or X-Rate-Limit-Limit)." - severity: warn - - # Require 429 Too Many Requests response - rule/require-429-response: - subject: - type: Responses - property: "429" - assertions: - defined: true - message: "Operations should define a 429 (Too Many Requests) response for rate limiting." - severity: warn - - # Retry-After header required for 429 responses - rule/retry-after-header-429: - subject: - type: Header - where: - - subject: - type: Response - filterInParentKeys: ["429"] - assertions: - defined: true - assertions: - pattern: /^Retry-After$/i - message: "429 responses must include a Retry-After header to indicate when clients can retry." - severity: error - - # Array schemas must specify maxItems - rule/array-max-items: - subject: - type: Schema - property: maxItems - where: - - subject: - type: Schema - property: type - assertions: - const: array - assertions: - defined: true - message: "Array schemas must specify maxItems to prevent resource exhaustion attacks." - severity: error - - # String schemas must have length constraints - rule/string-length-limit: - subject: - type: Schema - where: - - subject: - type: Schema - property: type - assertions: - const: string - assertions: - requireAny: - - maxLength - - enum - - const - - pattern - message: "String schemas must specify maxLength, enum, const, or pattern to limit resource consumption." - severity: error - - # Integer schemas must have min/max constraints - rule/integer-constraints: - subject: - type: Schema - where: - - subject: - type: Schema - property: type - assertions: - const: integer - assertions: - required: [minimum, maximum] - message: "Integer schemas must specify minimum and maximum values to prevent resource exhaustion." - severity: error - - # Integer schemas should specify format - rule/integer-format: - subject: - type: Schema - property: format - where: - - subject: - type: Schema - property: type - assertions: - const: integer - assertions: - enum: [int32, int64] - message: "Integer schemas should specify format (int32 or int64) for precise validation." - severity: warn - - # Advanced rate limiting consistency validation (requires custom functions) - # NOTE: Commented out - requires security plugin - # rule/rate-limit-consistency: - # subject: - # type: Root - # assertions: - # security/validateRateLimitConsistency: - # requiredHeaders: [RateLimit, X-RateLimit-Limit, X-Rate-Limit-Limit] - # message: "Rate limiting configurations should be consistent across operations" - # severity: warn - - # ========================================== - # API5:2023 - Broken Function Level Authorization - # ========================================== - - # Administrative endpoints should have stricter security - rule/admin-endpoints-secured: - subject: - type: Operation - property: security - where: - - subject: - type: PathItem - assertions: - pattern: /(admin|manage|control|configure)/i - assertions: - defined: true - nonEmpty: true - message: "Administrative endpoints must have defined security schemes with appropriate authorization levels." - severity: error - - # Advanced admin security isolation validation (requires custom functions) - # NOTE: Commented out - requires security plugin - # rule/admin-security-isolation: - # subject: - # type: Root - # assertions: - # security/validateAdminSecurity: - # adminUrlPattern: "/admin" - # message: "Administrative endpoints must use different security schemes than regular operations" - # severity: error - - # Advanced OAuth scope validation (requires custom functions) - # NOTE: Commented out - requires security plugin - # rule/oauth-scope-validation: - # subject: - # type: Root - # assertions: - # security/validateOAuthScopes: - # adminOperations: [delete, post, put, patch] - # requiredAdminScopes: [admin, write, manage] - # adminPathPatterns: ["/admin", "/manage", "/config", "/system"] - # message: "OAuth scopes must be appropriate for operation sensitivity" - # severity: error - - # ========================================== - # API7:2023 - Server Side Request Forgery - # ========================================== - - # Warn about URL parameters that might lead to SSRF - rule/ssrf-url-parameters: - subject: - type: Parameter - property: name - assertions: - notPattern: /(callback|redirect|url|uri|endpoint|webhook|fetch|proxy)/i - message: "URL-related parameters may be vulnerable to Server Side Request Forgery. Ensure proper validation and allowlisting." - severity: warn - - # ========================================== - # API8:2023 - Security Misconfiguration - # ========================================== - - # Require CORS headers in responses - rule/cors-access-control-allow-origin: - subject: - type: Header - where: - - subject: - type: Response - assertions: - defined: true - assertions: - pattern: /^Access-Control-Allow-Origin$/i - message: "Responses should define CORS headers (Access-Control-Allow-Origin) to control cross-origin access." - severity: warn - - # Require error response schemas (400, 401, 403, 500) - rule/error-responses-defined: - subject: - type: Responses - assertions: - requireAny: ["400", "401", "403", "422", "4XX"] - message: "Operations should define appropriate error responses (400, 401, 403, 422, or 4XX) with proper schemas." - severity: warn - - # Require 401 unauthorized responses for secured operations - rule/unauthorized-response-required: - subject: - type: Responses - property: "401" - where: - - subject: - type: Operation - property: security - assertions: - defined: true - assertions: - defined: true - message: "Secured operations should define 401 (Unauthorized) responses." - severity: warn - - # Require 500 server error responses - rule/server-error-response: - subject: - type: Responses - property: "500" - assertions: - defined: true - message: "Operations should define 500 (Internal Server Error) responses to handle server errors gracefully." - severity: warn - - # ========================================== - # API9:2023 - Improper Inventory Management - # ========================================== - - # Server objects should declare internal/external audience - rule/server-audience-declaration: - subject: - type: Server - property: x-internal - assertions: - defined: true - enum: ['true', 'false'] - message: "Servers should declare their intended audience using x-internal (true for internal, false for external)." - severity: error - - # Server descriptions should indicate environment - rule/server-environment-declaration: - subject: - type: Server - property: description - assertions: - pattern: /(local|dev|development|test|testing|stage|staging|prod|production|live|sandbox)/i - message: "Server descriptions should clearly indicate the environment (development, testing, staging, production)." - severity: error - - # API version should be clearly defined - rule/api-version-defined: - subject: - type: Info - property: version - assertions: - defined: true - pattern: /^\d+\.\d+\.\d+/ - message: "API version should be clearly defined using semantic versioning (e.g., 1.0.0)." - severity: error - - # ========================================== - # Additional Security Rules - # ========================================== - - # Prevent sensitive data in examples - rule/no-sensitive-data-in-examples: - subject: - type: Schema - property: example - assertions: - notPattern: /(password|secret|token|key|credential|ssn|social.?security|credit.?card|api.?key)/i - message: "Examples should not contain sensitive data like passwords, tokens, or personal information." - severity: warn - - # Ensure request bodies have proper content types - rule/secure-content-types: - subject: - type: MediaType - where: - - subject: - type: RequestBody - assertions: - defined: true - assertions: - enum: - - application/json - - application/xml - - application/x-www-form-urlencoded - - multipart/form-data - - text/plain - message: "Use secure and well-defined content types. Avoid allowing arbitrary content types." - severity: warn - - # Prevent overly broad schemas - rule/no-empty-schemas: - subject: - type: Schema - assertions: - requireAny: - - type - - properties - - items - - allOf - - anyOf - - oneOf - - $ref - message: "Schemas should not be empty. Define proper constraints to prevent accepting arbitrary data." - severity: error diff --git a/learn/security/_filesets/security-functions.ts b/learn/security/_filesets/security-functions.ts deleted file mode 100644 index 9e91d6ae..00000000 --- a/learn/security/_filesets/security-functions.ts +++ /dev/null @@ -1,239 +0,0 @@ -// Custom security validation functions for Redocly -// These implement the advanced security checks from the Spectral OWASP ruleset - -export default function securityPlugin() { - return { - id: 'security', - assertions: { - // Validates that operations have appropriate security based on HTTP method - checkOperationSecurity: (openapi, options, ctx) => { - const errors = []; - const { methods = [], nullable = false } = options; - const { paths, security: globalSecurity } = openapi; - - if (!paths || typeof paths !== 'object') { - return errors; - } - - // Iterate through all operations - for (const [pathKey, pathItem] of Object.entries(paths)) { - if (!pathItem || typeof pathItem !== 'object') continue; - - const httpMethods = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']; - - for (const method of httpMethods) { - const operation = pathItem[method]; - if (!operation || typeof operation !== 'object') continue; - - // Skip if method not in configured methods list - if (methods.length > 0 && !methods.includes(method)) continue; - - let operationSecurity = operation.security; - - // Fall back to global security if operation security not defined - if (operationSecurity === undefined) { - operationSecurity = globalSecurity; - } - - // Check if security is properly defined - if (!operationSecurity || operationSecurity.length === 0) { - errors.push({ - message: `${method.toUpperCase()} operation at ${pathKey} has no security scheme defined`, - location: ctx.baseLocation.child(['paths', pathKey, method, 'security']), - }); - continue; - } - - // Validate each security requirement - if (Array.isArray(operationSecurity)) { - for (const [idx, securityEntry] of operationSecurity.entries()) { - if (typeof securityEntry !== 'object') continue; - - const securitySchemeIds = Object.keys(securityEntry); - if (securitySchemeIds.length === 0 && !nullable) { - errors.push({ - message: `${method.toUpperCase()} operation at ${pathKey} has empty security requirement at index ${idx}`, - location: ctx.baseLocation.child(['paths', pathKey, method, 'security', idx]), - }); - } - } - } - } - } - - return errors; - }, - - // Ensures admin endpoints use different security schemes than regular endpoints - validateAdminSecurity: (openapi, options, ctx) => { - const errors = []; - const { adminUrlPattern = '/admin' } = options; - const { paths } = openapi; - - if (!paths || typeof paths !== 'object') { - return errors; - } - - const nonAdminSecurityHashes = new Set(); - const adminSecurityEntries = []; - - // First pass: collect all security configurations - for (const [pathKey, pathItem] of Object.entries(paths)) { - if (!pathItem || typeof pathItem !== 'object') continue; - - const httpMethods = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']; - - for (const method of httpMethods) { - const operation = pathItem[method]; - if (!operation || typeof operation !== 'object') continue; - - const operationSecurity = operation.security; - if (!operationSecurity || !Array.isArray(operationSecurity)) continue; - - // Create hash of security configuration for comparison - const securityHash = JSON.stringify(operationSecurity); - - if (pathKey.includes(adminUrlPattern)) { - adminSecurityEntries.push({ - path: pathKey, - method, - hash: securityHash, - location: ctx.baseLocation.child(['paths', pathKey, method, 'security']), - }); - } else { - nonAdminSecurityHashes.add(securityHash); - } - } - } - - // Second pass: validate admin endpoints use unique security - for (const adminEntry of adminSecurityEntries) { - if (nonAdminSecurityHashes.has(adminEntry.hash)) { - errors.push({ - message: `Admin endpoint ${adminEntry.path} (${adminEntry.method.toUpperCase()}) uses the same security scheme as non-admin endpoints. Admin operations should have stricter authentication.`, - location: adminEntry.location, - }); - } - } - - return errors; - }, - - // Validates OAuth scopes are appropriate for operation sensitivity - validateOAuthScopes: (openapi, options, ctx) => { - const errors = []; - const { - adminOperations = ['delete', 'post', 'put', 'patch'], - requiredAdminScopes = ['admin', 'write', 'manage'], - adminPathPatterns = ['/admin', '/manage', '/config'] - } = options; - - const { paths, components } = openapi; - - if (!paths || !components?.securitySchemes) { - return errors; - } - - // Find OAuth2 security schemes - const oauthSchemes = Object.entries(components.securitySchemes) - .filter(([_, scheme]) => scheme.type === 'oauth2') - .map(([name, _]) => name); - - if (oauthSchemes.length === 0) return errors; - - for (const [pathKey, pathItem] of Object.entries(paths)) { - if (!pathItem || typeof pathItem !== 'object') continue; - - const isAdminPath = adminPathPatterns.some(pattern => pathKey.includes(pattern)); - - for (const method of adminOperations) { - const operation = pathItem[method]; - if (!operation || typeof operation !== 'object') continue; - - const operationSecurity = operation.security; - if (!operationSecurity || !Array.isArray(operationSecurity)) continue; - - // Check if this operation uses OAuth and has appropriate scopes - for (const securityReq of operationSecurity) { - for (const [schemeName, scopes] of Object.entries(securityReq)) { - if (oauthSchemes.includes(schemeName)) { - const hasAdminScope = requiredAdminScopes.some(scope => - Array.isArray(scopes) && scopes.includes(scope) - ); - - if ((isAdminPath || adminOperations.includes(method)) && !hasAdminScope) { - errors.push({ - message: `${method.toUpperCase()} operation at ${pathKey} should require admin scopes (${requiredAdminScopes.join(', ')}) for sensitive operations`, - location: ctx.baseLocation.child(['paths', pathKey, method, 'security']), - }); - } - } - } - } - } - } - - return errors; - }, - - // Validates rate limiting configuration consistency - validateRateLimitConsistency: (openapi, options, ctx) => { - const errors = []; - const { requiredHeaders = ['RateLimit', 'X-RateLimit-Limit'] } = options; - const { paths } = openapi; - - if (!paths || typeof paths !== 'object') { - return errors; - } - - const rateLimitConfigs = new Map(); - - // Collect all rate limiting configurations - for (const [pathKey, pathItem] of Object.entries(paths)) { - if (!pathItem || typeof pathItem !== 'object') continue; - - const httpMethods = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options']; - - for (const method of httpMethods) { - const operation = pathItem[method]; - if (!operation?.responses) continue; - - for (const [statusCode, response] of Object.entries(operation.responses)) { - if (!statusCode.match(/^[24]/)) continue; // Only 2xx and 4xx responses - - const headers = response.headers || {}; - const hasRateLimit = requiredHeaders.some(header => headers[header]); - - if (hasRateLimit) { - const config = requiredHeaders - .filter(header => headers[header]) - .map(header => ({ header, schema: headers[header] })); - - const configKey = `${pathKey}:${method}`; - rateLimitConfigs.set(configKey, config); - } - } - } - } - - // Validate consistency across operations - const configValues = Array.from(rateLimitConfigs.values()); - if (configValues.length > 1) { - const firstConfig = JSON.stringify(configValues[0]); - - for (const [pathMethod, config] of rateLimitConfigs.entries()) { - if (JSON.stringify(config) !== firstConfig) { - const [path, method] = pathMethod.split(':'); - errors.push({ - message: `Rate limiting configuration at ${path} (${method.toUpperCase()}) differs from other operations. Consider using consistent rate limiting headers across your API.`, - location: ctx.baseLocation.child(['paths', path, method, 'responses']), - }); - } - } - } - - return errors; - } - }, - }; -} diff --git a/redocly.yaml b/redocly.yaml index a2ab6772..ef782f74 100644 --- a/redocly.yaml +++ b/redocly.yaml @@ -11,7 +11,6 @@ redirects: ignore: - '.github' - 'learn/arazzo/_filesets/**' - - 'learn/security/_filesets/**' - '**/code-walkthrough-files/**' - docs/realm/.templates From 13fafeb56551c3ef92707354d9113901ac3a5bc5 Mon Sep 17 00:00:00 2001 From: Matt Williams Date: Wed, 15 Oct 2025 10:20:15 -0500 Subject: [PATCH 25/27] Fix heading casing to use sentence case per style guidelines --- .../security/api-input-validation-injection-prevention.md | 4 ++-- learn/security/api-rate-limiting-abuse-prevention.md | 4 ++-- learn/security/api-tls-encryption-https-best-practices.md | 4 ++-- learn/security/authentication-authorization-openapi.md | 4 ++-- learn/security/index.md | 8 ++++---- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/learn/security/api-input-validation-injection-prevention.md b/learn/security/api-input-validation-injection-prevention.md index eea94964..c223cbf4 100644 --- a/learn/security/api-input-validation-injection-prevention.md +++ b/learn/security/api-input-validation-injection-prevention.md @@ -6,11 +6,11 @@ seo: description: Prevent API injection attacks and mass assignment vulnerabilities using OpenAPI schema validation and automated governance. --- -# Input Validation and Injection Prevention +# Input validation and injection prevention *This comprehensive guide is coming soon and will cover:* -## What You'll Learn +## What you'll learn - **SQL Injection Prevention**: Parameterized queries and input sanitization - **Mass Assignment Protection**: Schema-based validation and field filtering diff --git a/learn/security/api-rate-limiting-abuse-prevention.md b/learn/security/api-rate-limiting-abuse-prevention.md index b97ceced..e1b16354 100644 --- a/learn/security/api-rate-limiting-abuse-prevention.md +++ b/learn/security/api-rate-limiting-abuse-prevention.md @@ -6,11 +6,11 @@ seo: description: Implement API rate limiting strategies to prevent DoS attacks, brute force attempts, and business logic abuse. --- -# Rate Limiting and Abuse Prevention for APIs +# Rate limiting and abuse prevention for APIs *This comprehensive guide is coming soon and will cover:* -## What You'll Learn +## What you'll learn - **Rate Limiting Algorithms**: Token bucket, sliding window, and fixed window approaches - **OpenAPI Documentation**: x-rateLimit extensions and client communication diff --git a/learn/security/api-tls-encryption-https-best-practices.md b/learn/security/api-tls-encryption-https-best-practices.md index 1d12fcf3..ca0ff727 100644 --- a/learn/security/api-tls-encryption-https-best-practices.md +++ b/learn/security/api-tls-encryption-https-best-practices.md @@ -6,11 +6,11 @@ seo: description: Protect data in transit with proper TLS configuration, certificate management, and HTTPS enforcement using OpenAPI security contracts. --- -# TLS Encryption and HTTPS Best Practices for APIs +# TLS encryption and HTTPS best practices for APIs *This comprehensive guide is coming soon and will cover:* -## What You'll Learn +## What you'll learn - **TLS 1.3 Configuration**: Modern encryption standards and cipher suite selection - **Certificate Management**: Best practices for SSL/TLS certificate lifecycle diff --git a/learn/security/authentication-authorization-openapi.md b/learn/security/authentication-authorization-openapi.md index 4e2c5e6b..38074779 100644 --- a/learn/security/authentication-authorization-openapi.md +++ b/learn/security/authentication-authorization-openapi.md @@ -6,11 +6,11 @@ seo: description: Implement secure access control using OpenAPI security schemes and modern authentication patterns. --- -# Authentication and Authorization with OpenAPI +# Authentication and authorization with OpenAPI *This comprehensive guide is coming soon and will cover:* -## What You'll Learn +## What you'll learn - **Authentication Methods**: JWT, OAuth2, API Keys, and Mutual TLS patterns - **Authorization Strategies**: RBAC, scope-based access, and fine-grained permissions diff --git a/learn/security/index.md b/learn/security/index.md index 60a4a736..ac824743 100644 --- a/learn/security/index.md +++ b/learn/security/index.md @@ -72,7 +72,7 @@ graph TD Each security domain requires specific knowledge and implementation techniques. Choose the guide that matches your current focus: -### API TLS Encryption and HTTPS Best Practices +### API TLS encryption and HTTPS best practices **What you'll learn:** Protect data in transit with proper TLS configuration, certificate management, and HTTPS enforcement. **Key topics:** @@ -86,7 +86,7 @@ Each security domain requires specific knowledge and implementation techniques. --- -### API Input Validation and Injection Prevention +### API input validation and injection prevention **What you'll learn:** Stop injection attacks using OpenAPI schema validation and automated governance rules. **Key topics:** @@ -100,7 +100,7 @@ Each security domain requires specific knowledge and implementation techniques. --- -### API Rate Limiting and Abuse Prevention +### API rate limiting and abuse prevention **What you'll learn:** Prevent DoS attacks, brute force attempts, and business logic abuse through strategic rate limiting. **Key topics:** @@ -114,7 +114,7 @@ Each security domain requires specific knowledge and implementation techniques. --- -### Authentication and Authorization with OpenAPI +### Authentication and authorization with OpenAPI **What you'll learn:** Implement secure access control using OpenAPI security schemes and modern authentication patterns. **Key topics:** From 57a7099e25cad8385ad501b7fc4cc5e608df8abf Mon Sep 17 00:00:00 2001 From: Matt Williams Date: Wed, 15 Oct 2025 10:27:10 -0500 Subject: [PATCH 26/27] Fix heading casing to use sentence case per style guidelines --- .../api-rate-limiting-abuse-prevention.md | 4 +-- ...api-tls-encryption-https-best-practices.md | 4 +-- .../authentication-authorization-openapi.md | 2 +- learn/security/index.md | 32 +++++++++---------- 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/learn/security/api-rate-limiting-abuse-prevention.md b/learn/security/api-rate-limiting-abuse-prevention.md index b97ceced..e1b16354 100644 --- a/learn/security/api-rate-limiting-abuse-prevention.md +++ b/learn/security/api-rate-limiting-abuse-prevention.md @@ -6,11 +6,11 @@ seo: description: Implement API rate limiting strategies to prevent DoS attacks, brute force attempts, and business logic abuse. --- -# Rate Limiting and Abuse Prevention for APIs +# Rate limiting and abuse prevention for APIs *This comprehensive guide is coming soon and will cover:* -## What You'll Learn +## What you'll learn - **Rate Limiting Algorithms**: Token bucket, sliding window, and fixed window approaches - **OpenAPI Documentation**: x-rateLimit extensions and client communication diff --git a/learn/security/api-tls-encryption-https-best-practices.md b/learn/security/api-tls-encryption-https-best-practices.md index 1d12fcf3..ca0ff727 100644 --- a/learn/security/api-tls-encryption-https-best-practices.md +++ b/learn/security/api-tls-encryption-https-best-practices.md @@ -6,11 +6,11 @@ seo: description: Protect data in transit with proper TLS configuration, certificate management, and HTTPS enforcement using OpenAPI security contracts. --- -# TLS Encryption and HTTPS Best Practices for APIs +# TLS encryption and HTTPS best practices for APIs *This comprehensive guide is coming soon and will cover:* -## What You'll Learn +## What you'll learn - **TLS 1.3 Configuration**: Modern encryption standards and cipher suite selection - **Certificate Management**: Best practices for SSL/TLS certificate lifecycle diff --git a/learn/security/authentication-authorization-openapi.md b/learn/security/authentication-authorization-openapi.md index b6473f90..0123bd6b 100644 --- a/learn/security/authentication-authorization-openapi.md +++ b/learn/security/authentication-authorization-openapi.md @@ -6,7 +6,7 @@ seo: description: Implement secure access control using OpenAPI security schemes and modern authentication patterns. --- -# Authentication and Authorization with OpenAPI +# Authentication and authorization with OpenAPI --- diff --git a/learn/security/index.md b/learn/security/index.md index 20c11e4b..ac824743 100644 --- a/learn/security/index.md +++ b/learn/security/index.md @@ -12,7 +12,7 @@ _Build secure APIs from the ground up using OpenAPI security contracts and autom --- -## Key Takeaways +## Key takeaways Many teams discover security vulnerabilities after they're already in production, but it doesn't have to be that way! @@ -26,19 +26,19 @@ This comprehensive guide shows you how to turn your OpenAPI specification into a --- -## From Reactive Patching to Proactive API Security +## From reactive patching to proactive API security High-profile data breaches frequently trace back to insecure APIs, exposing a fundamental flaw in traditional security approaches. The conventional method—identifying and patching vulnerabilities in production—is reactive, costly, and ultimately inadequate. In its typical form, this paradigm treats security as an afterthought. Shifting security practices to the left in the development lifecycle, known as the "shift-left" imperative, addresses this by integrating security into the earliest stages of design and development. This proactive model prevents vulnerabilities from being introduced in the first place, rather than attempting to remediate them under pressure in production environments. -### OpenAPI as Your Security Contract +### OpenAPI as your security contract The core of this strategy is treating your OpenAPI specification not merely as documentation, but as an executable security contract. This contract declaratively defines a set of security requirements, constraints, and policies before any application code is written. It becomes the single source of truth that dictates how an API must behave to be considered secure, effectively implementing a "policy-as-code" approach for APIs. However, a contract, much like a law, is only as strong as its enforcement. This is where automated governance and linting tools provide value by transforming your contract into dynamic, automated guardrails that validate security requirements at every stage of development. When integrated into a Continuous Integration/Continuous Deployment (CI/CD) pipeline, this automated governance acts as a gatekeeper, failing builds that violate the security contract and requiring fixes before deployment. -## The Four Pillars of API Security +## The four pillars of API security Building secure APIs doesn't have to feel like playing whack-a-mole with vulnerabilities. Once you shift from reactive patching to proactive design, you'll wonder why you ever did it any other way. Let's explore how to make security an automatic part of your API development process. @@ -68,11 +68,11 @@ graph TD *Architecture diagram showing the four essential areas of API security (TLS encryption, input validation, rate limiting, access control) supported by OpenAPI specifications and automated governance tools.* -## Deep Dive Guides +## Deep dive guides Each security domain requires specific knowledge and implementation techniques. Choose the guide that matches your current focus: -### API TLS Encryption and HTTPS Best Practices +### API TLS encryption and HTTPS best practices **What you'll learn:** Protect data in transit with proper TLS configuration, certificate management, and HTTPS enforcement. **Key topics:** @@ -86,7 +86,7 @@ Each security domain requires specific knowledge and implementation techniques. --- -### API Input Validation and Injection Prevention +### API input validation and injection prevention **What you'll learn:** Stop injection attacks using OpenAPI schema validation and automated governance rules. **Key topics:** @@ -100,7 +100,7 @@ Each security domain requires specific knowledge and implementation techniques. --- -### API Rate Limiting and Abuse Prevention +### API rate limiting and abuse prevention **What you'll learn:** Prevent DoS attacks, brute force attempts, and business logic abuse through strategic rate limiting. **Key topics:** @@ -114,7 +114,7 @@ Each security domain requires specific knowledge and implementation techniques. --- -### Authentication and Authorization with OpenAPI +### Authentication and authorization with OpenAPI **What you'll learn:** Implement secure access control using OpenAPI security schemes and modern authentication patterns. **Key topics:** @@ -126,11 +126,11 @@ Each security domain requires specific knowledge and implementation techniques. **Perfect for:** Identity and access management teams, full-stack developers, and security engineers -## Understanding Design-Time vs Runtime Security +## Understanding design-time vs runtime security It's important to understand that OpenAPI-based security governance operates at **design-time**, not runtime. This governance approach excels at preventing configuration errors, missing security controls, and specification inconsistencies before they reach production. That said, it cannot prevent runtime vulnerabilities in the underlying implementation. -### API Security Implementation Timeline +### API security implementation timeline ```mermaid timeline @@ -173,7 +173,7 @@ timeline True "secure by design" requires both: design-time contracts enforced through OpenAPI governance *and* runtime security posture management as part of a comprehensive DevSecOps practice. -## API Security Maturity Model +## API security maturity model Implementing comprehensive API security is a journey. Organizations typically progress through distinct maturity levels as they build more sophisticated security practices: @@ -220,7 +220,7 @@ graph TD Most organizations find that advancing one level at a time provides the most sustainable improvement path. The techniques covered in this guide primarily support progression from Level 0 to Level 2, with Level 3 requiring additional infrastructure and organizational maturity. -## Frequently Asked Questions +## Frequently asked questions ### What is design-first API security? Design-first API security means defining security requirements in your OpenAPI specification before writing code, then using automated governance tools to enforce those requirements throughout the development lifecycle. This prevents vulnerabilities from reaching production rather than patching them after discovery. @@ -239,16 +239,16 @@ Authentication verifies *who* the user is (like checking an ID card), while auth ## Resources -### Security Standards and Guidelines +### Security standards and guidelines - OWASP API Security Top 10 - Comprehensive vulnerability guide including injection attacks (API3:2023), resource consumption (API4:2023), and business logic abuse (API6:2023) - NIST SP 800-52 Rev. 2 - Official guidelines for secure TLS implementation and configuration requirements - IETF RFC 8446 - TLS 1.3 protocol specification and security requirements -### Practical Implementation Tools +### Practical implementation tools - Mozilla SSL Configuration Generator - Generate secure, up-to-date TLS configurations for various web servers and security levels - OpenAPI Generator - Code generation tool for creating secure client SDKs and server stubs from OpenAPI specifications - OpenAPI Specification - Official OpenAPI 3.1 specification including security scheme definitions -### DevSecOps and API Governance +### DevSecOps and API governance - OWASP API Security Project - Community-driven API security best practices and threat modeling - OpenAPI Security Schemes - Official specification for defining authentication and authorization in OpenAPI \ No newline at end of file From c0bd996dcf2a2e611345b6806d1397b47f0239c7 Mon Sep 17 00:00:00 2001 From: Matt Williams Date: Wed, 15 Oct 2025 10:40:19 -0500 Subject: [PATCH 27/27] Address review feedback: Update OpenAPI 3.1 to 3.2, convert deep dive guides to Markdoc cards --- learn/security/index.md | 36 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/learn/security/index.md b/learn/security/index.md index ac824743..ef1d3b24 100644 --- a/learn/security/index.md +++ b/learn/security/index.md @@ -72,59 +72,55 @@ graph TD Each security domain requires specific knowledge and implementation techniques. Choose the guide that matches your current focus: -### API TLS encryption and HTTPS best practices -**What you'll learn:** Protect data in transit with proper TLS configuration, certificate management, and HTTPS enforcement. +{% cards %} +{% card title="API TLS encryption and HTTPS best practices" to="/learn/security/api-tls-encryption-https-best-practices" %} +Protect data in transit with proper TLS configuration, certificate management, and HTTPS enforcement. **Key topics:** - TLS 1.3 implementation and cipher suite selection - OpenAPI server URL security contracts - Mutual TLS (mTLS) for service-to-service communication - Real-world case study: Heartbleed vulnerability and lessons learned -- Automated governance for transport security **Perfect for:** Infrastructure teams, DevOps engineers, and security architects +{% /card %} ---- - -### API input validation and injection prevention -**What you'll learn:** Stop injection attacks using OpenAPI schema validation and automated governance rules. +{% card title="API input validation and injection prevention" to="/learn/security/api-input-validation-injection-prevention" %} +Stop injection attacks using OpenAPI schema validation and automated governance rules. **Key topics:** - JSON Schema security constraints and validation patterns - Mass assignment attack prevention - SQL injection and OGNL injection defense strategies - Real-world case study: Equifax breach analysis -- Automated validation governance and linting **Perfect for:** Backend developers, security engineers, and API architects +{% /card %} ---- - -### API rate limiting and abuse prevention -**What you'll learn:** Prevent DoS attacks, brute force attempts, and business logic abuse through strategic rate limiting. +{% card title="API rate limiting and abuse prevention" to="/learn/security/api-rate-limiting-abuse-prevention" %} +Prevent DoS attacks, brute force attempts, and business logic abuse through strategic rate limiting. **Key topics:** - Rate limiting algorithms and implementation patterns - OpenAPI x-rateLimit extensions and documentation - Multi-tier rate limiting strategies - Real-world case study: Facebook phone number scraping incident -- Client-side backoff and error handling **Perfect for:** API product managers, DevOps teams, and security operations +{% /card %} ---- - -### Authentication and authorization with OpenAPI -**What you'll learn:** Implement secure access control using OpenAPI security schemes and modern authentication patterns. +{% card title="Authentication and authorization with OpenAPI" to="/learn/security/authentication-authorization-openapi" %} +Implement secure access control using OpenAPI security schemes and modern authentication patterns. **Key topics:** - OpenAPI security schemes (JWT, OAuth2, API Keys, mTLS) - Authentication vs authorization flow patterns - Scope-based access control and permission systems - Security scheme governance and automation -- Token validation and session management **Perfect for:** Identity and access management teams, full-stack developers, and security engineers +{% /card %} +{% /cards %} ## Understanding design-time vs runtime security @@ -247,8 +243,8 @@ Authentication verifies *who* the user is (like checking an ID card), while auth ### Practical implementation tools - Mozilla SSL Configuration Generator - Generate secure, up-to-date TLS configurations for various web servers and security levels - OpenAPI Generator - Code generation tool for creating secure client SDKs and server stubs from OpenAPI specifications -- OpenAPI Specification - Official OpenAPI 3.1 specification including security scheme definitions +- OpenAPI Specification - Official OpenAPI 3.2 specification including security scheme definitions ### DevSecOps and API governance - OWASP API Security Project - Community-driven API security best practices and threat modeling -- OpenAPI Security Schemes - Official specification for defining authentication and authorization in OpenAPI \ No newline at end of file +- OpenAPI Security Schemes - Official specification for defining authentication and authorization in OpenAPI \ No newline at end of file