Urgent.News

What's breaking now, across thousands of outlets.

Tech

Multiple security schemes in OpenAPI: AND vs OR, optional auth, and per-operation overrides

The security keyword is small and surprisingly easy to invert. It is an array of alternatives, where each alternative is itself a set of schemes that must all be satisfied. Miss the distinction between the outer array and the inner object and you either leave a sensitive endpoint protected by a single factor when you required two, or force credentials on an endpoint that was meant to be public.…

The security keyword in OpenAPI is an array of alternatives, where each alternative is a set of schemes that must all be satisfied. A common mistake is to confuse the outer array with the inner object, leading to either too little or too much protection for endpoints. Understanding security as an OR of ANDs can help clarify multi-authentication designs.

In YAML, the security keyword can be written as separate objects for each scheme, or as a single object containing multiple schemes. For example, security: - apiKeyAuth: [] oauth2: [ read: orders ] requires the caller to provide both an API key and an OAuth token.

To express either an API key or OAuth, use two separate array elements: security: - apiKeyAuth: [] - oauth2: [ read: orders ]. This allows for greater flexibility in authentication schemes.

A single array element containing two schemes requires the caller to send both required credentials, while defining schemes once under components.securitySchemes and referencing them with the security keyword keeps the declarations organized.

Global defaults for authentication can be set at the root level and overridden for specific operations. For example, security: - bearerAuth: [] sets a default global bearer token requirement, which can be overridden for individual endpoints.

Operation-level security replaces the global security entirely, meaning it does not merge. This behavior is often misinterpreted, leading to incorrect implementation. For instance, security: - bearerAuth: [] paths: /public/status: get security: [] explicitly sets an unauthenticated operation, overriding the global bearer token requirement.

In cases where an endpoint requires the global scheme in addition to an extra one, the global scheme must be restated within the operation's requirement. Optional authentication that returns different data based on credentials should be explicitly defined using an empty alternative alongside the authenticated one: security: - {} - bearerAuth: [] - apiKeyAuth: [].

For OAuth2 and OpenID Connect, the scope list inside a requirement is an AND over scopes, meaning the token must carry every listed scope. Assign each operation the minimum set of scopes it needs to ensure least privilege. For example, /orders: post security: - oauth2: [ write:orders ] handles write operations, while /orders/{id}: get security: - oauth2: [ read:orders ] handles read operations.

When an endpoint accepts either scoped OAuth or a simpler API key, list them as separate requirement objects to avoid confusion. Document that the API key may carry different rate limits or permissions, ensuring clear communication between clients and servers.

Mutual TLS (mTLS) and cookie/session authentication are modeled differently than header-based authentication. mTLS uses type: mutualTLS, while cookie/session auth is represented as type: apiKey. These methods are not sent as headers but occur at the transport level.

Written by urgent.news from Dev.to's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.

Read the original at dev.to →

More in Tech

Health checks for APIs: /healthz, /readyz, /livez, version, and metrics in OpenAPI

A single /health endpoint that checks the database, the cache, and three downstream services, and returns 500 if any of them is briefly unreachable, is actively harmful.

  • The /health endpoint can be /livez, /readyz, /livez, version, and metrics in OpenAPI
  • /livez probe should only check if the process is alive, not if dependencies are reachable
  • /readyz probe verifies if the instance can serve requests right now, stopping traffic if not

More from Thursday 8 October →