Skip to content

Commit d9b0711

Browse files
committed
Add SASL2/BIND2/FAST tests
1 parent 917f30b commit d9b0711

File tree

1 file changed

+288
-0
lines changed

1 file changed

+288
-0
lines changed

packages/sasl2/test.js

+288
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,288 @@
1+
"use strict";
2+
3+
const test = require("ava");
4+
const { mockClient, promise } = require("@xmpp/test");
5+
const parse = require("@xmpp/xml/lib/parse.js");
6+
7+
const username = "foo";
8+
const password = "bar";
9+
const credentials = { username, password };
10+
11+
test("no compatibles mechanisms", async (t) => {
12+
const { entity } = mockClient({ username, password });
13+
14+
entity.mockInput(
15+
<features xmlns="http://etherx.jabber.org/streams">
16+
<authentication xmlns="urn:xmpp:sasl:2">
17+
<mechanism>FOO</mechanism>
18+
</authentication>
19+
</features>,
20+
);
21+
22+
const error = await promise(entity, "error");
23+
t.true(error instanceof Error);
24+
t.is(error.message, "No compatible mechanism");
25+
});
26+
27+
test("with object credentials", async (t) => {
28+
const { entity } = mockClient({ credentials });
29+
30+
entity.mockInput(
31+
<features xmlns="http://etherx.jabber.org/streams">
32+
<authentication xmlns="urn:xmpp:sasl:2">
33+
<mechanism>PLAIN</mechanism>
34+
</authentication>
35+
</features>,
36+
);
37+
38+
t.deepEqual(
39+
await promise(entity, "send"),
40+
<authenticate xmlns="urn:xmpp:sasl:2" mechanism="PLAIN">
41+
<initial-response>AGZvbwBiYXI=</initial-response>
42+
</authenticate>,
43+
);
44+
45+
entity.mockInput(<success xmlns="urn:xmpp:sasl:2" />);
46+
entity.mockInput(<features xmlns="http://etherx.jabber.org/streams" />);
47+
48+
await promise(entity, "online");
49+
});
50+
51+
test("with function credentials", async (t) => {
52+
const mech = "PLAIN";
53+
54+
function authenticate(auth, mechanisms) {
55+
t.deepEqual(mechanisms, [{ name: mech, canFast: false, canOther: true }]);
56+
return auth(credentials, mech);
57+
}
58+
59+
const { entity } = mockClient({ credentials: authenticate });
60+
61+
entity.mockInput(
62+
<features xmlns="http://etherx.jabber.org/streams">
63+
<authentication xmlns="urn:xmpp:sasl:2">
64+
<mechanism>{mech}</mechanism>
65+
</authentication>
66+
</features>,
67+
);
68+
69+
t.deepEqual(
70+
await promise(entity, "send"),
71+
<authenticate xmlns="urn:xmpp:sasl:2" mechanism={mech}>
72+
<initial-response>AGZvbwBiYXI=</initial-response>
73+
</authenticate>,
74+
);
75+
76+
entity.mockInput(<success xmlns="urn:xmpp:sasl:2" />);
77+
entity.mockInput(<features xmlns="http://etherx.jabber.org/streams" />);
78+
79+
await promise(entity, "online");
80+
});
81+
82+
test("failure", async (t) => {
83+
const { entity } = mockClient({ credentials });
84+
85+
entity.mockInput(
86+
<features xmlns="http://etherx.jabber.org/streams">
87+
<authentication xmlns="urn:xmpp:sasl:2">
88+
<mechanism>PLAIN</mechanism>
89+
</authentication>
90+
</features>,
91+
);
92+
93+
t.deepEqual(
94+
await promise(entity, "send"),
95+
<authenticate xmlns="urn:xmpp:sasl:2" mechanism="PLAIN">
96+
<initial-response>AGZvbwBiYXI=</initial-response>
97+
</authenticate>,
98+
);
99+
100+
const failure = (
101+
<failure xmlns="urn:xmpp:sasl:2">
102+
<some-condition />
103+
</failure>
104+
);
105+
106+
entity.mockInput(failure);
107+
108+
const error = await promise(entity, "error");
109+
t.true(error instanceof Error);
110+
t.is(error.name, "SASLError");
111+
t.is(error.condition, "some-condition");
112+
t.is(error.element, failure);
113+
});
114+
115+
test("prefers SCRAM-SHA-1", async (t) => {
116+
const { entity } = mockClient({ credentials });
117+
118+
entity.mockInput(
119+
<features xmlns="http://etherx.jabber.org/streams">
120+
<authentication xmlns="urn:xmpp:sasl:2">
121+
<mechanism>ANONYMOUS</mechanism>
122+
<mechanism>PLAIN</mechanism>
123+
<mechanism>SCRAM-SHA-1</mechanism>
124+
</authentication>
125+
</features>,
126+
);
127+
128+
const result = await promise(entity, "send");
129+
t.deepEqual(result.attrs.mechanism, "SCRAM-SHA-1");
130+
});
131+
132+
test("use ANONYMOUS if username and password are not provided", async (t) => {
133+
const { entity } = mockClient();
134+
135+
entity.mockInput(
136+
<features xmlns="http://etherx.jabber.org/streams">
137+
<authentication xmlns="urn:xmpp:sasl:2">
138+
<mechanism>ANONYMOUS</mechanism>
139+
<mechanism>PLAIN</mechanism>
140+
<mechanism>SCRAM-SHA-1</mechanism>
141+
</authentication>
142+
</features>,
143+
);
144+
145+
const result = await promise(entity, "send");
146+
t.deepEqual(result.attrs.mechanism, "ANONYMOUS");
147+
});
148+
149+
test("with whitespaces", async (t) => {
150+
const { entity } = mockClient();
151+
152+
entity.mockInput(
153+
parse(
154+
`
155+
<features xmlns="http://etherx.jabber.org/streams">
156+
<authentication xmlns="urn:xmpp:sasl:2">
157+
<mechanism>ANONYMOUS</mechanism>
158+
<mechanism>PLAIN</mechanism>
159+
<mechanism>SCRAM-SHA-1</mechanism>
160+
</authentication>
161+
</features>
162+
`.trim(),
163+
),
164+
);
165+
166+
const result = await promise(entity, "send");
167+
t.deepEqual(result.attrs.mechanism, "ANONYMOUS");
168+
});
169+
170+
test("with bind2", async (t) => {
171+
const { entity } = mockClient({
172+
credentials,
173+
clientId: "uniqueid",
174+
software: "xmpp.js",
175+
device: "script",
176+
});
177+
178+
entity.mockInput(
179+
<features xmlns="http://etherx.jabber.org/streams">
180+
<authentication xmlns="urn:xmpp:sasl:2">
181+
<mechanism>PLAIN</mechanism>
182+
<inline>
183+
<bind xmlns="urn:xmpp:bind:0" />
184+
</inline>
185+
</authentication>
186+
</features>,
187+
);
188+
189+
t.deepEqual(
190+
await promise(entity, "send"),
191+
<authenticate xmlns="urn:xmpp:sasl:2" mechanism="PLAIN">
192+
<initial-response>AGZvbwBiYXI=</initial-response>
193+
<user-agent id="uniqueid">
194+
<software>xmpp.js</software>
195+
<device>script</device>
196+
</user-agent>
197+
<bind xmlns="urn:xmpp:bind:0">
198+
<tag>xmpp.js</tag>
199+
</bind>
200+
</authenticate>,
201+
);
202+
203+
entity.mockInput(<success xmlns="urn:xmpp:sasl:2" />);
204+
entity.mockInput(<features xmlns="http://etherx.jabber.org/streams" />);
205+
206+
await promise(entity, "online");
207+
});
208+
209+
test("with FAST", async (t) => {
210+
const { entity } = mockClient({
211+
credentials: (callback, mechanisms) => {
212+
t.deepEqual(mechanisms, [
213+
{ canFast: true, canOther: false, name: "HT-SHA-256-NONE" },
214+
{ canFast: false, canOther: true, name: "PLAIN" },
215+
]);
216+
callback(
217+
{ ...credentials, requestToken: mechanisms[0].name },
218+
mechanisms[1].name,
219+
);
220+
},
221+
});
222+
223+
entity.mockInput(
224+
<features xmlns="http://etherx.jabber.org/streams">
225+
<authentication xmlns="urn:xmpp:sasl:2">
226+
<mechanism>PLAIN</mechanism>
227+
<inline>
228+
<fast xmlns="urn:xmpp:fast:0">
229+
<mechanism>HT-SHA-256-NONE</mechanism>
230+
</fast>
231+
</inline>
232+
</authentication>
233+
</features>,
234+
);
235+
236+
t.deepEqual(
237+
await promise(entity, "send"),
238+
<authenticate xmlns="urn:xmpp:sasl:2" mechanism="PLAIN">
239+
<initial-response>AGZvbwBiYXI=</initial-response>
240+
<request-token xmlns="urn:xmpp:fast:0" mechanism="HT-SHA-256-NONE" />
241+
</authenticate>,
242+
);
243+
244+
entity.mockInput(<success xmlns="urn:xmpp:sasl:2" />);
245+
entity.mockInput(<features xmlns="http://etherx.jabber.org/streams" />);
246+
247+
await promise(entity, "online");
248+
});
249+
250+
test("with FAST token", async (t) => {
251+
const { entity } = mockClient({
252+
credentials: (callback, mechanisms) => {
253+
t.deepEqual(mechanisms, [
254+
{ canFast: true, canOther: false, name: "HT-SHA-256-NONE" },
255+
{ canFast: false, canOther: true, name: "PLAIN" },
256+
]);
257+
callback({ password: "TOKEN", fastCount: 2 }, mechanisms[0].name);
258+
},
259+
});
260+
261+
entity.mockInput(
262+
<features xmlns="http://etherx.jabber.org/streams">
263+
<authentication xmlns="urn:xmpp:sasl:2">
264+
<mechanism>PLAIN</mechanism>
265+
<inline>
266+
<fast xmlns="urn:xmpp:fast:0">
267+
<mechanism>HT-SHA-256-NONE</mechanism>
268+
</fast>
269+
</inline>
270+
</authentication>
271+
</features>,
272+
);
273+
274+
t.deepEqual(
275+
await promise(entity, "send"),
276+
<authenticate xmlns="urn:xmpp:sasl:2" mechanism="HT-SHA-256-NONE">
277+
<initial-response>
278+
bnVsbAAAXAywUfR/w4Mr9SUDUtNAgPDajNI073fqfiZLMYcmfA==
279+
</initial-response>
280+
<fast xmlns="urn:xmpp:fast:0" count="2" />
281+
</authenticate>,
282+
);
283+
284+
entity.mockInput(<success xmlns="urn:xmpp:sasl:2" />);
285+
entity.mockInput(<features xmlns="http://etherx.jabber.org/streams" />);
286+
287+
await promise(entity, "online");
288+
});

0 commit comments

Comments
 (0)