@boxyhq/saml-jackson 0.2.3-beta.226 → 0.2.3-beta.227
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.
- package/package.json +1 -1
- package/src/db/sql/sql.ts +9 -8
- package/src/jackson.ts +4 -4
- package/src/test/oauth.test.ts +36 -27
- package/src/typings.ts +1 -1
package/package.json
CHANGED
package/src/db/sql/sql.ts
CHANGED
@@ -5,20 +5,21 @@ require('reflect-metadata');
|
|
5
5
|
import { DatabaseDriver, DatabaseOption, Index, Encrypted } from 'saml-jackson';
|
6
6
|
import { Connection, createConnection } from 'typeorm';
|
7
7
|
import * as dbutils from '../utils';
|
8
|
+
import JacksonIndexEntity from './entity/JacksonIndex';
|
9
|
+
import JacksonStoreEntity from './entity/JacksonStore';
|
10
|
+
import {
|
11
|
+
JacksonTTL,
|
12
|
+
JacksonTTL as JacksonTTLEntity,
|
13
|
+
} from './entity/JacksonTTL';
|
8
14
|
import { JacksonIndex } from './model/JacksonIndex';
|
9
15
|
import { JacksonStore } from './model/JacksonStore';
|
10
|
-
import { JacksonTTL } from './entity/JacksonTTL';
|
11
|
-
|
12
|
-
import JacksonStoreEntity from './entity/JacksonStore';
|
13
|
-
import JacksonIndexEntity from './entity/JacksonIndex';
|
14
|
-
import { JacksonTTL as JacksonTTLEntity } from './entity/JacksonTTL';
|
15
16
|
|
16
17
|
class Sql implements DatabaseDriver {
|
17
18
|
private options: DatabaseOption;
|
18
19
|
private connection!: Connection;
|
19
|
-
private storeRepository;
|
20
|
-
private indexRepository;
|
21
|
-
private ttlRepository;
|
20
|
+
private storeRepository;
|
21
|
+
private indexRepository;
|
22
|
+
private ttlRepository;
|
22
23
|
private ttlCleanup;
|
23
24
|
private timerId;
|
24
25
|
|
package/src/jackson.ts
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
import cors from 'cors';
|
2
2
|
import express from 'express';
|
3
|
+
import { IOAuthController, ISAMLConfig } from 'saml-jackson';
|
3
4
|
import { JacksonError } from './controller/error';
|
4
5
|
import { extractAuthToken } from './controller/utils';
|
5
6
|
import env from './env';
|
6
7
|
import jackson from './index';
|
7
8
|
|
8
|
-
let apiController;
|
9
|
-
let oauthController;
|
9
|
+
let apiController: ISAMLConfig;
|
10
|
+
let oauthController: IOAuthController;
|
10
11
|
|
11
12
|
const oauthPath = '/oauth';
|
12
13
|
const apiPath = '/api/v1/saml';
|
@@ -62,7 +63,7 @@ app.get(oauthPath + '/userinfo', async (req, res) => {
|
|
62
63
|
}
|
63
64
|
|
64
65
|
if (!token) {
|
65
|
-
res.status(401).json({ message: 'Unauthorized' });
|
66
|
+
return res.status(401).json({ message: 'Unauthorized' });
|
66
67
|
}
|
67
68
|
|
68
69
|
const profile = await oauthController.userInfo(token);
|
@@ -80,7 +81,6 @@ const server = app.listen(env.hostPort, async () => {
|
|
80
81
|
`🚀 The path of the righteous server: http://${env.hostUrl}:${env.hostPort}`
|
81
82
|
);
|
82
83
|
|
83
|
-
// TODO: Fix it
|
84
84
|
// @ts-ignore
|
85
85
|
const ctrlrModule = await jackson(env);
|
86
86
|
|
package/src/test/oauth.test.ts
CHANGED
@@ -1,30 +1,36 @@
|
|
1
1
|
import crypto from 'crypto';
|
2
2
|
import { promises as fs } from 'fs';
|
3
3
|
import path from 'path';
|
4
|
-
import {
|
4
|
+
import {
|
5
|
+
IOAuthController,
|
6
|
+
ISAMLConfig,
|
7
|
+
JacksonOption,
|
8
|
+
OAuthReqBody,
|
9
|
+
OAuthTokenReq,
|
10
|
+
SAMLResponsePayload,
|
11
|
+
} from 'saml-jackson';
|
5
12
|
import sinon from 'sinon';
|
6
13
|
import tap from 'tap';
|
7
14
|
import { JacksonError } from '../controller/error';
|
8
15
|
import readConfig from '../read-config';
|
9
16
|
import saml from '../saml/saml';
|
10
17
|
|
11
|
-
|
12
|
-
let
|
13
|
-
let oauthController;
|
18
|
+
let apiController: ISAMLConfig;
|
19
|
+
let oauthController: IOAuthController;
|
14
20
|
|
15
21
|
const code = '1234567890';
|
16
22
|
const token = '24c1550190dd6a5a9bd6fe2a8ff69d593121c7b9';
|
17
23
|
|
18
24
|
const metadataPath = path.join(__dirname, '/data/metadata');
|
19
25
|
|
20
|
-
const options = {
|
26
|
+
const options = <JacksonOption>{
|
21
27
|
externalUrl: 'https://my-cool-app.com',
|
22
28
|
samlAudience: 'https://saml.boxyhq.com',
|
23
29
|
samlPath: '/sso/oauth/saml',
|
24
30
|
db: {
|
25
31
|
engine: 'mem',
|
26
32
|
},
|
27
|
-
}
|
33
|
+
};
|
28
34
|
|
29
35
|
const samlConfig = {
|
30
36
|
tenant: 'boxyhq.com',
|
@@ -57,13 +63,13 @@ tap.teardown(async () => {
|
|
57
63
|
|
58
64
|
tap.test('authorize()', async (t) => {
|
59
65
|
t.test('Should throw an error if `redirect_uri` null', async (t) => {
|
60
|
-
const body = {
|
61
|
-
redirect_uri:
|
66
|
+
const body: Partial<OAuthReqBody> = {
|
67
|
+
redirect_uri: undefined,
|
62
68
|
state: 'state',
|
63
69
|
};
|
64
70
|
|
65
71
|
try {
|
66
|
-
await oauthController.authorize(body);
|
72
|
+
await oauthController.authorize(<OAuthReqBody>body);
|
67
73
|
t.fail('Expecting JacksonError.');
|
68
74
|
} catch (err) {
|
69
75
|
const { message, statusCode } = err as JacksonError;
|
@@ -79,13 +85,13 @@ tap.test('authorize()', async (t) => {
|
|
79
85
|
});
|
80
86
|
|
81
87
|
t.test('Should throw an error if `state` null', async (t) => {
|
82
|
-
const body = {
|
88
|
+
const body: Partial<OAuthReqBody> = {
|
83
89
|
redirect_uri: 'https://example.com/',
|
84
|
-
state:
|
90
|
+
state: undefined,
|
85
91
|
};
|
86
92
|
|
87
93
|
try {
|
88
|
-
await oauthController.authorize(body);
|
94
|
+
await oauthController.authorize(<OAuthReqBody>body);
|
89
95
|
|
90
96
|
t.fail('Expecting JacksonError.');
|
91
97
|
} catch (err) {
|
@@ -109,7 +115,7 @@ tap.test('authorize()', async (t) => {
|
|
109
115
|
};
|
110
116
|
|
111
117
|
try {
|
112
|
-
await oauthController.authorize(body);
|
118
|
+
await oauthController.authorize(<OAuthReqBody>body);
|
113
119
|
|
114
120
|
t.fail('Expecting JacksonError.');
|
115
121
|
} catch (err) {
|
@@ -135,7 +141,7 @@ tap.test('authorize()', async (t) => {
|
|
135
141
|
};
|
136
142
|
|
137
143
|
try {
|
138
|
-
await oauthController.authorize(body);
|
144
|
+
await oauthController.authorize(<OAuthReqBody>body);
|
139
145
|
|
140
146
|
t.fail('Expecting JacksonError.');
|
141
147
|
} catch (err) {
|
@@ -159,7 +165,7 @@ tap.test('authorize()', async (t) => {
|
|
159
165
|
client_id: `tenant=${samlConfig.tenant}&product=${samlConfig.product}`,
|
160
166
|
};
|
161
167
|
|
162
|
-
const response = await oauthController.authorize(body);
|
168
|
+
const response = await oauthController.authorize(<OAuthReqBody>body);
|
163
169
|
const params = new URLSearchParams(new URL(response.redirect_url).search);
|
164
170
|
|
165
171
|
t.ok('redirect_url' in response, 'got the Idp authorize URL');
|
@@ -179,7 +185,9 @@ tap.test('samlResponse()', async (t) => {
|
|
179
185
|
client_id: `tenant=${samlConfig.tenant}&product=${samlConfig.product}`,
|
180
186
|
};
|
181
187
|
|
182
|
-
const { redirect_url } = await oauthController.authorize(
|
188
|
+
const { redirect_url } = await oauthController.authorize(
|
189
|
+
<OAuthReqBody>authBody
|
190
|
+
);
|
183
191
|
|
184
192
|
const relayState = new URLSearchParams(new URL(redirect_url).search).get(
|
185
193
|
'RelayState'
|
@@ -191,12 +199,12 @@ tap.test('samlResponse()', async (t) => {
|
|
191
199
|
);
|
192
200
|
|
193
201
|
t.test('Should throw an error if `RelayState` is missing', async (t) => {
|
194
|
-
const responseBody = {
|
202
|
+
const responseBody: Partial<SAMLResponsePayload> = {
|
195
203
|
SAMLResponse: rawResponse,
|
196
204
|
};
|
197
205
|
|
198
206
|
try {
|
199
|
-
await oauthController.samlResponse(responseBody);
|
207
|
+
await oauthController.samlResponse(<SAMLResponsePayload>responseBody);
|
200
208
|
|
201
209
|
t.fail('Expecting JacksonError.');
|
202
210
|
} catch (err) {
|
@@ -224,10 +232,13 @@ tap.test('samlResponse()', async (t) => {
|
|
224
232
|
const stubValidateAsync = sinon
|
225
233
|
.stub(saml, 'validateAsync')
|
226
234
|
.resolves({ audience: '', claims: {}, issuer: '', sessionIndex: '' });
|
235
|
+
|
227
236
|
//@ts-ignore
|
228
237
|
const stubRandomBytes = sinon.stub(crypto, 'randomBytes').returns(code);
|
229
238
|
|
230
|
-
const response = await oauthController.samlResponse(
|
239
|
+
const response = await oauthController.samlResponse(
|
240
|
+
<SAMLResponsePayload>responseBody
|
241
|
+
);
|
231
242
|
|
232
243
|
const params = new URLSearchParams(new URL(response.redirect_url).search);
|
233
244
|
|
@@ -257,7 +268,7 @@ tap.test('token()', (t) => {
|
|
257
268
|
};
|
258
269
|
|
259
270
|
try {
|
260
|
-
await oauthController.token(body);
|
271
|
+
await oauthController.token(<OAuthTokenReq>body);
|
261
272
|
|
262
273
|
t.fail('Expecting JacksonError.');
|
263
274
|
} catch (err) {
|
@@ -280,7 +291,7 @@ tap.test('token()', (t) => {
|
|
280
291
|
};
|
281
292
|
|
282
293
|
try {
|
283
|
-
await oauthController.token(body);
|
294
|
+
await oauthController.token(<OAuthTokenReq>body);
|
284
295
|
|
285
296
|
t.fail('Expecting JacksonError.');
|
286
297
|
} catch (err) {
|
@@ -293,16 +304,15 @@ tap.test('token()', (t) => {
|
|
293
304
|
});
|
294
305
|
|
295
306
|
t.test('Should throw an error if `code` is invalid', async (t) => {
|
296
|
-
const body = {
|
307
|
+
const body: Partial<OAuthTokenReq> = {
|
297
308
|
grant_type: 'authorization_code',
|
298
309
|
client_id: `tenant=${samlConfig.tenant}&product=${samlConfig.product}`,
|
299
310
|
client_secret: 'some-secret',
|
300
|
-
redirect_uri: null,
|
301
311
|
code: 'invalid-code',
|
302
312
|
};
|
303
313
|
|
304
314
|
try {
|
305
|
-
await oauthController.token(body);
|
315
|
+
await oauthController.token(<OAuthTokenReq>body);
|
306
316
|
|
307
317
|
t.fail('Expecting JacksonError.');
|
308
318
|
} catch (err) {
|
@@ -315,11 +325,10 @@ tap.test('token()', (t) => {
|
|
315
325
|
});
|
316
326
|
|
317
327
|
t.test('Should return the `access_token` for a valid request', async (t) => {
|
318
|
-
const body = {
|
328
|
+
const body: Partial<OAuthTokenReq> = {
|
319
329
|
grant_type: 'authorization_code',
|
320
330
|
client_id: `tenant=${samlConfig.tenant}&product=${samlConfig.product}`,
|
321
331
|
client_secret: 'some-secret',
|
322
|
-
redirect_uri: null,
|
323
332
|
code: code,
|
324
333
|
};
|
325
334
|
|
@@ -329,7 +338,7 @@ tap.test('token()', (t) => {
|
|
329
338
|
//@ts-ignore
|
330
339
|
.returns(token);
|
331
340
|
|
332
|
-
const response = await oauthController.token(body);
|
341
|
+
const response = await oauthController.token(<OAuthTokenReq>body);
|
333
342
|
|
334
343
|
t.ok(stubRandomBytes.calledOnce, 'randomBytes called once');
|
335
344
|
t.ok('access_token' in response, 'includes access_token');
|
package/src/typings.ts
CHANGED
@@ -51,7 +51,7 @@ declare module 'saml-jackson' {
|
|
51
51
|
authorize(body: OAuthReqBody): Promise<{ redirect_url: string }>;
|
52
52
|
samlResponse(body: SAMLResponsePayload): Promise<{ redirect_url: string }>;
|
53
53
|
token(body: OAuthTokenReq): Promise<OAuthTokenRes>;
|
54
|
-
userInfo(
|
54
|
+
userInfo(token: string): Promise<Profile>;
|
55
55
|
}
|
56
56
|
|
57
57
|
export interface OAuthReqBody {
|