skip to content

Security Schemes

API keys, HTTP bearer or basic, OAuth2 flows with scopes and OpenID Connect, declared once and required globally or per operation. Interviewers ask because specs without auth yield uncallable clients.

part ofAPI stylesoverview, primer and where to startread it →
on this pageshow

questions

5

In OpenAPI 3.x, where are security schemes declared and what type values may they have?

level: juniorimportance: must knowfreq 65%

answer

  1. Definitions live in one components sub-map
  2. The map key is your own identifier
  3. Four types in 3.0, one more in 3.1
  4. One type wraps the HTTP auth framework
  5. Declaring is not the same as applying

basics

~20 s

Security schemes live under components.securitySchemes as named entries. OpenAPI 3.0 defines four types — apiKey, http, oauth2 and openIdConnect — and 3.1 adds mutualTLS. Operations then reference a scheme by its name in a security requirement.

solid answer

~40 s

Every scheme is a named entry under `components.securitySchemes`; the name is arbitrary and is the handle operations use in their `security` lists. The `type` field selects the shape. **`apiKey`** needs `name` and `in` (`query`, `header` or `cookie`). **`http`** needs `scheme`, an HTTP authentication scheme name such as `basic` or `bearer`, plus an optional `bearerFormat` hint. **`oauth2`** needs a `flows` object describing one or more of the authorization-code, client-credentials, password and implicit flows, each with its URLs and a `scopes` map. **`openIdConnect`** needs only `openIdConnectUrl`, pointing at the provider's discovery document. OpenAPI 3.1 adds **`mutualTLS`**, which takes no extra fields. Declaring a scheme alone changes nothing; it must be applied via a security requirement before any tool treats an operation as protected.

code

yaml · 16 lines
yaml
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
    apiKeyAuth:
      type: apiKey
      in: header
      name: X-API-Key
    oidc:
      type: openIdConnect
      openIdConnectUrl: https://issuer.example.com/.well-known/openid-configuration

security:
  - bearerAuth: []

go deeper

for a junior

Be able to write a bearer scheme under components.securitySchemes and apply it with a root-level security entry; know the four 3.0 type values by name.

for a middle

Explain what each type requires — name/in, scheme, flows, openIdConnectUrl — and why the map key is only an identifier with no wire meaning.

for a senior

Show that you treat the document as a description and know where real enforcement lives, and that you catch the apiKey-as-Authorization mistake in review before it reaches generated SDKs.

for a principal

Own the estate-wide choice of scheme type and how the document stays in step with the identity provider, including whether services declare oauth2 inline or delegate to an openIdConnect discovery URL.

## Where schemes live Authentication in an OpenAPI document is described in two halves. The first half — this question — is the **definition**: a map at `components.securitySchemes` from an arbitrary name you choose to a Security Scheme Object. The second half is the **application**: `security` lists at the document root or on an operation that name those schemes. A scheme that is defined but never applied protects nothing; a `security` entry naming a scheme that does not exist in `components.securitySchemes` is an invalid document. The key you pick (`bearerAuth`, `apiKeyAuth`, `myOauth`) is just an identifier. It has no meaning to a client — it is not a header name, not a scheme name, not a scope — and it exists solely so `security` can refer to the definition. Renderers do surface it, so pick something readable. ## The type values **`apiKey`** — a value carried in a named field. Requires `name` (the field's name) and `in`, which is `query`, `header` or `cookie`. This is how you describe `X-API-Key: abc123` or `?api_key=abc123`. **`http`** — authentication using the HTTP `Authorization` header's own framework. Requires `scheme`, whose value is an HTTP authentication scheme name from the IANA registry defined alongside RFC 7235 — `basic`, `bearer`, `digest` and others. For `bearer`, an optional `bearerFormat` string hints at the token format (commonly the literal `JWT`). You do **not** describe the `Authorization` header as a header parameter; a header parameter with that name is explicitly ignored by the specification because this is where it belongs. **`oauth2`** — requires a `flows` object whose members are `implicit`, `password`, `clientCredentials` and `authorizationCode`. Each declared flow supplies the URLs it needs (`authorizationUrl`, `tokenUrl`, optional `refreshUrl`) and a required `scopes` map of scope name to human description. The `scopes` map is the registry of scope names the document may then reference. **`openIdConnect`** — requires only `openIdConnectUrl`, a URL to the OpenID Connect discovery document. The scheme delegates the details to that document rather than restating flows and endpoints inline. **`mutualTLS`** — added in OpenAPI **3.1**. It declares that the API authenticates the client by its TLS certificate, and it carries no additional fields. It does not exist in 3.0 documents. All five share the optional `description` field, which is CommonMark and is what documentation renderers show next to the Authorize control. ## What tooling does with a scheme Documentation renderers use the definitions to build their authorization UI — Swagger UI's **Authorize** dialog is driven entirely by `securitySchemes` plus the `security` lists. Client generators use them to add a credential parameter or an interceptor to the generated SDK. Server-stub generators may scaffold a security filter hook. Linters check that every applied name is defined and, in many rule sets, that at least one scheme is applied. ## What a scheme does not do A Security Scheme Object is a **declaration**, not an enforcement mechanism. Nothing about writing `type: http, scheme: bearer` causes any token to be verified; the gateway, framework or filter chain does that, and the document is only a description of what the client is expected to send. Drift between the two — a spec that says an operation is protected while the service happily serves it anonymously, or the reverse — is invisible to validators and is a real production hazard. ## Frequent mistakes The most common by far is describing bearer authentication as `type: apiKey, in: header, name: Authorization`. It renders roughly, and generated clients then require the caller to type the word `Bearer` themselves; the correct declaration is `type: http, scheme: bearer`. The habit comes from **Swagger 2.0**, which had no `http` type at all — it offered `basic`, `apiKey` and `oauth2` under a top-level `securityDefinitions` key. A second mistake is defining schemes and never applying them, which leaves generated clients with no way to send credentials at all.

  • Why is type: apiKey with name: Authorization the wrong way to describe bearer tokens?
    It models the Authorization header as an opaque named field, so a generated client asks the caller for the entire header value — including the literal `Bearer ` prefix — and renderers cannot show the right control. The correct declaration is `type: http` with `scheme: bearer`, which tells tooling to build the header itself. The apiKey habit is a Swagger 2.0 carryover, since 2.0 had no `http` type.
  • What does an openIdConnect scheme require, and what does it save you writing?
    Only `openIdConnectUrl`, pointing at the provider's discovery document. Everything the `oauth2` type would restate inline — endpoints, supported flows, available scopes — is fetched from that document instead, so the spec cannot drift from the provider's real configuration. The tradeoff is that a reader or a tool must resolve the URL to know what the API actually accepts.
  • Does defining a security scheme make an operation protected?
    No. Definition and application are separate: `components.securitySchemes` defines, and a `security` list at the root or on an operation applies. A scheme that is defined but never referenced changes nothing — documentation shows no requirement and generated clients offer no way to send the credential. Even once applied, the document only describes what should happen; enforcement lives in the service.

saying these in an interview costs you the question

  • Declares bearer auth as apiKey named Authorization
  • Thinks defining a scheme protects operations
  • Believes mutualTLS exists in OpenAPI 3.0
  • Uses securityDefinitions, the Swagger 2.0 key
  • Treats the scheme's map key as a header name

context

open as a page

In an OpenAPI document, how does operation-level security interact with the root security block?

level: middleimportance: must knowfreq 55%

basics

~20 s

A root-level OpenAPI security block is the default for every operation. An operation's own security field replaces that default entirely rather than adding to it, and an empty array removes the inherited requirement, making the operation public.

open as a page

In an OpenAPI document, what is the difference between two schemes in one security requirement object versus two objects?

level: middleimportance: should knowfreq 45%

basics

~20 s

Two schemes inside one OpenAPI security requirement object mean AND — the caller must satisfy both. Two requirement objects in the security array are alternatives, meaning OR — satisfying any one of them authorizes the request.

open as a page

In an OpenAPI security scheme of type http, what do scheme and bearerFormat actually specify?

level: middleimportance: should knowfreq 50%

basics

~20 s

OpenAPI's http scheme field names an HTTP authentication scheme from the IANA registry — basic, bearer, digest — and determines the Authorization header's form. bearerFormat is a free-text documentation hint about the token's format and is ignored by tooling.

open as a page

In an OpenAPI oauth2 security scheme, what do the flows object and its scopes declare?

level: seniorimportance: should knowfreq 40%

basics

~20 s

An OpenAPI oauth2 scheme's flows object names which grant types the API supports — authorizationCode, clientCredentials, password, implicit — each with its endpoint URLs and a required scopes map of scope name to description. Operations then reference subsets of those scope names.

open as a page