@boxyhq/saml-jackson 0.2.3-beta.230 → 0.2.3-beta.231
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/controller/api.ts +2 -2
- package/src/controller/error.ts +1 -1
- package/src/controller/oauth.ts +4 -7
- package/src/db/db.ts +11 -11
- package/src/db/mem.ts +2 -2
- package/src/db/mongo.ts +2 -2
- package/src/db/redis.ts +3 -3
- package/src/db/store.ts +2 -2
- package/src/env.ts +1 -1
- package/src/jackson.ts +0 -1
- package/src/saml/saml.ts +8 -9
- package/src/test/api.test.ts +1 -1
- package/src/typings.ts +2 -2
package/package.json
CHANGED
package/src/controller/api.ts
CHANGED
@@ -56,13 +56,13 @@ export class SAMLConfig implements ISAMLConfig {
|
|
56
56
|
|
57
57
|
idpMetadata.provider = providerName ? providerName : 'Unknown';
|
58
58
|
|
59
|
-
|
59
|
+
const clientID = dbutils.keyDigest(
|
60
60
|
dbutils.keyFromParts(tenant, product, idpMetadata.entityID)
|
61
61
|
);
|
62
62
|
|
63
63
|
let clientSecret;
|
64
64
|
|
65
|
-
|
65
|
+
const exists = await this.configStore.get(clientID);
|
66
66
|
|
67
67
|
if (exists) {
|
68
68
|
clientSecret = exists.clientSecret;
|
package/src/controller/error.ts
CHANGED
package/src/controller/oauth.ts
CHANGED
@@ -66,7 +66,7 @@ export class OAuthController implements IOAuthController {
|
|
66
66
|
product,
|
67
67
|
code_challenge,
|
68
68
|
code_challenge_method = '',
|
69
|
-
// eslint-disable-next-line no-unused-vars
|
69
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
70
70
|
provider = 'saml',
|
71
71
|
} = body;
|
72
72
|
|
@@ -134,7 +134,6 @@ export class OAuthController implements IOAuthController {
|
|
134
134
|
}
|
135
135
|
|
136
136
|
const samlReq = saml.request({
|
137
|
-
// @ts-ignore
|
138
137
|
entityID: this.opts.samlAudience,
|
139
138
|
callbackUrl: this.opts.externalUrl + this.opts.samlPath,
|
140
139
|
signingKey: samlConfig.certs.privateKey,
|
@@ -190,8 +189,6 @@ export class OAuthController implements IOAuthController {
|
|
190
189
|
|
191
190
|
const samlConfigs = await this.configStore.getByIndex({
|
192
191
|
name: IndexNames.EntityID,
|
193
|
-
|
194
|
-
// @ts-ignore
|
195
192
|
value: parsedResp?.issuer,
|
196
193
|
});
|
197
194
|
|
@@ -214,7 +211,7 @@ export class OAuthController implements IOAuthController {
|
|
214
211
|
}
|
215
212
|
}
|
216
213
|
|
217
|
-
|
214
|
+
const validateOpts: Record<string, string> = {
|
218
215
|
thumbprint: samlConfig.idpMetadata.thumbprint,
|
219
216
|
audience: this.opts.samlAudience,
|
220
217
|
};
|
@@ -228,7 +225,7 @@ export class OAuthController implements IOAuthController {
|
|
228
225
|
// store details against a code
|
229
226
|
const code = crypto.randomBytes(20).toString('hex');
|
230
227
|
|
231
|
-
|
228
|
+
const codeVal: Record<string, unknown> = {
|
232
229
|
profile,
|
233
230
|
clientID: samlConfig.clientID,
|
234
231
|
clientSecret: samlConfig.clientSecret,
|
@@ -248,7 +245,7 @@ export class OAuthController implements IOAuthController {
|
|
248
245
|
throw new JacksonError('Redirect URL is not allowed.', 403);
|
249
246
|
}
|
250
247
|
|
251
|
-
|
248
|
+
const params: Record<string, string> = {
|
252
249
|
code,
|
253
250
|
};
|
254
251
|
|
package/src/db/db.ts
CHANGED
@@ -13,7 +13,7 @@ import redis from './redis';
|
|
13
13
|
import sql from './sql/sql';
|
14
14
|
import store from './store';
|
15
15
|
|
16
|
-
const decrypt = (res: Encrypted, encryptionKey: EncryptionKey):
|
16
|
+
const decrypt = (res: Encrypted, encryptionKey: EncryptionKey): unknown => {
|
17
17
|
if (res.iv && res.tag) {
|
18
18
|
return JSON.parse(
|
19
19
|
encrypter.decrypt(res.value, res.iv, res.tag, encryptionKey)
|
@@ -24,15 +24,15 @@ const decrypt = (res: Encrypted, encryptionKey: EncryptionKey): any => {
|
|
24
24
|
};
|
25
25
|
|
26
26
|
class DB implements DatabaseDriver {
|
27
|
-
private db:
|
27
|
+
private db: DatabaseDriver;
|
28
28
|
private encryptionKey: EncryptionKey;
|
29
29
|
|
30
|
-
constructor(db:
|
30
|
+
constructor(db: DatabaseDriver, encryptionKey: EncryptionKey) {
|
31
31
|
this.db = db;
|
32
32
|
this.encryptionKey = encryptionKey;
|
33
33
|
}
|
34
34
|
|
35
|
-
async get(namespace: string, key: string): Promise<
|
35
|
+
async get(namespace: string, key: string): Promise<unknown> {
|
36
36
|
const res = await this.db.get(namespace, key);
|
37
37
|
|
38
38
|
if (!res) {
|
@@ -42,7 +42,7 @@ class DB implements DatabaseDriver {
|
|
42
42
|
return decrypt(res, this.encryptionKey);
|
43
43
|
}
|
44
44
|
|
45
|
-
async getByIndex(namespace: string, idx: Index): Promise<
|
45
|
+
async getByIndex(namespace: string, idx: Index): Promise<unknown[]> {
|
46
46
|
const res = await this.db.getByIndex(namespace, idx);
|
47
47
|
const encryptionKey = this.encryptionKey;
|
48
48
|
return res.map((r) => {
|
@@ -54,10 +54,10 @@ class DB implements DatabaseDriver {
|
|
54
54
|
async put(
|
55
55
|
namespace: string,
|
56
56
|
key: string,
|
57
|
-
val:
|
58
|
-
ttl
|
59
|
-
...indexes:
|
60
|
-
): Promise<
|
57
|
+
val: unknown,
|
58
|
+
ttl = 0,
|
59
|
+
...indexes: Index[]
|
60
|
+
): Promise<unknown> {
|
61
61
|
if (ttl > 0 && indexes && indexes.length > 0) {
|
62
62
|
throw new Error('secondary indexes not allow on a store with ttl');
|
63
63
|
}
|
@@ -69,11 +69,11 @@ class DB implements DatabaseDriver {
|
|
69
69
|
return await this.db.put(namespace, key, dbVal, ttl, ...indexes);
|
70
70
|
}
|
71
71
|
|
72
|
-
async delete(namespace: string, key: string): Promise<
|
72
|
+
async delete(namespace: string, key: string): Promise<unknown> {
|
73
73
|
return await this.db.delete(namespace, key);
|
74
74
|
}
|
75
75
|
|
76
|
-
store(namespace: string, ttl
|
76
|
+
store(namespace: string, ttl = 0): Storable {
|
77
77
|
return store.new(namespace, this, ttl);
|
78
78
|
}
|
79
79
|
}
|
package/src/db/mem.ts
CHANGED
@@ -43,7 +43,7 @@ class Mem implements DatabaseDriver {
|
|
43
43
|
}
|
44
44
|
|
45
45
|
async get(namespace: string, key: string): Promise<any> {
|
46
|
-
|
46
|
+
const res = this.store[dbutils.key(namespace, key)];
|
47
47
|
if (res) {
|
48
48
|
return res;
|
49
49
|
}
|
@@ -66,7 +66,7 @@ class Mem implements DatabaseDriver {
|
|
66
66
|
namespace: string,
|
67
67
|
key: string,
|
68
68
|
val: Encrypted,
|
69
|
-
ttl
|
69
|
+
ttl = 0,
|
70
70
|
...indexes: any[]
|
71
71
|
): Promise<any> {
|
72
72
|
const k = dbutils.key(namespace, key);
|
package/src/db/mongo.ts
CHANGED
@@ -36,7 +36,7 @@ class Mongo implements DatabaseDriver {
|
|
36
36
|
}
|
37
37
|
|
38
38
|
async get(namespace: string, key: string): Promise<any> {
|
39
|
-
|
39
|
+
const res = await this.collection.findOne({
|
40
40
|
_id: dbutils.key(namespace, key),
|
41
41
|
});
|
42
42
|
if (res && res.value) {
|
@@ -65,7 +65,7 @@ class Mongo implements DatabaseDriver {
|
|
65
65
|
namespace: string,
|
66
66
|
key: string,
|
67
67
|
val: Encrypted,
|
68
|
-
ttl
|
68
|
+
ttl = 0,
|
69
69
|
...indexes: any[]
|
70
70
|
): Promise<void> {
|
71
71
|
const doc = <Document>{
|
package/src/db/redis.ts
CHANGED
@@ -11,7 +11,7 @@ class Redis implements DatabaseDriver {
|
|
11
11
|
}
|
12
12
|
|
13
13
|
async init(): Promise<Redis> {
|
14
|
-
|
14
|
+
const opts = {};
|
15
15
|
|
16
16
|
if (this.options && this.options.url) {
|
17
17
|
opts['socket'] = {
|
@@ -30,7 +30,7 @@ class Redis implements DatabaseDriver {
|
|
30
30
|
}
|
31
31
|
|
32
32
|
async get(namespace: string, key: string): Promise<any> {
|
33
|
-
|
33
|
+
const res = await this.client.get(dbutils.key(namespace, key));
|
34
34
|
if (res) {
|
35
35
|
return JSON.parse(res);
|
36
36
|
}
|
@@ -55,7 +55,7 @@ class Redis implements DatabaseDriver {
|
|
55
55
|
namespace: string,
|
56
56
|
key: string,
|
57
57
|
val: Encrypted,
|
58
|
-
ttl
|
58
|
+
ttl = 0,
|
59
59
|
...indexes: any[]
|
60
60
|
): Promise<void> {
|
61
61
|
let tx = this.client.multi();
|
package/src/db/store.ts
CHANGED
@@ -6,7 +6,7 @@ class Store implements Storable {
|
|
6
6
|
private db: any;
|
7
7
|
private ttl: number;
|
8
8
|
|
9
|
-
constructor(namespace: string, db: any, ttl
|
9
|
+
constructor(namespace: string, db: any, ttl = 0) {
|
10
10
|
this.namespace = namespace;
|
11
11
|
this.db = db;
|
12
12
|
this.ttl = ttl;
|
@@ -43,7 +43,7 @@ class Store implements Storable {
|
|
43
43
|
}
|
44
44
|
|
45
45
|
export default {
|
46
|
-
new: (namespace: string, db: any, ttl
|
46
|
+
new: (namespace: string, db: any, ttl = 0): Storable => {
|
47
47
|
return new Store(namespace, db, ttl);
|
48
48
|
},
|
49
49
|
};
|
package/src/env.ts
CHANGED
@@ -9,7 +9,7 @@ const internalHostPort = +(process.env.INTERNAL_HOST_PORT || '6000');
|
|
9
9
|
|
10
10
|
const apiKeys = (process.env.JACKSON_API_KEYS || '').split(',');
|
11
11
|
|
12
|
-
const samlAudience = process.env.SAML_AUDIENCE;
|
12
|
+
const samlAudience = process.env.SAML_AUDIENCE || 'https://saml.boxyhq.com';
|
13
13
|
const preLoadedConfig = process.env.PRE_LOADED_CONFIG;
|
14
14
|
|
15
15
|
const idpEnabled = process.env.IDP_ENABLED;
|
package/src/jackson.ts
CHANGED
package/src/saml/saml.ts
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
import saml from '@boxyhq/saml20';
|
2
|
+
import xml2js from 'xml2js';
|
3
|
+
import thumbprint from 'thumbprint';
|
4
|
+
import xmlcrypto from 'xml-crypto';
|
5
5
|
import * as rambda from 'rambda';
|
6
6
|
import xmlbuilder from 'xmlbuilder';
|
7
7
|
import crypto from 'crypto';
|
@@ -53,7 +53,8 @@ const request = ({
|
|
53
53
|
const id = idPrefix + crypto.randomBytes(10).toString('hex');
|
54
54
|
const date = new Date().toISOString();
|
55
55
|
|
56
|
-
|
56
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
57
|
+
const samlReq: Record<string, any> = {
|
57
58
|
'samlp:AuthnRequest': {
|
58
59
|
'@xmlns:samlp': 'urn:oasis:names:tc:SAML:2.0:protocol',
|
59
60
|
'@ID': id,
|
@@ -97,9 +98,7 @@ const request = ({
|
|
97
98
|
};
|
98
99
|
};
|
99
100
|
|
100
|
-
const parseAsync = async (
|
101
|
-
rawAssertion: string
|
102
|
-
): Promise<SAMLProfile | void> => {
|
101
|
+
const parseAsync = async (rawAssertion: string): Promise<SAMLProfile> => {
|
103
102
|
return new Promise((resolve, reject) => {
|
104
103
|
saml.parse(
|
105
104
|
rawAssertion,
|
@@ -118,7 +117,7 @@ const parseAsync = async (
|
|
118
117
|
const validateAsync = async (
|
119
118
|
rawAssertion: string,
|
120
119
|
options
|
121
|
-
): Promise<SAMLProfile
|
120
|
+
): Promise<SAMLProfile> => {
|
122
121
|
return new Promise((resolve, reject) => {
|
123
122
|
saml.validate(
|
124
123
|
rawAssertion,
|
package/src/test/api.test.ts
CHANGED
@@ -144,7 +144,7 @@ tap.test('controller/api', async (t) => {
|
|
144
144
|
t.equal(response.client_id, CLIENT_ID);
|
145
145
|
t.equal(response.provider, PROVIDER);
|
146
146
|
|
147
|
-
|
147
|
+
const savedConf = await apiController.getConfig({
|
148
148
|
clientID: CLIENT_ID,
|
149
149
|
});
|
150
150
|
|
package/src/typings.ts
CHANGED
@@ -104,7 +104,7 @@ declare module 'saml-jackson' {
|
|
104
104
|
key: string,
|
105
105
|
val: any,
|
106
106
|
ttl: number,
|
107
|
-
indexes: Index[]
|
107
|
+
...indexes: Index[]
|
108
108
|
): Promise<any>;
|
109
109
|
delete(namespace: string, key: string): Promise<any>;
|
110
110
|
getByIndex(namespace: string, idx: Index): Promise<any>;
|
@@ -159,7 +159,7 @@ declare module 'saml-jackson' {
|
|
159
159
|
export interface JacksonOption {
|
160
160
|
externalUrl: string;
|
161
161
|
samlPath: string;
|
162
|
-
samlAudience
|
162
|
+
samlAudience: string;
|
163
163
|
preLoadedConfig?: string;
|
164
164
|
idpEnabled?: boolean;
|
165
165
|
db: DatabaseOption;
|