78 lines
3.1 KiB
JavaScript
78 lines
3.1 KiB
JavaScript
'use strict';
|
|
|
|
const { test } = require('node:test');
|
|
const assert = require('node:assert');
|
|
|
|
const config = require('../../config');
|
|
const auth = require('../../lib/auth');
|
|
|
|
function withPasswords(upload, admin, fn) {
|
|
const before = { uploadPass: config.uploadPass, adminPass: config.adminPass, tokenSecret: config.tokenSecret };
|
|
Object.assign(config, { uploadPass: upload, adminPass: admin, tokenSecret: '' });
|
|
try {
|
|
return fn();
|
|
} finally {
|
|
Object.assign(config, before);
|
|
}
|
|
}
|
|
|
|
test('issued token verifies until it expires', () => withPasswords('up', 'ad', () => {
|
|
const now = 1_000_000;
|
|
const { token, exp } = auth.issue({}, 60, 'session', now);
|
|
assert.strictEqual(exp, now + 60_000);
|
|
assert.ok(auth.verify(token, 'session', now + 59_000));
|
|
assert.strictEqual(auth.verify(token, 'session', now + 60_000), null);
|
|
}));
|
|
|
|
test('tampered token is rejected', () => withPasswords('up', 'ad', () => {
|
|
const { token } = auth.issue({}, 60);
|
|
const [payload, sig] = token.split('.');
|
|
const forged = Buffer.from(JSON.stringify({ exp: Date.now() + 1e12 })).toString('base64url');
|
|
assert.strictEqual(auth.verify(`${ forged }.${ sig }`), null);
|
|
assert.strictEqual(auth.verify(`${ payload }.${ sig.slice(0, -2) }xx`), null);
|
|
assert.strictEqual(auth.verify('garbage'), null);
|
|
assert.strictEqual(auth.verify(''), null);
|
|
assert.strictEqual(auth.verify(undefined), null);
|
|
}));
|
|
|
|
test('a token is only valid for its purpose', () => withPasswords('up', 'ad', () => {
|
|
const { token } = auth.issue({ sid: 'x' }, 60, 'admin-download');
|
|
assert.strictEqual(auth.verify(token, 'session'), null);
|
|
assert.strictEqual(auth.verify(token, 'admin-download').sid, 'x');
|
|
}));
|
|
|
|
test('changing the upload or the admin password invalidates tokens', () => {
|
|
const { token } = withPasswords('up', 'ad', () => auth.issue({}, 60));
|
|
assert.ok(withPasswords('up', 'ad', () => auth.verify(token)));
|
|
assert.strictEqual(withPasswords('other', 'ad', () => auth.verify(token)), null);
|
|
assert.strictEqual(withPasswords('up', 'other', () => auth.verify(token)), null);
|
|
// works without an admin password too
|
|
const { token: t2 } = withPasswords('up', false, () => auth.issue({}, 60));
|
|
assert.ok(withPasswords('up', false, () => auth.verify(t2)));
|
|
});
|
|
|
|
test('an explicit token secret survives password changes', () => {
|
|
const issue = pass => {
|
|
config.tokenSecret = 'fixed-secret';
|
|
return withPasswords(pass, 'ad', () => { config.tokenSecret = 'fixed-secret'; return auth.issue({}, 60); });
|
|
};
|
|
const { token } = issue('up');
|
|
config.tokenSecret = 'fixed-secret';
|
|
const before = { uploadPass: config.uploadPass };
|
|
config.uploadPass = 'changed';
|
|
try {
|
|
assert.ok(auth.verify(token));
|
|
} finally {
|
|
config.tokenSecret = '';
|
|
config.uploadPass = before.uploadPass;
|
|
}
|
|
});
|
|
|
|
test('safeEqual compares secrets', () => {
|
|
assert.strictEqual(auth.safeEqual('abc', 'abc'), true);
|
|
assert.strictEqual(auth.safeEqual('abc', 'abd'), false);
|
|
assert.strictEqual(auth.safeEqual('abc', 'abcd'), false);
|
|
assert.strictEqual(auth.safeEqual(undefined, 'abc'), false);
|
|
assert.strictEqual(auth.safeEqual(undefined, undefined), true);
|
|
});
|