Skip to content

Commit 7b23d9e

Browse files
OAS Hub: Security Refresh/New (#47)
Co-authored-by: Sagar Batchu <sagar.batchu92@gmail.com>
1 parent 00c3e2a commit 7b23d9e

File tree

6 files changed

+409
-105
lines changed

6 files changed

+409
-105
lines changed

openapi/security.mdx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ When designing an API, it is important to consider the security requirements for
1111

1212
Firstly, "security" is a general term which covers multiple authentication and authorization systems which are commonly used to keep API operations being used by only the intended actors.
1313

14-
In OpenAPI this is broken in two halves.
14+
In OpenAPI this is broken in two halves.
1515

1616
1. Security schemes
1717
2. Security requirements
@@ -160,14 +160,14 @@ paths:
160160
security:
161161
- apiKey: [] # Can be access with an API key, or...
162162
- oauth2: # an oauth2 token which has the read scope
163-
- read
163+
- read
164164
post:
165165
operationId: createDrink
166166
summary: Create a new drink
167167
security:
168-
- apiKey: [] # Can be accessed with an API key, or...
168+
- apiKey: [] # Can be accessed with an API key, or...
169169
- oauth2: # an oauth2 token which has the write scope
170-
- write
170+
- write
171171
172172
components:
173173
securitySchemes:

openapi/security/security-schemes/security-api-key.mdx

Lines changed: 56 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,40 @@ import { Table } from "@/mdx/components";
66

77
# API Key Security Scheme in OpenAPI
88

9+
910
An API Key security scheme is the most common form of authentication for machine-to-machine APIs and supports passing a pre-shared secret in several ways. The secret can be passed either via the Authorization header (or another custom header), as a query parameter, or via a cookie.
1011

11-
While this is probably the most commonly used mechanism, it is generally one of the least secure. This is especially true if the key is passed outside of headers or cookies (that is, via query params, as various logging mechanisms normally store query param information).
12+
13+
Here's an example of an API key being passed in the query string.
14+
15+
```http
16+
GET /drinks?api_key=abcdef12345
17+
```
18+
19+
or as a request header:
20+
21+
```http
22+
GET /something HTTP/1.1
23+
24+
Speakeasy-API-Key: abcdef12345
25+
```
26+
27+
or as a cookie:
28+
29+
```http
30+
GET /something HTTP/1.1
31+
32+
Cookie: X-API-KEY=abcdef12345
33+
```
34+
35+
API Keys are one of the most commonly used mechanism, but depending on what that key is and how its generated it may not well be very secure. This is especially true if the key is passed outside of headers or cookies (that is, via query params, as various logging mechanisms normally store query param information).
1236

1337
The biggest security flaw is that most pre-shared secrets are long-lived and if intercepted, can be used until they are either revoked or expire (generally in months or years). This risk is normally tolerated for machine-to-machine applications as the chance of interception (especially when using private VPCs/TLS and other mechanisms) is relatively low compared to a key from a user's device traveling on a public network.
1438

39+
Regardless of which method you use, HTTPS/TLS is highly recommended.
40+
41+
## API Key Object
42+
1543
The fields for an API Key security scheme are as follows:
1644

1745
<Table
@@ -30,13 +58,37 @@ The fields for an API Key security scheme are as follows:
3058
]}
3159
/>
3260

61+
To describe an API key, create an object in `securitySchemes` with a name of whatever you like. Perhaps it's just called `ApiKey` but it could be called `anythingYOULikeAuth`. So long as its easy to remember and a valid YAML string. Then the object defines `type: apiKey` and the name of the header/query/cookie parameter as it should show up in the HTTP request.
62+
3363
```yaml
3464
components:
3565
securitySchemes:
36-
api_key:
66+
ApiKey:
3767
type: apiKey
38-
name: api_key
68+
name: Speakeasy-API-Key
3969
in: header
4070
security:
41-
- api_key: []
71+
- ApiKey: []
72+
```
73+
74+
A description can be added to let API users know where to go to find an API key, or an email address to request one.
75+
76+
## Multiple API keys
77+
78+
Some APIs require two API keys to be used at once, like an app ID and an app Key. In this case, it's possible to define both keys as `securitySchemes` then reference them both in the same [security requirement object](../../security.mdx).
79+
80+
```yaml
81+
security:
82+
- AppId: []
83+
AppKey: [] # no leading dash
84+
components:
85+
securitySchemes:
86+
AppId:
87+
type: apiKey
88+
name: Speakeasy-App-Id
89+
in: header
90+
AppKey:
91+
type: apiKey
92+
name: Speakeasy-App-Key
93+
in: header
4294
```

openapi/security/security-schemes/security-http.mdx

Lines changed: 94 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,11 +127,11 @@ Since all APIs need to be accurately described (warts and all), here's how to de
127127
{ key: "field", header: "Field" },
128128
{ key: "type", header: "Type" },
129129
{ key: "required", header: "Required" },
130-
{ key: "description", header: "Description" },
130+
{ key: "description", header: "Description" }
131131
]}
132132
/>
133133

134-
For example:
134+
For example:
135135

136136
```yaml
137137
components:
@@ -143,6 +143,20 @@ security:
143143
- auth: []
144144
```
145145

146+
The description field can be used to warn developers about the risks of using Basic authentication, and to encourage them to use more secure alternatives like Bearer tokens or OAuth2.
147+
148+
```yaml
149+
components:
150+
securitySchemes:
151+
auth:
152+
type: http
153+
scheme: basic
154+
description: |
155+
**Warning:** Basic authentication sends credentials in an easily decodable format, so this
156+
should only be used over HTTPS. Instead of using your password please only use a short lived access token
157+
which can be obtained from <https://example.com/tokens>.
158+
```
159+
146160
## HTTP Digest
147161

148162
The Digest security scheme is a more secure alternative to Basic authentication. Instead of sending the username and password in plain text, Digest authentication uses a challenge-response mechanism that hashes credentials with a nonce provided by the server. This helps protect against replay attacks and credential interception.
@@ -205,3 +219,81 @@ components:
205219
security:
206220
- digestAuth: []
207221
```
222+
223+
## Overlap with other security schemes
224+
225+
The HTTP security scheme overlaps with a few other more specific schemes.
226+
227+
The [API Key](./security-api-key.mdx) security scheme is better suited for non-standard API keys using custom headers like `Acme-API-Key`, whereas HTTP security schemes are specifically designed for HTTP-based authentication methods using `Authorization` header.
228+
229+
There is also some overlap with [OAuth2](./security-oauth2.mdx) and [OpenID Connect](./security-openid.mdx) security schemes. These may use bearer tokens, and they may use the JWT format, but they are more complex and involve additional flows and endpoints. The `oauth2` and `openidConnect` security schemes are better suited for any APIs using the OAuth 2.0 and OpenID Connect protocols than trying to cover it with the `http` security scheme.
230+
231+
### Unauthorized Response
232+
233+
As well as describing the security requirements, it also helps to describe what will happen when those requirements are not met. The 401 Unauthorized response can be returned for requests with missing security credentials, showing what the client can expect to see if this happens. This response includes the `WWW-Authenticate` header, which you may want to mention. As with other generic responses, the 401 response can be defined as a component in the `responses` section, and referenced with `$ref` to avoid repetition.
234+
235+
```yaml
236+
paths:
237+
/drinks:
238+
get:
239+
# ...
240+
responses:
241+
# ...
242+
'401':
243+
$ref: '#/components/responses/HttpErrorUnauthorized'
244+
post:
245+
# ...
246+
responses:
247+
# ...
248+
'401':
249+
$ref: '#/components/responses/HttpErrorUnauthorized'
250+
251+
components:
252+
responses:
253+
HttpErrorUnauthorized:
254+
description: Unauthorized
255+
headers:
256+
WWW_Authenticate:
257+
schema:
258+
type: string
259+
content:
260+
application/problem+json:
261+
schema:
262+
$ref: '#/components/schemas/ProblemDetails'
263+
```
264+
265+
Learn more about describing [responses](../../responses.mdx).
266+
267+
## Forbidden Response
268+
269+
The 403 Forbidden response can be returned for requests that are authenticated but not authorized to access the resource. This response can also include the `WWW-Authenticate` header, but it is not required.
270+
271+
As with the 401 response, the 403 response can be defined as a component in the `responses` section, and referenced with `$ref` to avoid repetition. This error is using the HTTP Problem Details format, which is a standard way to provide more information about the error.
272+
273+
```yaml
274+
paths:
275+
/drinks:
276+
get:
277+
# ...
278+
responses:
279+
# ...
280+
'403':
281+
$ref: '#/components/responses/HttpErrorForbidden'
282+
post:
283+
# ...
284+
responses:
285+
# ...
286+
'403':
287+
$ref: '#/components/responses/HttpErrorForbidden'
288+
components:
289+
responses:
290+
HttpErrorForbidden:
291+
description: Forbidden
292+
headers:
293+
WWW_Authenticate:
294+
type: string
295+
content:
296+
application/problem+json:
297+
schema:
298+
$ref: '#/components/schemas/ProblemDetails'
299+
```

openapi/security/security-schemes/security-mutualtls.mdx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
title: MutualTLS in OpenAPI
3-
description: >
3+
description: >
44
Mutual TLS (mTLS) is a security protocol that enhances the security of API
55
communication by requiring both the client and server to authenticate each
66
other using digital certificates.
@@ -45,4 +45,5 @@ components:
4545
full information about what this application is to obtain a certificate.
4646
```
4747

48-
That's all there is to this one.
48+
Learn more about Mutual TLS in the [OpenAPI Specification](https://spec.openapis.org/oas/v3.1.0#mutual-tls-security-scheme),
49+
or on Cloudflare's [What is Mutual TLS](https://www.cloudflare.com/learning/access-management/what-is-mutual-tls/).

0 commit comments

Comments
 (0)