@boxyhq/saml-jackson 1.33.1-beta.1 → 1.34.0
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/typings.d.ts +1 -1
- package/package.json +1 -1
- package/dist/controller/oauth/oidc-issuer.d.ts +0 -2
- package/dist/controller/oauth/oidc-issuer.js +0 -25
- package/dist/controller/oauth/oidc-issuer.js.map +0 -1
- package/dist/src/controller/admin.d.ts +0 -27
- package/dist/src/controller/admin.js +0 -60
- package/dist/src/controller/admin.js.map +0 -1
- package/dist/src/controller/analytics.d.ts +0 -16
- package/dist/src/controller/analytics.js +0 -79
- package/dist/src/controller/analytics.js.map +0 -1
- package/dist/src/controller/api.d.ts +0 -557
- package/dist/src/controller/api.js +0 -806
- package/dist/src/controller/api.js.map +0 -1
- package/dist/src/controller/connection/oidc.d.ts +0 -7
- package/dist/src/controller/connection/oidc.js +0 -181
- package/dist/src/controller/connection/oidc.js.map +0 -1
- package/dist/src/controller/connection/saml.d.ts +0 -7
- package/dist/src/controller/connection/saml.js +0 -250
- package/dist/src/controller/connection/saml.js.map +0 -1
- package/dist/src/controller/error.d.ts +0 -10
- package/dist/src/controller/error.js +0 -13
- package/dist/src/controller/error.js.map +0 -1
- package/dist/src/controller/health-check.d.ts +0 -11
- package/dist/src/controller/health-check.js +0 -51
- package/dist/src/controller/health-check.js.map +0 -1
- package/dist/src/controller/logout.d.ts +0 -18
- package/dist/src/controller/logout.js +0 -132
- package/dist/src/controller/logout.js.map +0 -1
- package/dist/src/controller/oauth/allowed.d.ts +0 -1
- package/dist/src/controller/oauth/allowed.js +0 -30
- package/dist/src/controller/oauth/allowed.js.map +0 -1
- package/dist/src/controller/oauth/code-verifier.d.ts +0 -1
- package/dist/src/controller/oauth/code-verifier.js +0 -8
- package/dist/src/controller/oauth/code-verifier.js.map +0 -1
- package/dist/src/controller/oauth/oidc-client.d.ts +0 -12
- package/dist/src/controller/oauth/oidc-client.js +0 -89
- package/dist/src/controller/oauth/oidc-client.js.map +0 -1
- package/dist/src/controller/oauth/redirect.d.ts +0 -1
- package/dist/src/controller/oauth/redirect.js +0 -13
- package/dist/src/controller/oauth/redirect.js.map +0 -1
- package/dist/src/controller/oauth.d.ts +0 -142
- package/dist/src/controller/oauth.js +0 -1112
- package/dist/src/controller/oauth.js.map +0 -1
- package/dist/src/controller/oidc-discovery.d.ts +0 -22
- package/dist/src/controller/oidc-discovery.js +0 -47
- package/dist/src/controller/oidc-discovery.js.map +0 -1
- package/dist/src/controller/setup-link.d.ts +0 -307
- package/dist/src/controller/setup-link.js +0 -462
- package/dist/src/controller/setup-link.js.map +0 -1
- package/dist/src/controller/sp-config.d.ts +0 -22
- package/dist/src/controller/sp-config.js +0 -89
- package/dist/src/controller/sp-config.js.map +0 -1
- package/dist/src/controller/sso-handler.d.ts +0 -66
- package/dist/src/controller/sso-handler.js +0 -306
- package/dist/src/controller/sso-handler.js.map +0 -1
- package/dist/src/controller/utils.d.ts +0 -84
- package/dist/src/controller/utils.js +0 -328
- package/dist/src/controller/utils.js.map +0 -1
- package/dist/src/cron/lock.d.ts +0 -18
- package/dist/src/cron/lock.js +0 -98
- package/dist/src/cron/lock.js.map +0 -1
- package/dist/src/db/db.d.ts +0 -5
- package/dist/src/db/db.js +0 -178
- package/dist/src/db/db.js.map +0 -1
- package/dist/src/db/defaultDb.d.ts +0 -2
- package/dist/src/db/defaultDb.js +0 -18
- package/dist/src/db/defaultDb.js.map +0 -1
- package/dist/src/db/dynamoDb.d.ts +0 -19
- package/dist/src/db/dynamoDb.js +0 -320
- package/dist/src/db/dynamoDb.js.map +0 -1
- package/dist/src/db/encrypter.d.ts +0 -3
- package/dist/src/db/encrypter.js +0 -22
- package/dist/src/db/encrypter.js.map +0 -1
- package/dist/src/db/mem.d.ts +0 -23
- package/dist/src/db/mem.js +0 -186
- package/dist/src/db/mem.js.map +0 -1
- package/dist/src/db/mongo.d.ts +0 -22
- package/dist/src/db/mongo.js +0 -177
- package/dist/src/db/mongo.js.map +0 -1
- package/dist/src/db/planetscale/entity/JacksonIndex.d.ts +0 -5
- package/dist/src/db/planetscale/entity/JacksonIndex.js +0 -32
- package/dist/src/db/planetscale/entity/JacksonIndex.js.map +0 -1
- package/dist/src/db/planetscale/entity/JacksonStore.d.ts +0 -9
- package/dist/src/db/planetscale/entity/JacksonStore.js +0 -63
- package/dist/src/db/planetscale/entity/JacksonStore.js.map +0 -1
- package/dist/src/db/planetscale/entity/JacksonTTL.d.ts +0 -4
- package/dist/src/db/planetscale/entity/JacksonTTL.js +0 -27
- package/dist/src/db/planetscale/entity/JacksonTTL.js.map +0 -1
- package/dist/src/db/redis.d.ts +0 -18
- package/dist/src/db/redis.js +0 -214
- package/dist/src/db/redis.js.map +0 -1
- package/dist/src/db/sql/entity/JacksonIndex.d.ts +0 -7
- package/dist/src/db/sql/entity/JacksonIndex.js +0 -39
- package/dist/src/db/sql/entity/JacksonIndex.js.map +0 -1
- package/dist/src/db/sql/entity/JacksonStore.d.ts +0 -9
- package/dist/src/db/sql/entity/JacksonStore.js +0 -61
- package/dist/src/db/sql/entity/JacksonStore.js.map +0 -1
- package/dist/src/db/sql/entity/JacksonTTL.d.ts +0 -4
- package/dist/src/db/sql/entity/JacksonTTL.js +0 -27
- package/dist/src/db/sql/entity/JacksonTTL.js.map +0 -1
- package/dist/src/db/sql/mariadb/entity/JacksonIndex.d.ts +0 -7
- package/dist/src/db/sql/mariadb/entity/JacksonIndex.js +0 -39
- package/dist/src/db/sql/mariadb/entity/JacksonIndex.js.map +0 -1
- package/dist/src/db/sql/mariadb/entity/JacksonStore.d.ts +0 -9
- package/dist/src/db/sql/mariadb/entity/JacksonStore.js +0 -63
- package/dist/src/db/sql/mariadb/entity/JacksonStore.js.map +0 -1
- package/dist/src/db/sql/mariadb/entity/JacksonTTL.d.ts +0 -4
- package/dist/src/db/sql/mariadb/entity/JacksonTTL.js +0 -27
- package/dist/src/db/sql/mariadb/entity/JacksonTTL.js.map +0 -1
- package/dist/src/db/sql/mssql/entity/JacksonIndex.d.ts +0 -7
- package/dist/src/db/sql/mssql/entity/JacksonIndex.js +0 -39
- package/dist/src/db/sql/mssql/entity/JacksonIndex.js.map +0 -1
- package/dist/src/db/sql/mssql/entity/JacksonStore.d.ts +0 -9
- package/dist/src/db/sql/mssql/entity/JacksonStore.js +0 -61
- package/dist/src/db/sql/mssql/entity/JacksonStore.js.map +0 -1
- package/dist/src/db/sql/mssql/entity/JacksonTTL.d.ts +0 -4
- package/dist/src/db/sql/mssql/entity/JacksonTTL.js +0 -27
- package/dist/src/db/sql/mssql/entity/JacksonTTL.js.map +0 -1
- package/dist/src/db/sql/mssql.d.ts +0 -1
- package/dist/src/db/sql/mssql.js +0 -44
- package/dist/src/db/sql/mssql.js.map +0 -1
- package/dist/src/db/sql/sql.d.ts +0 -32
- package/dist/src/db/sql/sql.js +0 -318
- package/dist/src/db/sql/sql.js.map +0 -1
- package/dist/src/db/sql/sqlite/entity/JacksonIndex.d.ts +0 -7
- package/dist/src/db/sql/sqlite/entity/JacksonIndex.js +0 -39
- package/dist/src/db/sql/sqlite/entity/JacksonIndex.js.map +0 -1
- package/dist/src/db/sql/sqlite/entity/JacksonStore.d.ts +0 -9
- package/dist/src/db/sql/sqlite/entity/JacksonStore.js +0 -61
- package/dist/src/db/sql/sqlite/entity/JacksonStore.js.map +0 -1
- package/dist/src/db/sql/sqlite/entity/JacksonTTL.d.ts +0 -4
- package/dist/src/db/sql/sqlite/entity/JacksonTTL.js +0 -27
- package/dist/src/db/sql/sqlite/entity/JacksonTTL.js.map +0 -1
- package/dist/src/db/store.d.ts +0 -5
- package/dist/src/db/store.js +0 -65
- package/dist/src/db/store.js.map +0 -1
- package/dist/src/db/utils.d.ts +0 -16
- package/dist/src/db/utils.js +0 -28
- package/dist/src/db/utils.js.map +0 -1
- package/dist/src/directory-sync/batch-events/queue.d.ts +0 -40
- package/dist/src/directory-sync/batch-events/queue.js +0 -225
- package/dist/src/directory-sync/batch-events/queue.js.map +0 -1
- package/dist/src/directory-sync/index.d.ts +0 -27
- package/dist/src/directory-sync/index.js +0 -97
- package/dist/src/directory-sync/index.js.map +0 -1
- package/dist/src/directory-sync/non-scim/google/api.d.ts +0 -36
- package/dist/src/directory-sync/non-scim/google/api.js +0 -143
- package/dist/src/directory-sync/non-scim/google/api.js.map +0 -1
- package/dist/src/directory-sync/non-scim/google/index.d.ts +0 -12
- package/dist/src/directory-sync/non-scim/google/index.js +0 -10
- package/dist/src/directory-sync/non-scim/google/index.js.map +0 -1
- package/dist/src/directory-sync/non-scim/google/oauth.d.ts +0 -27
- package/dist/src/directory-sync/non-scim/google/oauth.js +0 -105
- package/dist/src/directory-sync/non-scim/google/oauth.js.map +0 -1
- package/dist/src/directory-sync/non-scim/index.d.ts +0 -24
- package/dist/src/directory-sync/non-scim/index.js +0 -85
- package/dist/src/directory-sync/non-scim/index.js.map +0 -1
- package/dist/src/directory-sync/non-scim/syncGroupMembers.d.ts +0 -23
- package/dist/src/directory-sync/non-scim/syncGroupMembers.js +0 -105
- package/dist/src/directory-sync/non-scim/syncGroupMembers.js.map +0 -1
- package/dist/src/directory-sync/non-scim/syncGroups.d.ts +0 -24
- package/dist/src/directory-sync/non-scim/syncGroups.js +0 -120
- package/dist/src/directory-sync/non-scim/syncGroups.js.map +0 -1
- package/dist/src/directory-sync/non-scim/syncUsers.d.ts +0 -24
- package/dist/src/directory-sync/non-scim/syncUsers.js +0 -120
- package/dist/src/directory-sync/non-scim/syncUsers.js.map +0 -1
- package/dist/src/directory-sync/non-scim/utils.d.ts +0 -36
- package/dist/src/directory-sync/non-scim/utils.js +0 -109
- package/dist/src/directory-sync/non-scim/utils.js.map +0 -1
- package/dist/src/directory-sync/request.d.ts +0 -14
- package/dist/src/directory-sync/request.js +0 -29
- package/dist/src/directory-sync/request.js.map +0 -1
- package/dist/src/directory-sync/scim/Base.d.ts +0 -12
- package/dist/src/directory-sync/scim/Base.js +0 -23
- package/dist/src/directory-sync/scim/Base.js.map +0 -1
- package/dist/src/directory-sync/scim/DirectoryConfig.d.ts +0 -343
- package/dist/src/directory-sync/scim/DirectoryConfig.js +0 -580
- package/dist/src/directory-sync/scim/DirectoryConfig.js.map +0 -1
- package/dist/src/directory-sync/scim/DirectoryGroups.d.ts +0 -28
- package/dist/src/directory-sync/scim/DirectoryGroups.js +0 -252
- package/dist/src/directory-sync/scim/DirectoryGroups.js.map +0 -1
- package/dist/src/directory-sync/scim/DirectoryUsers.d.ts +0 -25
- package/dist/src/directory-sync/scim/DirectoryUsers.js +0 -193
- package/dist/src/directory-sync/scim/DirectoryUsers.js.map +0 -1
- package/dist/src/directory-sync/scim/Groups.d.ts +0 -166
- package/dist/src/directory-sync/scim/Groups.js +0 -348
- package/dist/src/directory-sync/scim/Groups.js.map +0 -1
- package/dist/src/directory-sync/scim/Users.d.ts +0 -99
- package/dist/src/directory-sync/scim/Users.js +0 -215
- package/dist/src/directory-sync/scim/Users.js.map +0 -1
- package/dist/src/directory-sync/scim/WebhookEventsLogger.d.ts +0 -101
- package/dist/src/directory-sync/scim/WebhookEventsLogger.js +0 -165
- package/dist/src/directory-sync/scim/WebhookEventsLogger.js.map +0 -1
- package/dist/src/directory-sync/scim/transform.d.ts +0 -6
- package/dist/src/directory-sync/scim/transform.js +0 -37
- package/dist/src/directory-sync/scim/transform.js.map +0 -1
- package/dist/src/directory-sync/scim/utils.d.ts +0 -33
- package/dist/src/directory-sync/scim/utils.js +0 -129
- package/dist/src/directory-sync/scim/utils.js.map +0 -1
- package/dist/src/directory-sync/types.d.ts +0 -195
- package/dist/src/directory-sync/types.js +0 -10
- package/dist/src/directory-sync/types.js.map +0 -1
- package/dist/src/directory-sync/utils.d.ts +0 -19
- package/dist/src/directory-sync/utils.js +0 -56
- package/dist/src/directory-sync/utils.js.map +0 -1
- package/dist/src/ee/branding/index.d.ts +0 -17
- package/dist/src/ee/branding/index.js +0 -49
- package/dist/src/ee/branding/index.js.map +0 -1
- package/dist/src/ee/common/checkLicense.d.ts +0 -3
- package/dist/src/ee/common/checkLicense.js +0 -23
- package/dist/src/ee/common/checkLicense.js.map +0 -1
- package/dist/src/ee/identity-federation/app.d.ts +0 -328
- package/dist/src/ee/identity-federation/app.js +0 -532
- package/dist/src/ee/identity-federation/app.js.map +0 -1
- package/dist/src/ee/identity-federation/idp-login.d.ts +0 -18
- package/dist/src/ee/identity-federation/idp-login.js +0 -98
- package/dist/src/ee/identity-federation/idp-login.js.map +0 -1
- package/dist/src/ee/identity-federation/index.d.ts +0 -15
- package/dist/src/ee/identity-federation/index.js +0 -43
- package/dist/src/ee/identity-federation/index.js.map +0 -1
- package/dist/src/ee/identity-federation/sso.d.ts +0 -24
- package/dist/src/ee/identity-federation/sso.js +0 -124
- package/dist/src/ee/identity-federation/sso.js.map +0 -1
- package/dist/src/ee/identity-federation/types.d.ts +0 -38
- package/dist/src/ee/identity-federation/types.js +0 -2
- package/dist/src/ee/identity-federation/types.js.map +0 -1
- package/dist/src/ee/ory/ory.d.ts +0 -18
- package/dist/src/ee/ory/ory.js +0 -195
- package/dist/src/ee/ory/ory.js.map +0 -1
- package/dist/src/ee/product/index.d.ts +0 -14
- package/dist/src/ee/product/index.js +0 -45
- package/dist/src/ee/product/index.js.map +0 -1
- package/dist/src/event/axios.d.ts +0 -2
- package/dist/src/event/axios.js +0 -27
- package/dist/src/event/axios.js.map +0 -1
- package/dist/src/event/index.d.ts +0 -11
- package/dist/src/event/index.js +0 -53
- package/dist/src/event/index.js.map +0 -1
- package/dist/src/event/types.d.ts +0 -21
- package/dist/src/event/types.js +0 -2
- package/dist/src/event/types.js.map +0 -1
- package/dist/src/event/utils.d.ts +0 -4
- package/dist/src/event/utils.js +0 -33
- package/dist/src/event/utils.js.map +0 -1
- package/dist/src/event/webhook.d.ts +0 -3
- package/dist/src/event/webhook.js +0 -34
- package/dist/src/event/webhook.js.map +0 -1
- package/dist/src/index.d.ts +0 -35
- package/dist/src/index.js +0 -161
- package/dist/src/index.js.map +0 -1
- package/dist/src/loadConnection.d.ts +0 -4
- package/dist/src/loadConnection.js +0 -38
- package/dist/src/loadConnection.js.map +0 -1
- package/dist/src/opentelemetry/metrics.d.ts +0 -14
- package/dist/src/opentelemetry/metrics.js +0 -64
- package/dist/src/opentelemetry/metrics.js.map +0 -1
- package/dist/src/saml/claims.d.ts +0 -12
- package/dist/src/saml/claims.js +0 -57
- package/dist/src/saml/claims.js.map +0 -1
- package/dist/src/saml/lib.d.ts +0 -8
- package/dist/src/saml/lib.js +0 -29
- package/dist/src/saml/lib.js.map +0 -1
- package/dist/src/saml/x509.d.ts +0 -9
- package/dist/src/saml/x509.js +0 -93
- package/dist/src/saml/x509.js.map +0 -1
- package/dist/src/sso-traces/index.d.ts +0 -114
- package/dist/src/sso-traces/index.js +0 -229
- package/dist/src/sso-traces/index.js.map +0 -1
- package/dist/src/sso-traces/types.d.ts +0 -44
- package/dist/src/sso-traces/types.js +0 -2
- package/dist/src/sso-traces/types.js.map +0 -1
- package/dist/src/typings.d.ts +0 -540
- package/dist/src/typings.js +0 -5
- package/dist/src/typings.js.map +0 -1
- package/dist/typeorm.d.ts +0 -3
- package/dist/typeorm.js +0 -58
- package/dist/typeorm.js.map +0 -1
@@ -1,1112 +0,0 @@
|
|
1
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
2
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
3
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
4
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
5
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
6
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
7
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
8
|
-
});
|
9
|
-
};
|
10
|
-
var __rest = (this && this.__rest) || function (s, e) {
|
11
|
-
var t = {};
|
12
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
13
|
-
t[p] = s[p];
|
14
|
-
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
15
|
-
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
16
|
-
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
17
|
-
t[p[i]] = s[p[i]];
|
18
|
-
}
|
19
|
-
return t;
|
20
|
-
};
|
21
|
-
import crypto from 'crypto';
|
22
|
-
import * as jose from 'jose';
|
23
|
-
import { promisify } from 'util';
|
24
|
-
import { deflateRaw } from 'zlib';
|
25
|
-
import saml from '@boxyhq/saml20';
|
26
|
-
import { clientIDFederatedPrefix, clientIDOIDCPrefix, relayStatePrefix, IndexNames, OAuthErrorResponse, getErrorMessage, loadJWSPrivateKey, computeKid, isJWSKeyPairLoaded, extractOIDCUserProfile, getScopeValues, getEncodedTenantProduct, isConnectionActive, } from './utils';
|
27
|
-
import * as metrics from '../opentelemetry/metrics';
|
28
|
-
import { JacksonError } from './error';
|
29
|
-
import * as allowed from './oauth/allowed';
|
30
|
-
import * as codeVerifier from './oauth/code-verifier';
|
31
|
-
import * as redirect from './oauth/redirect';
|
32
|
-
import { getDefaultCertificate } from '../saml/x509';
|
33
|
-
import { SSOHandler } from './sso-handler';
|
34
|
-
import { extractSAMLResponseAttributes } from '../saml/lib';
|
35
|
-
import { oidcClientConfig } from './oauth/oidc-client';
|
36
|
-
const deflateRawAsync = promisify(deflateRaw);
|
37
|
-
export class OAuthController {
|
38
|
-
constructor({ connectionStore, sessionStore, codeStore, tokenStore, ssoTraces, opts, idFedApp }) {
|
39
|
-
this.connectionStore = connectionStore;
|
40
|
-
this.sessionStore = sessionStore;
|
41
|
-
this.codeStore = codeStore;
|
42
|
-
this.tokenStore = tokenStore;
|
43
|
-
this.ssoTraces = ssoTraces;
|
44
|
-
this.opts = opts;
|
45
|
-
this.idFedApp = idFedApp;
|
46
|
-
this.ssoHandler = new SSOHandler({
|
47
|
-
connection: connectionStore,
|
48
|
-
session: sessionStore,
|
49
|
-
opts,
|
50
|
-
});
|
51
|
-
}
|
52
|
-
authorize(body) {
|
53
|
-
return __awaiter(this, void 0, void 0, function* () {
|
54
|
-
var _a, _b, _c;
|
55
|
-
const { tenant, product, access_type, resource, response_type = 'code', client_id, redirect_uri, state, scope, nonce, code_challenge, code_challenge_method = '', idp_hint, forceAuthn = 'false', login_hint } = body, oidcParams = __rest(body, ["tenant", "product", "access_type", "resource", "response_type", "client_id", "redirect_uri", "state", "scope", "nonce", "code_challenge", "code_challenge_method", "idp_hint", "forceAuthn", "login_hint"]) // Rest of the params will be assumed as OIDC params and will be forwarded to the IdP
|
56
|
-
;
|
57
|
-
let requestedTenant;
|
58
|
-
let requestedProduct;
|
59
|
-
let requestedScopes;
|
60
|
-
let requestedOIDCFlow;
|
61
|
-
let isOIDCFederated;
|
62
|
-
let connection;
|
63
|
-
let fedApp;
|
64
|
-
try {
|
65
|
-
requestedTenant = tenant;
|
66
|
-
requestedProduct = product;
|
67
|
-
metrics.increment('oauthAuthorize');
|
68
|
-
if (!redirect_uri) {
|
69
|
-
throw new JacksonError('Please specify a redirect URL.', 400);
|
70
|
-
}
|
71
|
-
requestedScopes = getScopeValues(scope);
|
72
|
-
requestedOIDCFlow = requestedScopes.includes('openid');
|
73
|
-
if (tenant && product) {
|
74
|
-
const response = yield this.ssoHandler.resolveConnection({
|
75
|
-
tenant,
|
76
|
-
product,
|
77
|
-
idp_hint,
|
78
|
-
authFlow: 'oauth',
|
79
|
-
originalParams: Object.assign({}, body),
|
80
|
-
});
|
81
|
-
if ('redirectUrl' in response) {
|
82
|
-
return {
|
83
|
-
redirect_url: response.redirectUrl,
|
84
|
-
};
|
85
|
-
}
|
86
|
-
if ('connection' in response) {
|
87
|
-
connection = response.connection;
|
88
|
-
}
|
89
|
-
}
|
90
|
-
else if (client_id && client_id !== '' && client_id !== 'undefined' && client_id !== 'null') {
|
91
|
-
// if tenant and product are encoded in the client_id then we parse it and check for the relevant connection(s)
|
92
|
-
let sp = getEncodedTenantProduct(client_id);
|
93
|
-
if (!sp && access_type) {
|
94
|
-
sp = getEncodedTenantProduct(access_type);
|
95
|
-
}
|
96
|
-
if (!sp && resource) {
|
97
|
-
sp = getEncodedTenantProduct(resource);
|
98
|
-
if (sp === null) {
|
99
|
-
oidcParams.resource = resource;
|
100
|
-
}
|
101
|
-
}
|
102
|
-
if (!sp && requestedScopes) {
|
103
|
-
const encodedParams = requestedScopes.find((scope) => scope.includes('=') && scope.includes('&')); // for now assume only one encoded param i.e. for tenant/product
|
104
|
-
if (encodedParams) {
|
105
|
-
sp = getEncodedTenantProduct(encodedParams);
|
106
|
-
}
|
107
|
-
}
|
108
|
-
if (sp && sp.tenant && sp.product) {
|
109
|
-
const { tenant, product } = sp;
|
110
|
-
requestedTenant = tenant;
|
111
|
-
requestedProduct = product;
|
112
|
-
const response = yield this.ssoHandler.resolveConnection({
|
113
|
-
tenant,
|
114
|
-
product,
|
115
|
-
idp_hint,
|
116
|
-
authFlow: 'oauth',
|
117
|
-
originalParams: Object.assign({}, body),
|
118
|
-
});
|
119
|
-
if ('redirectUrl' in response) {
|
120
|
-
return {
|
121
|
-
redirect_url: response.redirectUrl,
|
122
|
-
};
|
123
|
-
}
|
124
|
-
if ('connection' in response) {
|
125
|
-
connection = response.connection;
|
126
|
-
}
|
127
|
-
}
|
128
|
-
else {
|
129
|
-
// client_id is not encoded, so we look for the connection using the client_id
|
130
|
-
// First we check if it's a federated connection
|
131
|
-
if (client_id.startsWith(`${clientIDFederatedPrefix}${clientIDOIDCPrefix}`)) {
|
132
|
-
isOIDCFederated = true;
|
133
|
-
fedApp = yield this.idFedApp.get({
|
134
|
-
id: client_id.replace(clientIDFederatedPrefix, ''),
|
135
|
-
});
|
136
|
-
const response = yield this.ssoHandler.resolveConnection({
|
137
|
-
tenant: fedApp.tenant,
|
138
|
-
product: fedApp.product,
|
139
|
-
idp_hint,
|
140
|
-
authFlow: 'oauth',
|
141
|
-
originalParams: Object.assign({}, body),
|
142
|
-
tenants: fedApp.tenants,
|
143
|
-
idFedAppId: fedApp.id,
|
144
|
-
fedType: fedApp.type,
|
145
|
-
});
|
146
|
-
if ('redirectUrl' in response) {
|
147
|
-
return {
|
148
|
-
redirect_url: response.redirectUrl,
|
149
|
-
};
|
150
|
-
}
|
151
|
-
if ('connection' in response) {
|
152
|
-
connection = response.connection;
|
153
|
-
requestedTenant = fedApp.tenant;
|
154
|
-
requestedProduct = fedApp.product;
|
155
|
-
}
|
156
|
-
}
|
157
|
-
else {
|
158
|
-
// If it's not a federated connection, we look for the connection using the client_id
|
159
|
-
connection = yield this.connectionStore.get(client_id);
|
160
|
-
if (connection) {
|
161
|
-
requestedTenant = connection.tenant;
|
162
|
-
requestedProduct = connection.product;
|
163
|
-
}
|
164
|
-
}
|
165
|
-
}
|
166
|
-
}
|
167
|
-
else {
|
168
|
-
throw new JacksonError('You need to specify client_id or tenant & product', 403);
|
169
|
-
}
|
170
|
-
if (!connection) {
|
171
|
-
throw new JacksonError('IdP connection not found.', 403);
|
172
|
-
}
|
173
|
-
if (!allowed.redirect(redirect_uri, connection.redirectUrl)) {
|
174
|
-
if (fedApp) {
|
175
|
-
if (!allowed.redirect(redirect_uri, fedApp.redirectUrl)) {
|
176
|
-
throw new JacksonError('Redirect URL is not allowed.', 403);
|
177
|
-
}
|
178
|
-
}
|
179
|
-
else {
|
180
|
-
throw new JacksonError('Redirect URL is not allowed.', 403);
|
181
|
-
}
|
182
|
-
}
|
183
|
-
if (!isConnectionActive(connection)) {
|
184
|
-
throw new JacksonError('SSO connection is deactivated. Please contact your administrator.', 403);
|
185
|
-
}
|
186
|
-
}
|
187
|
-
catch (err) {
|
188
|
-
const error_description = getErrorMessage(err);
|
189
|
-
// Save the error trace
|
190
|
-
yield this.ssoTraces.saveTrace({
|
191
|
-
error: error_description,
|
192
|
-
context: {
|
193
|
-
tenant: requestedTenant || '',
|
194
|
-
product: requestedProduct || '',
|
195
|
-
clientID: (connection === null || connection === void 0 ? void 0 : connection.clientID) || '',
|
196
|
-
requestedOIDCFlow,
|
197
|
-
isOIDCFederated,
|
198
|
-
redirectUri: redirect_uri,
|
199
|
-
},
|
200
|
-
});
|
201
|
-
throw err;
|
202
|
-
}
|
203
|
-
const isMissingJWTKeysForOIDCFlow = requestedOIDCFlow &&
|
204
|
-
(!((_a = this.opts.openid) === null || _a === void 0 ? void 0 : _a.jwtSigningKeys) || !isJWSKeyPairLoaded(this.opts.openid.jwtSigningKeys));
|
205
|
-
const oAuthClientReqError = !state || response_type !== 'code';
|
206
|
-
const connectionIsSAML = 'idpMetadata' in connection && connection.idpMetadata !== undefined;
|
207
|
-
const connectionIsOIDC = 'oidcProvider' in connection && connection.oidcProvider !== undefined;
|
208
|
-
if (isMissingJWTKeysForOIDCFlow || oAuthClientReqError || (!connectionIsSAML && !connectionIsOIDC)) {
|
209
|
-
let error, error_description;
|
210
|
-
if (isMissingJWTKeysForOIDCFlow) {
|
211
|
-
error = 'server_error';
|
212
|
-
error_description =
|
213
|
-
'OAuth server not configured correctly for openid flow, check if JWT signing keys are loaded';
|
214
|
-
}
|
215
|
-
if (!state) {
|
216
|
-
error = 'invalid_request';
|
217
|
-
error_description = 'Please specify a state to safeguard against XSRF attacks';
|
218
|
-
}
|
219
|
-
if (response_type !== 'code') {
|
220
|
-
error = 'unsupported_response_type';
|
221
|
-
error_description = 'Only Authorization Code grant is supported';
|
222
|
-
}
|
223
|
-
if (!connectionIsSAML && !connectionIsOIDC) {
|
224
|
-
error = 'server_error';
|
225
|
-
error_description = 'Connection appears to be misconfigured';
|
226
|
-
}
|
227
|
-
// Save the error trace
|
228
|
-
const traceId = yield this.ssoTraces.saveTrace({
|
229
|
-
error: error_description,
|
230
|
-
context: {
|
231
|
-
tenant: requestedTenant,
|
232
|
-
product: requestedProduct,
|
233
|
-
clientID: connection.clientID,
|
234
|
-
requestedOIDCFlow,
|
235
|
-
isOIDCFederated,
|
236
|
-
redirectUri: redirect_uri,
|
237
|
-
},
|
238
|
-
});
|
239
|
-
return {
|
240
|
-
redirect_url: OAuthErrorResponse({
|
241
|
-
error,
|
242
|
-
error_description: traceId ? `${traceId}: ${error_description}` : error_description,
|
243
|
-
redirect_uri,
|
244
|
-
state,
|
245
|
-
}),
|
246
|
-
};
|
247
|
-
}
|
248
|
-
// Connection retrieved: Handover to IdP starts here
|
249
|
-
let ssoUrl;
|
250
|
-
let post = false;
|
251
|
-
// Init sessionId
|
252
|
-
const sessionId = crypto.randomBytes(16).toString('hex');
|
253
|
-
const relayState = relayStatePrefix + sessionId;
|
254
|
-
// SAML connection: SAML request will be constructed here
|
255
|
-
let samlReq;
|
256
|
-
if (connectionIsSAML) {
|
257
|
-
try {
|
258
|
-
const { sso } = connection.idpMetadata;
|
259
|
-
if ('redirectUrl' in sso) {
|
260
|
-
// HTTP Redirect binding
|
261
|
-
ssoUrl = sso.redirectUrl;
|
262
|
-
}
|
263
|
-
else if ('postUrl' in sso) {
|
264
|
-
// HTTP-POST binding
|
265
|
-
ssoUrl = sso.postUrl;
|
266
|
-
post = true;
|
267
|
-
}
|
268
|
-
else {
|
269
|
-
// This code here is kept for backward compatibility. We now have validation while adding the SSO connection to ensure binding is present.
|
270
|
-
const error_description = 'SAML binding could not be retrieved';
|
271
|
-
// Save the error trace
|
272
|
-
const traceId = yield this.ssoTraces.saveTrace({
|
273
|
-
error: error_description,
|
274
|
-
context: {
|
275
|
-
tenant: requestedTenant,
|
276
|
-
product: requestedProduct,
|
277
|
-
clientID: connection.clientID,
|
278
|
-
requestedOIDCFlow,
|
279
|
-
isOIDCFederated,
|
280
|
-
redirectUri: redirect_uri,
|
281
|
-
},
|
282
|
-
});
|
283
|
-
return {
|
284
|
-
redirect_url: OAuthErrorResponse({
|
285
|
-
error: 'invalid_request',
|
286
|
-
error_description: traceId ? `${traceId}: ${error_description}` : error_description,
|
287
|
-
redirect_uri,
|
288
|
-
state,
|
289
|
-
}),
|
290
|
-
};
|
291
|
-
}
|
292
|
-
const cert = yield getDefaultCertificate();
|
293
|
-
samlReq = saml.request({
|
294
|
-
ssoUrl,
|
295
|
-
entityID: this.opts.samlAudience,
|
296
|
-
callbackUrl: this.opts.externalUrl + this.opts.samlPath,
|
297
|
-
signingKey: cert.privateKey,
|
298
|
-
publicKey: cert.publicKey,
|
299
|
-
forceAuthn: forceAuthn === 'true' ? true : !!connection.forceAuthn,
|
300
|
-
identifierFormat: connection.identifierFormat
|
301
|
-
? connection.identifierFormat
|
302
|
-
: 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress',
|
303
|
-
});
|
304
|
-
}
|
305
|
-
catch (err) {
|
306
|
-
const error_description = getErrorMessage(err);
|
307
|
-
// Save the error trace
|
308
|
-
const traceId = yield this.ssoTraces.saveTrace({
|
309
|
-
error: error_description,
|
310
|
-
context: {
|
311
|
-
tenant: requestedTenant,
|
312
|
-
product: requestedProduct,
|
313
|
-
clientID: connection.clientID,
|
314
|
-
requestedOIDCFlow,
|
315
|
-
isOIDCFederated,
|
316
|
-
redirectUri: redirect_uri,
|
317
|
-
},
|
318
|
-
});
|
319
|
-
return {
|
320
|
-
redirect_url: OAuthErrorResponse({
|
321
|
-
error: 'server_error',
|
322
|
-
error_description: traceId ? `${traceId}: ${error_description}` : error_description,
|
323
|
-
redirect_uri,
|
324
|
-
state,
|
325
|
-
}),
|
326
|
-
};
|
327
|
-
}
|
328
|
-
}
|
329
|
-
// OIDC Connection: Issuer discovery, openid-client init and extraction of authorization endpoint happens here
|
330
|
-
let oidcCodeVerifier;
|
331
|
-
let oidcNonce;
|
332
|
-
if (connectionIsOIDC) {
|
333
|
-
const { discoveryUrl, metadata, clientId, clientSecret } = connection.oidcProvider;
|
334
|
-
const { ssoTraces } = this;
|
335
|
-
try {
|
336
|
-
if (!this.opts.oidcPath) {
|
337
|
-
throw new JacksonError('OpenID response handler path (oidcPath) is not set');
|
338
|
-
}
|
339
|
-
const client = yield import('openid-client');
|
340
|
-
const oidcConfig = yield oidcClientConfig({
|
341
|
-
discoveryUrl,
|
342
|
-
metadata,
|
343
|
-
clientId,
|
344
|
-
clientSecret,
|
345
|
-
ssoTraces: {
|
346
|
-
instance: ssoTraces,
|
347
|
-
context: {
|
348
|
-
tenant: requestedTenant,
|
349
|
-
product: requestedProduct,
|
350
|
-
clientID: connection.clientID,
|
351
|
-
requestedOIDCFlow,
|
352
|
-
isOIDCFederated,
|
353
|
-
redirectUri: redirect_uri,
|
354
|
-
},
|
355
|
-
},
|
356
|
-
});
|
357
|
-
oidcCodeVerifier = client.randomPKCECodeVerifier();
|
358
|
-
const code_challenge = yield client.calculatePKCECodeChallenge(oidcCodeVerifier);
|
359
|
-
oidcNonce = client.randomNonce();
|
360
|
-
const standardScopes = ((_b = this.opts.openid) === null || _b === void 0 ? void 0 : _b.requestProfileScope)
|
361
|
-
? ['openid', 'email', 'profile']
|
362
|
-
: ['openid', 'email'];
|
363
|
-
const paramsToForward = ((_c = this.opts.openid) === null || _c === void 0 ? void 0 : _c.forwardOIDCParams) ? oidcParams : {};
|
364
|
-
if (login_hint) {
|
365
|
-
paramsToForward.login_hint = login_hint;
|
366
|
-
}
|
367
|
-
ssoUrl = client.buildAuthorizationUrl(oidcConfig, Object.assign({ scope: [...requestedScopes, ...standardScopes]
|
368
|
-
.filter((value, index, self) => self.indexOf(value) === index) // filter out duplicates
|
369
|
-
.join(' '), code_challenge, code_challenge_method: 'S256', state: relayState, nonce: oidcNonce, redirect_uri: this.opts.externalUrl + this.opts.oidcPath }, paramsToForward)).href;
|
370
|
-
}
|
371
|
-
catch (err) {
|
372
|
-
const error_description = getErrorMessage(err);
|
373
|
-
// Save the error trace
|
374
|
-
const traceId = yield this.ssoTraces.saveTrace({
|
375
|
-
error: error_description,
|
376
|
-
context: {
|
377
|
-
tenant: requestedTenant,
|
378
|
-
product: requestedProduct,
|
379
|
-
clientID: connection.clientID,
|
380
|
-
requestedOIDCFlow,
|
381
|
-
isOIDCFederated,
|
382
|
-
redirectUri: redirect_uri,
|
383
|
-
},
|
384
|
-
});
|
385
|
-
if (err) {
|
386
|
-
return {
|
387
|
-
redirect_url: OAuthErrorResponse({
|
388
|
-
error: 'server_error',
|
389
|
-
error_description: traceId ? `${traceId}: ${error_description}` : error_description,
|
390
|
-
redirect_uri,
|
391
|
-
state,
|
392
|
-
}),
|
393
|
-
};
|
394
|
-
}
|
395
|
-
}
|
396
|
-
}
|
397
|
-
// Session persistence happens here
|
398
|
-
try {
|
399
|
-
const requested = { client_id, state, redirect_uri };
|
400
|
-
if (requestedTenant) {
|
401
|
-
requested.tenant = requestedTenant;
|
402
|
-
}
|
403
|
-
if (requestedProduct) {
|
404
|
-
requested.product = requestedProduct;
|
405
|
-
}
|
406
|
-
if (idp_hint) {
|
407
|
-
requested.idp_hint = idp_hint;
|
408
|
-
}
|
409
|
-
else {
|
410
|
-
if (fedApp) {
|
411
|
-
requested.idp_hint = connection.clientID;
|
412
|
-
}
|
413
|
-
}
|
414
|
-
if (requestedOIDCFlow) {
|
415
|
-
requested.oidc = true;
|
416
|
-
if (nonce) {
|
417
|
-
requested.nonce = nonce;
|
418
|
-
}
|
419
|
-
}
|
420
|
-
if (requestedScopes) {
|
421
|
-
requested.scope = requestedScopes;
|
422
|
-
}
|
423
|
-
const sessionObj = {
|
424
|
-
redirect_uri,
|
425
|
-
response_type,
|
426
|
-
state,
|
427
|
-
code_challenge,
|
428
|
-
code_challenge_method,
|
429
|
-
requested,
|
430
|
-
oidcFederated: fedApp
|
431
|
-
? {
|
432
|
-
redirectUrl: fedApp.redirectUrl,
|
433
|
-
id: fedApp.id,
|
434
|
-
clientID: fedApp.clientID,
|
435
|
-
clientSecret: fedApp.clientSecret,
|
436
|
-
}
|
437
|
-
: undefined,
|
438
|
-
};
|
439
|
-
yield this.sessionStore.put(sessionId, connectionIsSAML
|
440
|
-
? Object.assign(Object.assign({}, sessionObj), { id: samlReq === null || samlReq === void 0 ? void 0 : samlReq.id }) : Object.assign(Object.assign({}, sessionObj), { id: connection.clientID, oidcCodeVerifier, oidcNonce }));
|
441
|
-
// Redirect to IdP
|
442
|
-
if (connectionIsSAML) {
|
443
|
-
let redirectUrl;
|
444
|
-
let authorizeForm;
|
445
|
-
if (!post) {
|
446
|
-
// HTTP Redirect binding
|
447
|
-
redirectUrl = redirect.success(ssoUrl, {
|
448
|
-
RelayState: relayState,
|
449
|
-
SAMLRequest: Buffer.from(yield deflateRawAsync(samlReq.request)).toString('base64'),
|
450
|
-
});
|
451
|
-
}
|
452
|
-
else {
|
453
|
-
// HTTP POST binding
|
454
|
-
authorizeForm = saml.createPostForm(ssoUrl, [
|
455
|
-
{
|
456
|
-
name: 'RelayState',
|
457
|
-
value: relayState,
|
458
|
-
},
|
459
|
-
{
|
460
|
-
name: 'SAMLRequest',
|
461
|
-
value: Buffer.from(samlReq.request).toString('base64'),
|
462
|
-
},
|
463
|
-
]);
|
464
|
-
}
|
465
|
-
return {
|
466
|
-
redirect_url: redirectUrl,
|
467
|
-
authorize_form: authorizeForm,
|
468
|
-
};
|
469
|
-
}
|
470
|
-
if (connectionIsOIDC) {
|
471
|
-
return { redirect_url: ssoUrl };
|
472
|
-
}
|
473
|
-
throw 'Connection appears to be misconfigured';
|
474
|
-
}
|
475
|
-
catch (err) {
|
476
|
-
const error_description = getErrorMessage(err);
|
477
|
-
// Save the error trace
|
478
|
-
const traceId = yield this.ssoTraces.saveTrace({
|
479
|
-
error: error_description,
|
480
|
-
context: {
|
481
|
-
tenant: requestedTenant,
|
482
|
-
product: requestedProduct,
|
483
|
-
clientID: connection.clientID,
|
484
|
-
requestedOIDCFlow,
|
485
|
-
isOIDCFederated,
|
486
|
-
redirectUri: redirect_uri,
|
487
|
-
samlRequest: (samlReq === null || samlReq === void 0 ? void 0 : samlReq.request) || '',
|
488
|
-
},
|
489
|
-
});
|
490
|
-
return {
|
491
|
-
redirect_url: OAuthErrorResponse({
|
492
|
-
error: 'server_error',
|
493
|
-
error_description: traceId ? `${traceId}: ${error_description}` : error_description,
|
494
|
-
redirect_uri,
|
495
|
-
state,
|
496
|
-
}),
|
497
|
-
};
|
498
|
-
}
|
499
|
-
});
|
500
|
-
}
|
501
|
-
samlResponse(body) {
|
502
|
-
return __awaiter(this, void 0, void 0, function* () {
|
503
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
|
504
|
-
let connection;
|
505
|
-
let rawResponse;
|
506
|
-
let sessionId;
|
507
|
-
let session;
|
508
|
-
let issuer;
|
509
|
-
let isIdPFlow;
|
510
|
-
let isSAMLFederated;
|
511
|
-
let isOIDCFederated;
|
512
|
-
let validateOpts;
|
513
|
-
let redirect_uri;
|
514
|
-
const { SAMLResponse, idp_hint, RelayState = '' } = body;
|
515
|
-
try {
|
516
|
-
isIdPFlow = !RelayState.startsWith(relayStatePrefix);
|
517
|
-
rawResponse = Buffer.from(SAMLResponse, 'base64').toString();
|
518
|
-
issuer = saml.parseIssuer(rawResponse);
|
519
|
-
if (!this.opts.idpEnabled && isIdPFlow) {
|
520
|
-
// IdP login is disabled so block the request
|
521
|
-
throw new JacksonError('IdP (Identity Provider) flow has been disabled. Please head to your Service Provider to login.', 403);
|
522
|
-
}
|
523
|
-
sessionId = RelayState.replace(relayStatePrefix, '');
|
524
|
-
if (!issuer) {
|
525
|
-
throw new JacksonError('Issuer not found.', 403);
|
526
|
-
}
|
527
|
-
const connections = (yield this.connectionStore.getByIndex({
|
528
|
-
name: IndexNames.EntityID,
|
529
|
-
value: issuer,
|
530
|
-
})).data;
|
531
|
-
if (!connections || connections.length === 0) {
|
532
|
-
throw new JacksonError('SAML connection not found.', 403);
|
533
|
-
}
|
534
|
-
session = sessionId ? yield this.sessionStore.get(sessionId) : null;
|
535
|
-
if (!isIdPFlow && !session) {
|
536
|
-
throw new JacksonError('Unable to validate state from the origin request.', 403);
|
537
|
-
}
|
538
|
-
isSAMLFederated = session && 'samlFederated' in session;
|
539
|
-
isOIDCFederated = session && 'oidcFederated' in session;
|
540
|
-
const isSPFlow = !isIdPFlow && !isSAMLFederated;
|
541
|
-
// IdP initiated SSO flow
|
542
|
-
if (isIdPFlow) {
|
543
|
-
const response = yield this.ssoHandler.resolveConnection({
|
544
|
-
idp_hint,
|
545
|
-
authFlow: 'idp-initiated',
|
546
|
-
entityId: issuer,
|
547
|
-
originalParams: {
|
548
|
-
SAMLResponse,
|
549
|
-
},
|
550
|
-
});
|
551
|
-
// Redirect to the product selection page
|
552
|
-
if ('postForm' in response) {
|
553
|
-
return {
|
554
|
-
app_select_form: response.postForm,
|
555
|
-
};
|
556
|
-
}
|
557
|
-
// Found a connection
|
558
|
-
if ('connection' in response) {
|
559
|
-
connection = response.connection;
|
560
|
-
if (!isConnectionActive(connection)) {
|
561
|
-
throw new JacksonError('SSO connection is deactivated. Please contact your administrator.', 403);
|
562
|
-
}
|
563
|
-
}
|
564
|
-
}
|
565
|
-
// SP initiated SSO flow
|
566
|
-
// Resolve if there are multiple matches for SP login
|
567
|
-
if (isSPFlow || isSAMLFederated || isOIDCFederated) {
|
568
|
-
connection = connections.filter((c) => {
|
569
|
-
return (c.clientID === session.requested.client_id ||
|
570
|
-
c.clientID === session.requested.idp_hint ||
|
571
|
-
(c.tenant === session.requested.tenant && c.product === session.requested.product));
|
572
|
-
})[0];
|
573
|
-
}
|
574
|
-
if (!connection) {
|
575
|
-
throw new JacksonError('SAML connection not found.', 403);
|
576
|
-
}
|
577
|
-
if (session &&
|
578
|
-
session.redirect_uri &&
|
579
|
-
!allowed.redirect(session.redirect_uri, connection.redirectUrl)) {
|
580
|
-
if (isOIDCFederated) {
|
581
|
-
if (!allowed.redirect(session.redirect_uri, (_a = session.oidcFederated) === null || _a === void 0 ? void 0 : _a.redirectUrl)) {
|
582
|
-
throw new JacksonError('Redirect URL is not allowed.', 403);
|
583
|
-
}
|
584
|
-
}
|
585
|
-
else {
|
586
|
-
throw new JacksonError('Redirect URL is not allowed.', 403);
|
587
|
-
}
|
588
|
-
}
|
589
|
-
const { privateKey } = yield getDefaultCertificate();
|
590
|
-
validateOpts = {
|
591
|
-
audience: `${this.opts.samlAudience}`,
|
592
|
-
privateKey,
|
593
|
-
};
|
594
|
-
if (connection.idpMetadata.publicKey) {
|
595
|
-
validateOpts.publicKey = connection.idpMetadata.publicKey;
|
596
|
-
}
|
597
|
-
else if (connection.idpMetadata.thumbprint) {
|
598
|
-
validateOpts.thumbprint = connection.idpMetadata.thumbprint;
|
599
|
-
}
|
600
|
-
if (session && session.id) {
|
601
|
-
validateOpts['inResponseTo'] = session.id;
|
602
|
-
}
|
603
|
-
redirect_uri = (session && session.redirect_uri) || connection.defaultRedirectUrl;
|
604
|
-
}
|
605
|
-
catch (err) {
|
606
|
-
// Save the error trace
|
607
|
-
yield this.ssoTraces.saveTrace({
|
608
|
-
error: getErrorMessage(err),
|
609
|
-
context: {
|
610
|
-
samlResponse: rawResponse,
|
611
|
-
tenant: ((_b = session === null || session === void 0 ? void 0 : session.requested) === null || _b === void 0 ? void 0 : _b.tenant) || (connection === null || connection === void 0 ? void 0 : connection.tenant),
|
612
|
-
product: ((_c = session === null || session === void 0 ? void 0 : session.requested) === null || _c === void 0 ? void 0 : _c.product) || (connection === null || connection === void 0 ? void 0 : connection.product),
|
613
|
-
clientID: ((_d = session === null || session === void 0 ? void 0 : session.requested) === null || _d === void 0 ? void 0 : _d.client_id) || (connection === null || connection === void 0 ? void 0 : connection.clientID),
|
614
|
-
providerName: (_e = connection === null || connection === void 0 ? void 0 : connection.idpMetadata) === null || _e === void 0 ? void 0 : _e.provider,
|
615
|
-
redirectUri: isIdPFlow ? connection === null || connection === void 0 ? void 0 : connection.defaultRedirectUrl : session === null || session === void 0 ? void 0 : session.redirect_uri,
|
616
|
-
issuer,
|
617
|
-
isSAMLFederated,
|
618
|
-
isOIDCFederated,
|
619
|
-
isIdPFlow,
|
620
|
-
requestedOIDCFlow: !!((_f = session === null || session === void 0 ? void 0 : session.requested) === null || _f === void 0 ? void 0 : _f.oidc),
|
621
|
-
acsUrl: (_g = session === null || session === void 0 ? void 0 : session.requested) === null || _g === void 0 ? void 0 : _g.acsUrl,
|
622
|
-
entityId: (_h = session === null || session === void 0 ? void 0 : session.requested) === null || _h === void 0 ? void 0 : _h.entityId,
|
623
|
-
relayState: RelayState,
|
624
|
-
},
|
625
|
-
});
|
626
|
-
throw err; // Rethrow the error
|
627
|
-
}
|
628
|
-
let profile;
|
629
|
-
try {
|
630
|
-
profile = yield extractSAMLResponseAttributes(rawResponse, validateOpts);
|
631
|
-
// This is a federated SAML flow, let's create a new SAMLResponse and POST it to the SP
|
632
|
-
if (isSAMLFederated) {
|
633
|
-
const { responseForm } = yield this.ssoHandler.createSAMLResponse({ profile, session });
|
634
|
-
yield this.sessionStore.delete(sessionId);
|
635
|
-
return { response_form: responseForm };
|
636
|
-
}
|
637
|
-
const code = yield this._buildAuthorizationCode(connection, profile, session, isIdPFlow);
|
638
|
-
const params = {
|
639
|
-
code,
|
640
|
-
};
|
641
|
-
if (session && session.state) {
|
642
|
-
params['state'] = session.state;
|
643
|
-
}
|
644
|
-
yield this.sessionStore.delete(sessionId);
|
645
|
-
return { redirect_url: redirect.success(redirect_uri, params) };
|
646
|
-
}
|
647
|
-
catch (err) {
|
648
|
-
const error_description = getErrorMessage(err);
|
649
|
-
// Trace the error
|
650
|
-
const traceId = yield this.ssoTraces.saveTrace({
|
651
|
-
error: error_description,
|
652
|
-
context: {
|
653
|
-
samlResponse: rawResponse,
|
654
|
-
tenant: connection.tenant,
|
655
|
-
product: connection.product,
|
656
|
-
clientID: connection.clientID,
|
657
|
-
providerName: (_j = connection === null || connection === void 0 ? void 0 : connection.idpMetadata) === null || _j === void 0 ? void 0 : _j.provider,
|
658
|
-
redirectUri: isIdPFlow ? connection === null || connection === void 0 ? void 0 : connection.defaultRedirectUrl : session === null || session === void 0 ? void 0 : session.redirect_uri,
|
659
|
-
isSAMLFederated,
|
660
|
-
isOIDCFederated,
|
661
|
-
isIdPFlow,
|
662
|
-
acsUrl: (_k = session === null || session === void 0 ? void 0 : session.requested) === null || _k === void 0 ? void 0 : _k.acsUrl,
|
663
|
-
entityId: (_l = session === null || session === void 0 ? void 0 : session.requested) === null || _l === void 0 ? void 0 : _l.entityId,
|
664
|
-
requestedOIDCFlow: !!((_m = session === null || session === void 0 ? void 0 : session.requested) === null || _m === void 0 ? void 0 : _m.oidc),
|
665
|
-
relayState: RelayState,
|
666
|
-
issuer,
|
667
|
-
profile,
|
668
|
-
},
|
669
|
-
});
|
670
|
-
if (isSAMLFederated) {
|
671
|
-
throw err;
|
672
|
-
}
|
673
|
-
return {
|
674
|
-
redirect_url: OAuthErrorResponse({
|
675
|
-
error: 'access_denied',
|
676
|
-
error_description: traceId ? `${traceId}: ${error_description}` : error_description,
|
677
|
-
redirect_uri,
|
678
|
-
state: (_o = session === null || session === void 0 ? void 0 : session.requested) === null || _o === void 0 ? void 0 : _o.state,
|
679
|
-
}),
|
680
|
-
};
|
681
|
-
}
|
682
|
-
});
|
683
|
-
}
|
684
|
-
oidcAuthzResponse(body) {
|
685
|
-
return __awaiter(this, void 0, void 0, function* () {
|
686
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
|
687
|
-
let oidcConnection;
|
688
|
-
let session;
|
689
|
-
let isSAMLFederated;
|
690
|
-
let isOIDCFederated;
|
691
|
-
let redirect_uri;
|
692
|
-
let profile;
|
693
|
-
const callbackParams = body;
|
694
|
-
let RelayState = callbackParams.state || '';
|
695
|
-
try {
|
696
|
-
if (!RelayState) {
|
697
|
-
throw new JacksonError('State from original request is missing.', 403);
|
698
|
-
}
|
699
|
-
RelayState = RelayState.replace(relayStatePrefix, '');
|
700
|
-
session = yield this.sessionStore.get(RelayState);
|
701
|
-
if (!session) {
|
702
|
-
throw new JacksonError('Unable to validate state from the original request.', 403);
|
703
|
-
}
|
704
|
-
isSAMLFederated = session && 'samlFederated' in session;
|
705
|
-
isOIDCFederated = session && 'oidcFederated' in session;
|
706
|
-
oidcConnection = yield this.connectionStore.get(session.id);
|
707
|
-
if (!oidcConnection) {
|
708
|
-
throw new JacksonError('OIDC connection not found.', 403);
|
709
|
-
}
|
710
|
-
if (!isSAMLFederated) {
|
711
|
-
redirect_uri = session && session.redirect_uri;
|
712
|
-
if (!redirect_uri) {
|
713
|
-
throw new JacksonError('Redirect URL from the authorization request could not be retrieved', 403);
|
714
|
-
}
|
715
|
-
if (redirect_uri && !allowed.redirect(redirect_uri, oidcConnection.redirectUrl)) {
|
716
|
-
if (isOIDCFederated) {
|
717
|
-
if (!allowed.redirect(redirect_uri, (_a = session.oidcFederated) === null || _a === void 0 ? void 0 : _a.redirectUrl)) {
|
718
|
-
throw new JacksonError('Redirect URL is not allowed.', 403);
|
719
|
-
}
|
720
|
-
}
|
721
|
-
else {
|
722
|
-
throw new JacksonError('Redirect URL is not allowed.', 403);
|
723
|
-
}
|
724
|
-
}
|
725
|
-
}
|
726
|
-
}
|
727
|
-
catch (err) {
|
728
|
-
yield this.ssoTraces.saveTrace({
|
729
|
-
error: getErrorMessage(err),
|
730
|
-
context: {
|
731
|
-
tenant: ((_b = session === null || session === void 0 ? void 0 : session.requested) === null || _b === void 0 ? void 0 : _b.tenant) || (oidcConnection === null || oidcConnection === void 0 ? void 0 : oidcConnection.tenant),
|
732
|
-
product: ((_c = session === null || session === void 0 ? void 0 : session.requested) === null || _c === void 0 ? void 0 : _c.product) || (oidcConnection === null || oidcConnection === void 0 ? void 0 : oidcConnection.product),
|
733
|
-
clientID: ((_d = session === null || session === void 0 ? void 0 : session.requested) === null || _d === void 0 ? void 0 : _d.client_id) || (oidcConnection === null || oidcConnection === void 0 ? void 0 : oidcConnection.clientID),
|
734
|
-
providerName: (_e = oidcConnection === null || oidcConnection === void 0 ? void 0 : oidcConnection.oidcProvider) === null || _e === void 0 ? void 0 : _e.provider,
|
735
|
-
acsUrl: (_f = session === null || session === void 0 ? void 0 : session.requested) === null || _f === void 0 ? void 0 : _f.acsUrl,
|
736
|
-
entityId: (_g = session === null || session === void 0 ? void 0 : session.requested) === null || _g === void 0 ? void 0 : _g.entityId,
|
737
|
-
redirectUri: redirect_uri,
|
738
|
-
relayState: RelayState,
|
739
|
-
isSAMLFederated,
|
740
|
-
isOIDCFederated,
|
741
|
-
requestedOIDCFlow: !!((_h = session === null || session === void 0 ? void 0 : session.requested) === null || _h === void 0 ? void 0 : _h.oidc),
|
742
|
-
oidcIdPRequest: (_j = session === null || session === void 0 ? void 0 : session.requested) === null || _j === void 0 ? void 0 : _j.oidcIdPRequest,
|
743
|
-
},
|
744
|
-
});
|
745
|
-
// Rethrow err and redirect to Jackson error page
|
746
|
-
throw err;
|
747
|
-
}
|
748
|
-
// Reconstruct the oidcClient, code exchange for token and user profile happens here
|
749
|
-
const { discoveryUrl, metadata, clientId, clientSecret } = oidcConnection.oidcProvider;
|
750
|
-
const { ssoTraces } = this;
|
751
|
-
let tokens = undefined;
|
752
|
-
try {
|
753
|
-
const client = yield import('openid-client');
|
754
|
-
const oidcConfig = yield oidcClientConfig({
|
755
|
-
discoveryUrl,
|
756
|
-
metadata,
|
757
|
-
clientId,
|
758
|
-
clientSecret,
|
759
|
-
ssoTraces: {
|
760
|
-
instance: ssoTraces,
|
761
|
-
context: {
|
762
|
-
tenant: oidcConnection.tenant,
|
763
|
-
product: oidcConnection.product,
|
764
|
-
clientID: oidcConnection.clientID,
|
765
|
-
providerName: oidcConnection.oidcProvider.provider,
|
766
|
-
redirectUri: redirect_uri,
|
767
|
-
relayState: RelayState,
|
768
|
-
isSAMLFederated,
|
769
|
-
isOIDCFederated,
|
770
|
-
acsUrl: session.requested.acsUrl,
|
771
|
-
entityId: session.requested.entityId,
|
772
|
-
requestedOIDCFlow: !!session.requested.oidc,
|
773
|
-
oidcIdPRequest: (_k = session === null || session === void 0 ? void 0 : session.requested) === null || _k === void 0 ? void 0 : _k.oidcIdPRequest,
|
774
|
-
},
|
775
|
-
},
|
776
|
-
});
|
777
|
-
const currentUrl = new URL(this.opts.externalUrl + this.opts.oidcPath + '?' + new URLSearchParams(callbackParams));
|
778
|
-
tokens = yield client.authorizationCodeGrant(oidcConfig, currentUrl, {
|
779
|
-
pkceCodeVerifier: session.oidcCodeVerifier,
|
780
|
-
expectedNonce: session.oidcNonce,
|
781
|
-
expectedState: callbackParams.state,
|
782
|
-
idTokenExpected: true,
|
783
|
-
});
|
784
|
-
profile = yield extractOIDCUserProfile(tokens, oidcConfig);
|
785
|
-
if (isSAMLFederated) {
|
786
|
-
const { responseForm } = yield this.ssoHandler.createSAMLResponse({ profile, session });
|
787
|
-
yield this.sessionStore.delete(RelayState);
|
788
|
-
return { response_form: responseForm };
|
789
|
-
}
|
790
|
-
const code = yield this._buildAuthorizationCode(oidcConnection, profile, session, false);
|
791
|
-
const params = {
|
792
|
-
code,
|
793
|
-
};
|
794
|
-
if (session && session.state) {
|
795
|
-
params['state'] = session.state;
|
796
|
-
}
|
797
|
-
yield this.sessionStore.delete(RelayState);
|
798
|
-
return { redirect_url: redirect.success(redirect_uri, params) };
|
799
|
-
}
|
800
|
-
catch (err) {
|
801
|
-
const { error, error_description, error_uri, session_state, scope, stack } = err;
|
802
|
-
const error_message = error_description || getErrorMessage(err);
|
803
|
-
const traceId = yield this.ssoTraces.saveTrace({
|
804
|
-
error: error_message,
|
805
|
-
context: {
|
806
|
-
tenant: oidcConnection.tenant,
|
807
|
-
product: oidcConnection.product,
|
808
|
-
clientID: oidcConnection.clientID,
|
809
|
-
providerName: oidcConnection.oidcProvider.provider,
|
810
|
-
redirectUri: redirect_uri,
|
811
|
-
relayState: RelayState,
|
812
|
-
isSAMLFederated,
|
813
|
-
isOIDCFederated,
|
814
|
-
acsUrl: session.requested.acsUrl,
|
815
|
-
entityId: session.requested.entityId,
|
816
|
-
requestedOIDCFlow: !!session.requested.oidc,
|
817
|
-
oidcIdPRequest: (_l = session === null || session === void 0 ? void 0 : session.requested) === null || _l === void 0 ? void 0 : _l.oidcIdPRequest,
|
818
|
-
profile,
|
819
|
-
error,
|
820
|
-
error_description,
|
821
|
-
error_uri,
|
822
|
-
session_state_from_op_error: session_state,
|
823
|
-
scope_from_op_error: scope,
|
824
|
-
stack,
|
825
|
-
oidcTokenSet: { id_token: tokens === null || tokens === void 0 ? void 0 : tokens.id_token, access_token: tokens === null || tokens === void 0 ? void 0 : tokens.access_token },
|
826
|
-
},
|
827
|
-
});
|
828
|
-
if (isSAMLFederated) {
|
829
|
-
throw err;
|
830
|
-
}
|
831
|
-
return {
|
832
|
-
redirect_url: OAuthErrorResponse({
|
833
|
-
error: error || 'server_error',
|
834
|
-
error_description: traceId ? `${traceId}: ${error_message}` : error_message,
|
835
|
-
redirect_uri: redirect_uri,
|
836
|
-
state: session.state,
|
837
|
-
}),
|
838
|
-
};
|
839
|
-
}
|
840
|
-
});
|
841
|
-
}
|
842
|
-
// Build the authorization code for the session
|
843
|
-
_buildAuthorizationCode(connection, profile, session, isIdPFlow) {
|
844
|
-
return __awaiter(this, void 0, void 0, function* () {
|
845
|
-
// Store details against a code
|
846
|
-
const code = crypto.randomBytes(20).toString('hex');
|
847
|
-
const requested = isIdPFlow
|
848
|
-
? { isIdPFlow: true, tenant: connection.tenant, product: connection.product }
|
849
|
-
: session
|
850
|
-
? session.requested
|
851
|
-
: null;
|
852
|
-
const codeVal = {
|
853
|
-
profile,
|
854
|
-
clientID: connection.clientID,
|
855
|
-
clientSecret: connection.clientSecret,
|
856
|
-
requested,
|
857
|
-
isIdPFlow,
|
858
|
-
};
|
859
|
-
if (session) {
|
860
|
-
codeVal['session'] = session;
|
861
|
-
}
|
862
|
-
yield this.codeStore.put(code, codeVal);
|
863
|
-
return code;
|
864
|
-
});
|
865
|
-
}
|
866
|
-
/**
|
867
|
-
* @swagger
|
868
|
-
*
|
869
|
-
* /oauth/token:
|
870
|
-
* post:
|
871
|
-
* summary: Code exchange
|
872
|
-
* operationId: oauth-code-exchange
|
873
|
-
* tags:
|
874
|
-
* - OAuth
|
875
|
-
* consumes:
|
876
|
-
* - application/x-www-form-urlencoded
|
877
|
-
* parameters:
|
878
|
-
* - name: grant_type
|
879
|
-
* in: formData
|
880
|
-
* type: string
|
881
|
-
* description: Grant type should be 'authorization_code'
|
882
|
-
* default: authorization_code
|
883
|
-
* required: true
|
884
|
-
* - name: client_id
|
885
|
-
* in: formData
|
886
|
-
* type: string
|
887
|
-
* description: Use the client_id returned by the SAML connection API
|
888
|
-
* required: true
|
889
|
-
* - name: client_secret
|
890
|
-
* in: formData
|
891
|
-
* type: string
|
892
|
-
* description: Use the client_secret returned by the SAML connection API
|
893
|
-
* required: true
|
894
|
-
* - name: code_verifier
|
895
|
-
* in: formData
|
896
|
-
* type: string
|
897
|
-
* description: code_verifier against the code_challenge in the authz request (relevant to PKCE flow)
|
898
|
-
* - name: redirect_uri
|
899
|
-
* in: formData
|
900
|
-
* type: string
|
901
|
-
* description: Redirect URI
|
902
|
-
* required: true
|
903
|
-
* - name: code
|
904
|
-
* in: formData
|
905
|
-
* type: string
|
906
|
-
* description: Code
|
907
|
-
* required: true
|
908
|
-
* responses:
|
909
|
-
* '200':
|
910
|
-
* description: Success
|
911
|
-
* schema:
|
912
|
-
* type: object
|
913
|
-
* properties:
|
914
|
-
* access_token:
|
915
|
-
* type: string
|
916
|
-
* token_type:
|
917
|
-
* type: string
|
918
|
-
* expires_in:
|
919
|
-
* type: string
|
920
|
-
* example:
|
921
|
-
* access_token: 8958e13053832b5af58fdf2ee83f35f5d013dc74
|
922
|
-
* token_type: bearer
|
923
|
-
* expires_in: 300
|
924
|
-
*/
|
925
|
-
token(body, authHeader) {
|
926
|
-
return __awaiter(this, void 0, void 0, function* () {
|
927
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
|
928
|
-
let basic_client_id;
|
929
|
-
let basic_client_secret;
|
930
|
-
try {
|
931
|
-
if (authHeader) {
|
932
|
-
// Authorization: Basic {Base64(<client_id>:<client_secret>)}
|
933
|
-
const base64Credentials = authHeader.split(' ')[1];
|
934
|
-
const credentials = Buffer.from(base64Credentials, 'base64').toString('ascii');
|
935
|
-
[basic_client_id, basic_client_secret] = credentials.split(':');
|
936
|
-
}
|
937
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
938
|
-
}
|
939
|
-
catch (err) {
|
940
|
-
// no-op
|
941
|
-
}
|
942
|
-
const { code, grant_type = 'authorization_code', redirect_uri } = body;
|
943
|
-
const client_id = 'client_id' in body ? body.client_id : basic_client_id;
|
944
|
-
const client_secret = 'client_secret' in body ? body.client_secret : basic_client_secret;
|
945
|
-
const code_verifier = 'code_verifier' in body ? body.code_verifier : undefined;
|
946
|
-
metrics.increment('oauthToken');
|
947
|
-
if (grant_type !== 'authorization_code') {
|
948
|
-
throw new JacksonError('Unsupported grant_type', 400);
|
949
|
-
}
|
950
|
-
if (!code) {
|
951
|
-
throw new JacksonError('Please specify code', 400);
|
952
|
-
}
|
953
|
-
const codeVal = yield this.codeStore.get(code);
|
954
|
-
if (!codeVal || !codeVal.profile) {
|
955
|
-
throw new JacksonError('Invalid code', 403);
|
956
|
-
}
|
957
|
-
if ((_a = codeVal.requested) === null || _a === void 0 ? void 0 : _a.redirect_uri) {
|
958
|
-
if (redirect_uri !== codeVal.requested.redirect_uri) {
|
959
|
-
throw new JacksonError(`Invalid request: ${!redirect_uri ? 'redirect_uri missing' : 'redirect_uri mismatch'}`, 400);
|
960
|
-
}
|
961
|
-
}
|
962
|
-
if (code_verifier) {
|
963
|
-
// PKCE flow
|
964
|
-
let cv = code_verifier;
|
965
|
-
if (((_b = codeVal.session.code_challenge_method) === null || _b === void 0 ? void 0 : _b.toLowerCase()) === 's256') {
|
966
|
-
cv = codeVerifier.encode(code_verifier);
|
967
|
-
}
|
968
|
-
if (codeVal.session.code_challenge !== cv) {
|
969
|
-
throw new JacksonError('Invalid code_verifier', 401);
|
970
|
-
}
|
971
|
-
// For Federation flow, we need to verify the client_secret
|
972
|
-
if (client_id === null || client_id === void 0 ? void 0 : client_id.startsWith(`${clientIDFederatedPrefix}${clientIDOIDCPrefix}`)) {
|
973
|
-
if (client_id !== ((_d = (_c = codeVal.session) === null || _c === void 0 ? void 0 : _c.oidcFederated) === null || _d === void 0 ? void 0 : _d.clientID) ||
|
974
|
-
client_secret !== ((_f = (_e = codeVal.session) === null || _e === void 0 ? void 0 : _e.oidcFederated) === null || _f === void 0 ? void 0 : _f.clientSecret)) {
|
975
|
-
throw new JacksonError('Invalid client_id or client_secret', 401);
|
976
|
-
}
|
977
|
-
}
|
978
|
-
}
|
979
|
-
else if (client_id && client_secret) {
|
980
|
-
// check if we have an encoded client_id
|
981
|
-
if (client_id !== 'dummy') {
|
982
|
-
const sp = getEncodedTenantProduct(client_id);
|
983
|
-
if (!sp) {
|
984
|
-
// OAuth flow
|
985
|
-
if (client_id !== codeVal.clientID || client_secret !== codeVal.clientSecret) {
|
986
|
-
throw new JacksonError('Invalid client_id or client_secret', 401);
|
987
|
-
}
|
988
|
-
}
|
989
|
-
else {
|
990
|
-
if (!codeVal.isIdPFlow &&
|
991
|
-
(sp.tenant !== ((_g = codeVal.requested) === null || _g === void 0 ? void 0 : _g.tenant) || sp.product !== ((_h = codeVal.requested) === null || _h === void 0 ? void 0 : _h.product))) {
|
992
|
-
throw new JacksonError('Invalid tenant or product', 401);
|
993
|
-
}
|
994
|
-
// encoded client_id, verify client_secret
|
995
|
-
if (client_secret !== this.opts.clientSecretVerifier) {
|
996
|
-
throw new JacksonError('Invalid client_secret', 401);
|
997
|
-
}
|
998
|
-
}
|
999
|
-
}
|
1000
|
-
else {
|
1001
|
-
if (client_secret !== this.opts.clientSecretVerifier && client_secret !== codeVal.clientSecret) {
|
1002
|
-
throw new JacksonError('Invalid client_secret', 401);
|
1003
|
-
}
|
1004
|
-
}
|
1005
|
-
}
|
1006
|
-
else if (codeVal && codeVal.session) {
|
1007
|
-
throw new JacksonError('Please specify client_secret or code_verifier', 401);
|
1008
|
-
}
|
1009
|
-
// store details against a token
|
1010
|
-
const token = crypto.randomBytes(20).toString('hex');
|
1011
|
-
const tokenVal = Object.assign(Object.assign({}, codeVal.profile), { requested: codeVal.requested });
|
1012
|
-
const requestedOIDCFlow = !!((_j = codeVal.requested) === null || _j === void 0 ? void 0 : _j.oidc);
|
1013
|
-
const requestHasNonce = !!((_k = codeVal.requested) === null || _k === void 0 ? void 0 : _k.nonce);
|
1014
|
-
if (requestedOIDCFlow) {
|
1015
|
-
const { jwtSigningKeys, jwsAlg } = (_l = this.opts.openid) !== null && _l !== void 0 ? _l : {};
|
1016
|
-
if (!jwtSigningKeys || !isJWSKeyPairLoaded(jwtSigningKeys)) {
|
1017
|
-
throw new JacksonError('JWT signing keys are not loaded', 500);
|
1018
|
-
}
|
1019
|
-
let claims = requestHasNonce ? { nonce: codeVal.requested.nonce } : {};
|
1020
|
-
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 });
|
1021
|
-
const signingKey = yield loadJWSPrivateKey(jwtSigningKeys.private, jwsAlg);
|
1022
|
-
const kid = yield computeKid(jwtSigningKeys.public, jwsAlg);
|
1023
|
-
const id_token = yield new jose.SignJWT(claims)
|
1024
|
-
.setProtectedHeader({ alg: jwsAlg, kid })
|
1025
|
-
.setIssuedAt()
|
1026
|
-
.setIssuer(this.opts.externalUrl)
|
1027
|
-
.setSubject(codeVal.profile.claims.id)
|
1028
|
-
.setAudience(tokenVal.requested.client_id)
|
1029
|
-
.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.
|
1030
|
-
.sign(signingKey);
|
1031
|
-
tokenVal.id_token = id_token;
|
1032
|
-
tokenVal.claims.sub = codeVal.profile.claims.id;
|
1033
|
-
}
|
1034
|
-
yield this.tokenStore.put(token, tokenVal);
|
1035
|
-
// delete the code
|
1036
|
-
try {
|
1037
|
-
yield this.codeStore.delete(code);
|
1038
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
1039
|
-
}
|
1040
|
-
catch (_err) {
|
1041
|
-
// ignore error
|
1042
|
-
}
|
1043
|
-
const tokenResponse = {
|
1044
|
-
access_token: token,
|
1045
|
-
token_type: 'bearer',
|
1046
|
-
expires_in: this.opts.db.ttl,
|
1047
|
-
};
|
1048
|
-
if (requestedOIDCFlow) {
|
1049
|
-
tokenResponse.id_token = tokenVal.id_token;
|
1050
|
-
}
|
1051
|
-
return tokenResponse;
|
1052
|
-
});
|
1053
|
-
}
|
1054
|
-
/**
|
1055
|
-
* @swagger
|
1056
|
-
*
|
1057
|
-
* /oauth/userinfo:
|
1058
|
-
* get:
|
1059
|
-
* summary: Get profile
|
1060
|
-
* operationId: oauth-get-profile
|
1061
|
-
* tags:
|
1062
|
-
* - OAuth
|
1063
|
-
* responses:
|
1064
|
-
* '200':
|
1065
|
-
* description: Success
|
1066
|
-
* schema:
|
1067
|
-
* type: object
|
1068
|
-
* properties:
|
1069
|
-
* id:
|
1070
|
-
* type: string
|
1071
|
-
* email:
|
1072
|
-
* type: string
|
1073
|
-
* firstName:
|
1074
|
-
* type: string
|
1075
|
-
* lastName:
|
1076
|
-
* type: string
|
1077
|
-
* roles:
|
1078
|
-
* type: array
|
1079
|
-
* items:
|
1080
|
-
* type: string
|
1081
|
-
* groups:
|
1082
|
-
* type: array
|
1083
|
-
* items:
|
1084
|
-
* type: string
|
1085
|
-
* raw:
|
1086
|
-
* type: object
|
1087
|
-
* requested:
|
1088
|
-
* type: object
|
1089
|
-
* example:
|
1090
|
-
* id: 32b5af58fdf
|
1091
|
-
* email: jackson@coolstartup.com
|
1092
|
-
* firstName: SAML
|
1093
|
-
* lastName: Jackson
|
1094
|
-
* raw: {
|
1095
|
-
*
|
1096
|
-
* }
|
1097
|
-
* requested: {
|
1098
|
-
*
|
1099
|
-
* }
|
1100
|
-
*/
|
1101
|
-
userInfo(token) {
|
1102
|
-
return __awaiter(this, void 0, void 0, function* () {
|
1103
|
-
const rsp = yield this.tokenStore.get(token);
|
1104
|
-
metrics.increment('oauthUserInfo');
|
1105
|
-
if (!rsp || !rsp.claims) {
|
1106
|
-
throw new JacksonError('Invalid token', 403);
|
1107
|
-
}
|
1108
|
-
return Object.assign(Object.assign({}, rsp.claims), { requested: rsp.requested });
|
1109
|
-
});
|
1110
|
-
}
|
1111
|
-
}
|
1112
|
-
//# sourceMappingURL=oauth.js.map
|