@boxyhq/saml-jackson 1.3.1 → 1.3.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -108,6 +108,10 @@ export declare class OAuthController implements IOAuthController {
108
108
  * type: string
109
109
  * lastName:
110
110
  * type: string
111
+ * roles:
112
+ * type: array
113
+ * groups:
114
+ * type: array
111
115
  * raw:
112
116
  * type: object
113
117
  * requested:
@@ -100,11 +100,12 @@ class OAuthController {
100
100
  else if (this.opts.idpDiscoveryPath) {
101
101
  if (!isIdpFlow) {
102
102
  // redirect to IdP selection page
103
- const idpList = connections.map(({ idpMetadata, oidcProvider, clientID }) => {
103
+ const idpList = connections.map(({ idpMetadata, oidcProvider, clientID, name }) => {
104
104
  var _a;
105
105
  return JSON.stringify({
106
106
  provider: (_a = idpMetadata === null || idpMetadata === void 0 ? void 0 : idpMetadata.provider) !== null && _a !== void 0 ? _a : oidcProvider === null || oidcProvider === void 0 ? void 0 : oidcProvider.provider,
107
107
  clientID,
108
+ name,
108
109
  connectionIsSAML: idpMetadata && typeof idpMetadata === 'object',
109
110
  connectionIsOIDC: oidcProvider && typeof oidcProvider === 'object',
110
111
  });
@@ -381,7 +382,7 @@ class OAuthController {
381
382
  oidcCodeVerifier = openid_client_1.generators.codeVerifier();
382
383
  const code_challenge = openid_client_1.generators.codeChallenge(oidcCodeVerifier);
383
384
  ssoUrl = oidcClient.authorizationUrl({
384
- scope: [...requestedScopes, 'openid', 'email', 'profile']
385
+ scope: [...requestedScopes, 'openid', 'email', 'profile', 'groups']
385
386
  .filter((value, index, self) => self.indexOf(value) === index) // filter out duplicates
386
387
  .join(' '),
387
388
  code_challenge,
@@ -615,7 +616,7 @@ class OAuthController {
615
616
  });
616
617
  }
617
618
  extractOIDCUserProfile(tokenSet, oidcClient) {
618
- var _a, _b, _c;
619
+ var _a, _b, _c, _d, _e;
619
620
  return __awaiter(this, void 0, void 0, function* () {
620
621
  const profile = { claims: {} };
621
622
  const idTokenClaims = tokenSet.claims();
@@ -624,6 +625,8 @@ class OAuthController {
624
625
  profile.claims.email = (_a = idTokenClaims.email) !== null && _a !== void 0 ? _a : userinfo.email;
625
626
  profile.claims.firstName = (_b = idTokenClaims.given_name) !== null && _b !== void 0 ? _b : userinfo.given_name;
626
627
  profile.claims.lastName = (_c = idTokenClaims.family_name) !== null && _c !== void 0 ? _c : userinfo.family_name;
628
+ profile.claims.roles = (_d = idTokenClaims.roles) !== null && _d !== void 0 ? _d : userinfo.roles;
629
+ profile.claims.groups = (_e = idTokenClaims.groups) !== null && _e !== void 0 ? _e : userinfo.groups;
627
630
  profile.claims.raw = userinfo;
628
631
  return profile;
629
632
  });
@@ -867,7 +870,7 @@ class OAuthController {
867
870
  throw new error_1.JacksonError('JWT signing keys are not loaded', 500);
868
871
  }
869
872
  let claims = requestHasNonce ? { nonce: codeVal.requested.nonce } : {};
870
- 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 });
873
+ 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, roles: codeVal.profile.claims.roles, groups: codeVal.profile.claims.groups });
871
874
  const signingKey = yield (0, utils_1.loadJWSPrivateKey)(jwtSigningKeys.private, jwsAlg);
872
875
  const id_token = yield new jose.SignJWT(claims)
873
876
  .setProtectedHeader({ alg: jwsAlg })
@@ -922,6 +925,10 @@ class OAuthController {
922
925
  * type: string
923
926
  * lastName:
924
927
  * type: string
928
+ * roles:
929
+ * type: array
930
+ * groups:
931
+ * type: array
925
932
  * raw:
926
933
  * type: object
927
934
  * requested:
@@ -34,16 +34,22 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
34
34
  Object.defineProperty(exports, "__esModule", { value: true });
35
35
  const fs = __importStar(require("fs"));
36
36
  const path = __importStar(require("path"));
37
+ const url = __importStar(require("url"));
37
38
  const loadConnection = (preLoadedConnection) => __awaiter(void 0, void 0, void 0, function* () {
38
39
  if (preLoadedConnection.startsWith('./')) {
39
40
  preLoadedConnection = path.resolve(process.cwd(), preLoadedConnection);
40
41
  }
42
+ else {
43
+ preLoadedConnection = path.resolve(preLoadedConnection);
44
+ }
41
45
  const files = yield fs.promises.readdir(preLoadedConnection);
42
46
  const connections = [];
43
47
  for (const idx in files) {
44
48
  const file = files[idx];
45
49
  if (file.endsWith('.js')) {
46
- const { default: connection, } = yield Promise.resolve().then(() => __importStar(require(/* webpackIgnore: true */ path.join(preLoadedConnection, file))));
50
+ const filePath = path.join(preLoadedConnection, file);
51
+ const fileUrl = preLoadedConnection.startsWith('/') ? filePath : url.pathToFileURL(filePath).toString();
52
+ const { default: connection, } = yield Promise.resolve().then(() => __importStar(require(/* webpackIgnore: true */ fileUrl)));
47
53
  if (!('oidcDiscoveryUrl' in connection)) {
48
54
  const rawMetadata = yield fs.promises.readFile(path.join(preLoadedConnection, path.parse(file).name + '.xml'), 'utf8');
49
55
  connection.encodedRawMetadata = Buffer.from(rawMetadata, 'utf8').toString('base64');
@@ -1,6 +1,6 @@
1
1
  declare const _default: {
2
- map: (claims: Record<"id" | "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier" | "email" | "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" | "firstName" | "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname" | "lastName" | "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname", unknown>) => {
3
- raw: Record<"id" | "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier" | "email" | "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" | "firstName" | "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname" | "lastName" | "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname", unknown>;
2
+ map: (claims: Record<string, unknown>) => {
3
+ raw: Record<string, unknown>;
4
4
  };
5
5
  };
6
6
  export default _default;
@@ -1,5 +1,19 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ const rolesAttribute = 'roles';
4
+ const rolesSchema = 'http://schemas.microsoft.com/ws/2008/06/identity/claims/role';
5
+ const groupsAttribute = 'groups';
6
+ const groupsSchema = 'http://schemas.xmlsoap.org/claims/Group';
7
+ const arrayMapping = [
8
+ {
9
+ attribute: rolesAttribute,
10
+ schema: rolesSchema,
11
+ },
12
+ {
13
+ attribute: groupsAttribute,
14
+ schema: groupsSchema,
15
+ },
16
+ ];
3
17
  const mapping = [
4
18
  {
5
19
  attribute: 'id',
@@ -17,8 +31,17 @@ const mapping = [
17
31
  attribute: 'lastName',
18
32
  schema: 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname',
19
33
  },
34
+ ...arrayMapping,
20
35
  ];
21
36
  const map = (claims) => {
37
+ arrayMapping.forEach((m) => {
38
+ if (claims[m.attribute]) {
39
+ claims[m.attribute] = [].concat(claims[m.attribute]);
40
+ }
41
+ else if (claims[m.schema]) {
42
+ claims[m.schema] = [].concat(claims[m.schema]);
43
+ }
44
+ });
22
45
  const profile = {
23
46
  raw: claims,
24
47
  };
package/dist/typings.d.ts CHANGED
@@ -228,7 +228,10 @@ export interface Profile {
228
228
  email: string;
229
229
  firstName: string;
230
230
  lastName: string;
231
+ roles?: string[];
232
+ groups?: string[];
231
233
  requested: Record<string, string>;
234
+ raw: any;
232
235
  }
233
236
  export interface Index {
234
237
  name: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@boxyhq/saml-jackson",
3
- "version": "1.3.1",
3
+ "version": "1.3.3",
4
4
  "description": "SAML Jackson library",
5
5
  "keywords": [
6
6
  "SAML 2.0"
@@ -38,13 +38,13 @@
38
38
  "statements": 70
39
39
  },
40
40
  "dependencies": {
41
- "@boxyhq/saml20": "1.0.7",
41
+ "@boxyhq/saml20": "1.0.11",
42
42
  "@opentelemetry/api": "1.0.4",
43
43
  "@opentelemetry/api-metrics": "0.27.0",
44
- "axios": "1.1.2",
45
- "jose": "4.10.0",
44
+ "axios": "1.1.3",
45
+ "jose": "4.10.3",
46
46
  "marked": "4.1.1",
47
- "mongodb": "4.10.0",
47
+ "mongodb": "4.11.0",
48
48
  "mysql2": "2.3.3",
49
49
  "openid-client": "5.1.10",
50
50
  "node-forge": "1.3.1",
@@ -57,14 +57,14 @@
57
57
  "xmlbuilder": "15.1.1"
58
58
  },
59
59
  "devDependencies": {
60
- "@faker-js/faker": "7.5.0",
61
- "@types/node": "18.8.3",
60
+ "@faker-js/faker": "7.6.0",
61
+ "@types/node": "18.11.5",
62
62
  "@types/sinon": "10.0.13",
63
63
  "@types/tap": "15.0.7",
64
64
  "@typescript-eslint/eslint-plugin": "5.40.0",
65
- "@typescript-eslint/parser": "5.38.1",
65
+ "@typescript-eslint/parser": "5.41.0",
66
66
  "cross-env": "7.0.3",
67
- "eslint": "8.25.0",
67
+ "eslint": "8.26.0",
68
68
  "eslint-config-prettier": "8.5.0",
69
69
  "prettier": "2.7.1",
70
70
  "sinon": "14.0.1",