@boxyhq/saml-jackson 0.2.3 → 0.3.0-beta.247

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. package/Dockerfile +9 -7
  2. package/README.md +1 -2
  3. package/dist/controller/api.d.ts +32 -0
  4. package/dist/controller/api.js +193 -0
  5. package/dist/controller/error.d.ts +5 -0
  6. package/dist/controller/error.js +12 -0
  7. package/dist/controller/oauth/allowed.d.ts +1 -0
  8. package/dist/controller/oauth/allowed.js +17 -0
  9. package/dist/controller/oauth/code-verifier.d.ts +2 -0
  10. package/dist/controller/oauth/code-verifier.js +15 -0
  11. package/dist/controller/oauth/redirect.d.ts +1 -0
  12. package/dist/controller/oauth/redirect.js +11 -0
  13. package/dist/controller/oauth.d.ts +23 -0
  14. package/dist/controller/oauth.js +263 -0
  15. package/dist/controller/utils.d.ts +6 -0
  16. package/dist/controller/utils.js +17 -0
  17. package/dist/db/db.d.ts +15 -0
  18. package/dist/db/db.js +107 -0
  19. package/dist/db/encrypter.d.ts +3 -0
  20. package/dist/db/encrypter.js +29 -0
  21. package/dist/db/mem.d.ts +20 -0
  22. package/dist/db/mem.js +128 -0
  23. package/dist/db/mongo.d.ts +17 -0
  24. package/dist/db/mongo.js +106 -0
  25. package/dist/db/redis.d.ts +15 -0
  26. package/dist/db/redis.js +107 -0
  27. package/dist/db/sql/entity/JacksonIndex.d.ts +7 -0
  28. package/dist/db/sql/entity/JacksonIndex.js +41 -0
  29. package/dist/db/sql/entity/JacksonStore.d.ts +6 -0
  30. package/dist/db/sql/entity/JacksonStore.js +42 -0
  31. package/dist/db/sql/entity/JacksonTTL.d.ts +4 -0
  32. package/dist/db/sql/entity/JacksonTTL.js +29 -0
  33. package/dist/db/sql/sql.d.ts +20 -0
  34. package/dist/db/sql/sql.js +174 -0
  35. package/dist/db/store.d.ts +5 -0
  36. package/dist/db/store.js +68 -0
  37. package/dist/db/utils.d.ts +7 -0
  38. package/dist/db/utils.js +29 -0
  39. package/dist/env.d.ts +22 -0
  40. package/dist/env.js +35 -0
  41. package/dist/index.d.ts +9 -0
  42. package/dist/index.js +82 -0
  43. package/dist/jackson.d.ts +1 -0
  44. package/dist/jackson.js +153 -0
  45. package/dist/read-config.d.ts +3 -0
  46. package/dist/read-config.js +50 -0
  47. package/dist/saml/claims.d.ts +6 -0
  48. package/dist/saml/claims.js +35 -0
  49. package/dist/saml/saml.d.ts +11 -0
  50. package/dist/saml/saml.js +200 -0
  51. package/dist/saml/x509.d.ts +7 -0
  52. package/dist/saml/x509.js +69 -0
  53. package/dist/typings.d.ts +137 -0
  54. package/dist/typings.js +2 -0
  55. package/package.json +41 -21
  56. package/.dockerignore +0 -2
  57. package/.eslintrc.js +0 -13
  58. package/.github/ISSUE_TEMPLATE/bug_report.md +0 -27
  59. package/.github/ISSUE_TEMPLATE/config.yml +0 -5
  60. package/.github/ISSUE_TEMPLATE/feature_request.md +0 -43
  61. package/.github/pull_request_template.md +0 -31
  62. package/.github/workflows/codesee-arch-diagram.yml +0 -81
  63. package/.github/workflows/main.yml +0 -123
  64. package/_dev/docker-compose.yml +0 -37
  65. package/map.js +0 -1
  66. package/prettier.config.js +0 -4
  67. package/src/controller/api.js +0 -167
  68. package/src/controller/error.js +0 -12
  69. package/src/controller/oauth/allowed.js +0 -19
  70. package/src/controller/oauth/code-verifier.js +0 -16
  71. package/src/controller/oauth/redirect.js +0 -18
  72. package/src/controller/oauth.js +0 -321
  73. package/src/controller/utils.js +0 -19
  74. package/src/db/db.js +0 -81
  75. package/src/db/db.test.js +0 -302
  76. package/src/db/encrypter.js +0 -36
  77. package/src/db/mem.js +0 -111
  78. package/src/db/mongo.js +0 -89
  79. package/src/db/redis.js +0 -88
  80. package/src/db/sql/entity/JacksonIndex.js +0 -42
  81. package/src/db/sql/entity/JacksonStore.js +0 -42
  82. package/src/db/sql/entity/JacksonTTL.js +0 -23
  83. package/src/db/sql/model/JacksonIndex.js +0 -9
  84. package/src/db/sql/model/JacksonStore.js +0 -10
  85. package/src/db/sql/model/JacksonTTL.js +0 -8
  86. package/src/db/sql/sql.js +0 -153
  87. package/src/db/store.js +0 -42
  88. package/src/db/utils.js +0 -30
  89. package/src/env.js +0 -39
  90. package/src/index.js +0 -67
  91. package/src/jackson.js +0 -161
  92. package/src/read-config.js +0 -24
  93. package/src/saml/claims.js +0 -40
  94. package/src/saml/saml.js +0 -223
  95. package/src/saml/x509.js +0 -48
  96. package/src/test/api.test.js +0 -186
  97. package/src/test/data/metadata/boxyhq.js +0 -6
  98. package/src/test/data/metadata/boxyhq.xml +0 -30
  99. package/src/test/data/saml_response +0 -1
  100. package/src/test/oauth.test.js +0 -342
package/src/env.js DELETED
@@ -1,39 +0,0 @@
1
- const hostUrl = process.env.HOST_URL || 'localhost';
2
- const hostPort = (process.env.HOST_PORT || '5000') * 1;
3
- const externalUrl =
4
- process.env.EXTERNAL_URL || 'http://' + hostUrl + ':' + hostPort;
5
- const samlPath = process.env.SAML_PATH || '/oauth/saml';
6
-
7
- const internalHostUrl = process.env.INTERNAL_HOST_URL || 'localhost';
8
- const internalHostPort = (process.env.INTERNAL_HOST_PORT || '6000') * 1;
9
-
10
- const apiKeys = (process.env.JACKSON_API_KEYS || '').split(',');
11
-
12
- const samlAudience = process.env.SAML_AUDIENCE;
13
- const preLoadedConfig = process.env.PRE_LOADED_CONFIG;
14
-
15
- const idpEnabled = process.env.IDP_ENABLED;
16
- const db = {
17
- engine: process.env.DB_ENGINE,
18
- url: process.env.DB_URL,
19
- type: process.env.DB_TYPE,
20
- ttl: process.env.DB_TTL,
21
- encryptionKey: process.env.DB_ENCRYPTION_KEY,
22
- };
23
-
24
- module.exports = {
25
- hostUrl,
26
- hostPort,
27
- externalUrl,
28
- samlPath,
29
- samlAudience,
30
- preLoadedConfig,
31
- internalHostUrl,
32
- internalHostPort,
33
- apiKeys,
34
- idpEnabled,
35
- db,
36
- useInternalServer: !(
37
- hostUrl === internalHostUrl && hostPort === internalHostPort
38
- ),
39
- };
package/src/index.js DELETED
@@ -1,67 +0,0 @@
1
- const DB = require('./db/db.js');
2
- const readConfig = require('./read-config.js');
3
-
4
- const defaultOpts = (opts) => {
5
- const newOpts = {
6
- ...opts,
7
- };
8
-
9
- if (!newOpts.externalUrl) {
10
- throw new Error('externalUrl is required');
11
- }
12
- if (!newOpts.samlPath) {
13
- throw new Error('samlPath is required');
14
- }
15
-
16
- newOpts.samlAudience = newOpts.samlAudience || 'https://saml.boxyhq.com';
17
- 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).
18
- newOpts.idpEnabled = newOpts.idpEnabled === true;
19
- newOpts.db = newOpts.db || {};
20
- newOpts.db.engine = newOpts.db.engine || 'sql'; // Supported values: redis, sql, mongo, mem. Keep comment in sync with db.js
21
- newOpts.db.url =
22
- newOpts.db.url || 'postgresql://postgres:postgres@localhost:5432/postgres';
23
- newOpts.db.type = newOpts.db.type || 'postgres'; // Only needed if DB_ENGINE is sql. Supported values: postgres, cockroachdb, mysql, mariadb
24
- newOpts.db.ttl = (newOpts.db.ttl || 300) * 1; // TTL for the code, session and token stores (in seconds)
25
- newOpts.db.cleanupLimit = (newOpts.db.cleanupLimit || 1000) * 1; // Limit cleanup of TTL entries to this many items at a time
26
-
27
- return newOpts;
28
- };
29
-
30
- module.exports = async function (opts) {
31
- opts = defaultOpts(opts);
32
-
33
- const db = await DB.new(opts.db);
34
- const configStore = db.store('saml:config');
35
- const sessionStore = db.store('oauth:session', opts.db.ttl);
36
- const codeStore = db.store('oauth:code', opts.db.ttl);
37
- const tokenStore = db.store('oauth:token', opts.db.ttl);
38
-
39
- const apiController = require('./controller/api.js')({ configStore });
40
- const oauthController = require('./controller/oauth.js')({
41
- configStore,
42
- sessionStore,
43
- codeStore,
44
- tokenStore,
45
- opts,
46
- });
47
- // write pre-loaded config if present
48
- if (opts.preLoadedConfig && opts.preLoadedConfig.length > 0) {
49
- const configs = await readConfig(opts.preLoadedConfig);
50
-
51
- for (const config of configs) {
52
- await apiController.config(config);
53
- console.log(
54
- `loaded config for tenant "${config.tenant}" and product "${config.product}"`
55
- );
56
- }
57
- }
58
-
59
- const type =
60
- opts.db.engine === 'sql' && opts.db.type ? ' Type: ' + opts.db.type : '';
61
- console.log(`Using engine: ${opts.db.engine}.${type}`);
62
-
63
- return {
64
- apiController,
65
- oauthController,
66
- };
67
- };
package/src/jackson.js DELETED
@@ -1,161 +0,0 @@
1
- const express = require('express');
2
- const cors = require('cors');
3
-
4
- const env = require('./env.js');
5
- const { extractAuthToken } = require('./controller/utils.js');
6
-
7
- let apiController;
8
- let oauthController;
9
-
10
- const oauthPath = '/oauth';
11
- const apiPath = '/api/v1/saml';
12
-
13
- const app = express();
14
-
15
- app.use(express.json());
16
- app.use(express.urlencoded({ extended: true }));
17
-
18
- app.get(oauthPath + '/authorize', async (req, res) => {
19
- try {
20
- const { redirect_url } = await oauthController.authorize(req.query);
21
-
22
- res.redirect(redirect_url);
23
- } catch (err) {
24
- const { message, statusCode = 500 } = err;
25
-
26
- res.status(statusCode).send(message);
27
- }
28
- });
29
-
30
- app.post(env.samlPath, async (req, res) => {
31
- try {
32
- const { redirect_url } = await oauthController.samlResponse(req.body);
33
-
34
- res.redirect(redirect_url);
35
- } catch (err) {
36
- const { message, statusCode = 500 } = err;
37
-
38
- res.status(statusCode).send(message);
39
- }
40
- });
41
-
42
- app.post(oauthPath + '/token', cors(), async (req, res) => {
43
- try {
44
- const result = await oauthController.token(req.body);
45
-
46
- res.json(result);
47
- } catch (err) {
48
- const { message, statusCode = 500 } = err;
49
-
50
- res.status(statusCode).send(message);
51
- }
52
- });
53
-
54
- app.get(oauthPath + '/userinfo', async (req, res) => {
55
- try {
56
- let token = extractAuthToken(req);
57
-
58
- // check for query param
59
- if (!token) {
60
- token = req.query.access_token;
61
- }
62
-
63
- if (!token) {
64
- res.status(401).json({ message: 'Unauthorized' });
65
- }
66
-
67
- const profile = await oauthController.userInfo(token);
68
-
69
- res.json(profile);
70
- } catch (err) {
71
- const { message, statusCode = 500 } = err;
72
-
73
- res.status(statusCode).json({ message });
74
- }
75
- });
76
-
77
- const server = app.listen(env.hostPort, async () => {
78
- console.log(
79
- `🚀 The path of the righteous server: http://${env.hostUrl}:${env.hostPort}`
80
- );
81
-
82
- const ret = await require('./index.js')(env);
83
- apiController = ret.apiController;
84
- oauthController = ret.oauthController;
85
- });
86
-
87
- // Internal routes, recommended not to expose this to the public interface though it would be guarded by API key(s)
88
- let internalApp = app;
89
-
90
- if (env.useInternalServer) {
91
- internalApp = express();
92
-
93
- internalApp.use(express.json());
94
- internalApp.use(express.urlencoded({ extended: true }));
95
- }
96
-
97
- const validateApiKey = (token) => {
98
- return env.apiKeys.includes(token);
99
- };
100
-
101
- internalApp.post(apiPath + '/config', async (req, res) => {
102
- try {
103
- const apiKey = extractAuthToken(req);
104
- if (!validateApiKey(apiKey)) {
105
- res.status(401).send('Unauthorized');
106
- return;
107
- }
108
-
109
- res.json(await apiController.config(req.body));
110
- } catch (err) {
111
- res.status(500).json({
112
- error: err.message,
113
- });
114
- }
115
- });
116
-
117
- internalApp.get(apiPath + '/config', async (req, res) => {
118
- try {
119
- const apiKey = extractAuthToken(req);
120
- if (!validateApiKey(apiKey)) {
121
- res.status(401).send('Unauthorized');
122
- return;
123
- }
124
-
125
- res.json(await apiController.getConfig(req.query));
126
- } catch (err) {
127
- res.status(500).json({
128
- error: err.message,
129
- });
130
- }
131
- });
132
-
133
- internalApp.delete(apiPath + '/config', async (req, res) => {
134
- try {
135
- const apiKey = extractAuthToken(req);
136
- if (!validateApiKey(apiKey)) {
137
- res.status(401).send('Unauthorized');
138
- return;
139
- }
140
- await apiController.deleteConfig(req.body);
141
- res.status(200).end();
142
- } catch (err) {
143
- res.status(500).json({
144
- error: err.message,
145
- });
146
- }
147
- });
148
-
149
- let internalServer = server;
150
- if (env.useInternalServer) {
151
- internalServer = internalApp.listen(env.internalHostPort, async () => {
152
- console.log(
153
- `🚀 The path of the righteous internal server: http://${env.internalHostUrl}:${env.internalHostPort}`
154
- );
155
- });
156
- }
157
-
158
- module.exports = {
159
- server,
160
- internalServer,
161
- };
@@ -1,24 +0,0 @@
1
- const fs = require('fs');
2
- const path = require('path');
3
-
4
- module.exports = async function (preLoadedConfig) {
5
- if (preLoadedConfig.startsWith('./')) {
6
- preLoadedConfig = path.resolve(process.cwd(), preLoadedConfig);
7
- }
8
- const files = await fs.promises.readdir(preLoadedConfig);
9
- const configs = [];
10
- for (let idx in files) {
11
- const file = files[idx];
12
- if (file.endsWith('.js')) {
13
- const config = require(path.join(preLoadedConfig, file));
14
- const rawMetadata = await fs.promises.readFile(
15
- path.join(preLoadedConfig, path.parse(file).name + '.xml'),
16
- 'utf8'
17
- );
18
- config.rawMetadata = rawMetadata;
19
- configs.push(config);
20
- }
21
- }
22
-
23
- return configs;
24
- };
@@ -1,40 +0,0 @@
1
- const mapping = [
2
- {
3
- attribute: 'id',
4
- schema:
5
- 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier',
6
- },
7
- {
8
- attribute: 'email',
9
- schema:
10
- 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress',
11
- },
12
- {
13
- attribute: 'firstName',
14
- schema: 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname',
15
- },
16
- {
17
- attribute: 'lastName',
18
- schema: 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname',
19
- },
20
- ];
21
-
22
- const map = (claims) => {
23
- const profile = {
24
- raw: claims,
25
- };
26
-
27
- mapping.forEach((m) => {
28
- if (claims[m.attribute]) {
29
- profile[m.attribute] = claims[m.attribute];
30
- } else if (claims[m.schema]) {
31
- profile[m.attribute] = claims[m.schema];
32
- }
33
- });
34
-
35
- return profile;
36
- };
37
-
38
- module.exports = {
39
- map,
40
- };
package/src/saml/saml.js DELETED
@@ -1,223 +0,0 @@
1
- const saml = require('@boxyhq/saml20');
2
- const xml2js = require('xml2js');
3
- const rambda = require('rambda');
4
- const thumbprint = require('thumbprint');
5
- const xmlbuilder = require('xmlbuilder');
6
- const crypto = require('crypto');
7
- const xmlcrypto = require('xml-crypto');
8
- const claims = require('./claims');
9
-
10
- const idPrefix = '_';
11
- const authnXPath =
12
- '/*[local-name(.)="AuthnRequest" and namespace-uri(.)="urn:oasis:names:tc:SAML:2.0:protocol"]';
13
- const issuerXPath =
14
- '/*[local-name(.)="Issuer" and namespace-uri(.)="urn:oasis:names:tc:SAML:2.0:assertion"]';
15
-
16
- const signRequest = (xml, signingKey) => {
17
- if (!xml) {
18
- throw new Error('Please specify xml');
19
- }
20
- if (!signingKey) {
21
- throw new Error('Please specify signingKey');
22
- }
23
-
24
- const sig = new xmlcrypto.SignedXml();
25
- sig.signatureAlgorithm = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256';
26
- sig.signingKey = signingKey;
27
- sig.addReference(
28
- authnXPath,
29
- [
30
- 'http://www.w3.org/2000/09/xmldsig#enveloped-signature',
31
- 'http://www.w3.org/2001/10/xml-exc-c14n#',
32
- ],
33
- 'http://www.w3.org/2001/04/xmlenc#sha256'
34
- );
35
- sig.computeSignature(xml, {
36
- location: { reference: authnXPath + issuerXPath, action: 'after' },
37
- });
38
-
39
- return sig.getSignedXml();
40
- };
41
-
42
- module.exports = {
43
- request: ({
44
- ssoUrl,
45
- entityID,
46
- callbackUrl,
47
- isPassive = false,
48
- forceAuthn = false,
49
- identifierFormat = 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress',
50
- providerName = 'BoxyHQ',
51
- signingKey,
52
- }) => {
53
- const id = idPrefix + crypto.randomBytes(10).toString('hex');
54
- const date = new Date().toISOString();
55
-
56
- const samlReq = {
57
- 'samlp:AuthnRequest': {
58
- '@xmlns:samlp': 'urn:oasis:names:tc:SAML:2.0:protocol',
59
- '@ID': id,
60
- '@Version': '2.0',
61
- '@IssueInstant': date,
62
- '@ProtocolBinding': 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST',
63
- '@Destination': ssoUrl,
64
- 'saml:Issuer': {
65
- '@xmlns:saml': 'urn:oasis:names:tc:SAML:2.0:assertion',
66
- '#text': entityID,
67
- },
68
- },
69
- };
70
-
71
- if (isPassive) samlReq['samlp:AuthnRequest']['@IsPassive'] = true;
72
-
73
- if (forceAuthn) {
74
- samlReq['samlp:AuthnRequest']['@ForceAuthn'] = true;
75
- }
76
-
77
- samlReq['samlp:AuthnRequest']['@AssertionConsumerServiceURL'] = callbackUrl;
78
-
79
- samlReq['samlp:AuthnRequest']['samlp:NameIDPolicy'] = {
80
- '@xmlns:samlp': 'urn:oasis:names:tc:SAML:2.0:protocol',
81
- '@Format': identifierFormat,
82
- '@AllowCreate': 'true',
83
- };
84
-
85
- if (providerName != null) {
86
- samlReq['samlp:AuthnRequest']['@ProviderName'] = providerName;
87
- }
88
-
89
- let xml = xmlbuilder.create(samlReq).end({});
90
- if (signingKey) {
91
- xml = signRequest(xml, signingKey);
92
- }
93
-
94
- return {
95
- id,
96
- request: xml,
97
- };
98
- },
99
-
100
- parseAsync: async (rawAssertion) => {
101
- return new Promise((resolve, reject) => {
102
- saml.parse(rawAssertion, function onParseAsync(err, profile) {
103
- if (err) {
104
- reject(err);
105
- return;
106
- }
107
-
108
- resolve(profile);
109
- });
110
- });
111
- },
112
-
113
- validateAsync: async (rawAssertion, options) => {
114
- return new Promise((resolve, reject) => {
115
- saml.validate(
116
- rawAssertion,
117
- options,
118
- function onValidateAsync(err, profile) {
119
- if (err) {
120
- reject(err);
121
- return;
122
- }
123
-
124
- if (profile && profile.claims) {
125
- // we map claims to our attributes id, email, firstName, lastName where possible. We also map original claims to raw
126
- profile.claims = claims.map(profile.claims);
127
-
128
- // some providers don't return the id in the assertion, we set it to a sha256 hash of the email
129
- if (!profile.claims.id) {
130
- profile.claims.id = crypto
131
- .createHash('sha256')
132
- .update(profile.claims.email)
133
- .digest('hex');
134
- }
135
- }
136
-
137
- resolve(profile);
138
- }
139
- );
140
- });
141
- },
142
-
143
- parseMetadataAsync: async (idpMeta) => {
144
- return new Promise((resolve, reject) => {
145
- xml2js.parseString(
146
- idpMeta,
147
- { tagNameProcessors: [xml2js.processors.stripPrefix] },
148
- (err, res) => {
149
- if (err) {
150
- reject(err);
151
- return;
152
- }
153
-
154
- const entityID = rambda.path('EntityDescriptor.$.entityID', res);
155
- let X509Certificate = null;
156
- let ssoPostUrl = null;
157
- let ssoRedirectUrl = null;
158
- let loginType = 'idp';
159
-
160
- let ssoDes = rambda.pathOr(
161
- null,
162
- 'EntityDescriptor.IDPSSODescriptor',
163
- res
164
- );
165
- if (!ssoDes) {
166
- ssoDes = rambda.pathOr([], 'EntityDescriptor.SPSSODescriptor', res);
167
- if (!ssoDes) {
168
- loginType = 'sp';
169
- }
170
- }
171
-
172
- for (const ssoDesRec of ssoDes) {
173
- const keyDes = ssoDesRec['KeyDescriptor'];
174
- for (const keyDesRec of keyDes) {
175
- if (keyDesRec['$'] && keyDesRec['$'].use === 'signing') {
176
- const ki = keyDesRec['KeyInfo'][0];
177
- const cd = ki['X509Data'][0];
178
- X509Certificate = cd['X509Certificate'][0];
179
- }
180
- }
181
-
182
- const ssoSvc =
183
- ssoDesRec['SingleSignOnService'] ||
184
- ssoDesRec['AssertionConsumerService'] ||
185
- [];
186
- for (const ssoSvcRec of ssoSvc) {
187
- if (
188
- rambda.pathOr('', '$.Binding', ssoSvcRec).endsWith('HTTP-POST')
189
- ) {
190
- ssoPostUrl = rambda.path('$.Location', ssoSvcRec);
191
- } else if (
192
- rambda
193
- .pathOr('', '$.Binding', ssoSvcRec)
194
- .endsWith('HTTP-Redirect')
195
- ) {
196
- ssoRedirectUrl = rambda.path('$.Location', ssoSvcRec);
197
- }
198
- }
199
- }
200
-
201
- const ret = {
202
- sso: {},
203
- };
204
- if (entityID) {
205
- ret.entityID = entityID;
206
- }
207
- if (X509Certificate) {
208
- ret.thumbprint = thumbprint.calculate(X509Certificate);
209
- }
210
- if (ssoPostUrl) {
211
- ret.sso.postUrl = ssoPostUrl;
212
- }
213
- if (ssoRedirectUrl) {
214
- ret.sso.redirectUrl = ssoRedirectUrl;
215
- }
216
- ret.loginType = loginType;
217
-
218
- resolve(ret);
219
- }
220
- );
221
- });
222
- },
223
- };
package/src/saml/x509.js DELETED
@@ -1,48 +0,0 @@
1
- const x509 = require('@peculiar/x509');
2
- const { Crypto } = require('@peculiar/webcrypto');
3
-
4
- const crypto = new Crypto();
5
- x509.cryptoProvider.set(crypto);
6
-
7
- const alg = {
8
- name: 'RSASSA-PKCS1-v1_5',
9
- hash: 'SHA-256',
10
- publicExponent: new Uint8Array([1, 0, 1]),
11
- modulusLength: 2048,
12
- };
13
-
14
- const generate = async () => {
15
- const keys = await crypto.subtle.generateKey(alg, true, ['sign', 'verify']);
16
-
17
- const extensions = [
18
- new x509.BasicConstraintsExtension(false, undefined, true),
19
- ];
20
-
21
- extensions.push(
22
- new x509.KeyUsagesExtension(x509.KeyUsageFlags.digitalSignature, true)
23
- );
24
- extensions.push(
25
- await x509.SubjectKeyIdentifierExtension.create(keys.publicKey)
26
- );
27
-
28
- const cert = await x509.X509CertificateGenerator.createSelfSigned({
29
- serialNumber: '01',
30
- name: 'CN=BoxyHQ Jackson',
31
- notBefore: new Date(),
32
- notAfter: new Date('3021/01/01'), // TODO: set shorter expiry and rotate ceritifcates
33
- signingAlgorithm: alg,
34
- keys: keys,
35
- extensions,
36
- });
37
-
38
- const pkcs8 = await crypto.subtle.exportKey('pkcs8', keys.privateKey);
39
-
40
- return {
41
- publicKey: cert.toString('pem'),
42
- privateKey: x509.PemConverter.encode(pkcs8, 'private key'),
43
- };
44
- };
45
-
46
- module.exports = {
47
- generate,
48
- };