In OpenAPI 3.x, where are security schemes declared and what type values may they have?
answer
- Definitions live in one components sub-map
- The map key is your own identifier
- Four types in 3.0, one more in 3.1
- One type wraps the HTTP auth framework
- Declaring is not the same as applying
basics
~20 sSecurity 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 sEvery 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 linescomponents:
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
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.
Explain what each type requires — name/in, scheme, flows, openIdConnectUrl — and why the map key is only an identifier with no wire meaning.
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.
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