or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

analysis-metrics.mdapi-definition-reduction.mdextensions-customization.mdindex.mdopenapi-definition-management.mdoperation-discovery-analysis.mdparameter-handling-json-schema.mdrequest-response-management.mdschema-dereferencing-references.mdsecurity-authentication.mdserver-url-management.mdutils.md

security-authentication.mddocs/

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

```