mirror of
https://github.com/hanzoai/chat.git
synced 2026-09-30 20:51:17 +00:00
The shell hands the browser its IAM identity in a global that was called __HANZO_IAM__. Every value inside it was already correct — on lux.chat it reads serverUrl https://lux.id, clientId lux-chat, organization lux — so the last thing saying "Hanzo" on a Lux page was the name we picked for the container, and it is visible in view-source on the customer's own domain. That is the same class as a wrong mark or a wrong link, spelled as an identifier. __IAM__ says what it holds and belongs to no brand. Renamed at both ends in one change, because a half-rename does not degrade — it breaks login outright: the writer would publish a name the reader never looks up, every visitor would fall through to the bundle's compiled default, and lux.chat would send its customers to hanzo.id as hanzo-chat with a redirect_uri that client has never registered. There are exactly six sites and no others: the writer, the reader, two assertions and two comments. Co-authored-by: Hanzo Dev <[email protected]>
63 lines
2.2 KiB
JavaScript
63 lines
2.2 KiB
JavaScript
const { iamConfig, injectIamConfig } = require('./iamConfig');
|
|
|
|
const HTML = '<html><head><title>t</title></head><body><script type="module" src="/a.js"></script></body></html>';
|
|
|
|
describe('iamConfig', () => {
|
|
const saved = { ...process.env };
|
|
|
|
beforeEach(() => {
|
|
delete process.env.OPENID_ISSUER;
|
|
delete process.env.OPENID_CLIENT_ID;
|
|
delete process.env.OPENID_ORG;
|
|
});
|
|
|
|
afterAll(() => {
|
|
process.env = saved;
|
|
});
|
|
|
|
/* The whole point of the per-key shape: a deployment that states nothing must
|
|
behave exactly as it did before this existed, so the compiled defaults in
|
|
the bundle stay in charge. */
|
|
it('states nothing when the environment states nothing', () => {
|
|
expect(iamConfig()).toBeNull();
|
|
expect(injectIamConfig(HTML)).toBe(HTML);
|
|
});
|
|
|
|
it('omits a key rather than emitting it empty', () => {
|
|
process.env.OPENID_ISSUER = 'https://lux.id';
|
|
expect(iamConfig()).toEqual({ serverUrl: 'https://lux.id' });
|
|
});
|
|
|
|
it('reads the same variables the backend strategy registers with', () => {
|
|
process.env.OPENID_ISSUER = 'https://lux.id';
|
|
process.env.OPENID_CLIENT_ID = 'lux-chat';
|
|
process.env.OPENID_ORG = 'lux';
|
|
expect(iamConfig()).toEqual({
|
|
serverUrl: 'https://lux.id',
|
|
clientId: 'lux-chat',
|
|
organization: 'lux',
|
|
});
|
|
});
|
|
|
|
/* Ahead of the module scripts, which are declared in <body>. OAuthCallback
|
|
reads this before any config request exists, so it cannot be a fetch. */
|
|
it('injects ahead of the module scripts', () => {
|
|
process.env.OPENID_ISSUER = 'https://lux.id';
|
|
const out = injectIamConfig(HTML);
|
|
expect(out.indexOf('__IAM__')).toBeLessThan(out.indexOf('type="module"'));
|
|
expect(out).toContain('</script></head>');
|
|
});
|
|
|
|
it('cannot close its own script element', () => {
|
|
process.env.OPENID_CLIENT_ID = 'x</script><script>alert(1)';
|
|
const out = injectIamConfig(HTML);
|
|
expect(out).not.toContain('x</script>');
|
|
expect(out).toContain('\\u003c/script');
|
|
});
|
|
|
|
it('still delivers the config when there is no head to anchor to', () => {
|
|
process.env.OPENID_ISSUER = 'https://lux.id';
|
|
expect(injectIamConfig('<body>x</body>')).toContain('__IAM__');
|
|
});
|
|
});
|