80 lines
2.9 KiB
JavaScript
80 lines
2.9 KiB
JavaScript
'use strict';
|
|
|
|
const test = require('node:test');
|
|
const assert = require('node:assert/strict');
|
|
|
|
const { signHS256, verifyHS256 } = require('../src/jwt');
|
|
const { createIdentity } = require('../src/identity');
|
|
|
|
const SECRET = 'test-inbox-secret';
|
|
|
|
function decode(jwt) {
|
|
return JSON.parse(Buffer.from(jwt.split('.')[1], 'base64url').toString('utf8'));
|
|
}
|
|
|
|
test('jwt: sign/verify roundtrip + tamper detection', () => {
|
|
const token = signHS256({ external_user_id: 'cust-1', email: 'a@b.c' }, SECRET, 60);
|
|
const payload = verifyHS256(token, SECRET);
|
|
assert.equal(payload.external_user_id, 'cust-1');
|
|
assert.equal(payload.email, 'a@b.c');
|
|
|
|
const [h, c, s] = token.split('.');
|
|
const tampered = `${h}.${c}.${s.slice(0, -1)}x`;
|
|
assert.equal(verifyHS256(tampered, SECRET), null);
|
|
assert.equal(verifyHS256(token, 'wrong-secret'), null);
|
|
});
|
|
|
|
test('identity: dev mode issues LibreDesk widget JWT', async () => {
|
|
const identity = createIdentity({
|
|
libredeskInboxSecret: SECRET,
|
|
identityDevMode: true,
|
|
identityTtlSec: 120,
|
|
siteJwtSecret: '',
|
|
memberRpcUrl: '',
|
|
rpcTimeoutMs: 1000,
|
|
});
|
|
const out = await identity.issue({ email: 'Customer@Example.com', externalUserId: 'cust-9', firstName: 'Jan' });
|
|
const claims = decode(out.userJWT);
|
|
assert.equal(claims.external_user_id, 'cust-9');
|
|
assert.equal(claims.email, 'customer@example.com');
|
|
assert.equal(claims.first_name, 'Jan');
|
|
assert.ok(claims.exp > Math.floor(Date.now() / 1000));
|
|
});
|
|
|
|
test('identity: site token mode verifies HS256 and resolves email via RPC', async () => {
|
|
const siteToken = signHS256({ userId: 12345, type: 2, tenantId: 't1' }, 'site-secret', 60);
|
|
const rpc = {
|
|
calls: [],
|
|
async call(addr, method, params) {
|
|
this.calls.push({ addr, method, params });
|
|
return { result: { email: 'buyer@example.nl' } };
|
|
},
|
|
};
|
|
const identity = createIdentity(
|
|
{
|
|
libredeskInboxSecret: SECRET,
|
|
identityDevMode: false,
|
|
identityTtlSec: 60,
|
|
siteJwtSecret: 'site-secret',
|
|
memberRpcUrl: 'jsonrpc://member:1',
|
|
rpcTimeoutMs: 1000,
|
|
},
|
|
{ rpc }
|
|
);
|
|
const out = await identity.issue({ token: siteToken });
|
|
const claims = decode(out.userJWT);
|
|
assert.equal(claims.external_user_id, '12345');
|
|
assert.equal(claims.email, 'buyer@example.nl');
|
|
assert.equal(rpc.calls[0].method, '/customer/getBasicByCustomerId');
|
|
assert.equal(rpc.calls[0].params[0].customerId, '12345');
|
|
});
|
|
|
|
test('identity: rejects bad site token and unknown origin mode', async () => {
|
|
const identity = createIdentity(
|
|
{ libredeskInboxSecret: SECRET, identityDevMode: false, identityTtlSec: 60, siteJwtSecret: 'site-secret', memberRpcUrl: '', rpcTimeoutMs: 1000 },
|
|
{ rpc: { call: async () => ({}) } }
|
|
);
|
|
await assert.rejects(() => identity.issue({ token: 'not-a-jwt' }), /invalid or expired/);
|
|
await assert.rejects(() => identity.issue({ email: 'x@y.z' }), /token is required/);
|
|
});
|