@kwaight/node-linux-pam
Version:
Asynchronous PAM authentication for NodeJS
179 lines (150 loc) • 5.29 kB
JavaScript
const { pamAuthenticate, pamErrors } = require('../index');
const { userAdd, expiredUserAdd, userDel } = require('./helpers');
const USERNAME_OF_NON_EXISTENT_USER = 'callback-test-pam-non-existent-user';
const PASSWORD_OF_NON_EXISTENT_USER = 'callback-password';
const USERNAME_OF_AN_EXISTING_USER = 'callback-test-pam-user';
const PASSWORD_OF_AN_EXISTING_USER = 'callback-password';
const BAD_PASSWORD_OF_AN_EXISTING_USER = 'callback-bad-password';
describe('pamAuthenticate', () => {
describe('options', () => {
test('password option is required', () => {
const options = {
username: USERNAME_OF_NON_EXISTENT_USER,
};
expect(() => {
pamAuthenticate(options, () => {});
}).toThrow(TypeError('Password option is required'));
});
test('password option should ignore undefined', () => {
const options = {
username: USERNAME_OF_NON_EXISTENT_USER,
password: undefined,
};
expect(() => {
pamAuthenticate(options, () => {});
}).toThrow(TypeError('Password option is required'));
});
test('username option is required', () => {
const options = {
password: PASSWORD_OF_NON_EXISTENT_USER,
};
expect(() => {
pamAuthenticate(options, () => {});
}).toThrow(TypeError('Username option is required'));
});
test('username option should ignore undefined', () => {
const options = {
username: undefined,
password: PASSWORD_OF_NON_EXISTENT_USER,
};
expect(() => {
pamAuthenticate(options, () => {});
}).toThrow(TypeError('Username option is required'));
});
test('serviceName option should ignore undefined', (done) => {
const options = {
username: USERNAME_OF_NON_EXISTENT_USER,
password: PASSWORD_OF_NON_EXISTENT_USER,
serviceName: undefined,
};
pamAuthenticate(options, (err, code) => {
expect(code).toBe(pamErrors.PAM_AUTH_ERR);
done();
});
});
test('remoteHost option should ignore undefined', (done) => {
const options = {
username: USERNAME_OF_NON_EXISTENT_USER,
password: PASSWORD_OF_NON_EXISTENT_USER,
remoteHost: undefined,
};
pamAuthenticate(options, (err, code) => {
expect(code).toBe(pamErrors.PAM_AUTH_ERR);
done();
});
});
describe.each([
['username', 'Username should be a String'],
['password', 'Password should be a String'],
['serviceName', 'ServiceName should be a String'],
['remoteHost', 'RemoteHost should be a String'],
])('only string values can be passed to options', (option, expected) => {
const notStrings = [5, true, null, new Function(), {}, [], Symbol('sym')];
const options = {
username: USERNAME_OF_NON_EXISTENT_USER,
password: PASSWORD_OF_NON_EXISTENT_USER,
serviceName: '',
remoteHost: '',
};
test.each(notStrings)(`should throw exceptions if ${option} is %p`, (value) => {
options[option] = value;
expect(() => {
pamAuthenticate(options, () => {});
}).toThrow(TypeError(expected));
});
});
});
describe('when there is no user', () => {
test(`should return an error with code ${pamErrors.PAM_AUTH_ERR}`, (done) => {
const options = {
username: USERNAME_OF_NON_EXISTENT_USER,
password: PASSWORD_OF_NON_EXISTENT_USER,
};
pamAuthenticate(options, (err, code) => {
expect(code).toBe(pamErrors.PAM_AUTH_ERR);
done();
});
});
});
describe('when there is a user', () => {
beforeAll(() => {
// Create user
userAdd(USERNAME_OF_AN_EXISTING_USER, PASSWORD_OF_AN_EXISTING_USER);
});
afterAll(() => {
// Delete user
userDel(USERNAME_OF_AN_EXISTING_USER);
});
test(`should return code ${pamErrors.PAM_SUCCESS} with the correct password`, (done) => {
const options = {
username: USERNAME_OF_AN_EXISTING_USER,
password: PASSWORD_OF_AN_EXISTING_USER,
};
pamAuthenticate(options, (err, code) => {
expect(code).toBe(pamErrors.PAM_SUCCESS);
done();
});
});
test(`should return error with code ${pamErrors.PAM_AUTH_ERR} on wrong password`, (done) => {
const options = {
username: USERNAME_OF_AN_EXISTING_USER,
password: BAD_PASSWORD_OF_AN_EXISTING_USER,
};
pamAuthenticate(options, (err, code) => {
expect(code).toBe(pamErrors.PAM_AUTH_ERR);
done();
});
});
});
describe('when there is a user with an expired password', () => {
const username = USERNAME_OF_AN_EXISTING_USER + 'expired2';
beforeAll(() => {
// Create expired user
expiredUserAdd(username, PASSWORD_OF_AN_EXISTING_USER);
});
afterAll(() => {
// Delete user
userDel(username);
});
test(`should return an error with code ${pamErrors.PAM_NEW_AUTHTOK_REQD}`, (done) => {
const options = {
username: username,
password: PASSWORD_OF_AN_EXISTING_USER,
};
pamAuthenticate(options, (err, code) => {
expect(code).toBe(pamErrors.PAM_NEW_AUTHTOK_REQD);
done();
});
});
});
});