@simulacrum/auth0-simulator 0.2.1 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/README.md +13 -9
  3. package/bin/index.js +2 -0
  4. package/dist/auth/date.js +1 -1
  5. package/dist/auth/date.js.map +1 -1
  6. package/dist/auth/jwt.d.ts +1 -1
  7. package/dist/auth/jwt.d.ts.map +1 -1
  8. package/dist/auth/jwt.js +5 -4
  9. package/dist/auth/jwt.js.map +1 -1
  10. package/dist/handlers/auth0-handlers.d.ts +1 -1
  11. package/dist/handlers/auth0-handlers.d.ts.map +1 -1
  12. package/dist/handlers/auth0-handlers.js +82 -31
  13. package/dist/handlers/auth0-handlers.js.map +1 -1
  14. package/dist/handlers/get-service-url.js +1 -1
  15. package/dist/handlers/get-service-url.js.map +1 -1
  16. package/dist/handlers/login-redirect.js +1 -1
  17. package/dist/handlers/login-redirect.js.map +1 -1
  18. package/dist/handlers/openid-handlers.js +2 -2
  19. package/dist/handlers/openid-handlers.js.map +1 -1
  20. package/dist/handlers/web-message.js +4 -4
  21. package/dist/handlers/web-message.js.map +1 -1
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +33 -28
  24. package/dist/index.js.map +1 -1
  25. package/dist/middleware/create-cors.js +1 -1
  26. package/dist/middleware/create-cors.js.map +1 -1
  27. package/dist/middleware/session.js +1 -1
  28. package/dist/middleware/session.js.map +1 -1
  29. package/dist/rules/parse-rules-files.js +2 -2
  30. package/dist/rules/parse-rules-files.js.map +1 -1
  31. package/dist/rules/rules-runner.js +3 -3
  32. package/dist/rules/rules-runner.js.map +1 -1
  33. package/dist/start.js +35 -3
  34. package/dist/start.js.map +1 -1
  35. package/dist/types.d.ts +21 -0
  36. package/dist/types.d.ts.map +1 -1
  37. package/dist/views/login.js +1 -1
  38. package/dist/views/username-password.js +1 -1
  39. package/dist/views/username-password.js.map +1 -1
  40. package/dist/views/web-message.js +1 -1
  41. package/dist/views/web-message.js.map +1 -1
  42. package/package.json +19 -13
  43. package/docs/create-simulation.png +0 -0
  44. package/docs/person.png +0 -0
  45. package/src/auth/constants.ts +0 -16
  46. package/src/auth/date.ts +0 -4
  47. package/src/auth/jwt.ts +0 -23
  48. package/src/handlers/auth0-handlers.ts +0 -219
  49. package/src/handlers/get-service-url.ts +0 -10
  50. package/src/handlers/login-redirect.ts +0 -37
  51. package/src/handlers/openid-handlers.ts +0 -39
  52. package/src/handlers/url.ts +0 -1
  53. package/src/handlers/web-message.ts +0 -31
  54. package/src/index.ts +0 -70
  55. package/src/middleware/create-cors.ts +0 -14
  56. package/src/middleware/no-cache.ts +0 -7
  57. package/src/middleware/session.ts +0 -14
  58. package/src/rules/extensionless-file-name.ts +0 -4
  59. package/src/rules/parse-rules-files.ts +0 -40
  60. package/src/rules/rules-runner.ts +0 -72
  61. package/src/rules/types.ts +0 -25
  62. package/src/start.ts +0 -19
  63. package/src/types.ts +0 -29
  64. package/src/views/login.ts +0 -107
  65. package/src/views/public/img/frontside-logo.png +0 -0
  66. package/src/views/username-password.ts +0 -54
  67. package/src/views/web-message.ts +0 -72
  68. package/test/auth0.test.ts +0 -351
  69. package/test/helpers.ts +0 -23
  70. package/test/openid-handlers.test.ts +0 -57
  71. package/test/rules/avatar.js +0 -13
  72. package/test/rules/avatar.json +0 -5
  73. package/tsconfig.dist.json +0 -12
  74. package/tsconfig.dist.tsbuildinfo +0 -2236
  75. package/tsconfig.json +0 -11
  76. package/tsconfig.watch.json +0 -9
  77. package/watch.ts +0 -59
@@ -1,351 +0,0 @@
1
- import { describe, it, beforeEach } from '@effection/mocha';
2
- import expect from 'expect';
3
- import { createTestServer, Client, Simulation } from './helpers';
4
- import { auth0 } from '../src';
5
- import fetch from 'cross-fetch';
6
- import { stringify } from 'querystring';
7
- import { createHttpApp, person, Person } from '@simulacrum/server';
8
- import { decode, encode } from 'base64-url';
9
- import jwt from 'jsonwebtoken';
10
-
11
- import Keygrip from 'keygrip';
12
- import { removeTrailingSlash } from '../src/handlers/url';
13
-
14
- const createSessionCookie = <T>(data: T): string => {
15
- let cookie = Buffer.from(JSON.stringify(data)).toString('base64');
16
-
17
- let kg = Keygrip(['shhh']);
18
- let hash = kg.sign(`session=${cookie}`);
19
-
20
- return `session=${cookie};session.sig=${hash};`;
21
- };
22
-
23
- describe('Auth0 simulator', () => {
24
- let client: Client;
25
- let frontendUrl: string;
26
- let auth0Url: string;
27
-
28
- beforeEach(function*() {
29
- client = yield createTestServer({
30
- simulators: {
31
- auth0: (slice, options) => {
32
- let { services } = auth0(slice, options);
33
-
34
- return {
35
- services: {
36
- ...services,
37
- frontend: {
38
- protocol: 'http',
39
- app: createHttpApp().get('/', function * (_, res) {
40
- res.status(200).send('ok');
41
- })
42
- },
43
-
44
- },
45
- scenarios: { person }
46
- };
47
- }
48
- }
49
- });
50
- });
51
-
52
- describe("Creating a simulation with an Auth0 simulator", () => {
53
- let simulation: Simulation;
54
- beforeEach(function*() {
55
- simulation = yield client.createSimulation("auth0");
56
- });
57
-
58
- it('starts the simulation', function*() {
59
- expect(simulation.status).toEqual('running');
60
- });
61
- });
62
-
63
- describe('/authorize', () => {
64
- describe('response_mode=query', () => {
65
- beforeEach(function*() {
66
- let simulation: Simulation = yield client.createSimulation("auth0");
67
-
68
- auth0Url = simulation.services[0].url;
69
- frontendUrl = simulation.services[1].url;
70
- });
71
-
72
- it('should authorize', function *() {
73
- let res: Response = yield fetch(`${auth0Url}/authorize?${stringify({
74
- client_id: "1234",
75
- redirect_uri: frontendUrl,
76
- response_type: "code",
77
- response_mode: "query",
78
- state: "MVpFN0JXWGNFUVNVQnJjNGlXZWFNbGd2V3M2MC5VRkwyV1VKNW9wRTZVVw==",
79
- nonce: "dDJ6NX5aUFU3SlM4TEozQThyR0V0fjdjRlJDZ0YzfjNDcEV3OWIzWWVYbQ==",
80
- code_challenge: "2Arx2VYcTp6YDa5r-exGr99upqSIqYZQ_vBbI_7taQ0",
81
- code_challenge_method: "S256",
82
- auth0Client: "eyJuYW1lIjoiYXV0aDAtcmVhY3QiLCJ2ZXJzaW9uIjoiMS4xLjAifQ==",
83
- })}`);
84
-
85
- expect(res.redirected).toBe(true);
86
- expect(res.url).toContain('/login');
87
- });
88
- });
89
-
90
- describe('response_mode=web_message', () => {
91
- beforeEach(function*() {
92
- let simulation: Simulation = yield client.createSimulation("auth0");
93
-
94
- auth0Url = simulation.services[0].url;
95
- frontendUrl = simulation.services[1].url;
96
- });
97
-
98
- it('should return the web_message html', function *() {
99
- // /authorize web_message expects there to be a username in the session
100
- let cookie = createSessionCookie({ username: 'bob' });
101
-
102
- let res: Response = yield fetch(`${auth0Url}/authorize?${stringify({
103
- redirect_uri: frontendUrl,
104
- response_mode: "web_message",
105
- state: "MVpFN0JXWGNFUVNVQnJjNGlXZWFNbGd2V3M2MC5VRkwyV1VKNW9wRTZVVw==",
106
- nonce: "dDJ6NX5aUFU3SlM4TEozQThyR0V0fjdjRlJDZ0YzfjNDcEV3OWIzWWVYbQ==",
107
- auth0Client: "eyJuYW1lIjoiYXV0aDAtcmVhY3QiLCJ2ZXJzaW9uIjoiMS4xLjAifQ==",
108
- })}`, {
109
- credentials: 'same-origin',
110
- headers: {
111
- cookie
112
- }
113
- });
114
-
115
- expect(res.ok).toBe(true);
116
- expect(res.headers.get('content-type')).toBe('text/html; charset=utf-8');
117
- });
118
- });
119
- });
120
-
121
- let Fields = {
122
- audience: "https://thefrontside.auth0.com/api/v1/",
123
- client_id: "00000000000000000000000000000000",
124
- connection: "Username-Password-Authentication",
125
- nonce: "aGV6ODdFZjExbF9iMkdYZHVfQ3lYcDNVSldGRDR6dWdvREQwUms1Z0Ewaw==",
126
- redirect_uri: "http://localhost:3000",
127
- response_type: "token id_token",
128
- scope: "openid profile email offline_access",
129
- state: "sxmRf2Fq.IMN5SER~wQqbsXl5Hx0JHov",
130
- tenant: "localhost:4400",
131
- };
132
-
133
- describe('/login', () => {
134
- let simulation: Simulation;
135
- let person: {data: Person};
136
- let url: string;
137
-
138
- beforeEach(function* () {
139
- simulation = yield client.createSimulation("auth0");
140
- url = simulation.services[0].url;
141
-
142
- person = yield client.given(simulation, "person");
143
- });
144
-
145
- it('should login with valid credentials', function*(){
146
- let res: Response = yield fetch(`${url}/usernamepassword/login`, {
147
- method: 'POST',
148
- headers: {
149
- 'Content-Type': 'application/json'
150
- },
151
- body: JSON.stringify({
152
- ...Fields,
153
- username: person.data.email,
154
- password: person.data.password,
155
- })
156
- });
157
-
158
- expect(res.ok).toBe(true);
159
- });
160
-
161
- it('should fail with invalid credentials', function*(){
162
- let res: Response = yield fetch(`${url}/usernamepassword/login`, {
163
- method: 'POST',
164
- headers: {
165
- 'Content-Type': 'application/json'
166
- },
167
- body: JSON.stringify({
168
- ...Fields,
169
- username: 'bob',
170
- password: 'no-way',
171
- })
172
- });
173
-
174
- expect(res.status).toBe(400);
175
- });
176
- });
177
-
178
- describe('/login/callback', () => {
179
- let simulation: Simulation;
180
- let person: {data: Person};
181
-
182
- beforeEach(function* () {
183
- simulation = yield client.createSimulation("auth0", { services: {
184
- auth0: { port: 4400 }, frontend: { port: 3000 }
185
- } });
186
-
187
- person = yield client.given(simulation, "person");
188
-
189
- // prime the server with the nonce field
190
- yield fetch(`https://localhost:4400/usernamepassword/login`, {
191
- method: 'POST',
192
- headers: {
193
- 'Content-Type': 'application/json'
194
- },
195
- body: JSON.stringify({
196
- ...Fields,
197
- username: person.data.email,
198
- password: person.data.password,
199
- })
200
- });
201
- });
202
-
203
- it('should post to /login/callback', function* () {
204
- let fields = encodeURIComponent(JSON.stringify({
205
- ...Fields
206
- }));
207
-
208
- let res: Response = yield fetch(`https://localhost:4400/login/callback`, {
209
- method: 'POST',
210
- headers: {
211
- 'Content-Type': 'application/x-www-form-urlencoded'
212
- },
213
- body: `wctx=${fields}`
214
- });
215
-
216
- expect(res.status).toBe(200);
217
- expect(res.statusText).toBe('OK');
218
- });
219
- });
220
-
221
- describe('/oauth/token', () => {
222
- let simulation: Simulation;
223
- let person: {data: Person};
224
- let authUrl: string;
225
- let code: string;
226
-
227
- beforeEach(function* () {
228
- simulation = yield client.createSimulation("auth0", {
229
- options: {
230
- rulesDirectory: 'test/rules'
231
- },
232
- services: {
233
- auth0: { port: 4400 }, frontend: { port: 3000 }
234
- }
235
- });
236
-
237
- person = yield client.given(simulation, "person");
238
-
239
- authUrl = simulation.services[0].url;
240
-
241
- // prime the server with the nonce field
242
- yield fetch(`${authUrl}/usernamepassword/login`, {
243
- method: 'POST',
244
- headers: {
245
- 'Content-Type': 'application/json'
246
- },
247
- body: JSON.stringify({
248
- ...Fields,
249
- username: person.data.email,
250
- password: person.data.password,
251
- })
252
- });
253
-
254
- let res: Response = yield fetch(`https://localhost:4400/login/callback`, {
255
- method: 'POST',
256
- headers: {
257
- 'Content-Type': 'application/x-www-form-urlencoded'
258
- },
259
- body: `wctx=${encodeURIComponent(JSON.stringify({
260
- ...Fields
261
- }))}`
262
- });
263
-
264
- code = new URL(res.url).searchParams.get('code') as string;
265
- });
266
-
267
- describe('valid token', () => {
268
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
269
- let token: any;
270
- beforeEach(function * () {
271
- let res: Response = yield fetch(`${authUrl}/oauth/token`, {
272
- method: 'POST',
273
- headers: {
274
- 'Content-Type': 'application/json'
275
- },
276
- body: JSON.stringify({
277
- ...Fields,
278
- code
279
- })
280
- });
281
-
282
- expect(res.ok).toBe(true);
283
-
284
- let json = yield res.json();
285
-
286
- token = jwt.decode(json.id_token, { complete: true });
287
- });
288
-
289
- it('should return an iss field with a forward slash', function* () {
290
- expect(token.payload.iss).toBe('https://localhost:4400/');
291
- });
292
- });
293
-
294
-
295
- it('should return a 401 responsive with invalid credentials', function* () {
296
- let [nonce] = decode(code).split(":");
297
-
298
- let invalidCode = encode(`${nonce}:invalid-user`);
299
-
300
- let res: Response = yield fetch(`${authUrl}/oauth/token`, {
301
- method: 'POST',
302
- headers: {
303
- 'Content-Type': 'application/json'
304
- },
305
- body: JSON.stringify({
306
- ...Fields,
307
- code: invalidCode
308
- })
309
- });
310
-
311
- expect(res.status).toBe(401);
312
- });
313
-
314
- it('should have ran the rules', function* () {
315
- let res: Response = yield fetch(`${authUrl}/oauth/token`, {
316
- method: 'POST',
317
- headers: {
318
- 'Content-Type': 'application/json'
319
- },
320
- body: JSON.stringify({
321
- ...Fields,
322
- code
323
- })
324
- });
325
-
326
- let token = yield res.json();
327
-
328
- let idToken = jwt.decode(token.id_token, { complete: true });
329
-
330
- expect(idToken?.payload.picture).toContain('https://cdn.fakercloud.com/avatars');
331
- });
332
- });
333
-
334
- describe('/v2/logout', () => {
335
- beforeEach(function*() {
336
- let simulation: Simulation = yield client.createSimulation("auth0");
337
-
338
- auth0Url = simulation.services[0].url;
339
- frontendUrl = simulation.services[1].url;
340
- });
341
-
342
- it('should authorize', function *() {
343
- let res: Response = yield fetch(`${auth0Url}/v2/logout?${stringify({
344
- returnTo: frontendUrl
345
- })}`);
346
-
347
- expect(res.redirected).toBe(true);
348
- expect(removeTrailingSlash(res.url)).toBe(removeTrailingSlash(frontendUrl));
349
- });
350
- });
351
- });
package/test/helpers.ts DELETED
@@ -1,23 +0,0 @@
1
- import { Task, Resource } from 'effection';
2
- import { createClient, Client } from '@simulacrum/client';
3
- import { Server, ServerOptions, createSimulationServer } from '@simulacrum/server';
4
-
5
- export type { Client, Simulation } from '@simulacrum/client';
6
-
7
- export function createTestServer(options: ServerOptions): Resource<Client> {
8
- return {
9
- *init(scope: Task) {
10
- let server: Server = yield createSimulationServer(options);
11
- let { port } = server.address;
12
- let client = createClient(`http://localhost:${port}`);
13
- scope.run(function*() {
14
- try {
15
- yield;
16
- } finally {
17
- client.dispose();
18
- }
19
- });
20
- return client;
21
- }
22
- };
23
- }
@@ -1,57 +0,0 @@
1
- import { describe, it, beforeEach } from '@effection/mocha';
2
- import expect from 'expect';
3
- import { createTestServer, Client, Simulation } from './helpers';
4
- import { auth0 } from '../src';
5
- import fetch from 'cross-fetch';
6
- import { JWKS } from '../src/auth/constants';
7
-
8
- describe('openid routes', () => {
9
- let client: Client;
10
- let auth0Url: string;
11
-
12
- beforeEach(function*() {
13
- client = yield createTestServer({
14
- simulators: {
15
- auth0
16
- },
17
- });
18
- });
19
-
20
- describe('/.well-known/*', () => {
21
- beforeEach(function*() {
22
- let simulation: Simulation = yield client.createSimulation("auth0", {
23
- services: {
24
- auth0: { port: 4400 }
25
- }
26
- });
27
-
28
- auth0Url = simulation.services[0].url;
29
- });
30
-
31
- it('returns the JWKS keys', function *() {
32
- let res: Response = yield fetch(`${auth0Url}/.well-known/jwks.json`);
33
-
34
- let json: typeof JWKS = yield res.json();
35
-
36
- expect(res.ok).toBe(true);
37
-
38
- expect(json).toEqual(JWKS);
39
- });
40
-
41
- it('returns the openid configuration', function * () {
42
- let res: Response = yield fetch(`${auth0Url}/.well-known/openid-configuration`);
43
-
44
- let json: { token_endpoint: string } = yield res.json();
45
-
46
- expect(res.ok).toBe(true);
47
-
48
- expect(json).toEqual({
49
- issuer: 'https://localhost:4400/',
50
- authorization_endpoint: 'https://localhost:4400/authorize',
51
- token_endpoint: 'https://localhost:4400/oauth/token',
52
- userinfo_endpoint: 'https://localhost:4400/userinfo',
53
- jwks_uri: 'https://localhost:4400/.well-known/jwks.json'
54
- });
55
- });
56
- });
57
- });
@@ -1,13 +0,0 @@
1
- /*
2
- simple fake rule to add an avatar
3
- */
4
-
5
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
6
- function avatar(user, context, callback) {
7
- // eslint-disable-next-line @typescript-eslint/no-var-requires
8
- user.picture = require('faker').internet.avatar();
9
-
10
- console.log(`added avatar ${user.picture} to user`);
11
-
12
- callback(null, user, context);
13
- }
@@ -1,5 +0,0 @@
1
- {
2
- "enabled": true,
3
- "order": 1,
4
- "stage": "login_success"
5
- }
@@ -1,12 +0,0 @@
1
- {
2
- "extends": "./tsconfig.json",
3
- "references": [{
4
- "path": "../server/tsconfig.dist.json"
5
- }],
6
- "compilerOptions": {
7
- "outDir": "dist",
8
- "rootDir": "src",
9
- "noEmit": false
10
- },
11
- "exclude": ["test"]
12
- }