Skip to content

Commit 2cd22e1

Browse files
committed
feat(fxa-auth-server): Migrate Mocha integration tests to Jest and add remote test specs
1 parent adf1f60 commit 2cd22e1

25 files changed

+6887
-0
lines changed
Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
/* This Source Code Form is subject to the terms of the Mozilla Public
2+
* License, v. 2.0. If a copy of the MPL was not distributed with this
3+
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4+
5+
import { createTestServer, TestServerInstance } from '../support/helpers/test-server';
6+
7+
const Client = require('../client')();
8+
const ScopeSet = require('fxa-shared').oauth.scopes;
9+
const hashRefreshToken = require('fxa-shared/auth/encrypt').hash;
10+
11+
const buf = (v: any) => (Buffer.isBuffer(v) ? v : Buffer.from(v, 'hex'));
12+
const PUBLIC_CLIENT_ID = '3c49430b43dfba77';
13+
14+
let server: TestServerInstance;
15+
let oauthServerDb: any;
16+
let tokens: any;
17+
18+
beforeAll(async () => {
19+
server = await createTestServer();
20+
21+
const config = require('../../config').default.getProperties();
22+
tokens = require('../../lib/tokens')({ trace: () => {} }, config);
23+
oauthServerDb = require('../../lib/oauth/db');
24+
}, 120000);
25+
26+
afterAll(async () => {
27+
await server.stop();
28+
});
29+
30+
const testVersions = [
31+
{ version: '', tag: '' },
32+
{ version: 'V2', tag: 'V2' },
33+
];
34+
35+
describe.each(testVersions)(
36+
'#integration$tag - attached clients listing',
37+
({ version, tag }) => {
38+
const testOptions = { version };
39+
40+
it('correctly lists a variety of attached clients', async () => {
41+
const email = server.uniqueEmail();
42+
const password = 'test password';
43+
const client = await Client.createAndVerify(
44+
server.publicUrl, email, password, server.mailbox, testOptions
45+
);
46+
const mySessionTokenId = (
47+
await tokens.SessionToken.fromHex(client.sessionToken)
48+
).id;
49+
const deviceInfo = {
50+
name: 'test device \ud83c\udf53\ud83d\udd25\u5728\ud834\udf06',
51+
type: 'mobile',
52+
availableCommands: { foo: 'bar' },
53+
pushCallback: '',
54+
pushPublicKey: '',
55+
pushAuthKey: '',
56+
};
57+
58+
let allClients = await client.attachedClients();
59+
expect(allClients.length).toBe(1);
60+
expect(allClients[0].sessionTokenId).toBe(mySessionTokenId);
61+
expect(allClients[0].deviceId).toBeNull();
62+
expect(allClients[0].lastAccessTimeFormatted).toBe('a few seconds ago');
63+
64+
const device = await client.updateDevice(deviceInfo);
65+
66+
allClients = await client.attachedClients();
67+
expect(allClients.length).toBe(1);
68+
expect(allClients[0].sessionTokenId).toBe(mySessionTokenId);
69+
expect(allClients[0].deviceId).toBe(device.id);
70+
expect(allClients[0].name).toBe(deviceInfo.name);
71+
72+
const refreshToken = await oauthServerDb.generateRefreshToken({
73+
clientId: buf(PUBLIC_CLIENT_ID),
74+
userId: buf(client.uid),
75+
email: client.email,
76+
scope: ScopeSet.fromArray([
77+
'profile',
78+
'https://identity.mozilla.com/apps/oldsync',
79+
]),
80+
});
81+
const refreshTokenId = hashRefreshToken(refreshToken.token).toString('hex');
82+
83+
allClients = await client.attachedClients();
84+
expect(allClients.length).toBe(2);
85+
expect(allClients[0].sessionTokenId).toBe(mySessionTokenId);
86+
expect(allClients[1].sessionTokenId).toBeNull();
87+
expect(allClients[1].refreshTokenId).toBe(refreshTokenId);
88+
expect(allClients[1].lastAccessTimeFormatted).toBe('a few seconds ago');
89+
expect(allClients[1].name).toBe('Android Components Reference Browser');
90+
91+
const device2 = await client.updateDeviceWithRefreshToken(
92+
refreshToken.token.toString('hex'),
93+
{ name: 'test device', type: 'mobile' }
94+
);
95+
96+
allClients = await client.attachedClients();
97+
expect(allClients.length).toBe(2);
98+
const one = allClients.findIndex((c: any) => c.name === 'test device');
99+
const zero = (one + 1) % allClients.length;
100+
expect(allClients[zero].sessionTokenId).toBe(mySessionTokenId);
101+
expect(allClients[zero].deviceId).toBe(device.id);
102+
expect(allClients[one].refreshTokenId).toBe(refreshTokenId);
103+
expect(allClients[one].deviceId).toBe(device2.id);
104+
expect(allClients[one].name).toBe('test device');
105+
});
106+
107+
it('correctly deletes by device id', async () => {
108+
const email = server.uniqueEmail();
109+
const password = 'test password';
110+
const client = await Client.createAndVerify(
111+
server.publicUrl, email, password, server.mailbox, testOptions
112+
);
113+
const mySessionTokenId = (
114+
await tokens.SessionToken.fromHex(client.sessionToken)
115+
).id;
116+
117+
const client2 = await Client.login(server.publicUrl, email, password, testOptions);
118+
const device = await client2.updateDevice({ name: 'test', type: 'desktop' });
119+
120+
let allClients = await client.attachedClients();
121+
expect(allClients.length).toBe(2);
122+
123+
await client.destroyAttachedClient({ deviceId: device.id });
124+
125+
allClients = await client.attachedClients();
126+
expect(allClients.length).toBe(1);
127+
expect(allClients[0].sessionTokenId).toBe(mySessionTokenId);
128+
});
129+
130+
it('correctly deletes by sessionTokenId', async () => {
131+
const email = server.uniqueEmail();
132+
const password = 'test password';
133+
const client = await Client.createAndVerify(
134+
server.publicUrl, email, password, server.mailbox, testOptions
135+
);
136+
const mySessionTokenId = (
137+
await tokens.SessionToken.fromHex(client.sessionToken)
138+
).id;
139+
140+
const client2 = await Client.login(server.publicUrl, email, password, testOptions);
141+
const otherSessionTokenId = (
142+
await tokens.SessionToken.fromHex(client2.sessionToken)
143+
).id;
144+
145+
let allClients = await client.attachedClients();
146+
expect(allClients.length).toBe(2);
147+
148+
await client.destroyAttachedClient({ sessionTokenId: otherSessionTokenId });
149+
150+
allClients = await client.attachedClients();
151+
expect(allClients.length).toBe(1);
152+
expect(allClients[0].sessionTokenId).toBe(mySessionTokenId);
153+
});
154+
155+
it('correctly deletes by refreshTokenId', async () => {
156+
const email = server.uniqueEmail();
157+
const password = 'test password';
158+
const client = await Client.createAndVerify(
159+
server.publicUrl, email, password, server.mailbox, testOptions
160+
);
161+
const mySessionTokenId = (
162+
await tokens.SessionToken.fromHex(client.sessionToken)
163+
).id;
164+
165+
const refreshToken = await oauthServerDb.generateRefreshToken({
166+
clientId: buf(PUBLIC_CLIENT_ID),
167+
userId: buf(client.uid),
168+
email: client.email,
169+
scope: ScopeSet.fromArray([
170+
'profile',
171+
'https://identity.mozilla.com/apps/oldsync',
172+
]),
173+
});
174+
const refreshTokenId = hashRefreshToken(refreshToken.token).toString('hex');
175+
176+
let allClients = await client.attachedClients();
177+
expect(allClients.length).toBe(2);
178+
179+
await client.destroyAttachedClient({
180+
refreshTokenId,
181+
clientId: PUBLIC_CLIENT_ID,
182+
});
183+
184+
allClients = await client.attachedClients();
185+
expect(allClients.length).toBe(1);
186+
expect(allClients[0].sessionTokenId).toBe(mySessionTokenId);
187+
expect(allClients[0].refreshTokenId).toBeNull();
188+
});
189+
190+
it('correctly lists a unique list of clientIds for refresh tokens', async () => {
191+
const email = server.uniqueEmail();
192+
const password = 'test password';
193+
const client = await Client.createAndVerify(
194+
server.publicUrl, email, password, server.mailbox, testOptions
195+
);
196+
197+
let oauthClients = await client.attachedOAuthClients();
198+
expect(oauthClients.length).toBe(0);
199+
200+
const clientId = buf(PUBLIC_CLIENT_ID);
201+
const userId = buf(client.uid);
202+
const scope = ScopeSet.fromArray([
203+
'profile',
204+
'https://identity.mozilla.com/apps/oldsync',
205+
]);
206+
207+
await oauthServerDb.generateRefreshToken({
208+
clientId, userId, email: client.email, scope,
209+
});
210+
211+
const refreshToken2 = await oauthServerDb.generateRefreshToken({
212+
clientId, userId, email: client.email, scope,
213+
});
214+
215+
await new Promise((resolve) => setTimeout(resolve, 100));
216+
217+
const newerTimestamp = new Date(Date.now() + 5000);
218+
await oauthServerDb.mysql._touchRefreshToken(
219+
refreshToken2.tokenId,
220+
newerTimestamp
221+
);
222+
223+
oauthClients = await client.attachedOAuthClients();
224+
expect(oauthClients.length).toBe(1);
225+
expect(oauthClients[0].clientId).toBe(PUBLIC_CLIENT_ID);
226+
const timeDiff = Math.abs(
227+
oauthClients[0].lastAccessTime - newerTimestamp.getTime()
228+
);
229+
expect(timeDiff).toBeLessThan(1000);
230+
});
231+
}
232+
);

0 commit comments

Comments
 (0)