docs
0
# Security and Authentication
1
2
Security scheme parsing, authentication handling, and user-based auth token extraction for OpenAPI operations.
3
4
## Capabilities
5
6
### Get Security Requirements
7
8
Retrieve security requirements for an operation with fallback to global API security.
9
10
```typescript { .api }
11
/**
12
* Get security requirements for this operation
13
* @returns Array of security requirement objects (OR groups containing AND requirements)
14
*/
15
getSecurity(): SecurityRequirementObject[];
16
```
17
18
**Usage Examples:**
19
20
```typescript
21
const operation = oas.operation("/users", "post");
22
const security = operation.getSecurity();
23
24
security.forEach((requirement, index) => {
25
console.log(`Security Option ${index + 1}:`);
26
Object.entries(requirement).forEach(([schemeName, scopes]) => {
27
console.log(` ${schemeName}: ${scopes.join(', ') || 'no scopes'}`);
28
});
29
});
30
31
// Check if operation requires authentication
32
const requiresAuth = security.length > 0;
33
console.log(`Authentication required: ${requiresAuth}`);
34
```
35
36
### Get Security with Type Information
37
38
Get security requirements with resolved type information and scheme details.
39
40
```typescript { .api }
41
/**
42
* Get security requirements with type information
43
* @param filterInvalid - Filter out invalid/nonexistent security schemes
44
* @returns Array of OR groups containing AND requirements with type info
45
*/
46
getSecurityWithTypes(
47
filterInvalid?: boolean
48
): Array<Array<{security: KeyedSecuritySchemeObject, type: SecurityType} | false> | false>;
49
```
50
51
**Usage Examples:**
52
53
```typescript
54
const securityWithTypes = operation.getSecurityWithTypes(true); // Filter invalid schemes
55
56
securityWithTypes.forEach((orGroup, index) => {
57
if (!orGroup) return;
58
59
console.log(`Security Option ${index + 1}:`);
60
orGroup.forEach(andRequirement => {
61
if (!andRequirement) return;
62
63
const { security, type } = andRequirement;
64
console.log(` Type: ${type}`);
65
console.log(` Scheme: ${security._key}`);
66
console.log(` Scopes: ${security._requirements?.join(', ') || 'none'}`);
67
68
// Type-specific information
69
if (type === 'Bearer' && security.scheme === 'bearer') {
70
console.log(` Bearer format: ${security.bearerFormat || 'not specified'}`);
71
} else if (type === 'Header' && security.in === 'header') {
72
console.log(` Header name: ${security.name}`);
73
}
74
});
75
});
76
```
77
78
### Prepare Security by Type
79
80
Get security schemes organized by type for easier processing.
81
82
```typescript { .api }
83
/**
84
* Organize security schemes by type
85
* @returns Object with security types as keys and arrays of schemes as values
86
*/
87
prepareSecurity(): Record<SecurityType, KeyedSecuritySchemeObject[]>;
88
```
89
90
**Usage Examples:**
91
92
```typescript
93
const securityByType = operation.prepareSecurity();
94
95
// Handle different security types
96
if (securityByType.Bearer) {
97
console.log("Bearer tokens supported:");
98
securityByType.Bearer.forEach(scheme => {
99
console.log(` ${scheme._key}: ${scheme.bearerFormat || 'JWT'}`);
100
});
101
}
102
103
if (securityByType.Header) {
104
console.log("API key headers:");
105
securityByType.Header.forEach(scheme => {
106
console.log(` ${scheme.name}: ${scheme._key}`);
107
});
108
}
109
110
if (securityByType.OAuth2) {
111
console.log("OAuth2 flows:");
112
securityByType.OAuth2.forEach(scheme => {
113
if ('flows' in scheme) {
114
Object.keys(scheme.flows || {}).forEach(flow => {
115
console.log(` ${scheme._key}: ${flow} flow`);
116
});
117
}
118
});
119
}
120
```
121
122
### Get Authentication for User
123
124
Extract authentication credentials for a specific user from the API definition.
125
126
```typescript { .api }
127
/**
128
* Get authentication credentials for a user
129
* @param user - User information with potential auth credentials
130
* @param selectedApp - Specific app/key to use (optional)
131
* @returns Authentication data formatted for HAR requests
132
*/
133
getAuth(user: User, selectedApp?: number | string): AuthForHAR;
134
```
135
136
**Usage Examples:**
137
138
```typescript
139
// User with various auth methods
140
const user = {
141
apiKey: "sk-1234567890abcdef",
142
bearerToken: "eyJhbGciOiJIUzI1NiIs...",
143
keys: [
144
{ name: "app1", user: "john", pass: "secret123" },
145
{ name: "app2", user: "jane", pass: "password456" }
146
]
147
};
148
149
// Get auth for user
150
const auth = oas.getAuth(user);
151
console.log("Authentication data:", auth);
152
153
// Get auth for specific app
154
const appAuth = oas.getAuth(user, "app1");
155
console.log("App-specific auth:", appAuth);
156
157
// Use in HTTP requests
158
const headers = {};
159
Object.entries(auth).forEach(([key, value]) => {
160
if (typeof value === 'string') {
161
headers[key] = value;
162
} else if (value && typeof value === 'object' && 'user' in value) {
163
// Basic auth
164
const credentials = btoa(`${value.user}:${value.pass}`);
165
headers['Authorization'] = `Basic ${credentials}`;
166
}
167
});
168
```
169
170
## Security Type Definitions
171
172
```typescript { .api }
173
/** Security scheme types */
174
type SecurityType = 'apiKey' | 'Basic' | 'Bearer' | 'Cookie' | 'Header' | 'http' | 'OAuth2' | 'Query';
175
176
/** Security scheme with additional metadata */
177
interface KeyedSecuritySchemeObject extends SecuritySchemeObject {
178
/** The key for the security scheme */
179
_key: string;
180
/** Required scopes for OAuth2 */
181
_requirements?: string[];
182
/** Default value for authentication */
183
'x-default'?: number | string;
184
}
185
186
/** User information for authentication */
187
interface User {
188
[key: string]: unknown;
189
/** Array of app-specific credentials */
190
keys?: {
191
[key: string]: unknown;
192
name: number | string;
193
pass?: number | string;
194
user?: number | string;
195
}[];
196
}
197
198
/** Authentication data for HAR format */
199
type AuthForHAR = Record<string, number | string | { pass?: string; user?: string }>;
200
201
/** Security requirement object */
202
type SecurityRequirementObject = Record<string, string[]>;
203
```
204
205
## Advanced Security Handling
206
207
### OAuth2 Flow Analysis
208
209
```typescript
210
const securityByType = operation.prepareSecurity();
211
212
if (securityByType.OAuth2) {
213
securityByType.OAuth2.forEach(scheme => {
214
if ('flows' in scheme && scheme.flows) {
215
console.log(`OAuth2 scheme: ${scheme._key}`);
216
217
// Authorization Code flow
218
if (scheme.flows.authorizationCode) {
219
const flow = scheme.flows.authorizationCode;
220
console.log(` Auth URL: ${flow.authorizationUrl}`);
221
console.log(` Token URL: ${flow.tokenUrl}`);
222
console.log(` Scopes: ${Object.keys(flow.scopes || {}).join(', ')}`);
223
}
224
225
// Client Credentials flow
226
if (scheme.flows.clientCredentials) {
227
const flow = scheme.flows.clientCredentials;
228
console.log(` Token URL: ${flow.tokenUrl}`);
229
console.log(` Scopes: ${Object.keys(flow.scopes || {}).join(', ')}`);
230
}
231
}
232
});
233
}
234
```
235
236
### Multi-Factor Authentication
237
238
```typescript
239
// Handle operations requiring multiple auth methods (AND requirements)
240
const securityWithTypes = operation.getSecurityWithTypes();
241
242
securityWithTypes.forEach((orGroup, orIndex) => {
243
if (!orGroup || orGroup.length <= 1) return;
244
245
console.log(`Multi-factor option ${orIndex + 1}:`);
246
orGroup.forEach(andRequirement => {
247
if (andRequirement) {
248
console.log(` Required: ${andRequirement.type} (${andRequirement.security._key})`);
249
}
250
});
251
});
252
```
253
254
### Security Validation
255
256
```typescript
257
// Validate user has required credentials
258
function validateUserAuth(operation: Operation, user: User): boolean {
259
const security = operation.getSecurity();
260
if (security.length === 0) return true; // No auth required
261
262
const securityByType = operation.prepareSecurity();
263
264
// Check if user satisfies any OR requirement
265
return Object.entries(securityByType).some(([type, schemes]) => {
266
return schemes.some(scheme => {
267
switch (type) {
268
case 'Bearer':
269
return 'bearerToken' in user || 'authorization' in user;
270
case 'Header':
271
return scheme.name.toLowerCase() in user;
272
case 'Query':
273
return scheme.name in user;
274
case 'Basic':
275
return 'keys' in user && Array.isArray(user.keys);
276
default:
277
return false;
278
}
279
});
280
});
281
}
282
283
const isValid = validateUserAuth(operation, user);
284
console.log(`User has valid credentials: ${isValid}`);
285
```
286
287
### Custom Authentication Extensions
288
289
```typescript
290
// Handle ReadMe-specific auth defaults
291
const securityByType = operation.prepareSecurity();
292
293
Object.values(securityByType).flat().forEach(scheme => {
294
if ('x-default' in scheme && scheme['x-default'] !== undefined) {
295
console.log(`Default value for ${scheme._key}: ${scheme['x-default']}`);
296
}
297
});
298
```
299
300
## Error Handling
301
302
Security handling manages various edge cases:
303
304
- **Missing Security Schemes**: References to undefined schemes return `false` in arrays
305
- **Invalid Flows**: Malformed OAuth2 flows are handled gracefully
306
- **Missing User Data**: Authentication extraction returns empty objects for missing credentials
307
- **Circular References**: Security scheme resolution prevents infinite loops
308
309
```typescript
310
// Safe handling of missing security data
311
const operation = oas.operation("/public", "get");
312
const security = operation.getSecurity(); // [] for operations without security
313
314
const emptyUser = {};
315
const auth = oas.getAuth(emptyUser); // {} - empty auth object
316
317
// Filter invalid schemes
318
const validSecurity = operation.getSecurityWithTypes(true);
319
// Removes false entries for broken security scheme references
320
```
321
322
## Integration Patterns
323
324
### HTTP Client Integration
325
326
```typescript
327
// Generate headers for HTTP clients
328
function generateAuthHeaders(operation: Operation, user: User): Record<string, string> {
329
const auth = oas.getAuth(user);
330
const headers: Record<string, string> = {};
331
332
Object.entries(auth).forEach(([key, value]) => {
333
if (typeof value === 'string') {
334
headers[key] = value;
335
} else if (value && typeof value === 'object') {
336
// Handle Basic auth
337
const credentials = btoa(`${value.user}:${value.pass}`);
338
headers['Authorization'] = `Basic ${credentials}`;
339
}
340
});
341
342
return headers;
343
}
344
```
345
346
### Security Middleware
347
348
```typescript
349
// Express middleware for API security validation
350
function securityMiddleware(operation: Operation) {
351
return (req: Request, res: Response, next: NextFunction) => {
352
const security = operation.getSecurity();
353
354
if (security.length === 0) {
355
return next(); // No auth required
356
}
357
358
const securityByType = operation.prepareSecurity();
359
let isAuthenticated = false;
360
361
// Check each security type
362
if (securityByType.Bearer && req.headers.authorization?.startsWith('Bearer ')) {
363
isAuthenticated = true;
364
} else if (securityByType.Header) {
365
isAuthenticated = securityByType.Header.some(scheme =>
366
req.headers[scheme.name.toLowerCase()]
367
);
368
}
369
370
if (!isAuthenticated) {
371
return res.status(401).json({ error: 'Authentication required' });
372
}
373
374
next();
375
};
376
}
377
```