@boxyhq/saml-jackson 0.2.4-beta.198 → 0.3.0-beta.248

Sign up to get free protection for your applications and to get access to all the features.
Files changed (100) hide show
  1. package/Dockerfile +9 -7
  2. package/README.md +28 -29
  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
@@ -1,23 +0,0 @@
1
- const EntitySchema = require('typeorm').EntitySchema;
2
- const JacksonTTL = require('../model/JacksonTTL.js');
3
-
4
- module.exports = new EntitySchema({
5
- name: 'JacksonTTL',
6
- target: JacksonTTL,
7
- columns: {
8
- key: {
9
- primary: true,
10
- type: 'varchar',
11
- length: 1500,
12
- },
13
- expiresAt: {
14
- type: 'bigint',
15
- },
16
- },
17
- indices: [
18
- {
19
- name: '_jackson_ttl_expires_at',
20
- columns: ['expiresAt'],
21
- },
22
- ],
23
- });
@@ -1,9 +0,0 @@
1
- /*export */ class JacksonIndex {
2
- constructor(id, key, store) {
3
- this.id = id;
4
- this.key = key;
5
- this.store = store;
6
- }
7
- }
8
-
9
- module.exports = JacksonIndex;
@@ -1,10 +0,0 @@
1
- /*export */ class JacksonStore {
2
- constructor(key, value, iv, tag) {
3
- this.key = key;
4
- this.value = value;
5
- this.iv = iv;
6
- this.tag = tag;
7
- }
8
- }
9
-
10
- module.exports = JacksonStore;
@@ -1,8 +0,0 @@
1
- /*export */ class JacksonTTL {
2
- constructor(key, expiresAt) {
3
- this.key = key;
4
- this.expiresAt = expiresAt;
5
- }
6
- }
7
-
8
- module.exports = JacksonTTL;
package/src/db/sql/sql.js DELETED
@@ -1,153 +0,0 @@
1
- /*eslint no-constant-condition: ["error", { "checkLoops": false }]*/
2
-
3
- require('reflect-metadata');
4
- const typeorm = require('typeorm');
5
- const JacksonStore = require('./model/JacksonStore.js');
6
- const JacksonIndex = require('./model/JacksonIndex.js');
7
- const JacksonTTL = require('./model/JacksonTTL.js');
8
-
9
- const dbutils = require('../utils.js');
10
-
11
- class Sql {
12
- constructor(options) {
13
- return (async () => {
14
- while (true) {
15
- try {
16
- this.connection = await typeorm.createConnection({
17
- name: options.type + Math.floor(Math.random() * 100000),
18
- type: options.type,
19
- url: options.url,
20
- synchronize: true,
21
- migrationsTableName: '_jackson_migrations',
22
- logging: false,
23
- entities: [
24
- require('./entity/JacksonStore.js')(options.type),
25
- require('./entity/JacksonIndex.js'),
26
- require('./entity/JacksonTTL.js'),
27
- ],
28
- });
29
-
30
- break;
31
- } catch (err) {
32
- console.error(`error connecting to ${options.type} db: ${err}`);
33
- await dbutils.sleep(1000);
34
- continue;
35
- }
36
- }
37
-
38
- this.storeRepository = this.connection.getRepository(JacksonStore);
39
- this.indexRepository = this.connection.getRepository(JacksonIndex);
40
- this.ttlRepository = this.connection.getRepository(JacksonTTL);
41
-
42
- if (options.ttl && options.cleanupLimit) {
43
- this.ttlCleanup = async () => {
44
- const now = Date.now();
45
-
46
- while (true) {
47
- const ids = await this.ttlRepository
48
- .createQueryBuilder('jackson_ttl')
49
- .limit(options.cleanupLimit)
50
- .where('jackson_ttl.expiresAt <= :expiresAt', { expiresAt: now })
51
- .getMany();
52
-
53
- if (ids.length <= 0) {
54
- break;
55
- }
56
-
57
- const delIds = ids.map((id) => {
58
- return id.key;
59
- });
60
-
61
- await this.storeRepository.remove(ids);
62
- await this.ttlRepository.delete(delIds);
63
- }
64
-
65
- this.timerId = setTimeout(this.ttlCleanup, options.ttl * 1000);
66
- };
67
-
68
- this.timerId = setTimeout(this.ttlCleanup, options.ttl * 1000);
69
- } else {
70
- console.log(
71
- 'Warning: ttl cleanup not enabled, set both "ttl" and "cleanupLimit" options to enable it!'
72
- );
73
- }
74
-
75
- return this;
76
- })();
77
- }
78
-
79
- async get(namespace, key) {
80
- let res = await this.storeRepository.findOne({
81
- key: dbutils.key(namespace, key),
82
- });
83
-
84
- if (res && res.value) {
85
- return {
86
- value: res.value,
87
- iv: res.iv,
88
- tag: res.tag,
89
- };
90
- }
91
-
92
- return null;
93
- }
94
-
95
- async getByIndex(namespace, idx) {
96
- const res = await this.indexRepository.find({
97
- key: dbutils.keyForIndex(namespace, idx),
98
- });
99
-
100
- const ret = [];
101
-
102
- if (res) {
103
- res.forEach((r) => {
104
- ret.push({
105
- value: r.store.value,
106
- iv: r.store.iv,
107
- tag: r.store.tag,
108
- });
109
- });
110
- }
111
-
112
- return ret;
113
- }
114
-
115
- async put(namespace, key, val, ttl = 0, ...indexes) {
116
- await this.connection.transaction(async (transactionalEntityManager) => {
117
- const dbKey = dbutils.key(namespace, key);
118
- const store = new JacksonStore(dbKey, val.value, val.iv, val.tag);
119
- await transactionalEntityManager.save(store);
120
-
121
- if (ttl) {
122
- const ttlRec = new JacksonTTL(dbKey, Date.now() + ttl * 1000);
123
- await transactionalEntityManager.save(ttlRec);
124
- }
125
-
126
- // no ttl support for secondary indexes
127
- for (const idx of indexes || []) {
128
- const key = dbutils.keyForIndex(namespace, idx);
129
- const rec = await this.indexRepository.findOne({
130
- key,
131
- storeKey: store.key,
132
- });
133
- if (!rec) {
134
- await transactionalEntityManager.save(
135
- new JacksonIndex(0, key, store)
136
- );
137
- }
138
- }
139
- });
140
- }
141
-
142
- async delete(namespace, key) {
143
- return await this.storeRepository.remove({
144
- key: dbutils.key(namespace, key),
145
- });
146
- }
147
- }
148
-
149
- module.exports = {
150
- new: async (options) => {
151
- return new Sql(options);
152
- },
153
- };
package/src/db/store.js DELETED
@@ -1,42 +0,0 @@
1
- const dbutils = require('./utils.js');
2
-
3
- class Store {
4
- constructor(namespace, db, ttl = 0) {
5
- this.namespace = namespace;
6
- this.db = db;
7
- this.ttl = ttl;
8
- }
9
-
10
- async get(key) {
11
- return await this.db.get(this.namespace, dbutils.keyDigest(key));
12
- }
13
-
14
- async getByIndex(idx) {
15
- idx.value = dbutils.keyDigest(idx.value);
16
- return await this.db.getByIndex(this.namespace, idx);
17
- }
18
-
19
- async put(key, val, ...indexes) {
20
- indexes = (indexes || []).map((idx) => {
21
- idx.value = dbutils.keyDigest(idx.value);
22
- return idx;
23
- });
24
- return await this.db.put(
25
- this.namespace,
26
- dbutils.keyDigest(key),
27
- val,
28
- this.ttl,
29
- ...indexes
30
- );
31
- }
32
-
33
- async delete(key) {
34
- return await this.db.delete(this.namespace, dbutils.keyDigest(key));
35
- }
36
- }
37
-
38
- module.exports = {
39
- new: (namespace, db, ttl = 0) => {
40
- return new Store(namespace, db, ttl);
41
- },
42
- };
package/src/db/utils.js DELETED
@@ -1,30 +0,0 @@
1
- const Ripemd160 = require('ripemd160');
2
-
3
- const key = (namespace, k) => {
4
- return namespace + ':' + k;
5
- };
6
-
7
- const keyForIndex = (namespace, idx) => {
8
- return key(key(namespace, idx.name), idx.value);
9
- };
10
-
11
- const keyDigest = (k) => {
12
- return new Ripemd160().update(k).digest('hex');
13
- };
14
-
15
- const keyFromParts = (...parts) => {
16
- return parts.join(':'); // TODO: pick a better strategy, keys can collide now
17
- };
18
-
19
- const sleep = (ms) => {
20
- return new Promise((resolve) => setTimeout(resolve, ms));
21
- };
22
-
23
- module.exports = {
24
- key,
25
- keyForIndex,
26
- keyDigest,
27
- keyFromParts,
28
- sleep,
29
- indexPrefix: '_index',
30
- };
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
- };