fix(module): filter header params that duplicate security schemes#3785
fix(module): filter header params that duplicate security schemes#3785maruthang wants to merge 1 commit intonestjs:masterfrom
Conversation
When @headers("Authorization") is used alongside bearer auth, Swagger generated both a security requirement and a redundant header parameter. Now filters out header parameters whose names match security scheme headers (Authorization for http schemes, custom names for apiKey in header). Closes nestjs#3252
There was a problem hiding this comment.
Pull request overview
Fixes Swagger document generation to avoid showing redundant header parameters (e.g., Authorization) when those headers are already implied by configured OpenAPI security schemes, addressing confusion in Swagger UI.
Changes:
- Add post-processing step in
SwaggerModule.createDocument()to remove header parameters that duplicate security-scheme headers. - Implement security-scheme header-name collection and filtering across generated operations.
- Add regression tests covering bearer/basic/apiKey header filtering and non-security header preservation.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
lib/swagger-module.ts |
Adds document post-processing to filter operation header parameters that duplicate security-scheme headers. |
test/swagger-module-security-headers.spec.ts |
Adds regression tests validating header parameter filtering behavior across multiple security schemes. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| private static filterSecuritySchemeHeaders(document: OpenAPIObject): void { | ||
| const securityHeaders = this.getSecuritySchemeHeaderNames(document); | ||
| if (securityHeaders.size === 0) { | ||
| return; | ||
| } |
There was a problem hiding this comment.
filterSecuritySchemeHeaders() filters header parameters whenever any security scheme exists in components.securitySchemes, even if that scheme is never applied via document.security or operation.security. This can incorrectly remove legitimate @Headers('Authorization') / apiKey header parameters on operations that are not secured (or when the project only defines schemes to show the Authorize dialog but doesn’t add security requirements). Consider filtering per-operation only when the effective security requirements (operation.security if defined, else document.security) are non-empty, and only for the scheme names referenced there (respecting operation.security = [] overriding global security).
| ); | ||
| expect(authParam).toBeDefined(); | ||
| }); | ||
|
|
There was a problem hiding this comment.
Test coverage is missing for the case where security schemes are defined (e.g. via addBearerAuth() / addApiKey()) but no security requirements are set (document.security undefined/empty and no operation.security). With the current implementation, those headers would still be filtered, so adding a regression test for this scenario would both document and prevent the unintended behavior.
| it('should not filter security headers when schemes are defined without requirements', () => { | |
| const config = new DocumentBuilder() | |
| .setTitle('Test') | |
| .setVersion('1.0') | |
| .addBearerAuth() | |
| .build(); | |
| const document = SwaggerModule.createDocument(app, config); | |
| const params = document.paths['/test/bearer']?.get?.parameters || []; | |
| // Authorization should still appear since bearer auth is defined | |
| // but no document-level or operation-level security requirement uses it | |
| const authParam = params.find( | |
| (p: any) => p.in === 'header' && p.name === 'Authorization' | |
| ); | |
| expect(authParam).toBeDefined(); | |
| }); |
PR Checklist
PR Type
What is the current behavior?
When
@Headers("Authorization")is used alongside bearer auth security, Swagger generates both a security requirement and a redundant header parameter. The header parameter's value isn't sent by Swagger UI, making it confusing.Issue Number: #3252
What is the new behavior?
createDocument()now filters out header parameters whose names match security scheme headers (e.g., "Authorization" for http bearer/basic, custom names for apiKey in header). 6 regression tests added.Does this PR introduce a breaking change?