or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

advanced-features.mdcore-annotations.mdindex.mdresponses.mdschema-media.mdsecurity.mdservers-tags.md

security.mddocs/

0

# Security Configuration

1

2

This document covers annotations for configuring authentication and authorization schemes, including API keys, OAuth2, OpenID Connect, mutual TLS, and security requirements.

3

4

## Imports

5

6

```java { .api }

7

import io.swagger.v3.oas.annotations.security.SecurityScheme;

8

import io.swagger.v3.oas.annotations.security.SecuritySchemes;

9

import io.swagger.v3.oas.annotations.security.SecurityRequirement;

10

import io.swagger.v3.oas.annotations.security.SecurityRequirements;

11

import io.swagger.v3.oas.annotations.security.OAuthFlow;

12

import io.swagger.v3.oas.annotations.security.OAuthFlows;

13

import io.swagger.v3.oas.annotations.security.OAuthScope;

14

import io.swagger.v3.oas.annotations.enums.SecuritySchemeType;

15

import io.swagger.v3.oas.annotations.enums.SecuritySchemeIn;

16

```

17

18

## SecurityScheme

19

20

Defines security schemes that can be used by operations or the entire API. Security schemes are added to the components section of the OpenAPI specification.

21

22

### API Key Authentication

23

24

```java { .api }

25

@SecurityScheme(

26

name = "apiKey",

27

description = "API key authentication via X-API-Key header",

28

type = SecuritySchemeType.APIKEY,

29

in = SecuritySchemeIn.HEADER,

30

paramName = "X-API-Key",

31

extensions = {

32

@Extension(name = "x-example", properties = {

33

@ExtensionProperty(name = "value", value = "your-api-key-here")

34

})

35

}

36

)

37

38

@SecurityScheme(

39

name = "queryApiKey",

40

description = "API key authentication via query parameter",

41

type = SecuritySchemeType.APIKEY,

42

in = SecuritySchemeIn.QUERY,

43

paramName = "api_key"

44

)

45

46

@SecurityScheme(

47

name = "cookieAuth",

48

description = "API key authentication via cookie",

49

type = SecuritySchemeType.APIKEY,

50

in = SecuritySchemeIn.COOKIE,

51

paramName = "session_token"

52

)

53

```

54

55

### HTTP Authentication Schemes

56

57

```java { .api }

58

// Basic Authentication

59

@SecurityScheme(

60

name = "basicAuth",

61

description = "HTTP Basic authentication using username and password",

62

type = SecuritySchemeType.HTTP,

63

scheme = "basic"

64

)

65

66

// Bearer Token Authentication (JWT)

67

@SecurityScheme(

68

name = "bearerAuth",

69

description = "JWT token authentication via Authorization header",

70

type = SecuritySchemeType.HTTP,

71

scheme = "bearer",

72

bearerFormat = "JWT",

73

extensions = {

74

@Extension(name = "x-token-type", properties = {

75

@ExtensionProperty(name = "type", value = "JWT"),

76

@ExtensionProperty(name = "algorithm", value = "HS256")

77

})

78

}

79

)

80

81

// Custom HTTP Scheme

82

@SecurityScheme(

83

name = "customAuth",

84

description = "Custom HTTP authentication scheme",

85

type = SecuritySchemeType.HTTP,

86

scheme = "digest"

87

)

88

```

89

90

### OAuth2 Authentication

91

92

```java { .api }

93

@SecurityScheme(

94

name = "oauth2",

95

description = "OAuth2 authentication with multiple flow support",

96

type = SecuritySchemeType.OAUTH2,

97

flows = @OAuthFlows(

98

authorizationCode = @OAuthFlow(

99

authorizationUrl = "https://auth.petstore.io/oauth/authorize",

100

tokenUrl = "https://auth.petstore.io/oauth/token",

101

refreshUrl = "https://auth.petstore.io/oauth/refresh",

102

scopes = {

103

@OAuthScope(name = "read", description = "Read access to resources"),

104

@OAuthScope(name = "write", description = "Write access to resources"),

105

@OAuthScope(name = "admin", description = "Administrative access")

106

}

107

),

108

implicit = @OAuthFlow(

109

authorizationUrl = "https://auth.petstore.io/oauth/authorize",

110

scopes = {

111

@OAuthScope(name = "read", description = "Read access to resources"),

112

@OAuthScope(name = "write", description = "Write access to resources")

113

}

114

),

115

password = @OAuthFlow(

116

tokenUrl = "https://auth.petstore.io/oauth/token",

117

refreshUrl = "https://auth.petstore.io/oauth/refresh",

118

scopes = {

119

@OAuthScope(name = "read", description = "Read access to resources"),

120

@OAuthScope(name = "write", description = "Write access to resources"),

121

@OAuthScope(name = "admin", description = "Administrative access")

122

}

123

),

124

clientCredentials = @OAuthFlow(

125

tokenUrl = "https://auth.petstore.io/oauth/token",

126

scopes = {

127

@OAuthScope(name = "api_access", description = "API access for applications"),

128

@OAuthScope(name = "system_admin", description = "System administration access")

129

}

130

)

131

)

132

)

133

```

134

135

### OpenID Connect

136

137

```java { .api }

138

@SecurityScheme(

139

name = "openIdConnect",

140

description = "OpenID Connect authentication",

141

type = SecuritySchemeType.OPENIDCONNECT,

142

openIdConnectUrl = "https://auth.petstore.io/.well-known/openid-configuration",

143

extensions = {

144

@Extension(name = "x-client-id", properties = {

145

@ExtensionProperty(name = "value", value = "petstore-client")

146

}),

147

@Extension(name = "x-audience", properties = {

148

@ExtensionProperty(name = "value", value = "https://api.petstore.io")

149

})

150

}

151

)

152

```

153

154

### Mutual TLS Authentication

155

156

```java { .api }

157

@SecurityScheme(

158

name = "mutualTLS",

159

description = "Mutual TLS authentication using client certificates",

160

type = SecuritySchemeType.MUTUALTLS,

161

extensions = {

162

@Extension(name = "x-certificate-requirements", properties = {

163

@ExtensionProperty(name = "issuer", value = "CN=Pet Store CA"),

164

@ExtensionProperty(name = "keyUsage", value = "digitalSignature, keyEncipherment")

165

})

166

}

167

)

168

```

169

170

### Multiple Security Schemes

171

172

```java { .api }

173

@SecuritySchemes({

174

@SecurityScheme(

175

name = "apiKeyAuth",

176

type = SecuritySchemeType.APIKEY,

177

in = SecuritySchemeIn.HEADER,

178

paramName = "X-API-Key"

179

),

180

@SecurityScheme(

181

name = "bearerAuth",

182

type = SecuritySchemeType.HTTP,

183

scheme = "bearer",

184

bearerFormat = "JWT"

185

),

186

@SecurityScheme(

187

name = "oauth2Auth",

188

type = SecuritySchemeType.OAUTH2,

189

flows = @OAuthFlows(

190

authorizationCode = @OAuthFlow(

191

authorizationUrl = "https://auth.example.com/oauth/authorize",

192

tokenUrl = "https://auth.example.com/oauth/token",

193

scopes = {

194

@OAuthScope(name = "read", description = "Read access"),

195

@OAuthScope(name = "write", description = "Write access")

196

}

197

)

198

)

199

)

200

})

201

@RestController

202

public class SecureApiController {

203

// Controller implementation

204

}

205

```

206

207

### SecurityScheme Attributes

208

209

```java { .api }

210

public @interface SecurityScheme {

211

SecuritySchemeType type();

212

String name() default "";

213

String description() default "";

214

String paramName() default "";

215

SecuritySchemeIn in() default SecuritySchemeIn.DEFAULT;

216

String scheme() default "";

217

String bearerFormat() default "";

218

OAuthFlows flows() default @OAuthFlows;

219

String openIdConnectUrl() default "";

220

Extension[] extensions() default {};

221

String ref() default "";

222

}

223

```

224

225

## SecurityRequirement

226

227

Defines security requirements for operations or the entire API. Can specify multiple schemes and required scopes.

228

229

### Single Security Requirement

230

231

```java { .api }

232

@GetMapping("/pets")

233

@Operation(summary = "List all pets")

234

@SecurityRequirement(name = "apiKey")

235

public ResponseEntity<List<Pet>> getAllPets() {

236

return ResponseEntity.ok(petService.findAll());

237

}

238

239

// OAuth2 with specific scopes

240

@PostMapping("/pets")

241

@Operation(summary = "Create a new pet")

242

@SecurityRequirement(name = "oauth2", scopes = {"write", "pets:create"})

243

public ResponseEntity<Pet> createPet(@RequestBody Pet pet) {

244

return ResponseEntity.ok(petService.create(pet));

245

}

246

247

// Admin operation requiring elevated privileges

248

@DeleteMapping("/pets/{id}")

249

@Operation(summary = "Delete a pet")

250

@SecurityRequirement(name = "oauth2", scopes = {"admin", "pets:delete"})

251

public ResponseEntity<Void> deletePet(@PathVariable Long id) {

252

petService.delete(id);

253

return ResponseEntity.noContent().build();

254

}

255

```

256

257

### Multiple Security Requirements (OR Logic)

258

259

```java { .api }

260

@GetMapping("/pets/{id}")

261

@Operation(summary = "Get pet by ID")

262

@SecurityRequirements({

263

@SecurityRequirement(name = "apiKey"),

264

@SecurityRequirement(name = "bearerAuth"),

265

@SecurityRequirement(name = "oauth2", scopes = {"read"})

266

})

267

public ResponseEntity<Pet> getPetById(@PathVariable Long id) {

268

// Can be authenticated with ANY of the above schemes

269

return ResponseEntity.ok(petService.findById(id));

270

}

271

```

272

273

### Combined Security Requirements (AND Logic)

274

275

```java { .api }

276

// Requires BOTH API key AND OAuth2 token

277

@PostMapping("/admin/pets/bulk-import")

278

@Operation(summary = "Bulk import pets (admin only)")

279

@SecurityRequirement(name = "apiKey") // AND

280

@SecurityRequirement(name = "oauth2", scopes = {"admin", "bulk_operations"}) // AND this

281

public ResponseEntity<BulkImportResult> bulkImportPets(@RequestBody List<Pet> pets) {

282

// Requires both authentication methods

283

return ResponseEntity.ok(petService.bulkImport(pets));

284

}

285

```

286

287

### API-Level Security

288

289

```java { .api }

290

@OpenAPIDefinition(

291

info = @Info(title = "Secure Pet Store API", version = "1.0.0"),

292

security = {

293

@SecurityRequirement(name = "apiKey"),

294

@SecurityRequirement(name = "oauth2", scopes = {"read"})

295

}

296

)

297

@RestController

298

public class PetStoreController {

299

300

// This endpoint inherits API-level security

301

@GetMapping("/pets")

302

public ResponseEntity<List<Pet>> getAllPets() {

303

return ResponseEntity.ok(petService.findAll());

304

}

305

306

// This endpoint overrides API-level security

307

@GetMapping("/pets/public")

308

@Operation(security = {}) // No security required

309

public ResponseEntity<List<Pet>> getPublicPets() {

310

return ResponseEntity.ok(petService.findPublicPets());

311

}

312

313

// This endpoint adds additional security requirements

314

@PostMapping("/pets")

315

@SecurityRequirement(name = "oauth2", scopes = {"write"})

316

public ResponseEntity<Pet> createPet(@RequestBody Pet pet) {

317

// Requires API-level security AND write scope

318

return ResponseEntity.ok(petService.create(pet));

319

}

320

}

321

```

322

323

### Conditional Security Based on Operation

324

325

```java { .api }

326

@RestController

327

public class FlexibleSecurityController {

328

329

@GetMapping("/pets/search")

330

@Operation(summary = "Search pets with optional authentication")

331

@SecurityRequirements({

332

@SecurityRequirement(name = "none"), // No authentication

333

@SecurityRequirement(name = "apiKey"), // OR API key

334

@SecurityRequirement(name = "oauth2", scopes = {"read"}) // OR OAuth2

335

})

336

public ResponseEntity<List<Pet>> searchPets(

337

@RequestParam(required = false) String query,

338

@RequestParam(required = false) Boolean includePrivate

339

) {

340

// Authentication affects available data

341

if (includePrivate != null && includePrivate) {

342

// Requires authentication for private pets

343

return ResponseEntity.ok(petService.searchIncludingPrivate(query));

344

}

345

return ResponseEntity.ok(petService.searchPublic(query));

346

}

347

}

348

```

349

350

## OAuthFlows and OAuthScope

351

352

Define comprehensive OAuth2 flow configurations with detailed scope definitions.

353

354

### Complete OAuth2 Configuration

355

356

```java { .api }

357

@SecurityScheme(

358

name = "petStoreOAuth",

359

type = SecuritySchemeType.OAUTH2,

360

description = "Pet Store OAuth2 authentication with comprehensive flow support",

361

flows = @OAuthFlows(

362

authorizationCode = @OAuthFlow(

363

authorizationUrl = "https://auth.petstore.io/oauth/authorize",

364

tokenUrl = "https://auth.petstore.io/oauth/token",

365

refreshUrl = "https://auth.petstore.io/oauth/refresh",

366

scopes = {

367

@OAuthScope(

368

name = "pets:read",

369

description = "Read access to pet information"

370

),

371

@OAuthScope(

372

name = "pets:write",

373

description = "Create and update pet information"

374

),

375

@OAuthScope(

376

name = "pets:delete",

377

description = "Delete pet records"

378

),

379

@OAuthScope(

380

name = "categories:read",

381

description = "Read pet categories"

382

),

383

@OAuthScope(

384

name = "categories:manage",

385

description = "Create, update, and delete pet categories"

386

),

387

@OAuthScope(

388

name = "users:read",

389

description = "Read user profiles"

390

),

391

@OAuthScope(

392

name = "users:manage",

393

description = "Manage user accounts"

394

),

395

@OAuthScope(

396

name = "orders:read",

397

description = "Read order information"

398

),

399

@OAuthScope(

400

name = "orders:create",

401

description = "Create new orders"

402

),

403

@OAuthScope(

404

name = "admin",

405

description = "Full administrative access to all resources"

406

)

407

}

408

),

409

implicit = @OAuthFlow(

410

authorizationUrl = "https://auth.petstore.io/oauth/authorize",

411

scopes = {

412

@OAuthScope(name = "pets:read", description = "Read pet information"),

413

@OAuthScope(name = "pets:write", description = "Write pet information"),

414

@OAuthScope(name = "orders:read", description = "Read orders"),

415

@OAuthScope(name = "orders:create", description = "Create orders")

416

}

417

),

418

password = @OAuthFlow(

419

tokenUrl = "https://auth.petstore.io/oauth/token",

420

refreshUrl = "https://auth.petstore.io/oauth/refresh",

421

scopes = {

422

@OAuthScope(name = "pets:read", description = "Read pet information"),

423

@OAuthScope(name = "pets:write", description = "Write pet information"),

424

@OAuthScope(name = "users:read", description = "Read user profiles"),

425

@OAuthScope(name = "admin", description = "Administrative access")

426

}

427

),

428

clientCredentials = @OAuthFlow(

429

tokenUrl = "https://auth.petstore.io/oauth/token",

430

scopes = {

431

@OAuthScope(

432

name = "api:access",

433

description = "Basic API access for client applications"

434

),

435

@OAuthScope(

436

name = "webhook:receive",

437

description = "Receive webhook notifications"

438

),

439

@OAuthScope(

440

name = "system:monitor",

441

description = "Monitor system health and metrics"

442

)

443

}

444

)

445

)

446

)

447

```

448

449

### Fine-Grained Scope Usage

450

451

```java { .api }

452

@RestController

453

public class ScopedPetController {

454

455

@GetMapping("/pets")

456

@SecurityRequirement(name = "petStoreOAuth", scopes = {"pets:read"})

457

public ResponseEntity<List<Pet>> getAllPets() {

458

return ResponseEntity.ok(petService.findAll());

459

}

460

461

@PostMapping("/pets")

462

@SecurityRequirement(name = "petStoreOAuth", scopes = {"pets:write"})

463

public ResponseEntity<Pet> createPet(@RequestBody Pet pet) {

464

return ResponseEntity.ok(petService.create(pet));

465

}

466

467

@PutMapping("/pets/{id}")

468

@SecurityRequirement(name = "petStoreOAuth", scopes = {"pets:write"})

469

public ResponseEntity<Pet> updatePet(@PathVariable Long id, @RequestBody Pet pet) {

470

return ResponseEntity.ok(petService.update(id, pet));

471

}

472

473

@DeleteMapping("/pets/{id}")

474

@SecurityRequirement(name = "petStoreOAuth", scopes = {"pets:delete"})

475

public ResponseEntity<Void> deletePet(@PathVariable Long id) {

476

petService.delete(id);

477

return ResponseEntity.noContent().build();

478

}

479

480

@GetMapping("/admin/pets/analytics")

481

@SecurityRequirement(name = "petStoreOAuth", scopes = {"admin"})

482

public ResponseEntity<PetAnalytics> getPetAnalytics() {

483

return ResponseEntity.ok(petService.getAnalytics());

484

}

485

486

@PostMapping("/pets/batch")

487

@SecurityRequirement(name = "petStoreOAuth", scopes = {"pets:write", "admin"})

488

public ResponseEntity<List<Pet>> batchCreatePets(@RequestBody List<Pet> pets) {

489

// Requires both pets:write AND admin scopes

490

return ResponseEntity.ok(petService.batchCreate(pets));

491

}

492

}

493

```

494

495

## Security Enums

496

497

### SecuritySchemeType

498

499

Defines the type of security scheme being used.

500

501

```java { .api }

502

public enum SecuritySchemeType {

503

DEFAULT,

504

APIKEY, // API key authentication

505

HTTP, // HTTP authentication (Basic, Bearer, etc.)

506

OAUTH2, // OAuth 2.0 authentication

507

OPENIDCONNECT, // OpenID Connect authentication

508

MUTUALTLS // Mutual TLS authentication

509

}

510

```

511

512

### SecuritySchemeIn

513

514

Defines where the security parameter is located in HTTP requests.

515

516

```java { .api }

517

public enum SecuritySchemeIn {

518

DEFAULT,

519

HEADER, // HTTP header

520

QUERY, // Query parameter

521

COOKIE // HTTP cookie

522

}

523

```

524

525

## Advanced Security Configurations

526

527

### Multi-Tenant Security

528

529

```java { .api }

530

@SecuritySchemes({

531

@SecurityScheme(

532

name = "tenantApiKey",

533

type = SecuritySchemeType.APIKEY,

534

in = SecuritySchemeIn.HEADER,

535

paramName = "X-Tenant-API-Key",

536

description = "Tenant-specific API key authentication"

537

),

538

@SecurityScheme(

539

name = "userBearer",

540

type = SecuritySchemeType.HTTP,

541

scheme = "bearer",

542

bearerFormat = "JWT",

543

description = "User JWT token with tenant context"

544

)

545

})

546

@RestController

547

public class MultiTenantController {

548

549

@GetMapping("/tenant/{tenantId}/pets")

550

@SecurityRequirements({

551

@SecurityRequirement(name = "tenantApiKey"),

552

@SecurityRequirement(name = "userBearer")

553

})

554

public ResponseEntity<List<Pet>> getTenantPets(@PathVariable String tenantId) {

555

return ResponseEntity.ok(petService.findByTenant(tenantId));

556

}

557

}

558

```

559

560

### Role-Based Access Control

561

562

```java { .api }

563

@SecurityScheme(

564

name = "roleBasedAuth",

565

type = SecuritySchemeType.OAUTH2,

566

flows = @OAuthFlows(

567

authorizationCode = @OAuthFlow(

568

authorizationUrl = "https://auth.petstore.io/oauth/authorize",

569

tokenUrl = "https://auth.petstore.io/oauth/token",

570

scopes = {

571

@OAuthScope(name = "role:viewer", description = "Read-only access"),

572

@OAuthScope(name = "role:editor", description = "Read and write access"),

573

@OAuthScope(name = "role:admin", description = "Full administrative access"),

574

@OAuthScope(name = "role:owner", description = "Resource ownership privileges")

575

}

576

)

577

)

578

)

579

580

@RestController

581

public class RoleBasedController {

582

583

@GetMapping("/pets/{id}")

584

@SecurityRequirement(name = "roleBasedAuth", scopes = {"role:viewer"})

585

public ResponseEntity<Pet> viewPet(@PathVariable Long id) {

586

return ResponseEntity.ok(petService.findById(id));

587

}

588

589

@PutMapping("/pets/{id}")

590

@SecurityRequirement(name = "roleBasedAuth", scopes = {"role:editor"})

591

public ResponseEntity<Pet> editPet(@PathVariable Long id, @RequestBody Pet pet) {

592

return ResponseEntity.ok(petService.update(id, pet));

593

}

594

595

@DeleteMapping("/pets/{id}")

596

@SecurityRequirement(name = "roleBasedAuth", scopes = {"role:owner"})

597

public ResponseEntity<Void> deletePet(@PathVariable Long id) {

598

petService.delete(id);

599

return ResponseEntity.noContent().build();

600

}

601

}

602

```

603

604

### Time-Limited Access Tokens

605

606

```java { .api }

607

@SecurityScheme(

608

name = "temporaryAccess",

609

type = SecuritySchemeType.HTTP,

610

scheme = "bearer",

611

bearerFormat = "JWT",

612

description = "Temporary access token with expiration",

613

extensions = {

614

@Extension(name = "x-token-expiry", properties = {

615

@ExtensionProperty(name = "defaultDuration", value = "3600"),

616

@ExtensionProperty(name = "maxDuration", value = "86400")

617

}),

618

@Extension(name = "x-refresh-strategy", properties = {

619

@ExtensionProperty(name = "automatic", value = "true"),

620

@ExtensionProperty(name = "refreshBeforeExpiry", value = "300")

621

})

622

}

623

)

624

```