@boxyhq/saml-jackson 0.2.3-beta.235 → 0.2.3-beta.240
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.d.ts +32 -0
- package/dist/controller/api.js +193 -0
- package/dist/controller/error.d.ts +5 -0
- package/dist/controller/error.js +12 -0
- package/dist/controller/oauth/allowed.d.ts +1 -0
- package/dist/controller/oauth/allowed.js +17 -0
- package/dist/controller/oauth/code-verifier.d.ts +2 -0
- package/dist/controller/oauth/code-verifier.js +15 -0
- package/dist/controller/oauth/redirect.d.ts +1 -0
- package/dist/controller/oauth/redirect.js +11 -0
- package/dist/controller/oauth.d.ts +23 -0
- package/dist/controller/oauth.js +263 -0
- package/dist/controller/utils.d.ts +6 -0
- package/dist/controller/utils.js +17 -0
- package/dist/db/db.d.ts +15 -0
- package/dist/db/db.js +107 -0
- package/dist/db/encrypter.d.ts +3 -0
- package/dist/db/encrypter.js +29 -0
- package/dist/db/mem.d.ts +20 -0
- package/dist/db/mem.js +128 -0
- package/dist/db/mongo.d.ts +17 -0
- package/dist/db/mongo.js +106 -0
- package/dist/db/redis.d.ts +15 -0
- package/dist/db/redis.js +107 -0
- package/dist/db/sql/entity/JacksonIndex.d.ts +7 -0
- package/dist/db/sql/entity/JacksonIndex.js +41 -0
- package/dist/db/sql/entity/JacksonStore.d.ts +6 -0
- package/dist/db/sql/entity/JacksonStore.js +42 -0
- package/dist/db/sql/entity/JacksonTTL.d.ts +4 -0
- package/dist/db/sql/entity/JacksonTTL.js +29 -0
- package/dist/db/sql/sql.d.ts +20 -0
- package/dist/db/sql/sql.js +174 -0
- package/dist/db/store.d.ts +5 -0
- package/dist/db/store.js +68 -0
- package/dist/db/utils.d.ts +7 -0
- package/dist/db/utils.js +29 -0
- package/dist/env.d.ts +22 -0
- package/dist/env.js +35 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +80 -0
- package/dist/jackson.d.ts +1 -0
- package/dist/jackson.js +153 -0
- package/dist/read-config.d.ts +3 -0
- package/dist/read-config.js +50 -0
- package/dist/saml/claims.d.ts +6 -0
- package/dist/saml/claims.js +35 -0
- package/dist/saml/saml.d.ts +11 -0
- package/dist/saml/saml.js +200 -0
- package/dist/saml/x509.d.ts +7 -0
- package/dist/saml/x509.js +69 -0
- package/dist/typings.d.ts +137 -0
- package/dist/typings.js +2 -0
- package/package.json +2 -1
@@ -0,0 +1,20 @@
|
|
1
|
+
import { DatabaseDriver, DatabaseOption, Index, Encrypted } from '../../typings';
|
2
|
+
declare class Sql implements DatabaseDriver {
|
3
|
+
private options;
|
4
|
+
private connection;
|
5
|
+
private storeRepository;
|
6
|
+
private indexRepository;
|
7
|
+
private ttlRepository;
|
8
|
+
private ttlCleanup;
|
9
|
+
private timerId;
|
10
|
+
constructor(options: DatabaseOption);
|
11
|
+
init(): Promise<Sql>;
|
12
|
+
get(namespace: string, key: string): Promise<any>;
|
13
|
+
getByIndex(namespace: string, idx: Index): Promise<any>;
|
14
|
+
put(namespace: string, key: string, val: Encrypted, ttl?: number, ...indexes: any[]): Promise<void>;
|
15
|
+
delete(namespace: string, key: string): Promise<any>;
|
16
|
+
}
|
17
|
+
declare const _default: {
|
18
|
+
new: (options: DatabaseOption) => Promise<Sql>;
|
19
|
+
};
|
20
|
+
export default _default;
|
@@ -0,0 +1,174 @@
|
|
1
|
+
"use strict";
|
2
|
+
/*eslint no-constant-condition: ["error", { "checkLoops": false }]*/
|
3
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
4
|
+
if (k2 === undefined) k2 = k;
|
5
|
+
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
6
|
+
}) : (function(o, m, k, k2) {
|
7
|
+
if (k2 === undefined) k2 = k;
|
8
|
+
o[k2] = m[k];
|
9
|
+
}));
|
10
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
11
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
12
|
+
}) : function(o, v) {
|
13
|
+
o["default"] = v;
|
14
|
+
});
|
15
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
16
|
+
if (mod && mod.__esModule) return mod;
|
17
|
+
var result = {};
|
18
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
19
|
+
__setModuleDefault(result, mod);
|
20
|
+
return result;
|
21
|
+
};
|
22
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
23
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
24
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
25
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
26
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
27
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
28
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
29
|
+
});
|
30
|
+
};
|
31
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
32
|
+
require('reflect-metadata');
|
33
|
+
const typeorm_1 = require("typeorm");
|
34
|
+
const dbutils = __importStar(require("../utils"));
|
35
|
+
const JacksonStore_1 = require("./entity/JacksonStore");
|
36
|
+
const JacksonIndex_1 = require("./entity/JacksonIndex");
|
37
|
+
const JacksonTTL_1 = require("./entity/JacksonTTL");
|
38
|
+
class Sql {
|
39
|
+
constructor(options) {
|
40
|
+
this.options = options;
|
41
|
+
}
|
42
|
+
init() {
|
43
|
+
return __awaiter(this, void 0, void 0, function* () {
|
44
|
+
while (true) {
|
45
|
+
try {
|
46
|
+
this.connection = yield (0, typeorm_1.createConnection)({
|
47
|
+
name: this.options.type + Math.floor(Math.random() * 100000),
|
48
|
+
type: this.options.type,
|
49
|
+
url: this.options.url,
|
50
|
+
synchronize: true,
|
51
|
+
migrationsTableName: '_jackson_migrations',
|
52
|
+
logging: ['error'],
|
53
|
+
entities: [JacksonStore_1.JacksonStore, JacksonIndex_1.JacksonIndex, JacksonTTL_1.JacksonTTL],
|
54
|
+
});
|
55
|
+
break;
|
56
|
+
}
|
57
|
+
catch (err) {
|
58
|
+
console.error(`error connecting to ${this.options.type} db: ${err}`);
|
59
|
+
yield dbutils.sleep(1000);
|
60
|
+
continue;
|
61
|
+
}
|
62
|
+
}
|
63
|
+
this.storeRepository = this.connection.getRepository(JacksonStore_1.JacksonStore);
|
64
|
+
this.indexRepository = this.connection.getRepository(JacksonIndex_1.JacksonIndex);
|
65
|
+
this.ttlRepository = this.connection.getRepository(JacksonTTL_1.JacksonTTL);
|
66
|
+
if (this.options.ttl && this.options.cleanupLimit) {
|
67
|
+
this.ttlCleanup = () => __awaiter(this, void 0, void 0, function* () {
|
68
|
+
const now = Date.now();
|
69
|
+
while (true) {
|
70
|
+
const ids = yield this.ttlRepository
|
71
|
+
.createQueryBuilder('jackson_ttl')
|
72
|
+
.limit(this.options.cleanupLimit)
|
73
|
+
.where('jackson_ttl.expiresAt <= :expiresAt', {
|
74
|
+
expiresAt: now,
|
75
|
+
})
|
76
|
+
.getMany();
|
77
|
+
if (ids.length <= 0) {
|
78
|
+
break;
|
79
|
+
}
|
80
|
+
const delIds = ids.map((id) => {
|
81
|
+
return id.key;
|
82
|
+
});
|
83
|
+
yield this.storeRepository.remove(ids);
|
84
|
+
yield this.ttlRepository.delete(delIds);
|
85
|
+
}
|
86
|
+
this.timerId = setTimeout(this.ttlCleanup, this.options.ttl * 1000);
|
87
|
+
});
|
88
|
+
this.timerId = setTimeout(this.ttlCleanup, this.options.ttl * 1000);
|
89
|
+
}
|
90
|
+
else {
|
91
|
+
console.log('Warning: ttl cleanup not enabled, set both "ttl" and "cleanupLimit" options to enable it!');
|
92
|
+
}
|
93
|
+
return this;
|
94
|
+
});
|
95
|
+
}
|
96
|
+
get(namespace, key) {
|
97
|
+
return __awaiter(this, void 0, void 0, function* () {
|
98
|
+
let res = yield this.storeRepository.findOne({
|
99
|
+
key: dbutils.key(namespace, key),
|
100
|
+
});
|
101
|
+
if (res && res.value) {
|
102
|
+
return {
|
103
|
+
value: res.value,
|
104
|
+
iv: res.iv,
|
105
|
+
tag: res.tag,
|
106
|
+
};
|
107
|
+
}
|
108
|
+
return null;
|
109
|
+
});
|
110
|
+
}
|
111
|
+
getByIndex(namespace, idx) {
|
112
|
+
return __awaiter(this, void 0, void 0, function* () {
|
113
|
+
const res = yield this.indexRepository.find({
|
114
|
+
key: dbutils.keyForIndex(namespace, idx),
|
115
|
+
});
|
116
|
+
const ret = [];
|
117
|
+
if (res) {
|
118
|
+
res.forEach((r) => {
|
119
|
+
ret.push({
|
120
|
+
value: r.store.value,
|
121
|
+
iv: r.store.iv,
|
122
|
+
tag: r.store.tag,
|
123
|
+
});
|
124
|
+
});
|
125
|
+
}
|
126
|
+
return ret;
|
127
|
+
});
|
128
|
+
}
|
129
|
+
put(namespace, key, val, ttl = 0, ...indexes) {
|
130
|
+
return __awaiter(this, void 0, void 0, function* () {
|
131
|
+
yield this.connection.transaction((transactionalEntityManager) => __awaiter(this, void 0, void 0, function* () {
|
132
|
+
const dbKey = dbutils.key(namespace, key);
|
133
|
+
const store = new JacksonStore_1.JacksonStore();
|
134
|
+
store.key = dbKey;
|
135
|
+
store.value = val.value;
|
136
|
+
store.iv = val.iv;
|
137
|
+
store.tag = val.tag;
|
138
|
+
yield transactionalEntityManager.save(store);
|
139
|
+
if (ttl) {
|
140
|
+
const ttlRec = new JacksonTTL_1.JacksonTTL();
|
141
|
+
ttlRec.key = dbKey;
|
142
|
+
ttlRec.expiresAt = Date.now() + ttl * 1000;
|
143
|
+
yield transactionalEntityManager.save(ttlRec);
|
144
|
+
}
|
145
|
+
// no ttl support for secondary indexes
|
146
|
+
for (const idx of indexes || []) {
|
147
|
+
const key = dbutils.keyForIndex(namespace, idx);
|
148
|
+
const rec = yield this.indexRepository.findOne({
|
149
|
+
key,
|
150
|
+
storeKey: store.key,
|
151
|
+
});
|
152
|
+
if (!rec) {
|
153
|
+
const ji = new JacksonIndex_1.JacksonIndex();
|
154
|
+
ji.key = key;
|
155
|
+
ji.store = store;
|
156
|
+
yield transactionalEntityManager.save(ji);
|
157
|
+
}
|
158
|
+
}
|
159
|
+
}));
|
160
|
+
});
|
161
|
+
}
|
162
|
+
delete(namespace, key) {
|
163
|
+
return __awaiter(this, void 0, void 0, function* () {
|
164
|
+
return yield this.storeRepository.remove({
|
165
|
+
key: dbutils.key(namespace, key),
|
166
|
+
});
|
167
|
+
});
|
168
|
+
}
|
169
|
+
}
|
170
|
+
exports.default = {
|
171
|
+
new: (options) => __awaiter(void 0, void 0, void 0, function* () {
|
172
|
+
return yield new Sql(options).init();
|
173
|
+
}),
|
174
|
+
};
|
package/dist/db/store.js
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
3
|
+
if (k2 === undefined) k2 = k;
|
4
|
+
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
5
|
+
}) : (function(o, m, k, k2) {
|
6
|
+
if (k2 === undefined) k2 = k;
|
7
|
+
o[k2] = m[k];
|
8
|
+
}));
|
9
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
10
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
11
|
+
}) : function(o, v) {
|
12
|
+
o["default"] = v;
|
13
|
+
});
|
14
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
15
|
+
if (mod && mod.__esModule) return mod;
|
16
|
+
var result = {};
|
17
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
18
|
+
__setModuleDefault(result, mod);
|
19
|
+
return result;
|
20
|
+
};
|
21
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
22
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
23
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
24
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
25
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
26
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
27
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
28
|
+
});
|
29
|
+
};
|
30
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
31
|
+
const dbutils = __importStar(require("./utils"));
|
32
|
+
class Store {
|
33
|
+
constructor(namespace, db, ttl = 0) {
|
34
|
+
this.namespace = namespace;
|
35
|
+
this.db = db;
|
36
|
+
this.ttl = ttl;
|
37
|
+
}
|
38
|
+
get(key) {
|
39
|
+
return __awaiter(this, void 0, void 0, function* () {
|
40
|
+
return yield this.db.get(this.namespace, dbutils.keyDigest(key));
|
41
|
+
});
|
42
|
+
}
|
43
|
+
getByIndex(idx) {
|
44
|
+
return __awaiter(this, void 0, void 0, function* () {
|
45
|
+
idx.value = dbutils.keyDigest(idx.value);
|
46
|
+
return yield this.db.getByIndex(this.namespace, idx);
|
47
|
+
});
|
48
|
+
}
|
49
|
+
put(key, val, ...indexes) {
|
50
|
+
return __awaiter(this, void 0, void 0, function* () {
|
51
|
+
indexes = (indexes || []).map((idx) => {
|
52
|
+
idx.value = dbutils.keyDigest(idx.value);
|
53
|
+
return idx;
|
54
|
+
});
|
55
|
+
return yield this.db.put(this.namespace, dbutils.keyDigest(key), val, this.ttl, ...indexes);
|
56
|
+
});
|
57
|
+
}
|
58
|
+
delete(key) {
|
59
|
+
return __awaiter(this, void 0, void 0, function* () {
|
60
|
+
return yield this.db.delete(this.namespace, dbutils.keyDigest(key));
|
61
|
+
});
|
62
|
+
}
|
63
|
+
}
|
64
|
+
exports.default = {
|
65
|
+
new: (namespace, db, ttl = 0) => {
|
66
|
+
return new Store(namespace, db, ttl);
|
67
|
+
},
|
68
|
+
};
|
@@ -0,0 +1,7 @@
|
|
1
|
+
import { Index } from '../typings';
|
2
|
+
export declare const key: (namespace: string, k: string) => string;
|
3
|
+
export declare const keyForIndex: (namespace: string, idx: Index) => string;
|
4
|
+
export declare const keyDigest: (k: string) => string;
|
5
|
+
export declare const keyFromParts: (...parts: string[]) => string;
|
6
|
+
export declare const sleep: (ms: number) => Promise<void>;
|
7
|
+
export declare const indexPrefix = "_index";
|
package/dist/db/utils.js
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
4
|
+
};
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
6
|
+
exports.indexPrefix = exports.sleep = exports.keyFromParts = exports.keyDigest = exports.keyForIndex = exports.key = void 0;
|
7
|
+
const ripemd160_1 = __importDefault(require("ripemd160"));
|
8
|
+
const key = (namespace, k) => {
|
9
|
+
return namespace + ':' + k;
|
10
|
+
};
|
11
|
+
exports.key = key;
|
12
|
+
const keyForIndex = (namespace, idx) => {
|
13
|
+
return (0, exports.key)((0, exports.key)(namespace, idx.name), idx.value);
|
14
|
+
};
|
15
|
+
exports.keyForIndex = keyForIndex;
|
16
|
+
const keyDigest = (k) => {
|
17
|
+
return new ripemd160_1.default().update(k).digest('hex');
|
18
|
+
};
|
19
|
+
exports.keyDigest = keyDigest;
|
20
|
+
const keyFromParts = (...parts) => {
|
21
|
+
// TODO: pick a better strategy, keys can collide now
|
22
|
+
return parts.join(':');
|
23
|
+
};
|
24
|
+
exports.keyFromParts = keyFromParts;
|
25
|
+
const sleep = (ms) => {
|
26
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
27
|
+
};
|
28
|
+
exports.sleep = sleep;
|
29
|
+
exports.indexPrefix = '_index';
|
package/dist/env.d.ts
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
declare const env: {
|
2
|
+
hostUrl: string;
|
3
|
+
hostPort: number;
|
4
|
+
externalUrl: string;
|
5
|
+
samlPath: string;
|
6
|
+
samlAudience: string;
|
7
|
+
preLoadedConfig: string | undefined;
|
8
|
+
internalHostUrl: string;
|
9
|
+
internalHostPort: number;
|
10
|
+
apiKeys: string[];
|
11
|
+
idpEnabled: string | undefined;
|
12
|
+
db: {
|
13
|
+
engine: string | undefined;
|
14
|
+
url: string | undefined;
|
15
|
+
type: string | undefined;
|
16
|
+
ttl: string | undefined;
|
17
|
+
encryptionKey: string | undefined;
|
18
|
+
cleanupLimit: string | undefined;
|
19
|
+
};
|
20
|
+
useInternalServer: boolean;
|
21
|
+
};
|
22
|
+
export default env;
|
package/dist/env.js
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
const hostUrl = process.env.HOST_URL || 'localhost';
|
4
|
+
const hostPort = +(process.env.HOST_PORT || '5000');
|
5
|
+
const externalUrl = process.env.EXTERNAL_URL || 'http://' + hostUrl + ':' + hostPort;
|
6
|
+
const samlPath = process.env.SAML_PATH || '/oauth/saml';
|
7
|
+
const internalHostUrl = process.env.INTERNAL_HOST_URL || 'localhost';
|
8
|
+
const internalHostPort = +(process.env.INTERNAL_HOST_PORT || '6000');
|
9
|
+
const apiKeys = (process.env.JACKSON_API_KEYS || '').split(',');
|
10
|
+
const samlAudience = process.env.SAML_AUDIENCE || 'https://saml.boxyhq.com';
|
11
|
+
const preLoadedConfig = process.env.PRE_LOADED_CONFIG;
|
12
|
+
const idpEnabled = process.env.IDP_ENABLED;
|
13
|
+
const db = {
|
14
|
+
engine: process.env.DB_ENGINE,
|
15
|
+
url: process.env.DB_URL,
|
16
|
+
type: process.env.DB_TYPE,
|
17
|
+
ttl: process.env.DB_TTL,
|
18
|
+
encryptionKey: process.env.DB_ENCRYPTION_KEY,
|
19
|
+
cleanupLimit: process.env.DB_CLEANUP_LIMIT,
|
20
|
+
};
|
21
|
+
const env = {
|
22
|
+
hostUrl,
|
23
|
+
hostPort,
|
24
|
+
externalUrl,
|
25
|
+
samlPath,
|
26
|
+
samlAudience,
|
27
|
+
preLoadedConfig,
|
28
|
+
internalHostUrl,
|
29
|
+
internalHostPort,
|
30
|
+
apiKeys,
|
31
|
+
idpEnabled,
|
32
|
+
db,
|
33
|
+
useInternalServer: !(hostUrl === internalHostUrl && hostPort === internalHostPort),
|
34
|
+
};
|
35
|
+
exports.default = env;
|
package/dist/index.d.ts
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
import { JacksonOption } from './typings';
|
2
|
+
import { SAMLConfig } from './controller/api';
|
3
|
+
import { OAuthController } from './controller/oauth';
|
4
|
+
declare const controllers: (opts: JacksonOption) => Promise<{
|
5
|
+
apiController: SAMLConfig;
|
6
|
+
oauthController: OAuthController;
|
7
|
+
}>;
|
8
|
+
export default controllers;
|
9
|
+
export * from './typings';
|
package/dist/index.js
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
3
|
+
if (k2 === undefined) k2 = k;
|
4
|
+
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
5
|
+
}) : (function(o, m, k, k2) {
|
6
|
+
if (k2 === undefined) k2 = k;
|
7
|
+
o[k2] = m[k];
|
8
|
+
}));
|
9
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
10
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
11
|
+
};
|
12
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
13
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
14
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
15
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
16
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
17
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
18
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
19
|
+
});
|
20
|
+
};
|
21
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
22
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
23
|
+
};
|
24
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
25
|
+
const api_1 = require("./controller/api");
|
26
|
+
const oauth_1 = require("./controller/oauth");
|
27
|
+
const db_1 = __importDefault(require("./db/db"));
|
28
|
+
const read_config_1 = __importDefault(require("./read-config"));
|
29
|
+
const defaultOpts = (opts) => {
|
30
|
+
const newOpts = Object.assign({}, opts);
|
31
|
+
if (!newOpts.externalUrl) {
|
32
|
+
throw new Error('externalUrl is required');
|
33
|
+
}
|
34
|
+
if (!newOpts.samlPath) {
|
35
|
+
throw new Error('samlPath is required');
|
36
|
+
}
|
37
|
+
newOpts.samlAudience = newOpts.samlAudience || 'https://saml.boxyhq.com';
|
38
|
+
newOpts.preLoadedConfig = newOpts.preLoadedConfig || ''; // path to folder containing static SAML config that will be preloaded. This is useful for self-hosted deployments that only have to support a single tenant (or small number of known tenants).
|
39
|
+
newOpts.idpEnabled = newOpts.idpEnabled === true;
|
40
|
+
newOpts.db = newOpts.db || {};
|
41
|
+
newOpts.db.engine = newOpts.db.engine || 'sql';
|
42
|
+
newOpts.db.url =
|
43
|
+
newOpts.db.url || 'postgresql://postgres:postgres@localhost:5432/postgres';
|
44
|
+
newOpts.db.type = newOpts.db.type || 'postgres'; // Only needed if DB_ENGINE is sql.
|
45
|
+
newOpts.db.ttl = (newOpts.db.ttl || 300) * 1; // TTL for the code, session and token stores (in seconds)
|
46
|
+
newOpts.db.cleanupLimit = (newOpts.db.cleanupLimit || 1000) * 1; // Limit cleanup of TTL entries to this many items at a time
|
47
|
+
return newOpts;
|
48
|
+
};
|
49
|
+
const controllers = (opts) => __awaiter(void 0, void 0, void 0, function* () {
|
50
|
+
opts = defaultOpts(opts);
|
51
|
+
const db = yield db_1.default.new(opts.db);
|
52
|
+
const configStore = db.store('saml:config');
|
53
|
+
const sessionStore = db.store('oauth:session', opts.db.ttl);
|
54
|
+
const codeStore = db.store('oauth:code', opts.db.ttl);
|
55
|
+
const tokenStore = db.store('oauth:token', opts.db.ttl);
|
56
|
+
const apiController = new api_1.SAMLConfig({ configStore });
|
57
|
+
const oauthController = new oauth_1.OAuthController({
|
58
|
+
configStore,
|
59
|
+
sessionStore,
|
60
|
+
codeStore,
|
61
|
+
tokenStore,
|
62
|
+
opts,
|
63
|
+
});
|
64
|
+
// write pre-loaded config if present
|
65
|
+
if (opts.preLoadedConfig && opts.preLoadedConfig.length > 0) {
|
66
|
+
const configs = yield (0, read_config_1.default)(opts.preLoadedConfig);
|
67
|
+
for (const config of configs) {
|
68
|
+
yield apiController.config(config);
|
69
|
+
console.log(`loaded config for tenant "${config.tenant}" and product "${config.product}"`);
|
70
|
+
}
|
71
|
+
}
|
72
|
+
const type = opts.db.engine === 'sql' && opts.db.type ? ' Type: ' + opts.db.type : '';
|
73
|
+
console.log(`Using engine: ${opts.db.engine}.${type}`);
|
74
|
+
return {
|
75
|
+
apiController,
|
76
|
+
oauthController,
|
77
|
+
};
|
78
|
+
});
|
79
|
+
exports.default = controllers;
|
80
|
+
__exportStar(require("./typings"), exports);
|
@@ -0,0 +1 @@
|
|
1
|
+
export {};
|
package/dist/jackson.js
ADDED
@@ -0,0 +1,153 @@
|
|
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
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
13
|
+
};
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
15
|
+
const cors_1 = __importDefault(require("cors"));
|
16
|
+
const express_1 = __importDefault(require("express"));
|
17
|
+
const utils_1 = require("./controller/utils");
|
18
|
+
const env_1 = __importDefault(require("./env"));
|
19
|
+
const index_1 = __importDefault(require("./index"));
|
20
|
+
let apiController;
|
21
|
+
let oauthController;
|
22
|
+
const oauthPath = '/oauth';
|
23
|
+
const apiPath = '/api/v1/saml';
|
24
|
+
const app = (0, express_1.default)();
|
25
|
+
app.use(express_1.default.json());
|
26
|
+
app.use(express_1.default.urlencoded({ extended: true }));
|
27
|
+
app.get(oauthPath + '/authorize', (req, res) => __awaiter(void 0, void 0, void 0, function* () {
|
28
|
+
try {
|
29
|
+
// @ts-ignore
|
30
|
+
const { redirect_url } = yield oauthController.authorize(req.query);
|
31
|
+
res.redirect(redirect_url);
|
32
|
+
}
|
33
|
+
catch (err) {
|
34
|
+
const { message, statusCode = 500 } = err;
|
35
|
+
res.status(statusCode).send(message);
|
36
|
+
}
|
37
|
+
}));
|
38
|
+
app.post(env_1.default.samlPath, (req, res) => __awaiter(void 0, void 0, void 0, function* () {
|
39
|
+
try {
|
40
|
+
const { redirect_url } = yield oauthController.samlResponse(req.body);
|
41
|
+
res.redirect(redirect_url);
|
42
|
+
}
|
43
|
+
catch (err) {
|
44
|
+
const { message, statusCode = 500 } = err;
|
45
|
+
res.status(statusCode).send(message);
|
46
|
+
}
|
47
|
+
}));
|
48
|
+
app.post(oauthPath + '/token', (0, cors_1.default)(), (req, res) => __awaiter(void 0, void 0, void 0, function* () {
|
49
|
+
try {
|
50
|
+
const result = yield oauthController.token(req.body);
|
51
|
+
res.json(result);
|
52
|
+
}
|
53
|
+
catch (err) {
|
54
|
+
const { message, statusCode = 500 } = err;
|
55
|
+
res.status(statusCode).send(message);
|
56
|
+
}
|
57
|
+
}));
|
58
|
+
app.get(oauthPath + '/userinfo', (req, res) => __awaiter(void 0, void 0, void 0, function* () {
|
59
|
+
try {
|
60
|
+
let token = (0, utils_1.extractAuthToken)(req);
|
61
|
+
// check for query param
|
62
|
+
if (!token) {
|
63
|
+
// @ts-ignore
|
64
|
+
token = req.query.access_token;
|
65
|
+
}
|
66
|
+
if (!token) {
|
67
|
+
return res.status(401).json({ message: 'Unauthorized' });
|
68
|
+
}
|
69
|
+
const profile = yield oauthController.userInfo(token);
|
70
|
+
res.json(profile);
|
71
|
+
}
|
72
|
+
catch (err) {
|
73
|
+
const { message, statusCode = 500 } = err;
|
74
|
+
res.status(statusCode).json({ message });
|
75
|
+
}
|
76
|
+
}));
|
77
|
+
const server = app.listen(env_1.default.hostPort, () => __awaiter(void 0, void 0, void 0, function* () {
|
78
|
+
console.log(`🚀 The path of the righteous server: http://${env_1.default.hostUrl}:${env_1.default.hostPort}`);
|
79
|
+
// @ts-ignore
|
80
|
+
const ctrlrModule = yield (0, index_1.default)(env_1.default);
|
81
|
+
apiController = ctrlrModule.apiController;
|
82
|
+
oauthController = ctrlrModule.oauthController;
|
83
|
+
}));
|
84
|
+
// Internal routes, recommended not to expose this to the public interface though it would be guarded by API key(s)
|
85
|
+
let internalApp = app;
|
86
|
+
if (env_1.default.useInternalServer) {
|
87
|
+
internalApp = (0, express_1.default)();
|
88
|
+
internalApp.use(express_1.default.json());
|
89
|
+
internalApp.use(express_1.default.urlencoded({ extended: true }));
|
90
|
+
}
|
91
|
+
const validateApiKey = (token) => {
|
92
|
+
return env_1.default.apiKeys.includes(token);
|
93
|
+
};
|
94
|
+
internalApp.post(apiPath + '/config', (req, res) => __awaiter(void 0, void 0, void 0, function* () {
|
95
|
+
try {
|
96
|
+
const apiKey = (0, utils_1.extractAuthToken)(req);
|
97
|
+
if (!validateApiKey(apiKey)) {
|
98
|
+
res.status(401).send('Unauthorized');
|
99
|
+
return;
|
100
|
+
}
|
101
|
+
res.json(yield apiController.config(req.body));
|
102
|
+
}
|
103
|
+
catch (err) {
|
104
|
+
const { message } = err;
|
105
|
+
res.status(500).json({
|
106
|
+
error: message,
|
107
|
+
});
|
108
|
+
}
|
109
|
+
}));
|
110
|
+
internalApp.get(apiPath + '/config', (req, res) => __awaiter(void 0, void 0, void 0, function* () {
|
111
|
+
try {
|
112
|
+
const apiKey = (0, utils_1.extractAuthToken)(req);
|
113
|
+
if (!validateApiKey(apiKey)) {
|
114
|
+
res.status(401).send('Unauthorized');
|
115
|
+
return;
|
116
|
+
}
|
117
|
+
// @ts-ignore
|
118
|
+
res.json(yield apiController.getConfig(req.query));
|
119
|
+
}
|
120
|
+
catch (err) {
|
121
|
+
const { message } = err;
|
122
|
+
res.status(500).json({
|
123
|
+
error: message,
|
124
|
+
});
|
125
|
+
}
|
126
|
+
}));
|
127
|
+
internalApp.delete(apiPath + '/config', (req, res) => __awaiter(void 0, void 0, void 0, function* () {
|
128
|
+
try {
|
129
|
+
const apiKey = (0, utils_1.extractAuthToken)(req);
|
130
|
+
if (!validateApiKey(apiKey)) {
|
131
|
+
res.status(401).send('Unauthorized');
|
132
|
+
return;
|
133
|
+
}
|
134
|
+
yield apiController.deleteConfig(req.body);
|
135
|
+
res.status(200).end();
|
136
|
+
}
|
137
|
+
catch (err) {
|
138
|
+
const { message } = err;
|
139
|
+
res.status(500).json({
|
140
|
+
error: message,
|
141
|
+
});
|
142
|
+
}
|
143
|
+
}));
|
144
|
+
let internalServer = server;
|
145
|
+
if (env_1.default.useInternalServer) {
|
146
|
+
internalServer = internalApp.listen(env_1.default.internalHostPort, () => __awaiter(void 0, void 0, void 0, function* () {
|
147
|
+
console.log(`🚀 The path of the righteous internal server: http://${env_1.default.internalHostUrl}:${env_1.default.internalHostPort}`);
|
148
|
+
}));
|
149
|
+
}
|
150
|
+
module.exports = {
|
151
|
+
server,
|
152
|
+
internalServer,
|
153
|
+
};
|
@@ -0,0 +1,50 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
3
|
+
if (k2 === undefined) k2 = k;
|
4
|
+
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
5
|
+
}) : (function(o, m, k, k2) {
|
6
|
+
if (k2 === undefined) k2 = k;
|
7
|
+
o[k2] = m[k];
|
8
|
+
}));
|
9
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
10
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
11
|
+
}) : function(o, v) {
|
12
|
+
o["default"] = v;
|
13
|
+
});
|
14
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
15
|
+
if (mod && mod.__esModule) return mod;
|
16
|
+
var result = {};
|
17
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
18
|
+
__setModuleDefault(result, mod);
|
19
|
+
return result;
|
20
|
+
};
|
21
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
22
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
23
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
24
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
25
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
26
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
27
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
28
|
+
});
|
29
|
+
};
|
30
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
31
|
+
const fs = __importStar(require("fs"));
|
32
|
+
const path = __importStar(require("path"));
|
33
|
+
const readConfig = (preLoadedConfig) => __awaiter(void 0, void 0, void 0, function* () {
|
34
|
+
if (preLoadedConfig.startsWith('./')) {
|
35
|
+
preLoadedConfig = path.resolve(process.cwd(), preLoadedConfig);
|
36
|
+
}
|
37
|
+
const files = yield fs.promises.readdir(preLoadedConfig);
|
38
|
+
const configs = [];
|
39
|
+
for (const idx in files) {
|
40
|
+
const file = files[idx];
|
41
|
+
if (file.endsWith('.js')) {
|
42
|
+
const config = require(path.join(preLoadedConfig, file));
|
43
|
+
const rawMetadata = yield fs.promises.readFile(path.join(preLoadedConfig, path.parse(file).name + '.xml'), 'utf8');
|
44
|
+
config.rawMetadata = rawMetadata;
|
45
|
+
configs.push(config);
|
46
|
+
}
|
47
|
+
}
|
48
|
+
return configs;
|
49
|
+
});
|
50
|
+
exports.default = readConfig;
|