Files
2026-10-23 10:35:28 +08:00

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/);
});