diff --git a/src/execute/oas3/build-request.js b/src/execute/oas3/build-request.js index 0b928c415..b5b0b48de 100644 --- a/src/execute/oas3/build-request.js +++ b/src/execute/oas3/build-request.js @@ -148,7 +148,8 @@ export function applySecurities({request, securities = {}, operation = {}, spec} } else if (type === 'http') { if (schema.scheme === 'basic') { - const {username, password} = value + const username = value.username || '' + const password = value.password || '' const encoded = btoa(`${username}:${password}`) result.headers.Authorization = `Basic ${encoded}` } diff --git a/src/execute/swagger2/build-request.js b/src/execute/swagger2/build-request.js index bc019408b..979db2cd9 100644 --- a/src/execute/swagger2/build-request.js +++ b/src/execute/swagger2/build-request.js @@ -88,7 +88,9 @@ export function applySecurities({request, securities = {}, operation = {}, spec} result.headers.authorization = value.header } else { - value.base64 = btoa(`${value.username}:${value.password}`) + const username = value.username || '' + const password = value.password || '' + value.base64 = btoa(`${username}:${password}`) result.headers.authorization = `Basic ${value.base64}` } } diff --git a/test/oas3/execute/authorization.js b/test/oas3/execute/authorization.js index 122fe4005..ce2d28909 100644 --- a/test/oas3/execute/authorization.js +++ b/test/oas3/execute/authorization.js @@ -140,6 +140,56 @@ describe('Authorization - OpenAPI Specification 3.0', () => { }) } ) + test( + 'should allow empty password without casting undefined to string', + () => { + const spec = { + openapi: '3.0.0', + components: { + securitySchemes: { + myBasicAuth: { + type: 'http', + in: 'header', + scheme: 'basic' + } + } + }, + paths: { + '/': { + get: { + operationId: 'myOperation', + security: [{ + myBasicAuth: [] + }], + } + } + } + } + + // when + const req = buildRequest({ + spec, + operationId: 'myOperation', + securities: { + authorized: { + myBasicAuth: { + username: 'somebody', + password: undefined + } + } + } + }) + + expect(req).toEqual({ + method: 'GET', + url: '/', + credentials: 'same-origin', + headers: { + Authorization: `Basic ${btoa('somebody:')}` + }, + }) + } + ) }) describe('Bearer', () => { test('should add token to the Authorization header', () => { diff --git a/test/swagger2/execute/apply-securities.js b/test/swagger2/execute/apply-securities.js index b135d8d75..140a47ab6 100644 --- a/test/swagger2/execute/apply-securities.js +++ b/test/swagger2/execute/apply-securities.js @@ -123,6 +123,47 @@ describe('swagger2 - execute - applySecurities', () => { }) }) + test('should allow empty password without casting undefined to string', () => { + const spec = { + host: 'swagger.io', + basePath: '/v1', + security: [{authMe: []}], + paths: { + '/one': { + get: { + operationId: 'getMe', + security: [{authMe: []}] + } + } + }, + securityDefinitions: { + authMe: { + type: 'basic' + } + } + } + + const request = { + url: 'http://swagger.io/v1/one', + method: 'GET', + query: {} + } + const securities = { + authorized: { + authMe: { + username: 'foo', + password: undefined + } + } + } + + const applySecurity = applySecurities({request, securities, operation: spec.paths['/one'].get, spec}) + + expect(applySecurity.headers).toEqual({ + authorization: 'Basic Zm9vOg==' + }) + }) + test('should be able to apply multiple auths', () => { const spec = { host: 'swagger.io',