Files
shields/core/base-service/auth-helper.spec.js
dependabot[bot] 0f288a42fc chore(deps): bump got from 11.8.3 to 12.0.1 (#7370)
* chore(deps): bump got from 11.8.3 to 12.0.1
* update limit syntax
* update CancelError import
* update timeout syntax
* set missing user/pass to empty string for basic auth
* fix opm badge

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: chris48s <chris.shaw480@gmail.com>
Co-authored-by: chris48s <chris48s@users.noreply.github.com>
2022-01-29 20:04:11 +00:00

384 lines
12 KiB
JavaScript

import { expect } from 'chai'
import { test, given, forCases } from 'sazerac'
import { AuthHelper } from './auth-helper.js'
import { InvalidParameter } from './errors.js'
describe('AuthHelper', function () {
describe('constructor checks', function () {
it('throws without userKey or passKey', function () {
expect(() => new AuthHelper({}, {})).to.throw(
Error,
'Expected userKey or passKey to be set'
)
})
it('throws without serviceKey or authorizedOrigins', function () {
expect(
() => new AuthHelper({ userKey: 'myci_user', passKey: 'myci_pass' }, {})
).to.throw(Error, 'Expected authorizedOrigins or serviceKey to be set')
})
it('throws when authorizedOrigins is not an array', function () {
expect(
() =>
new AuthHelper(
{
userKey: 'myci_user',
passKey: 'myci_pass',
authorizedOrigins: true,
},
{ private: {} }
)
).to.throw(Error, 'Expected authorizedOrigins to be an array of origins')
})
})
describe('isValid', function () {
function validate(config, privateConfig) {
return new AuthHelper(
{ authorizedOrigins: ['https://example.test'], ...config },
{ private: privateConfig }
).isValid
}
test(validate, () => {
forCases([
// Fully configured user + pass.
given(
{ userKey: 'myci_user', passKey: 'myci_pass', isRequired: true },
{ myci_user: 'admin', myci_pass: 'abc123' }
),
given(
{ userKey: 'myci_user', passKey: 'myci_pass' },
{ myci_user: 'admin', myci_pass: 'abc123' }
),
// Fully configured user or pass.
given(
{ userKey: 'myci_user', isRequired: true },
{ myci_user: 'admin' }
),
given(
{ passKey: 'myci_pass', isRequired: true },
{ myci_pass: 'abc123' }
),
given({ userKey: 'myci_user' }, { myci_user: 'admin' }),
given({ passKey: 'myci_pass' }, { myci_pass: 'abc123' }),
// Empty config.
given({ userKey: 'myci_user', passKey: 'myci_pass' }, {}),
given({ userKey: 'myci_user' }, {}),
given({ passKey: 'myci_pass' }, {}),
]).expect(true)
forCases([
// Partly configured.
given(
{ userKey: 'myci_user', passKey: 'myci_pass', isRequired: true },
{ myci_user: 'admin' }
),
given(
{ userKey: 'myci_user', passKey: 'myci_pass' },
{ myci_user: 'admin' }
),
// Missing required config.
given(
{ userKey: 'myci_user', passKey: 'myci_pass', isRequired: true },
{}
),
given({ userKey: 'myci_user', isRequired: true }, {}),
given({ passKey: 'myci_pass', isRequired: true }, {}),
]).expect(false)
})
})
describe('_basicAuth', function () {
function validate(config, privateConfig) {
return new AuthHelper(
{ authorizedOrigins: ['https://example.test'], ...config },
{ private: privateConfig }
)._basicAuth
}
test(validate, () => {
forCases([
given(
{ userKey: 'myci_user', passKey: 'myci_pass', isRequired: true },
{ myci_user: 'admin', myci_pass: 'abc123' }
),
given(
{ userKey: 'myci_user', passKey: 'myci_pass' },
{ myci_user: 'admin', myci_pass: 'abc123' }
),
]).expect({ username: 'admin', password: 'abc123' })
given({ userKey: 'myci_user' }, { myci_user: 'admin' }).expect({
username: 'admin',
password: '',
})
given({ passKey: 'myci_pass' }, { myci_pass: 'abc123' }).expect({
username: '',
password: 'abc123',
})
given({ userKey: 'myci_user', passKey: 'myci_pass' }, {}).expect(
undefined
)
given(
{ passKey: 'myci_pass', defaultToEmptyStringForUser: true },
{ myci_pass: 'abc123' }
).expect({
username: '',
password: 'abc123',
})
})
})
describe('_isInsecureSslRequest', function () {
test(AuthHelper._isInsecureSslRequest, () => {
forCases([
given({ url: 'http://example.test' }),
given({ url: 'http://example.test', options: {} }),
given({
url: 'http://example.test',
options: { https: { rejectUnauthorized: true } },
}),
given({
url: 'http://example.test',
options: { https: { rejectUnauthorized: undefined } },
}),
]).expect(false)
given({
url: 'http://example.test',
options: { https: { rejectUnauthorized: false } },
}).expect(true)
})
})
describe('enforceStrictSsl', function () {
const authConfig = {
userKey: 'myci_user',
passKey: 'myci_pass',
serviceKey: 'myci',
}
context('by default', function () {
const authHelper = new AuthHelper(authConfig, {
public: {
services: { myci: { authorizedOrigins: ['http://myci.test'] } },
},
private: { myci_user: 'admin', myci_pass: 'abc123' },
})
it('does not throw for secure requests', function () {
expect(() => authHelper.enforceStrictSsl({})).not.to.throw()
})
it('throws for insecure requests', function () {
expect(() =>
authHelper.enforceStrictSsl({
options: { https: { rejectUnauthorized: false } },
})
).to.throw(InvalidParameter)
})
})
context("when strict SSL isn't required", function () {
const authHelper = new AuthHelper(authConfig, {
public: {
services: {
myci: {
authorizedOrigins: ['http://myci.test'],
requireStrictSsl: false,
},
},
},
private: { myci_user: 'admin', myci_pass: 'abc123' },
})
it('does not throw for secure requests', function () {
expect(() => authHelper.enforceStrictSsl({})).not.to.throw()
})
it('does not throw for insecure requests', function () {
expect(() =>
authHelper.enforceStrictSsl({
options: { https: { rejectUnauthorized: false } },
})
).not.to.throw()
})
})
})
describe('shouldAuthenticateRequest', function () {
const authConfig = {
userKey: 'myci_user',
passKey: 'myci_pass',
serviceKey: 'myci',
}
context('by default', function () {
const authHelper = new AuthHelper(authConfig, {
public: {
services: {
myci: {
authorizedOrigins: ['https://myci.test'],
},
},
},
private: { myci_user: 'admin', myci_pass: 'abc123' },
})
const shouldAuthenticateRequest = requestOptions =>
authHelper.shouldAuthenticateRequest(requestOptions)
describe('a secure request to an authorized origin', function () {
test(shouldAuthenticateRequest, () => {
given({ url: 'https://myci.test/api' }).expect(true)
})
})
describe('an insecure request', function () {
test(shouldAuthenticateRequest, () => {
given({
url: 'https://myci.test/api',
options: { https: { rejectUnauthorized: false } },
}).expect(false)
})
})
describe('a request to an unauthorized origin', function () {
test(shouldAuthenticateRequest, () => {
forCases([
given({ url: 'http://myci.test/api' }),
given({ url: 'https://myci.test:12345/api' }),
given({ url: 'https://other.test/api' }),
]).expect(false)
})
})
})
context('when auth over insecure SSL is allowed', function () {
const authHelper = new AuthHelper(authConfig, {
public: {
services: {
myci: {
authorizedOrigins: ['https://myci.test'],
requireStrictSslToAuthenticate: false,
},
},
},
private: { myci_user: 'admin', myci_pass: 'abc123' },
})
const shouldAuthenticateRequest = requestOptions =>
authHelper.shouldAuthenticateRequest(requestOptions)
describe('a secure request to an authorized origin', function () {
test(shouldAuthenticateRequest, () => {
given({ url: 'https://myci.test' }).expect(true)
})
})
describe('an insecure request', function () {
test(shouldAuthenticateRequest, () => {
given({
url: 'https://myci.test',
options: { https: { rejectUnauthorized: false } },
}).expect(true)
})
})
describe('a request to an unauthorized origin', function () {
test(shouldAuthenticateRequest, () => {
forCases([
given({ url: 'http://myci.test' }),
given({ url: 'https://myci.test:12345/' }),
given({ url: 'https://other.test' }),
]).expect(false)
})
})
})
context('when the service is partly configured', function () {
const authHelper = new AuthHelper(authConfig, {
public: {
services: {
myci: {
authorizedOrigins: ['https://myci.test'],
requireStrictSslToAuthenticate: false,
},
},
},
private: { myci_user: 'admin' },
})
const shouldAuthenticateRequest = requestOptions =>
authHelper.shouldAuthenticateRequest(requestOptions)
describe('a secure request to an authorized origin', function () {
test(shouldAuthenticateRequest, () => {
given({ url: 'https://myci.test' }).expect(false)
})
})
})
})
describe('withBasicAuth', function () {
const authHelper = new AuthHelper(
{
userKey: 'myci_user',
passKey: 'myci_pass',
serviceKey: 'myci',
},
{
public: {
services: {
myci: {
authorizedOrigins: ['https://myci.test'],
},
},
},
private: { myci_user: 'admin', myci_pass: 'abc123' },
}
)
const withBasicAuth = requestOptions =>
authHelper.withBasicAuth(requestOptions)
describe('authenticates a secure request to an authorized origin', function () {
test(withBasicAuth, () => {
given({
url: 'https://myci.test/api',
}).expect({
url: 'https://myci.test/api',
options: {
username: 'admin',
password: 'abc123',
},
})
given({
url: 'https://myci.test/api',
options: {
headers: { Accept: 'application/json' },
},
}).expect({
url: 'https://myci.test/api',
options: {
headers: { Accept: 'application/json' },
username: 'admin',
password: 'abc123',
},
})
})
})
describe('does not authenticate a request to an unauthorized origin', function () {
test(withBasicAuth, () => {
given({
url: 'https://other.test/api',
}).expect({
url: 'https://other.test/api',
})
given({
url: 'https://other.test/api',
options: {
headers: { Accept: 'application/json' },
},
}).expect({
url: 'https://other.test/api',
options: {
headers: { Accept: 'application/json' },
},
})
})
})
describe('throws on an insecure SSL request', function () {
expect(() =>
withBasicAuth({
url: 'https://myci.test/api',
options: { https: { rejectUnauthorized: false } },
})
).to.throw(InvalidParameter)
})
})
})