@boxyhq/saml-jackson 1.0.6 → 1.1.1
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/dist/controller/api.js +2 -2
- package/dist/controller/oauth.js +60 -4
- package/dist/controller/oidc-discovery.d.ts +50 -0
- package/dist/controller/oidc-discovery.js +49 -0
- package/dist/controller/utils.d.ts +9 -0
- package/dist/controller/utils.js +44 -2
- package/dist/db/db.js +17 -1
- package/dist/db/mongo.js +2 -1
- package/dist/db/planetscale/entity/JacksonIndex.d.ts +5 -0
- package/dist/db/planetscale/entity/JacksonIndex.js +34 -0
- package/dist/db/planetscale/entity/JacksonStore.d.ts +8 -0
- package/dist/db/planetscale/entity/JacksonStore.js +55 -0
- package/dist/db/planetscale/entity/JacksonTTL.d.ts +4 -0
- package/dist/db/planetscale/entity/JacksonTTL.js +29 -0
- package/dist/db/sql/sql.d.ts +9 -2
- package/dist/db/sql/sql.js +48 -28
- package/dist/index.d.ts +2 -0
- package/dist/index.js +5 -0
- package/dist/typings.d.ts +31 -1
- package/migration/planetscale/1653746497237-ms_nocascade.ts +22 -0
- package/package.json +13 -10
package/dist/controller/api.js
CHANGED
@@ -187,7 +187,7 @@ class APIController {
|
|
187
187
|
if (encodedRawMetadata) {
|
188
188
|
metaData = Buffer.from(encodedRawMetadata, 'base64').toString();
|
189
189
|
}
|
190
|
-
const idpMetadata = yield saml20_1.default.
|
190
|
+
const idpMetadata = yield saml20_1.default.parseMetadata(metaData, {});
|
191
191
|
// extract provider
|
192
192
|
let providerName = extractHostName(idpMetadata.entityID);
|
193
193
|
if (!providerName) {
|
@@ -323,7 +323,7 @@ class APIController {
|
|
323
323
|
}
|
324
324
|
let newMetadata;
|
325
325
|
if (metaData) {
|
326
|
-
newMetadata = yield saml20_1.default.
|
326
|
+
newMetadata = yield saml20_1.default.parseMetadata(metaData, {});
|
327
327
|
// extract provider
|
328
328
|
let providerName = extractHostName(newMetadata.entityID);
|
329
329
|
if (!providerName) {
|
package/dist/controller/oauth.js
CHANGED
@@ -39,6 +39,7 @@ exports.OAuthController = void 0;
|
|
39
39
|
const crypto_1 = __importDefault(require("crypto"));
|
40
40
|
const util_1 = require("util");
|
41
41
|
const zlib_1 = require("zlib");
|
42
|
+
const jose = __importStar(require("jose"));
|
42
43
|
const dbutils = __importStar(require("../db/utils"));
|
43
44
|
const metrics = __importStar(require("../opentelemetry/metrics"));
|
44
45
|
const saml20_1 = __importDefault(require("@boxyhq/saml20"));
|
@@ -78,6 +79,9 @@ function getEncodedTenantProduct(param) {
|
|
78
79
|
return null;
|
79
80
|
}
|
80
81
|
}
|
82
|
+
function getScopeValues(scope) {
|
83
|
+
return typeof scope === 'string' ? scope.split(' ').filter((s) => s.length > 0) : [];
|
84
|
+
}
|
81
85
|
class OAuthController {
|
82
86
|
constructor({ configStore, sessionStore, codeStore, tokenStore, opts }) {
|
83
87
|
this.configStore = configStore;
|
@@ -128,7 +132,7 @@ class OAuthController {
|
|
128
132
|
}
|
129
133
|
authorize(body) {
|
130
134
|
return __awaiter(this, void 0, void 0, function* () {
|
131
|
-
const { response_type = 'code', client_id, redirect_uri, state, tenant, product, access_type, scope, code_challenge, code_challenge_method = '',
|
135
|
+
const { response_type = 'code', client_id, redirect_uri, state, tenant, product, access_type, resource, scope, nonce, code_challenge, code_challenge_method = '',
|
132
136
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
133
137
|
provider = 'saml', idp_hint, } = body;
|
134
138
|
let requestedTenant = tenant;
|
@@ -138,6 +142,8 @@ class OAuthController {
|
|
138
142
|
throw new error_1.JacksonError('Please specify a redirect URL.', 400);
|
139
143
|
}
|
140
144
|
let samlConfig;
|
145
|
+
const requestedScopes = getScopeValues(scope);
|
146
|
+
const requestedOIDCFlow = requestedScopes.includes('openid');
|
141
147
|
if (tenant && product) {
|
142
148
|
const samlConfigs = yield this.configStore.getByIndex({
|
143
149
|
name: utils_1.IndexNames.TenantProduct,
|
@@ -172,8 +178,14 @@ class OAuthController {
|
|
172
178
|
if (!sp && access_type) {
|
173
179
|
sp = getEncodedTenantProduct(access_type);
|
174
180
|
}
|
175
|
-
if (!sp &&
|
176
|
-
sp = getEncodedTenantProduct(
|
181
|
+
if (!sp && resource) {
|
182
|
+
sp = getEncodedTenantProduct(resource);
|
183
|
+
}
|
184
|
+
if (!sp && requestedScopes) {
|
185
|
+
const encodedParams = requestedScopes.find((scope) => scope.includes('=') && scope.includes('&')); // for now assume only one encoded param i.e. for tenant/product
|
186
|
+
if (encodedParams) {
|
187
|
+
sp = getEncodedTenantProduct(encodedParams);
|
188
|
+
}
|
177
189
|
}
|
178
190
|
if (sp && sp.tenant && sp.product) {
|
179
191
|
requestedTenant = sp.tenant;
|
@@ -222,6 +234,16 @@ class OAuthController {
|
|
222
234
|
if (!allowed.redirect(redirect_uri, samlConfig.redirectUrl)) {
|
223
235
|
throw new error_1.JacksonError('Redirect URL is not allowed.', 403);
|
224
236
|
}
|
237
|
+
if (requestedOIDCFlow &&
|
238
|
+
(!this.opts.openid.jwtSigningKeys || !(0, utils_1.isJWSKeyPairLoaded)(this.opts.openid.jwtSigningKeys))) {
|
239
|
+
return {
|
240
|
+
redirect_url: (0, utils_1.OAuthErrorResponse)({
|
241
|
+
error: 'server_error',
|
242
|
+
error_description: 'OAuth server not configured correctly for openid flow, check if JWT signing keys are loaded',
|
243
|
+
redirect_uri,
|
244
|
+
}),
|
245
|
+
};
|
246
|
+
}
|
225
247
|
if (!state) {
|
226
248
|
return {
|
227
249
|
redirect_url: (0, utils_1.OAuthErrorResponse)({
|
@@ -282,6 +304,15 @@ class OAuthController {
|
|
282
304
|
if (idp_hint) {
|
283
305
|
requested.idp_hint = idp_hint;
|
284
306
|
}
|
307
|
+
if (requestedOIDCFlow) {
|
308
|
+
requested.oidc = true;
|
309
|
+
if (nonce) {
|
310
|
+
requested.nonce = nonce;
|
311
|
+
}
|
312
|
+
}
|
313
|
+
if (requestedScopes) {
|
314
|
+
requested.scope = requestedScopes;
|
315
|
+
}
|
285
316
|
yield this.sessionStore.put(sessionId, {
|
286
317
|
id: samlReq.id,
|
287
318
|
redirect_uri,
|
@@ -563,6 +594,27 @@ class OAuthController {
|
|
563
594
|
// store details against a token
|
564
595
|
const token = crypto_1.default.randomBytes(20).toString('hex');
|
565
596
|
const tokenVal = Object.assign(Object.assign({}, codeVal.profile), { requested: codeVal.requested });
|
597
|
+
const requestedOIDCFlow = !!codeVal.requested.oidc;
|
598
|
+
const requestHasNonce = !!codeVal.requested.nonce;
|
599
|
+
if (requestedOIDCFlow) {
|
600
|
+
const { jwtSigningKeys, jwsAlg } = this.opts.openid;
|
601
|
+
if (!jwtSigningKeys || !(0, utils_1.isJWSKeyPairLoaded)(jwtSigningKeys)) {
|
602
|
+
throw new error_1.JacksonError('JWT signing keys are not loaded', 500);
|
603
|
+
}
|
604
|
+
let claims = requestHasNonce ? { nonce: codeVal.requested.nonce } : {};
|
605
|
+
claims = Object.assign(Object.assign({}, claims), { id: codeVal.profile.claims.id, email: codeVal.profile.claims.email, firstName: codeVal.profile.claims.firstName, lastName: codeVal.profile.claims.lastName });
|
606
|
+
const signingKey = yield (0, utils_1.loadJWSPrivateKey)(jwtSigningKeys.private, jwsAlg);
|
607
|
+
const id_token = yield new jose.SignJWT(claims)
|
608
|
+
.setProtectedHeader({ alg: jwsAlg })
|
609
|
+
.setIssuedAt()
|
610
|
+
.setIssuer(this.opts.samlAudience || '')
|
611
|
+
.setSubject(codeVal.profile.claims.id)
|
612
|
+
.setAudience(tokenVal.requested.client_id)
|
613
|
+
.setExpirationTime(`${this.opts.db.ttl}s`) // identity token only really needs to be valid long enough for it to be verified by the client application.
|
614
|
+
.sign(signingKey);
|
615
|
+
tokenVal.id_token = id_token;
|
616
|
+
tokenVal.claims.sub = codeVal.profile.claims.id;
|
617
|
+
}
|
566
618
|
yield this.tokenStore.put(token, tokenVal);
|
567
619
|
// delete the code
|
568
620
|
try {
|
@@ -571,11 +623,15 @@ class OAuthController {
|
|
571
623
|
catch (_err) {
|
572
624
|
// ignore error
|
573
625
|
}
|
574
|
-
|
626
|
+
const tokenResponse = {
|
575
627
|
access_token: token,
|
576
628
|
token_type: 'bearer',
|
577
629
|
expires_in: this.opts.db.ttl,
|
578
630
|
};
|
631
|
+
if (requestedOIDCFlow) {
|
632
|
+
tokenResponse.id_token = tokenVal.id_token;
|
633
|
+
}
|
634
|
+
return tokenResponse;
|
579
635
|
});
|
580
636
|
}
|
581
637
|
/**
|
@@ -0,0 +1,50 @@
|
|
1
|
+
import { IOidcDiscoveryController } from '../typings';
|
2
|
+
export declare class OidcDiscoveryController implements IOidcDiscoveryController {
|
3
|
+
private opts;
|
4
|
+
constructor({ opts }: {
|
5
|
+
opts: any;
|
6
|
+
});
|
7
|
+
openidConfig(): {
|
8
|
+
issuer: string;
|
9
|
+
authorization_endpoint: string;
|
10
|
+
token_endpoint: string;
|
11
|
+
userinfo_endpoint: string;
|
12
|
+
jwks_uri: string;
|
13
|
+
response_types_supported: string[];
|
14
|
+
subject_types_supported: string[];
|
15
|
+
id_token_signing_alg_values_supported: string[];
|
16
|
+
grant_types_supported: string[];
|
17
|
+
code_challenge_methods_supported: string[];
|
18
|
+
};
|
19
|
+
jwks(): Promise<{
|
20
|
+
keys: {
|
21
|
+
kid: string;
|
22
|
+
alg: string;
|
23
|
+
use: string;
|
24
|
+
crv?: string | undefined;
|
25
|
+
d?: string | undefined;
|
26
|
+
dp?: string | undefined;
|
27
|
+
dq?: string | undefined;
|
28
|
+
e?: string | undefined;
|
29
|
+
ext?: boolean | undefined;
|
30
|
+
k?: string | undefined;
|
31
|
+
key_ops?: string[] | undefined;
|
32
|
+
kty?: string | undefined;
|
33
|
+
n?: string | undefined;
|
34
|
+
oth?: {
|
35
|
+
d?: string | undefined;
|
36
|
+
r?: string | undefined;
|
37
|
+
t?: string | undefined;
|
38
|
+
}[] | undefined;
|
39
|
+
p?: string | undefined;
|
40
|
+
q?: string | undefined;
|
41
|
+
qi?: string | undefined;
|
42
|
+
x?: string | undefined;
|
43
|
+
y?: string | undefined;
|
44
|
+
x5c?: string[] | undefined;
|
45
|
+
x5t?: string | undefined;
|
46
|
+
'x5t#S256'?: string | undefined;
|
47
|
+
x5u?: string | undefined;
|
48
|
+
}[];
|
49
|
+
}>;
|
50
|
+
}
|
@@ -0,0 +1,49 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
9
|
+
});
|
10
|
+
};
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
12
|
+
exports.OidcDiscoveryController = void 0;
|
13
|
+
const error_1 = require("./error");
|
14
|
+
const utils_1 = require("./utils");
|
15
|
+
class OidcDiscoveryController {
|
16
|
+
constructor({ opts }) {
|
17
|
+
this.opts = opts;
|
18
|
+
}
|
19
|
+
openidConfig() {
|
20
|
+
return {
|
21
|
+
issuer: this.opts.samlAudience,
|
22
|
+
authorization_endpoint: `${this.opts.externalUrl}/api/oauth/authorize`,
|
23
|
+
token_endpoint: `${this.opts.externalUrl}/api/oauth/token`,
|
24
|
+
userinfo_endpoint: `${this.opts.externalUrl}/api/oauth/userinfo`,
|
25
|
+
jwks_uri: `${this.opts.externalUrl}/oauth/jwks`,
|
26
|
+
response_types_supported: ['code'],
|
27
|
+
subject_types_supported: ['public'],
|
28
|
+
id_token_signing_alg_values_supported: ['RS256'],
|
29
|
+
grant_types_supported: ['authorization_code'],
|
30
|
+
code_challenge_methods_supported: ['plain', 'S256'],
|
31
|
+
};
|
32
|
+
}
|
33
|
+
jwks() {
|
34
|
+
return __awaiter(this, void 0, void 0, function* () {
|
35
|
+
const { jwtSigningKeys, jwsAlg } = this.opts.openid;
|
36
|
+
if (!jwtSigningKeys || !(0, utils_1.isJWSKeyPairLoaded)(jwtSigningKeys)) {
|
37
|
+
throw new error_1.JacksonError('JWT signing keys are not loaded', 501);
|
38
|
+
}
|
39
|
+
const importedPublicKey = yield (0, utils_1.importJWTPublicKey)(jwtSigningKeys.public, jwsAlg);
|
40
|
+
const publicKeyJWK = yield (0, utils_1.exportPublicKeyJWK)(importedPublicKey);
|
41
|
+
const jwkThumbprint = yield (0, utils_1.generateJwkThumbprint)(publicKeyJWK);
|
42
|
+
const jwks = {
|
43
|
+
keys: [Object.assign(Object.assign({}, publicKeyJWK), { kid: jwkThumbprint, alg: jwsAlg, use: 'sig' })],
|
44
|
+
};
|
45
|
+
return jwks;
|
46
|
+
});
|
47
|
+
}
|
48
|
+
}
|
49
|
+
exports.OidcDiscoveryController = OidcDiscoveryController;
|
@@ -1,4 +1,5 @@
|
|
1
1
|
import type { OAuthErrorHandlerParams } from '../typings';
|
2
|
+
import * as jose from 'jose';
|
2
3
|
export declare enum IndexNames {
|
3
4
|
EntityID = "entityID",
|
4
5
|
TenantProduct = "tenantProduct"
|
@@ -7,3 +8,11 @@ export declare const relayStatePrefix = "boxyhq_jackson_";
|
|
7
8
|
export declare const validateAbsoluteUrl: (url: any, message: any) => void;
|
8
9
|
export declare const OAuthErrorResponse: ({ error, error_description, redirect_uri, state, }: OAuthErrorHandlerParams) => string;
|
9
10
|
export declare function getErrorMessage(error: unknown): string;
|
11
|
+
export declare function loadJWSPrivateKey(key: string, alg: string): Promise<jose.KeyLike>;
|
12
|
+
export declare function isJWSKeyPairLoaded(jwsKeyPair: {
|
13
|
+
private: string;
|
14
|
+
public: string;
|
15
|
+
}): boolean;
|
16
|
+
export declare const importJWTPublicKey: (key: string, jwsAlg: string) => Promise<jose.KeyLike>;
|
17
|
+
export declare const exportPublicKeyJWK: (key: jose.KeyLike) => Promise<jose.JWK>;
|
18
|
+
export declare const generateJwkThumbprint: (jwk: jose.JWK) => Promise<string>;
|
package/dist/controller/utils.js
CHANGED
@@ -22,10 +22,20 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
22
22
|
__setModuleDefault(result, mod);
|
23
23
|
return result;
|
24
24
|
};
|
25
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
26
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
27
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
28
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
29
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
30
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
31
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
32
|
+
});
|
33
|
+
};
|
25
34
|
Object.defineProperty(exports, "__esModule", { value: true });
|
26
|
-
exports.getErrorMessage = exports.OAuthErrorResponse = exports.validateAbsoluteUrl = exports.relayStatePrefix = exports.IndexNames = void 0;
|
35
|
+
exports.generateJwkThumbprint = exports.exportPublicKeyJWK = exports.importJWTPublicKey = exports.isJWSKeyPairLoaded = exports.loadJWSPrivateKey = exports.getErrorMessage = exports.OAuthErrorResponse = exports.validateAbsoluteUrl = exports.relayStatePrefix = exports.IndexNames = void 0;
|
27
36
|
const error_1 = require("./error");
|
28
37
|
const redirect = __importStar(require("./oauth/redirect"));
|
38
|
+
const jose = __importStar(require("jose"));
|
29
39
|
var IndexNames;
|
30
40
|
(function (IndexNames) {
|
31
41
|
IndexNames["EntityID"] = "entityID";
|
@@ -47,8 +57,40 @@ const OAuthErrorResponse = ({ error, error_description, redirect_uri, state, })
|
|
47
57
|
exports.OAuthErrorResponse = OAuthErrorResponse;
|
48
58
|
// https://kentcdodds.com/blog/get-a-catch-block-error-message-with-typescript
|
49
59
|
function getErrorMessage(error) {
|
50
|
-
if (error instanceof Error)
|
60
|
+
if (error instanceof Error) {
|
51
61
|
return error.message;
|
62
|
+
}
|
52
63
|
return String(error);
|
53
64
|
}
|
54
65
|
exports.getErrorMessage = getErrorMessage;
|
66
|
+
function loadJWSPrivateKey(key, alg) {
|
67
|
+
return __awaiter(this, void 0, void 0, function* () {
|
68
|
+
const pkcs8 = Buffer.from(key, 'base64').toString('ascii');
|
69
|
+
const privateKey = yield jose.importPKCS8(pkcs8, alg);
|
70
|
+
return privateKey;
|
71
|
+
});
|
72
|
+
}
|
73
|
+
exports.loadJWSPrivateKey = loadJWSPrivateKey;
|
74
|
+
function isJWSKeyPairLoaded(jwsKeyPair) {
|
75
|
+
if (!jwsKeyPair.private || !jwsKeyPair.public) {
|
76
|
+
return false;
|
77
|
+
}
|
78
|
+
return true;
|
79
|
+
}
|
80
|
+
exports.isJWSKeyPairLoaded = isJWSKeyPairLoaded;
|
81
|
+
const importJWTPublicKey = (key, jwsAlg) => __awaiter(void 0, void 0, void 0, function* () {
|
82
|
+
const spki = Buffer.from(key, 'base64').toString('ascii');
|
83
|
+
const publicKey = yield jose.importSPKI(spki, jwsAlg);
|
84
|
+
return publicKey;
|
85
|
+
});
|
86
|
+
exports.importJWTPublicKey = importJWTPublicKey;
|
87
|
+
const exportPublicKeyJWK = (key) => __awaiter(void 0, void 0, void 0, function* () {
|
88
|
+
const publicJWK = yield jose.exportJWK(key);
|
89
|
+
return publicJWK;
|
90
|
+
});
|
91
|
+
exports.exportPublicKeyJWK = exportPublicKeyJWK;
|
92
|
+
const generateJwkThumbprint = (jwk) => __awaiter(void 0, void 0, void 0, function* () {
|
93
|
+
const thumbprint = yield jose.calculateJwkThumbprint(jwk);
|
94
|
+
return thumbprint;
|
95
|
+
});
|
96
|
+
exports.generateJwkThumbprint = generateJwkThumbprint;
|
package/dist/db/db.js
CHANGED
@@ -41,6 +41,12 @@ const mongo_1 = __importDefault(require("./mongo"));
|
|
41
41
|
const redis_1 = __importDefault(require("./redis"));
|
42
42
|
const sql_1 = __importDefault(require("./sql/sql"));
|
43
43
|
const store_1 = __importDefault(require("./store"));
|
44
|
+
const JacksonStore_1 = require("./sql/entity/JacksonStore");
|
45
|
+
const JacksonIndex_1 = require("./sql/entity/JacksonIndex");
|
46
|
+
const JacksonTTL_1 = require("./sql/entity/JacksonTTL");
|
47
|
+
const JacksonStore_2 = require("./planetscale/entity/JacksonStore");
|
48
|
+
const JacksonIndex_2 = require("./planetscale/entity/JacksonIndex");
|
49
|
+
const JacksonTTL_2 = require("./planetscale/entity/JacksonTTL");
|
44
50
|
const decrypt = (res, encryptionKey) => {
|
45
51
|
if (res.iv && res.tag) {
|
46
52
|
return JSON.parse(encrypter.decrypt(res.value, res.iv, res.tag, encryptionKey));
|
@@ -107,7 +113,17 @@ exports.default = {
|
|
107
113
|
case 'redis':
|
108
114
|
return new DB(yield redis_1.default.new(options), encryptionKey);
|
109
115
|
case 'sql':
|
110
|
-
return new DB(yield sql_1.default.new(options
|
116
|
+
return new DB(yield sql_1.default.new(options, {
|
117
|
+
JacksonStore: JacksonStore_1.JacksonStore,
|
118
|
+
JacksonIndex: JacksonIndex_1.JacksonIndex,
|
119
|
+
JacksonTTL: JacksonTTL_1.JacksonTTL,
|
120
|
+
}), encryptionKey);
|
121
|
+
case 'planetscale':
|
122
|
+
return new DB(yield sql_1.default.new(options, {
|
123
|
+
JacksonStore: JacksonStore_2.JacksonStore,
|
124
|
+
JacksonIndex: JacksonIndex_2.JacksonIndex,
|
125
|
+
JacksonTTL: JacksonTTL_2.JacksonTTL,
|
126
|
+
}), encryptionKey);
|
111
127
|
case 'mongo':
|
112
128
|
return new DB(yield mongo_1.default.new(options), encryptionKey);
|
113
129
|
case 'mem':
|
package/dist/db/mongo.js
CHANGED
@@ -67,8 +67,9 @@ class Mongo {
|
|
67
67
|
const docs = yield this.collection
|
68
68
|
.find({ _id: _namespaceMatch }, { sort: { createdAt: -1 }, skip: offset, limit: limit })
|
69
69
|
.toArray();
|
70
|
-
if (docs)
|
70
|
+
if (docs) {
|
71
71
|
return docs.map(({ value }) => value);
|
72
|
+
}
|
72
73
|
return [];
|
73
74
|
});
|
74
75
|
}
|
@@ -0,0 +1,34 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
7
|
+
};
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
9
|
+
exports.JacksonIndex = void 0;
|
10
|
+
const typeorm_1 = require("typeorm");
|
11
|
+
let JacksonIndex = class JacksonIndex {
|
12
|
+
};
|
13
|
+
__decorate([
|
14
|
+
(0, typeorm_1.PrimaryGeneratedColumn)()
|
15
|
+
], JacksonIndex.prototype, "id", void 0);
|
16
|
+
__decorate([
|
17
|
+
(0, typeorm_1.Index)('_jackson_index_key'),
|
18
|
+
(0, typeorm_1.Column)({
|
19
|
+
type: 'varchar',
|
20
|
+
length: 250,
|
21
|
+
})
|
22
|
+
], JacksonIndex.prototype, "key", void 0);
|
23
|
+
__decorate([
|
24
|
+
(0, typeorm_1.Index)('_jackson_index_store'),
|
25
|
+
(0, typeorm_1.Column)({
|
26
|
+
type: 'varchar',
|
27
|
+
length: 250,
|
28
|
+
})
|
29
|
+
], JacksonIndex.prototype, "storeKey", void 0);
|
30
|
+
JacksonIndex = __decorate([
|
31
|
+
(0, typeorm_1.Index)('_jackson_index_key_store', ['key', 'storeKey']),
|
32
|
+
(0, typeorm_1.Entity)()
|
33
|
+
], JacksonIndex);
|
34
|
+
exports.JacksonIndex = JacksonIndex;
|
@@ -0,0 +1,55 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
7
|
+
};
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
9
|
+
exports.JacksonStore = void 0;
|
10
|
+
const typeorm_1 = require("typeorm");
|
11
|
+
let JacksonStore = class JacksonStore {
|
12
|
+
};
|
13
|
+
__decorate([
|
14
|
+
(0, typeorm_1.Column)({
|
15
|
+
primary: true,
|
16
|
+
type: 'varchar',
|
17
|
+
length: 250,
|
18
|
+
})
|
19
|
+
], JacksonStore.prototype, "key", void 0);
|
20
|
+
__decorate([
|
21
|
+
(0, typeorm_1.Column)({
|
22
|
+
type: 'text',
|
23
|
+
})
|
24
|
+
], JacksonStore.prototype, "value", void 0);
|
25
|
+
__decorate([
|
26
|
+
(0, typeorm_1.Column)({
|
27
|
+
type: 'varchar',
|
28
|
+
length: 64,
|
29
|
+
nullable: true,
|
30
|
+
})
|
31
|
+
], JacksonStore.prototype, "iv", void 0);
|
32
|
+
__decorate([
|
33
|
+
(0, typeorm_1.Column)({
|
34
|
+
type: 'varchar',
|
35
|
+
length: 64,
|
36
|
+
nullable: true,
|
37
|
+
})
|
38
|
+
], JacksonStore.prototype, "tag", void 0);
|
39
|
+
__decorate([
|
40
|
+
(0, typeorm_1.Column)({
|
41
|
+
type: 'timestamp',
|
42
|
+
default: () => 'CURRENT_TIMESTAMP',
|
43
|
+
nullable: false,
|
44
|
+
})
|
45
|
+
], JacksonStore.prototype, "createdAt", void 0);
|
46
|
+
__decorate([
|
47
|
+
(0, typeorm_1.Column)({
|
48
|
+
type: 'timestamp',
|
49
|
+
nullable: true,
|
50
|
+
})
|
51
|
+
], JacksonStore.prototype, "modifiedAt", void 0);
|
52
|
+
JacksonStore = __decorate([
|
53
|
+
(0, typeorm_1.Entity)()
|
54
|
+
], JacksonStore);
|
55
|
+
exports.JacksonStore = JacksonStore;
|
@@ -0,0 +1,29 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
7
|
+
};
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
9
|
+
exports.JacksonTTL = void 0;
|
10
|
+
const typeorm_1 = require("typeorm");
|
11
|
+
let JacksonTTL = class JacksonTTL {
|
12
|
+
};
|
13
|
+
__decorate([
|
14
|
+
(0, typeorm_1.Column)({
|
15
|
+
primary: true,
|
16
|
+
type: 'varchar',
|
17
|
+
length: 250,
|
18
|
+
})
|
19
|
+
], JacksonTTL.prototype, "key", void 0);
|
20
|
+
__decorate([
|
21
|
+
(0, typeorm_1.Index)('_jackson_ttl_expires_at'),
|
22
|
+
(0, typeorm_1.Column)({
|
23
|
+
type: 'bigint',
|
24
|
+
})
|
25
|
+
], JacksonTTL.prototype, "expiresAt", void 0);
|
26
|
+
JacksonTTL = __decorate([
|
27
|
+
(0, typeorm_1.Entity)()
|
28
|
+
], JacksonTTL);
|
29
|
+
exports.JacksonTTL = JacksonTTL;
|
package/dist/db/sql/sql.d.ts
CHANGED
@@ -7,8 +7,15 @@ declare class Sql implements DatabaseDriver {
|
|
7
7
|
private ttlRepository;
|
8
8
|
private ttlCleanup;
|
9
9
|
private timerId;
|
10
|
+
private JacksonStore;
|
11
|
+
private JacksonIndex;
|
12
|
+
private JacksonTTL;
|
10
13
|
constructor(options: DatabaseOption);
|
11
|
-
init(
|
14
|
+
init({ JacksonStore, JacksonIndex, JacksonTTL }: {
|
15
|
+
JacksonStore: any;
|
16
|
+
JacksonIndex: any;
|
17
|
+
JacksonTTL: any;
|
18
|
+
}): Promise<Sql>;
|
12
19
|
get(namespace: string, key: string): Promise<any>;
|
13
20
|
getAll(namespace: string, pageOffset: number, pageLimit: number): Promise<unknown[]>;
|
14
21
|
getByIndex(namespace: string, idx: Index): Promise<any>;
|
@@ -16,6 +23,6 @@ declare class Sql implements DatabaseDriver {
|
|
16
23
|
delete(namespace: string, key: string): Promise<any>;
|
17
24
|
}
|
18
25
|
declare const _default: {
|
19
|
-
new: (options: DatabaseOption) => Promise<Sql>;
|
26
|
+
new: (options: DatabaseOption, entities: any) => Promise<Sql>;
|
20
27
|
};
|
21
28
|
export default _default;
|
package/dist/db/sql/sql.js
CHANGED
@@ -36,38 +36,39 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
require('reflect-metadata');
|
37
37
|
const typeorm_1 = require("typeorm");
|
38
38
|
const dbutils = __importStar(require("../utils"));
|
39
|
-
const JacksonStore_1 = require("./entity/JacksonStore");
|
40
|
-
const JacksonIndex_1 = require("./entity/JacksonIndex");
|
41
|
-
const JacksonTTL_1 = require("./entity/JacksonTTL");
|
42
39
|
class Sql {
|
43
40
|
constructor(options) {
|
44
41
|
this.options = options;
|
45
42
|
}
|
46
|
-
init() {
|
43
|
+
init({ JacksonStore, JacksonIndex, JacksonTTL }) {
|
47
44
|
return __awaiter(this, void 0, void 0, function* () {
|
45
|
+
const sqlType = this.options.engine === 'planetscale' ? 'mysql' : this.options.type;
|
48
46
|
while (true) {
|
49
47
|
try {
|
50
48
|
this.dataSource = new typeorm_1.DataSource({
|
51
|
-
|
52
|
-
type: this.options.type,
|
49
|
+
type: sqlType,
|
53
50
|
url: this.options.url,
|
54
|
-
synchronize:
|
51
|
+
synchronize: this.options.engine !== 'planetscale',
|
55
52
|
migrationsTableName: '_jackson_migrations',
|
56
53
|
logging: ['error'],
|
57
|
-
entities: [
|
54
|
+
entities: [JacksonStore, JacksonIndex, JacksonTTL],
|
55
|
+
ssl: this.options.ssl,
|
58
56
|
});
|
59
57
|
yield this.dataSource.initialize();
|
60
58
|
break;
|
61
59
|
}
|
62
60
|
catch (err) {
|
63
|
-
console.error(`error connecting to ${this.options.type} db: ${err}`);
|
61
|
+
console.error(`error connecting to engine: ${this.options.engine}, type: ${sqlType} db: ${err}`);
|
64
62
|
yield dbutils.sleep(1000);
|
65
63
|
continue;
|
66
64
|
}
|
67
65
|
}
|
68
|
-
this.
|
69
|
-
this.
|
70
|
-
this.
|
66
|
+
this.JacksonStore = JacksonStore;
|
67
|
+
this.JacksonIndex = JacksonIndex;
|
68
|
+
this.JacksonTTL = JacksonTTL;
|
69
|
+
this.storeRepository = this.dataSource.getRepository(JacksonStore);
|
70
|
+
this.indexRepository = this.dataSource.getRepository(JacksonIndex);
|
71
|
+
this.ttlRepository = this.dataSource.getRepository(JacksonTTL);
|
71
72
|
if (this.options.ttl && this.options.cleanupLimit) {
|
72
73
|
this.ttlCleanup = () => __awaiter(this, void 0, void 0, function* () {
|
73
74
|
const now = Date.now();
|
@@ -121,15 +122,11 @@ class Sql {
|
|
121
122
|
select: ['value', 'iv', 'tag'],
|
122
123
|
order: {
|
123
124
|
['createdAt']: 'DESC',
|
124
|
-
// ['createdAt']: 'ASC',
|
125
125
|
},
|
126
126
|
take: offsetAndLimitValueCheck ? this.options.pageLimit : pageLimit,
|
127
127
|
skip: offsetAndLimitValueCheck ? 0 : pageOffset,
|
128
128
|
});
|
129
|
-
|
130
|
-
if (returnValue)
|
131
|
-
return returnValue;
|
132
|
-
return [];
|
129
|
+
return JSON.parse(JSON.stringify(response)) || [];
|
133
130
|
});
|
134
131
|
}
|
135
132
|
getByIndex(namespace, idx) {
|
@@ -139,13 +136,19 @@ class Sql {
|
|
139
136
|
});
|
140
137
|
const ret = [];
|
141
138
|
if (res) {
|
142
|
-
|
139
|
+
for (const r of res) {
|
140
|
+
let value = r.store;
|
141
|
+
if (this.options.engine === 'planetscale') {
|
142
|
+
value = yield this.storeRepository.findOneBy({
|
143
|
+
key: r.storeKey,
|
144
|
+
});
|
145
|
+
}
|
143
146
|
ret.push({
|
144
|
-
value:
|
145
|
-
iv:
|
146
|
-
tag:
|
147
|
+
value: value.value,
|
148
|
+
iv: value.iv,
|
149
|
+
tag: value.tag,
|
147
150
|
});
|
148
|
-
}
|
151
|
+
}
|
149
152
|
}
|
150
153
|
return ret;
|
151
154
|
});
|
@@ -154,7 +157,7 @@ class Sql {
|
|
154
157
|
return __awaiter(this, void 0, void 0, function* () {
|
155
158
|
yield this.dataSource.transaction((transactionalEntityManager) => __awaiter(this, void 0, void 0, function* () {
|
156
159
|
const dbKey = dbutils.key(namespace, key);
|
157
|
-
const store = new
|
160
|
+
const store = new this.JacksonStore();
|
158
161
|
store.key = dbKey;
|
159
162
|
store.value = val.value;
|
160
163
|
store.iv = val.iv;
|
@@ -162,7 +165,7 @@ class Sql {
|
|
162
165
|
store.modifiedAt = new Date().toISOString();
|
163
166
|
yield transactionalEntityManager.save(store);
|
164
167
|
if (ttl) {
|
165
|
-
const ttlRec = new
|
168
|
+
const ttlRec = new this.JacksonTTL();
|
166
169
|
ttlRec.key = dbKey;
|
167
170
|
ttlRec.expiresAt = Date.now() + ttl * 1000;
|
168
171
|
yield transactionalEntityManager.save(ttlRec);
|
@@ -175,9 +178,14 @@ class Sql {
|
|
175
178
|
storeKey: store.key,
|
176
179
|
});
|
177
180
|
if (!rec) {
|
178
|
-
const ji = new
|
181
|
+
const ji = new this.JacksonIndex();
|
179
182
|
ji.key = key;
|
180
|
-
|
183
|
+
if (this.options.engine === 'planetscale') {
|
184
|
+
ji.storeKey = store.key;
|
185
|
+
}
|
186
|
+
else {
|
187
|
+
ji.store = store;
|
188
|
+
}
|
181
189
|
yield transactionalEntityManager.save(ji);
|
182
190
|
}
|
183
191
|
}
|
@@ -188,6 +196,18 @@ class Sql {
|
|
188
196
|
return __awaiter(this, void 0, void 0, function* () {
|
189
197
|
const dbKey = dbutils.key(namespace, key);
|
190
198
|
yield this.ttlRepository.remove({ key: dbKey });
|
199
|
+
if (this.options.engine === 'planetscale') {
|
200
|
+
const response = yield this.indexRepository.find({
|
201
|
+
where: { storeKey: dbKey },
|
202
|
+
select: ['id'],
|
203
|
+
});
|
204
|
+
const returnValue = response || [];
|
205
|
+
for (const r of returnValue) {
|
206
|
+
yield this.indexRepository.remove({
|
207
|
+
id: r.id,
|
208
|
+
});
|
209
|
+
}
|
210
|
+
}
|
191
211
|
return yield this.storeRepository.remove({
|
192
212
|
key: dbKey,
|
193
213
|
});
|
@@ -195,7 +215,7 @@ class Sql {
|
|
195
215
|
}
|
196
216
|
}
|
197
217
|
exports.default = {
|
198
|
-
new: (options) => __awaiter(void 0, void 0, void 0, function* () {
|
199
|
-
return yield new Sql(options).init();
|
218
|
+
new: (options, entities) => __awaiter(void 0, void 0, void 0, function* () {
|
219
|
+
return yield new Sql(options).init(entities);
|
200
220
|
}),
|
201
221
|
};
|
package/dist/index.d.ts
CHANGED
@@ -3,6 +3,7 @@ import { APIController } from './controller/api';
|
|
3
3
|
import { OAuthController } from './controller/oauth';
|
4
4
|
import { HealthCheckController } from './controller/health-check';
|
5
5
|
import { LogoutController } from './controller/logout';
|
6
|
+
import { OidcDiscoveryController } from './controller/oidc-discovery';
|
6
7
|
import { JacksonOption } from './typings';
|
7
8
|
export declare const controllers: (opts: JacksonOption) => Promise<{
|
8
9
|
apiController: APIController;
|
@@ -10,6 +11,7 @@ export declare const controllers: (opts: JacksonOption) => Promise<{
|
|
10
11
|
adminController: AdminController;
|
11
12
|
logoutController: LogoutController;
|
12
13
|
healthCheckController: HealthCheckController;
|
14
|
+
oidcDiscoveryController: OidcDiscoveryController;
|
13
15
|
}>;
|
14
16
|
export default controllers;
|
15
17
|
export * from './typings';
|
package/dist/index.js
CHANGED
@@ -32,6 +32,7 @@ const api_1 = require("./controller/api");
|
|
32
32
|
const oauth_1 = require("./controller/oauth");
|
33
33
|
const health_check_1 = require("./controller/health-check");
|
34
34
|
const logout_1 = require("./controller/logout");
|
35
|
+
const oidc_discovery_1 = require("./controller/oidc-discovery");
|
35
36
|
const db_1 = __importDefault(require("./db/db"));
|
36
37
|
const defaultDb_1 = __importDefault(require("./db/defaultDb"));
|
37
38
|
const read_config_1 = __importDefault(require("./read-config"));
|
@@ -49,6 +50,8 @@ const defaultOpts = (opts) => {
|
|
49
50
|
(0, defaultDb_1.default)(newOpts);
|
50
51
|
newOpts.clientSecretVerifier = newOpts.clientSecretVerifier || 'dummy';
|
51
52
|
newOpts.db.pageLimit = newOpts.db.pageLimit || 50;
|
53
|
+
newOpts.openid = newOpts.openid || {};
|
54
|
+
newOpts.openid.jwsAlg = newOpts.openid.jwsAlg || 'RS256';
|
52
55
|
return newOpts;
|
53
56
|
};
|
54
57
|
const controllers = (opts) => __awaiter(void 0, void 0, void 0, function* () {
|
@@ -75,6 +78,7 @@ const controllers = (opts) => __awaiter(void 0, void 0, void 0, function* () {
|
|
75
78
|
sessionStore,
|
76
79
|
opts,
|
77
80
|
});
|
81
|
+
const oidcDiscoveryController = new oidc_discovery_1.OidcDiscoveryController({ opts });
|
78
82
|
// write pre-loaded config if present
|
79
83
|
if (opts.preLoadedConfig && opts.preLoadedConfig.length > 0) {
|
80
84
|
const configs = yield (0, read_config_1.default)(opts.preLoadedConfig);
|
@@ -91,6 +95,7 @@ const controllers = (opts) => __awaiter(void 0, void 0, void 0, function* () {
|
|
91
95
|
adminController,
|
92
96
|
logoutController,
|
93
97
|
healthCheckController,
|
98
|
+
oidcDiscoveryController,
|
94
99
|
};
|
95
100
|
});
|
96
101
|
exports.controllers = controllers;
|
package/dist/typings.d.ts
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
import { type JWK } from 'jose';
|
1
2
|
export declare type IdPConfig = {
|
2
3
|
defaultRedirectUrl: string;
|
3
4
|
redirectUrl: string[] | string;
|
@@ -44,6 +45,23 @@ export interface IHealthCheckController {
|
|
44
45
|
}>;
|
45
46
|
init(): Promise<void>;
|
46
47
|
}
|
48
|
+
export interface IOidcDiscoveryController {
|
49
|
+
openidConfig(): {
|
50
|
+
issuer: string;
|
51
|
+
authorization_endpoint: string;
|
52
|
+
token_endpoint: string;
|
53
|
+
userinfo_endpoint: string;
|
54
|
+
jwks_uri: string;
|
55
|
+
response_types_supported: Array<string>;
|
56
|
+
subject_types_supported: Array<string>;
|
57
|
+
id_token_signing_alg_values_supported: Array<string>;
|
58
|
+
grant_types_supported: Array<string>;
|
59
|
+
code_challenge_methods_supported: Array<string>;
|
60
|
+
};
|
61
|
+
jwks(): Promise<{
|
62
|
+
keys: JWK[];
|
63
|
+
}>;
|
64
|
+
}
|
47
65
|
export interface OAuthReqBody {
|
48
66
|
response_type: 'code';
|
49
67
|
client_id: string;
|
@@ -52,7 +70,9 @@ export interface OAuthReqBody {
|
|
52
70
|
tenant?: string;
|
53
71
|
product?: string;
|
54
72
|
access_type?: string;
|
73
|
+
resource?: string;
|
55
74
|
scope?: string;
|
75
|
+
nonce?: string;
|
56
76
|
code_challenge: string;
|
57
77
|
code_challenge_method: 'plain' | 'S256' | '';
|
58
78
|
provider: 'saml';
|
@@ -72,11 +92,13 @@ export interface OAuthTokenReq {
|
|
72
92
|
}
|
73
93
|
export interface OAuthTokenRes {
|
74
94
|
access_token: string;
|
95
|
+
id_token?: string;
|
75
96
|
token_type: 'bearer';
|
76
97
|
expires_in: number;
|
77
98
|
}
|
78
99
|
export interface Profile {
|
79
100
|
id: string;
|
101
|
+
sub?: string;
|
80
102
|
email: string;
|
81
103
|
firstName: string;
|
82
104
|
lastName: string;
|
@@ -106,7 +128,7 @@ export interface Encrypted {
|
|
106
128
|
value: string;
|
107
129
|
}
|
108
130
|
export declare type EncryptionKey = any;
|
109
|
-
export declare type DatabaseEngine = 'redis' | 'sql' | 'mongo' | 'mem';
|
131
|
+
export declare type DatabaseEngine = 'redis' | 'sql' | 'mongo' | 'mem' | 'planetscale';
|
110
132
|
export declare type DatabaseType = 'postgres' | 'mysql' | 'mariadb';
|
111
133
|
export interface DatabaseOption {
|
112
134
|
engine?: DatabaseEngine;
|
@@ -116,6 +138,7 @@ export interface DatabaseOption {
|
|
116
138
|
cleanupLimit?: number;
|
117
139
|
encryptionKey?: string;
|
118
140
|
pageLimit?: number;
|
141
|
+
ssl?: any;
|
119
142
|
}
|
120
143
|
export interface JacksonOption {
|
121
144
|
externalUrl: string;
|
@@ -126,6 +149,13 @@ export interface JacksonOption {
|
|
126
149
|
db: DatabaseOption;
|
127
150
|
clientSecretVerifier?: string;
|
128
151
|
idpDiscoveryPath?: string;
|
152
|
+
openid: {
|
153
|
+
jwsAlg: string;
|
154
|
+
jwtSigningKeys?: {
|
155
|
+
private: string;
|
156
|
+
public: string;
|
157
|
+
};
|
158
|
+
};
|
129
159
|
}
|
130
160
|
export interface SLORequestParams {
|
131
161
|
nameId: string;
|
@@ -0,0 +1,22 @@
|
|
1
|
+
import { MigrationInterface, QueryRunner } from "typeorm";
|
2
|
+
|
3
|
+
export class msNocascade1653746497237 implements MigrationInterface {
|
4
|
+
name = 'msNocascade1653746497237'
|
5
|
+
|
6
|
+
public async up(queryRunner: QueryRunner): Promise<void> {
|
7
|
+
await queryRunner.query(`CREATE TABLE \`jackson_store\` (\`key\` varchar(250) NOT NULL, \`value\` text NOT NULL, \`iv\` varchar(64) NULL, \`tag\` varchar(64) NULL, \`createdAt\` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, \`modifiedAt\` timestamp NULL, PRIMARY KEY (\`key\`)) ENGINE=InnoDB`);
|
8
|
+
await queryRunner.query(`CREATE TABLE \`jackson_ttl\` (\`key\` varchar(250) NOT NULL, \`expiresAt\` bigint NOT NULL, INDEX \`_jackson_ttl_expires_at\` (\`expiresAt\`), PRIMARY KEY (\`key\`)) ENGINE=InnoDB`);
|
9
|
+
await queryRunner.query(`CREATE TABLE \`jackson_index\` (\`id\` int NOT NULL AUTO_INCREMENT, \`key\` varchar(250) NOT NULL, \`storeKey\` varchar(250) NOT NULL, INDEX \`_jackson_index_key\` (\`key\`), INDEX \`_jackson_index_store\` (\`storeKey\`), INDEX \`_jackson_index_key_store\` (\`key\`, \`storeKey\`), PRIMARY KEY (\`id\`)) ENGINE=InnoDB`);
|
10
|
+
}
|
11
|
+
|
12
|
+
public async down(queryRunner: QueryRunner): Promise<void> {
|
13
|
+
await queryRunner.query(`DROP INDEX \`_jackson_index_key_store\` ON \`jackson_index\``);
|
14
|
+
await queryRunner.query(`DROP INDEX \`_jackson_index_store\` ON \`jackson_index\``);
|
15
|
+
await queryRunner.query(`DROP INDEX \`_jackson_index_key\` ON \`jackson_index\``);
|
16
|
+
await queryRunner.query(`DROP TABLE \`jackson_index\``);
|
17
|
+
await queryRunner.query(`DROP INDEX \`_jackson_ttl_expires_at\` ON \`jackson_ttl\``);
|
18
|
+
await queryRunner.query(`DROP TABLE \`jackson_ttl\``);
|
19
|
+
await queryRunner.query(`DROP TABLE \`jackson_store\``);
|
20
|
+
}
|
21
|
+
|
22
|
+
}
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@boxyhq/saml-jackson",
|
3
|
-
"version": "1.
|
3
|
+
"version": "1.1.1",
|
4
4
|
"description": "SAML Jackson library",
|
5
5
|
"keywords": [
|
6
6
|
"SAML 2.0"
|
@@ -20,9 +20,11 @@
|
|
20
20
|
"build": "tsc -p tsconfig.build.json",
|
21
21
|
"db:migration:generate:postgres": "ts-node --transpile-only ./node_modules/typeorm/cli.js migration:generate -d typeorm.ts migration/postgres/pg_${MIGRATION_NAME}",
|
22
22
|
"db:migration:generate:mysql": "cross-env DB_TYPE=mysql DB_URL=mysql://root:mysql@localhost:3307/mysql ts-node --transpile-only ./node_modules/typeorm/cli.js migration:generate -d typeorm.ts migration/mysql/ms_${MIGRATION_NAME}",
|
23
|
+
"db:migration:generate:planetscale": "cross-env DB_ENGINE=planetscale DB_URL=mysql://root:mysql@localhost:3307/mysql ts-node --transpile-only ./node_modules/typeorm/cli.js migration:generate -d typeorm.ts migration/mysql/ms_${MIGRATION_NAME}",
|
23
24
|
"db:migration:generate:mariadb": "cross-env DB_TYPE=mariadb DB_URL=mariadb://root@localhost:3306/mysql ts-node --transpile-only ./node_modules/typeorm/cli.js migration:generate -d typeorm.ts migration/mariadb/md_${MIGRATION_NAME}",
|
24
25
|
"db:migration:run:postgres": "ts-node --transpile-only ./node_modules/typeorm/cli.js migration:run -d typeorm.ts",
|
25
26
|
"db:migration:run:mysql": "cross-env DB_TYPE=mysql DB_URL=mysql://root:mysql@localhost:3307/mysql ts-node --transpile-only ./node_modules/typeorm/cli.js migration:run -d typeorm.ts",
|
27
|
+
"db:migration:run:planetscale": "cross-env DB_SSL=true DB_ENGINE=planetscale DB_URL=${PLANETSCALE_URL} ts-node --transpile-only ./node_modules/typeorm/cli.js migration:run -d typeorm.ts",
|
26
28
|
"db:migration:run:mariadb": "cross-env DB_TYPE=mariadb DB_URL=mariadb://root@localhost:3306/mysql ts-node --transpile-only ./node_modules/typeorm/cli.js migration:run -d typeorm.ts",
|
27
29
|
"prepublishOnly": "npm run build",
|
28
30
|
"test": "tap --ts --timeout=100 --coverage test/**/*.test.ts",
|
@@ -36,12 +38,13 @@
|
|
36
38
|
"statements": 70
|
37
39
|
},
|
38
40
|
"dependencies": {
|
39
|
-
"@boxyhq/saml20": "1.0.
|
41
|
+
"@boxyhq/saml20": "1.0.4",
|
40
42
|
"@opentelemetry/api-metrics": "0.27.0",
|
41
43
|
"@opentelemetry/api": "1.0.4",
|
42
44
|
"@peculiar/webcrypto": "1.4.0",
|
43
|
-
"@peculiar/x509": "1.
|
44
|
-
"
|
45
|
+
"@peculiar/x509": "1.8.0",
|
46
|
+
"jose": "4.8.3",
|
47
|
+
"mongodb": "4.8.0",
|
45
48
|
"mysql2": "2.3.3",
|
46
49
|
"pg": "8.7.3",
|
47
50
|
"redis": "4.0.6",
|
@@ -52,18 +55,18 @@
|
|
52
55
|
"xmlbuilder": "15.1.1"
|
53
56
|
},
|
54
57
|
"devDependencies": {
|
55
|
-
"@types/node": "18.
|
56
|
-
"@types/sinon": "10.0.
|
58
|
+
"@types/node": "18.6.1",
|
59
|
+
"@types/sinon": "10.0.13",
|
57
60
|
"@types/tap": "15.0.7",
|
58
|
-
"@typescript-eslint/eslint-plugin": "5.30.
|
59
|
-
"@typescript-eslint/parser": "5.30.
|
61
|
+
"@typescript-eslint/eslint-plugin": "5.30.7",
|
62
|
+
"@typescript-eslint/parser": "5.30.7",
|
60
63
|
"cross-env": "7.0.3",
|
61
|
-
"eslint": "8.
|
64
|
+
"eslint": "8.20.0",
|
62
65
|
"eslint-config-prettier": "8.5.0",
|
63
66
|
"prettier": "2.7.1",
|
64
67
|
"sinon": "14.0.0",
|
65
68
|
"tap": "16.3.0",
|
66
|
-
"ts-node": "10.
|
69
|
+
"ts-node": "10.9.1",
|
67
70
|
"tsconfig-paths": "4.0.0",
|
68
71
|
"typescript": "4.7.4"
|
69
72
|
},
|