@backstage/plugin-auth-backend 0.4.7 → 0.5.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/CHANGELOG.md +68 -0
- package/README.md +6 -6
- package/dist/index.cjs.js +460 -351
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +121 -20
- package/package.json +9 -9
package/dist/index.cjs.js
CHANGED
|
@@ -17,12 +17,12 @@ var passportGoogleOauth20 = require('passport-google-oauth20');
|
|
|
17
17
|
var passportMicrosoft = require('passport-microsoft');
|
|
18
18
|
var got = require('got');
|
|
19
19
|
var OAuth2Strategy = require('passport-oauth2');
|
|
20
|
+
var openidClient = require('openid-client');
|
|
20
21
|
var passportOktaOauth = require('passport-okta-oauth');
|
|
21
22
|
var passportBitbucketOauth2 = require('passport-bitbucket-oauth2');
|
|
22
|
-
var fetch = require('
|
|
23
|
+
var fetch = require('node-fetch');
|
|
23
24
|
var NodeCache = require('node-cache');
|
|
24
25
|
var jose = require('jose');
|
|
25
|
-
var openidClient = require('openid-client');
|
|
26
26
|
var passportSaml = require('passport-saml');
|
|
27
27
|
var passportOneloginOauth = require('passport-onelogin-oauth');
|
|
28
28
|
var catalogClient = require('@backstage/catalog-client');
|
|
@@ -46,14 +46,12 @@ function _interopNamespace(e) {
|
|
|
46
46
|
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
47
47
|
Object.defineProperty(n, k, d.get ? d : {
|
|
48
48
|
enumerable: true,
|
|
49
|
-
get: function () {
|
|
50
|
-
return e[k];
|
|
51
|
-
}
|
|
49
|
+
get: function () { return e[k]; }
|
|
52
50
|
});
|
|
53
51
|
}
|
|
54
52
|
});
|
|
55
53
|
}
|
|
56
|
-
n[
|
|
54
|
+
n["default"] = e;
|
|
57
55
|
return Object.freeze(n);
|
|
58
56
|
}
|
|
59
57
|
|
|
@@ -88,7 +86,7 @@ const makeProfileInfo = (profile, idToken) => {
|
|
|
88
86
|
let displayName = (_b = (_a = profile.displayName) != null ? _a : profile.username) != null ? _b : profile.id;
|
|
89
87
|
if ((!email || !picture || !displayName) && idToken) {
|
|
90
88
|
try {
|
|
91
|
-
const decoded = jwtDecoder__default[
|
|
89
|
+
const decoded = jwtDecoder__default["default"](idToken);
|
|
92
90
|
if (!email && decoded.email) {
|
|
93
91
|
email = decoded.email;
|
|
94
92
|
}
|
|
@@ -112,16 +110,16 @@ const executeRedirectStrategy = async (req, providerStrategy, options) => {
|
|
|
112
110
|
return new Promise((resolve) => {
|
|
113
111
|
const strategy = Object.create(providerStrategy);
|
|
114
112
|
strategy.redirect = (url, status) => {
|
|
115
|
-
resolve({url, status: status != null ? status : void 0});
|
|
113
|
+
resolve({ url, status: status != null ? status : void 0 });
|
|
116
114
|
};
|
|
117
|
-
strategy.authenticate(req, {...options});
|
|
115
|
+
strategy.authenticate(req, { ...options });
|
|
118
116
|
});
|
|
119
117
|
};
|
|
120
118
|
const executeFrameHandlerStrategy = async (req, providerStrategy) => {
|
|
121
119
|
return new Promise((resolve, reject) => {
|
|
122
120
|
const strategy = Object.create(providerStrategy);
|
|
123
121
|
strategy.success = (result, privateInfo) => {
|
|
124
|
-
resolve({result, privateInfo});
|
|
122
|
+
resolve({ result, privateInfo });
|
|
125
123
|
};
|
|
126
124
|
strategy.fail = (info) => {
|
|
127
125
|
var _a;
|
|
@@ -193,7 +191,7 @@ const readState = (stateString) => {
|
|
|
193
191
|
return state;
|
|
194
192
|
};
|
|
195
193
|
const encodeState = (state) => {
|
|
196
|
-
const stateString = new URLSearchParams(pickBy__default[
|
|
194
|
+
const stateString = new URLSearchParams(pickBy__default["default"](state, (value) => value !== void 0)).toString();
|
|
197
195
|
return Buffer.from(stateString, "utf-8").toString("hex");
|
|
198
196
|
};
|
|
199
197
|
const verifyNonce = (req, providerId) => {
|
|
@@ -218,7 +216,7 @@ class OAuthEnvironmentHandler {
|
|
|
218
216
|
}
|
|
219
217
|
static mapConfig(config, factoryFunc) {
|
|
220
218
|
const envs = config.keys();
|
|
221
|
-
const handlers = new Map();
|
|
219
|
+
const handlers = /* @__PURE__ */ new Map();
|
|
222
220
|
for (const env of envs) {
|
|
223
221
|
const envConfig = config.getConfig(env);
|
|
224
222
|
const handler = factoryFunc(envConfig);
|
|
@@ -227,22 +225,22 @@ class OAuthEnvironmentHandler {
|
|
|
227
225
|
return new OAuthEnvironmentHandler(handlers);
|
|
228
226
|
}
|
|
229
227
|
async start(req, res) {
|
|
230
|
-
const provider = this.getProviderForEnv(req
|
|
231
|
-
await
|
|
228
|
+
const provider = this.getProviderForEnv(req);
|
|
229
|
+
await provider.start(req, res);
|
|
232
230
|
}
|
|
233
231
|
async frameHandler(req, res) {
|
|
234
|
-
const provider = this.getProviderForEnv(req
|
|
235
|
-
await
|
|
232
|
+
const provider = this.getProviderForEnv(req);
|
|
233
|
+
await provider.frameHandler(req, res);
|
|
236
234
|
}
|
|
237
235
|
async refresh(req, res) {
|
|
238
236
|
var _a;
|
|
239
|
-
const provider = this.getProviderForEnv(req
|
|
240
|
-
await ((_a = provider
|
|
237
|
+
const provider = this.getProviderForEnv(req);
|
|
238
|
+
await ((_a = provider.refresh) == null ? void 0 : _a.call(provider, req, res));
|
|
241
239
|
}
|
|
242
240
|
async logout(req, res) {
|
|
243
241
|
var _a;
|
|
244
|
-
const provider = this.getProviderForEnv(req
|
|
245
|
-
await ((_a = provider
|
|
242
|
+
const provider = this.getProviderForEnv(req);
|
|
243
|
+
await ((_a = provider.logout) == null ? void 0 : _a.call(provider, req, res));
|
|
246
244
|
}
|
|
247
245
|
getRequestFromEnv(req) {
|
|
248
246
|
var _a, _b;
|
|
@@ -257,19 +255,16 @@ class OAuthEnvironmentHandler {
|
|
|
257
255
|
const env = readState(stateParams).env;
|
|
258
256
|
return env;
|
|
259
257
|
}
|
|
260
|
-
getProviderForEnv(req
|
|
258
|
+
getProviderForEnv(req) {
|
|
261
259
|
const env = this.getRequestFromEnv(req);
|
|
262
260
|
if (!env) {
|
|
263
261
|
throw new errors.InputError(`Must specify 'env' query to select environment`);
|
|
264
262
|
}
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
<br>
|
|
269
|
-
For this flow to work you need to supply a valid configuration for the "${env}" environment of provider.`);
|
|
270
|
-
return void 0;
|
|
263
|
+
const handler = this.handlers.get(env);
|
|
264
|
+
if (!handler) {
|
|
265
|
+
throw new errors.NotFoundError(`No configuration available for the '${env}' environment of this provider.`);
|
|
271
266
|
}
|
|
272
|
-
return
|
|
267
|
+
return handler;
|
|
273
268
|
}
|
|
274
269
|
}
|
|
275
270
|
|
|
@@ -290,11 +285,11 @@ const postMessageResponse = (res, appOrigin, response) => {
|
|
|
290
285
|
window.close();
|
|
291
286
|
}, 100); // same as the interval of the core-app-api lib/loginPopup.ts (to address race conditions)
|
|
292
287
|
`;
|
|
293
|
-
const hash = crypto__default[
|
|
288
|
+
const hash = crypto__default["default"].createHash("sha256").update(script).digest("base64");
|
|
294
289
|
res.setHeader("Content-Type", "text/html");
|
|
295
290
|
res.setHeader("X-Frame-Options", "sameorigin");
|
|
296
291
|
res.setHeader("Content-Security-Policy", `script-src 'sha256-${hash}'`);
|
|
297
|
-
res.end(`<html><body><script>${script}
|
|
292
|
+
res.end(`<html><body><script>${script}<\/script></body></html>`);
|
|
298
293
|
};
|
|
299
294
|
const ensuresXRequestedWith = (req) => {
|
|
300
295
|
const requiredHeader = req.header("X-Requested-With");
|
|
@@ -304,6 +299,25 @@ const ensuresXRequestedWith = (req) => {
|
|
|
304
299
|
return true;
|
|
305
300
|
};
|
|
306
301
|
|
|
302
|
+
function parseJwtPayload(token) {
|
|
303
|
+
const [_header, payload, _signature] = token.split(".");
|
|
304
|
+
return JSON.parse(Buffer.from(payload, "base64").toString());
|
|
305
|
+
}
|
|
306
|
+
function prepareBackstageIdentityResponse(result) {
|
|
307
|
+
const { sub, ent } = parseJwtPayload(result.token);
|
|
308
|
+
return {
|
|
309
|
+
...{
|
|
310
|
+
idToken: result.token,
|
|
311
|
+
...result
|
|
312
|
+
},
|
|
313
|
+
identity: {
|
|
314
|
+
type: "user",
|
|
315
|
+
userEntityRef: sub,
|
|
316
|
+
ownershipEntityRefs: ent != null ? ent : []
|
|
317
|
+
}
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
|
|
307
321
|
const THOUSAND_DAYS_MS = 1e3 * 24 * 60 * 60 * 1e3;
|
|
308
322
|
const TEN_MINUTES_MS = 600 * 1e3;
|
|
309
323
|
class OAuthAdapter {
|
|
@@ -355,7 +369,7 @@ class OAuthAdapter {
|
|
|
355
369
|
};
|
|
356
370
|
}
|
|
357
371
|
static fromConfig(config, handlers, options) {
|
|
358
|
-
const {origin: appOrigin} = new url.URL(config.appUrl);
|
|
372
|
+
const { origin: appOrigin } = new url.URL(config.appUrl);
|
|
359
373
|
const secure = config.baseUrl.startsWith("https://");
|
|
360
374
|
const url$1 = new url.URL(config.baseUrl);
|
|
361
375
|
const cookiePath = `${url$1.pathname}/${options.providerId}`;
|
|
@@ -379,11 +393,11 @@ class OAuthAdapter {
|
|
|
379
393
|
if (this.options.persistScopes) {
|
|
380
394
|
this.setScopesCookie(res, scope);
|
|
381
395
|
}
|
|
382
|
-
const nonce = crypto__default[
|
|
396
|
+
const nonce = crypto__default["default"].randomBytes(16).toString("base64");
|
|
383
397
|
this.setNonceCookie(res, nonce);
|
|
384
|
-
const state = {nonce, env, origin};
|
|
385
|
-
const forwardReq = Object.assign(req, {scope, state});
|
|
386
|
-
const {url, status} = await this.handlers.start(forwardReq);
|
|
398
|
+
const state = { nonce, env, origin };
|
|
399
|
+
const forwardReq = Object.assign(req, { scope, state });
|
|
400
|
+
const { url, status } = await this.handlers.start(forwardReq);
|
|
387
401
|
res.statusCode = status || 302;
|
|
388
402
|
res.setHeader("Location", url);
|
|
389
403
|
res.setHeader("Content-Length", "0");
|
|
@@ -405,7 +419,7 @@ class OAuthAdapter {
|
|
|
405
419
|
}
|
|
406
420
|
}
|
|
407
421
|
verifyNonce(req, this.options.providerId);
|
|
408
|
-
const {response, refreshToken} = await this.handlers.handler(req);
|
|
422
|
+
const { response, refreshToken } = await this.handlers.handler(req);
|
|
409
423
|
if (this.options.persistScopes) {
|
|
410
424
|
const grantedScopes = this.getScopesFromCookie(req, this.options.providerId);
|
|
411
425
|
response.providerInfo.scope = grantedScopes;
|
|
@@ -413,63 +427,62 @@ class OAuthAdapter {
|
|
|
413
427
|
if (refreshToken && !this.options.disableRefresh) {
|
|
414
428
|
this.setRefreshTokenCookie(res, refreshToken);
|
|
415
429
|
}
|
|
416
|
-
await this.populateIdentity(response.backstageIdentity);
|
|
430
|
+
const identity = await this.populateIdentity(response.backstageIdentity);
|
|
417
431
|
return postMessageResponse(res, appOrigin, {
|
|
418
432
|
type: "authorization_response",
|
|
419
|
-
response
|
|
433
|
+
response: { ...response, backstageIdentity: identity }
|
|
420
434
|
});
|
|
421
435
|
} catch (error) {
|
|
422
|
-
const {name, message} = errors.isError(error) ? error : new Error("Encountered invalid error");
|
|
436
|
+
const { name, message } = errors.isError(error) ? error : new Error("Encountered invalid error");
|
|
423
437
|
return postMessageResponse(res, appOrigin, {
|
|
424
438
|
type: "authorization_response",
|
|
425
|
-
error: {name, message}
|
|
439
|
+
error: { name, message }
|
|
426
440
|
});
|
|
427
441
|
}
|
|
428
442
|
}
|
|
429
443
|
async logout(req, res) {
|
|
430
444
|
if (!ensuresXRequestedWith(req)) {
|
|
431
|
-
|
|
432
|
-
return;
|
|
445
|
+
throw new errors.AuthenticationError("Invalid X-Requested-With header");
|
|
433
446
|
}
|
|
434
447
|
this.removeRefreshTokenCookie(res);
|
|
435
|
-
res.status(200).
|
|
448
|
+
res.status(200).end();
|
|
436
449
|
}
|
|
437
450
|
async refresh(req, res) {
|
|
438
451
|
var _a, _b;
|
|
439
452
|
if (!ensuresXRequestedWith(req)) {
|
|
440
|
-
|
|
441
|
-
return;
|
|
453
|
+
throw new errors.AuthenticationError("Invalid X-Requested-With header");
|
|
442
454
|
}
|
|
443
455
|
if (!this.handlers.refresh || this.options.disableRefresh) {
|
|
444
|
-
|
|
445
|
-
return;
|
|
456
|
+
throw new errors.InputError(`Refresh token is not supported for provider ${this.options.providerId}`);
|
|
446
457
|
}
|
|
447
458
|
try {
|
|
448
459
|
const refreshToken = req.cookies[`${this.options.providerId}-refresh-token`];
|
|
449
460
|
if (!refreshToken) {
|
|
450
|
-
throw new
|
|
461
|
+
throw new errors.InputError("Missing session cookie");
|
|
451
462
|
}
|
|
452
463
|
const scope = (_b = (_a = req.query.scope) == null ? void 0 : _a.toString()) != null ? _b : "";
|
|
453
|
-
const forwardReq = Object.assign(req, {scope, refreshToken});
|
|
464
|
+
const forwardReq = Object.assign(req, { scope, refreshToken });
|
|
454
465
|
const response = await this.handlers.refresh(forwardReq);
|
|
455
|
-
await this.populateIdentity(response.backstageIdentity);
|
|
466
|
+
const backstageIdentity = await this.populateIdentity(response.backstageIdentity);
|
|
456
467
|
if (response.providerInfo.refreshToken && response.providerInfo.refreshToken !== refreshToken) {
|
|
457
468
|
this.setRefreshTokenCookie(res, response.providerInfo.refreshToken);
|
|
458
469
|
}
|
|
459
|
-
res.status(200).json(response);
|
|
470
|
+
res.status(200).json({ ...response, backstageIdentity });
|
|
460
471
|
} catch (error) {
|
|
461
|
-
|
|
472
|
+
throw new errors.AuthenticationError("Refresh failed", error);
|
|
462
473
|
}
|
|
463
474
|
}
|
|
464
475
|
async populateIdentity(identity) {
|
|
465
476
|
if (!identity) {
|
|
466
|
-
return;
|
|
477
|
+
return void 0;
|
|
467
478
|
}
|
|
468
|
-
if (
|
|
469
|
-
|
|
470
|
-
claims: {sub: identity.id}
|
|
471
|
-
});
|
|
479
|
+
if (identity.token) {
|
|
480
|
+
return prepareBackstageIdentityResponse(identity);
|
|
472
481
|
}
|
|
482
|
+
const token = await this.options.tokenIssuer.issueToken({
|
|
483
|
+
claims: { sub: identity.id }
|
|
484
|
+
});
|
|
485
|
+
return prepareBackstageIdentityResponse({ ...identity, token });
|
|
473
486
|
}
|
|
474
487
|
}
|
|
475
488
|
|
|
@@ -486,9 +499,9 @@ class CatalogIdentityClient {
|
|
|
486
499
|
filter[`metadata.annotations.${key}`] = value;
|
|
487
500
|
}
|
|
488
501
|
const token = await this.tokenIssuer.issueToken({
|
|
489
|
-
claims: {sub: "backstage.io/auth-backend"}
|
|
502
|
+
claims: { sub: "backstage.io/auth-backend" }
|
|
490
503
|
});
|
|
491
|
-
const {items} = await this.catalogApi.getEntities({filter}, {token});
|
|
504
|
+
const { items } = await this.catalogApi.getEntities({ filter }, { token });
|
|
492
505
|
if (items.length !== 1) {
|
|
493
506
|
if (items.length > 1) {
|
|
494
507
|
throw new errors.ConflictError("User lookup resulted in multiple matches");
|
|
@@ -498,10 +511,8 @@ class CatalogIdentityClient {
|
|
|
498
511
|
}
|
|
499
512
|
return items[0];
|
|
500
513
|
}
|
|
501
|
-
async resolveCatalogMembership({
|
|
502
|
-
entityRefs,
|
|
503
|
-
logger
|
|
504
|
-
}) {
|
|
514
|
+
async resolveCatalogMembership(query) {
|
|
515
|
+
const { entityRefs, logger } = query;
|
|
505
516
|
const resolvedEntityRefs = entityRefs.map((ref) => {
|
|
506
517
|
try {
|
|
507
518
|
const parsedRef = catalogModel.parseEntityRef(ref.toLocaleLowerCase("en-US"), {
|
|
@@ -519,7 +530,7 @@ class CatalogIdentityClient {
|
|
|
519
530
|
"metadata.namespace": ref.namespace,
|
|
520
531
|
"metadata.name": ref.name
|
|
521
532
|
}));
|
|
522
|
-
const entities = await this.catalogApi.getEntities({filter}).then((r) => r.items);
|
|
533
|
+
const entities = await this.catalogApi.getEntities({ filter }).then((r) => r.items);
|
|
523
534
|
if (entityRefs.length !== entities.length) {
|
|
524
535
|
const foundEntityNames = entities.map(catalogModel.stringifyEntityRef);
|
|
525
536
|
const missingEntityNames = resolvedEntityRefs.map(catalogModel.stringifyEntityRef).filter((s) => !foundEntityNames.includes(s));
|
|
@@ -563,7 +574,7 @@ class GithubAuthProvider {
|
|
|
563
574
|
userProfileURL: options.userProfileUrl,
|
|
564
575
|
authorizationURL: options.authorizationUrl
|
|
565
576
|
}, (accessToken, refreshToken, params, fullProfile, done) => {
|
|
566
|
-
done(void 0, {fullProfile, params, accessToken}, {refreshToken});
|
|
577
|
+
done(void 0, { fullProfile, params, accessToken }, { refreshToken });
|
|
567
578
|
});
|
|
568
579
|
}
|
|
569
580
|
async start(req) {
|
|
@@ -573,7 +584,7 @@ class GithubAuthProvider {
|
|
|
573
584
|
});
|
|
574
585
|
}
|
|
575
586
|
async handler(req) {
|
|
576
|
-
const {result, privateInfo} = await executeFrameHandlerStrategy(req, this._strategy);
|
|
587
|
+
const { result, privateInfo } = await executeFrameHandlerStrategy(req, this._strategy);
|
|
577
588
|
return {
|
|
578
589
|
response: await this.handleResult(result),
|
|
579
590
|
refreshToken: privateInfo.refreshToken
|
|
@@ -594,7 +605,7 @@ class GithubAuthProvider {
|
|
|
594
605
|
});
|
|
595
606
|
}
|
|
596
607
|
async handleResult(result) {
|
|
597
|
-
const {profile} = await this.authHandler(result);
|
|
608
|
+
const { profile } = await this.authHandler(result);
|
|
598
609
|
const expiresInStr = result.params.expires_in;
|
|
599
610
|
const response = {
|
|
600
611
|
providerInfo: {
|
|
@@ -619,12 +630,12 @@ class GithubAuthProvider {
|
|
|
619
630
|
}
|
|
620
631
|
}
|
|
621
632
|
const githubDefaultSignInResolver = async (info, ctx) => {
|
|
622
|
-
const {fullProfile} = info.result;
|
|
633
|
+
const { fullProfile } = info.result;
|
|
623
634
|
const userId = fullProfile.username || fullProfile.id;
|
|
624
635
|
const token = await ctx.tokenIssuer.issueToken({
|
|
625
|
-
claims: {sub: userId, ent: [`user:default/${userId}`]}
|
|
636
|
+
claims: { sub: userId, ent: [`user:default/${userId}`] }
|
|
626
637
|
});
|
|
627
|
-
return {id: userId, token};
|
|
638
|
+
return { id: userId, token };
|
|
628
639
|
};
|
|
629
640
|
const createGithubProvider = (options) => {
|
|
630
641
|
return ({
|
|
@@ -648,7 +659,7 @@ const createGithubProvider = (options) => {
|
|
|
648
659
|
catalogApi,
|
|
649
660
|
tokenIssuer
|
|
650
661
|
});
|
|
651
|
-
const authHandler = (options == null ? void 0 : options.authHandler) ? options.authHandler : async ({fullProfile}) => ({
|
|
662
|
+
const authHandler = (options == null ? void 0 : options.authHandler) ? options.authHandler : async ({ fullProfile }) => ({
|
|
652
663
|
profile: makeProfileInfo(fullProfile)
|
|
653
664
|
});
|
|
654
665
|
const signInResolverFn = (_b = (_a = options == null ? void 0 : options.signIn) == null ? void 0 : _a.resolver) != null ? _b : githubDefaultSignInResolver;
|
|
@@ -658,7 +669,7 @@ const createGithubProvider = (options) => {
|
|
|
658
669
|
logger
|
|
659
670
|
});
|
|
660
671
|
const stateEncoder = (_c = options == null ? void 0 : options.stateEncoder) != null ? _c : async (req) => {
|
|
661
|
-
return {encodedState: encodeState(req.state)};
|
|
672
|
+
return { encodedState: encodeState(req.state) };
|
|
662
673
|
};
|
|
663
674
|
const provider = new GithubAuthProvider({
|
|
664
675
|
clientId,
|
|
@@ -683,15 +694,15 @@ const createGithubProvider = (options) => {
|
|
|
683
694
|
};
|
|
684
695
|
|
|
685
696
|
const gitlabDefaultSignInResolver = async (info, ctx) => {
|
|
686
|
-
const {profile, result} = info;
|
|
697
|
+
const { profile, result } = info;
|
|
687
698
|
let id = result.fullProfile.id;
|
|
688
699
|
if (profile.email) {
|
|
689
700
|
id = profile.email.split("@")[0];
|
|
690
701
|
}
|
|
691
702
|
const token = await ctx.tokenIssuer.issueToken({
|
|
692
|
-
claims: {sub: id, ent: [`user:default/${id}`]}
|
|
703
|
+
claims: { sub: id, ent: [`user:default/${id}`] }
|
|
693
704
|
});
|
|
694
|
-
return {id, token};
|
|
705
|
+
return { id, token };
|
|
695
706
|
};
|
|
696
707
|
const gitlabDefaultAuthHandler = async ({
|
|
697
708
|
fullProfile,
|
|
@@ -712,7 +723,7 @@ class GitlabAuthProvider {
|
|
|
712
723
|
callbackURL: options.callbackUrl,
|
|
713
724
|
baseURL: options.baseUrl
|
|
714
725
|
}, (accessToken, refreshToken, params, fullProfile, done) => {
|
|
715
|
-
done(void 0, {fullProfile, params, accessToken}, {
|
|
726
|
+
done(void 0, { fullProfile, params, accessToken }, {
|
|
716
727
|
refreshToken
|
|
717
728
|
});
|
|
718
729
|
});
|
|
@@ -724,7 +735,7 @@ class GitlabAuthProvider {
|
|
|
724
735
|
});
|
|
725
736
|
}
|
|
726
737
|
async handler(req) {
|
|
727
|
-
const {result, privateInfo} = await executeFrameHandlerStrategy(req, this._strategy);
|
|
738
|
+
const { result, privateInfo } = await executeFrameHandlerStrategy(req, this._strategy);
|
|
728
739
|
return {
|
|
729
740
|
response: await this.handleResult(result),
|
|
730
741
|
refreshToken: privateInfo.refreshToken
|
|
@@ -745,7 +756,7 @@ class GitlabAuthProvider {
|
|
|
745
756
|
});
|
|
746
757
|
}
|
|
747
758
|
async handleResult(result) {
|
|
748
|
-
const {profile} = await this.authHandler(result);
|
|
759
|
+
const { profile } = await this.authHandler(result);
|
|
749
760
|
const response = {
|
|
750
761
|
providerInfo: {
|
|
751
762
|
idToken: result.params.id_token,
|
|
@@ -846,14 +857,14 @@ class GoogleAuthProvider {
|
|
|
846
857
|
});
|
|
847
858
|
}
|
|
848
859
|
async handler(req) {
|
|
849
|
-
const {result, privateInfo} = await executeFrameHandlerStrategy(req, this._strategy);
|
|
860
|
+
const { result, privateInfo } = await executeFrameHandlerStrategy(req, this._strategy);
|
|
850
861
|
return {
|
|
851
862
|
response: await this.handleResult(result),
|
|
852
863
|
refreshToken: privateInfo.refreshToken
|
|
853
864
|
};
|
|
854
865
|
}
|
|
855
866
|
async refresh(req) {
|
|
856
|
-
const {accessToken, params} = await executeRefreshTokenStrategy(this._strategy, req.refreshToken, req.scope);
|
|
867
|
+
const { accessToken, params } = await executeRefreshTokenStrategy(this._strategy, req.refreshToken, req.scope);
|
|
857
868
|
const fullProfile = await executeFetchUserProfileStrategy(this._strategy, accessToken);
|
|
858
869
|
return this.handleResult({
|
|
859
870
|
fullProfile,
|
|
@@ -863,7 +874,7 @@ class GoogleAuthProvider {
|
|
|
863
874
|
});
|
|
864
875
|
}
|
|
865
876
|
async handleResult(result) {
|
|
866
|
-
const {profile} = await this.authHandler(result);
|
|
877
|
+
const { profile } = await this.authHandler(result);
|
|
867
878
|
const response = {
|
|
868
879
|
providerInfo: {
|
|
869
880
|
idToken: result.params.id_token,
|
|
@@ -887,7 +898,7 @@ class GoogleAuthProvider {
|
|
|
887
898
|
}
|
|
888
899
|
}
|
|
889
900
|
const googleEmailSignInResolver = async (info, ctx) => {
|
|
890
|
-
const {profile} = info;
|
|
901
|
+
const { profile } = info;
|
|
891
902
|
if (!profile.email) {
|
|
892
903
|
throw new Error("Google profile contained no email");
|
|
893
904
|
}
|
|
@@ -897,11 +908,11 @@ const googleEmailSignInResolver = async (info, ctx) => {
|
|
|
897
908
|
}
|
|
898
909
|
});
|
|
899
910
|
const claims = getEntityClaims(entity);
|
|
900
|
-
const token = await ctx.tokenIssuer.issueToken({claims});
|
|
901
|
-
return {id: entity.metadata.name, entity, token};
|
|
911
|
+
const token = await ctx.tokenIssuer.issueToken({ claims });
|
|
912
|
+
return { id: entity.metadata.name, entity, token };
|
|
902
913
|
};
|
|
903
914
|
const googleDefaultSignInResolver = async (info, ctx) => {
|
|
904
|
-
const {profile} = info;
|
|
915
|
+
const { profile } = info;
|
|
905
916
|
if (!profile.email) {
|
|
906
917
|
throw new Error("Google profile contained no email");
|
|
907
918
|
}
|
|
@@ -918,9 +929,9 @@ const googleDefaultSignInResolver = async (info, ctx) => {
|
|
|
918
929
|
userId = profile.email.split("@")[0];
|
|
919
930
|
}
|
|
920
931
|
const token = await ctx.tokenIssuer.issueToken({
|
|
921
|
-
claims: {sub: userId, ent: [`user:default/${userId}`]}
|
|
932
|
+
claims: { sub: userId, ent: [`user:default/${userId}`] }
|
|
922
933
|
});
|
|
923
|
-
return {id: userId, token};
|
|
934
|
+
return { id: userId, token };
|
|
924
935
|
};
|
|
925
936
|
const createGoogleProvider = (options) => {
|
|
926
937
|
return ({
|
|
@@ -939,7 +950,7 @@ const createGoogleProvider = (options) => {
|
|
|
939
950
|
catalogApi,
|
|
940
951
|
tokenIssuer
|
|
941
952
|
});
|
|
942
|
-
const authHandler = (options == null ? void 0 : options.authHandler) ? options.authHandler : async ({fullProfile, params}) => ({
|
|
953
|
+
const authHandler = (options == null ? void 0 : options.authHandler) ? options.authHandler : async ({ fullProfile, params }) => ({
|
|
943
954
|
profile: makeProfileInfo(fullProfile, params.id_token)
|
|
944
955
|
});
|
|
945
956
|
const signInResolverFn = (_b = (_a = options == null ? void 0 : options.signIn) == null ? void 0 : _a.resolver) != null ? _b : googleDefaultSignInResolver;
|
|
@@ -981,7 +992,7 @@ class MicrosoftAuthProvider {
|
|
|
981
992
|
tokenURL: options.tokenUrl,
|
|
982
993
|
passReqToCallback: false
|
|
983
994
|
}, (accessToken, refreshToken, params, fullProfile, done) => {
|
|
984
|
-
done(void 0, {fullProfile, accessToken, params}, {refreshToken});
|
|
995
|
+
done(void 0, { fullProfile, accessToken, params }, { refreshToken });
|
|
985
996
|
});
|
|
986
997
|
}
|
|
987
998
|
async start(req) {
|
|
@@ -991,14 +1002,14 @@ class MicrosoftAuthProvider {
|
|
|
991
1002
|
});
|
|
992
1003
|
}
|
|
993
1004
|
async handler(req) {
|
|
994
|
-
const {result, privateInfo} = await executeFrameHandlerStrategy(req, this._strategy);
|
|
1005
|
+
const { result, privateInfo } = await executeFrameHandlerStrategy(req, this._strategy);
|
|
995
1006
|
return {
|
|
996
1007
|
response: await this.handleResult(result),
|
|
997
1008
|
refreshToken: privateInfo.refreshToken
|
|
998
1009
|
};
|
|
999
1010
|
}
|
|
1000
1011
|
async refresh(req) {
|
|
1001
|
-
const {accessToken, params} = await executeRefreshTokenStrategy(this._strategy, req.refreshToken, req.scope);
|
|
1012
|
+
const { accessToken, params } = await executeRefreshTokenStrategy(this._strategy, req.refreshToken, req.scope);
|
|
1002
1013
|
const fullProfile = await executeFetchUserProfileStrategy(this._strategy, accessToken);
|
|
1003
1014
|
return this.handleResult({
|
|
1004
1015
|
fullProfile,
|
|
@@ -1009,8 +1020,8 @@ class MicrosoftAuthProvider {
|
|
|
1009
1020
|
}
|
|
1010
1021
|
async handleResult(result) {
|
|
1011
1022
|
const photo = await this.getUserPhoto(result.accessToken);
|
|
1012
|
-
result.fullProfile.photos = photo ? [{value: photo}] : void 0;
|
|
1013
|
-
const {profile} = await this.authHandler(result);
|
|
1023
|
+
result.fullProfile.photos = photo ? [{ value: photo }] : void 0;
|
|
1024
|
+
const { profile } = await this.authHandler(result);
|
|
1014
1025
|
const response = {
|
|
1015
1026
|
providerInfo: {
|
|
1016
1027
|
idToken: result.params.id_token,
|
|
@@ -1034,7 +1045,7 @@ class MicrosoftAuthProvider {
|
|
|
1034
1045
|
}
|
|
1035
1046
|
getUserPhoto(accessToken) {
|
|
1036
1047
|
return new Promise((resolve) => {
|
|
1037
|
-
got__default[
|
|
1048
|
+
got__default["default"].get("https://graph.microsoft.com/v1.0/me/photos/48x48/$value", {
|
|
1038
1049
|
encoding: "binary",
|
|
1039
1050
|
responseType: "buffer",
|
|
1040
1051
|
headers: {
|
|
@@ -1051,7 +1062,7 @@ class MicrosoftAuthProvider {
|
|
|
1051
1062
|
}
|
|
1052
1063
|
}
|
|
1053
1064
|
const microsoftEmailSignInResolver = async (info, ctx) => {
|
|
1054
|
-
const {profile} = info;
|
|
1065
|
+
const { profile } = info;
|
|
1055
1066
|
if (!profile.email) {
|
|
1056
1067
|
throw new Error("Microsoft profile contained no email");
|
|
1057
1068
|
}
|
|
@@ -1061,19 +1072,19 @@ const microsoftEmailSignInResolver = async (info, ctx) => {
|
|
|
1061
1072
|
}
|
|
1062
1073
|
});
|
|
1063
1074
|
const claims = getEntityClaims(entity);
|
|
1064
|
-
const token = await ctx.tokenIssuer.issueToken({claims});
|
|
1065
|
-
return {id: entity.metadata.name, entity, token};
|
|
1075
|
+
const token = await ctx.tokenIssuer.issueToken({ claims });
|
|
1076
|
+
return { id: entity.metadata.name, entity, token };
|
|
1066
1077
|
};
|
|
1067
1078
|
const microsoftDefaultSignInResolver = async (info, ctx) => {
|
|
1068
|
-
const {profile} = info;
|
|
1079
|
+
const { profile } = info;
|
|
1069
1080
|
if (!profile.email) {
|
|
1070
1081
|
throw new Error("Profile contained no email");
|
|
1071
1082
|
}
|
|
1072
1083
|
const userId = profile.email.split("@")[0];
|
|
1073
1084
|
const token = await ctx.tokenIssuer.issueToken({
|
|
1074
|
-
claims: {sub: userId, ent: [`user:default/${userId}`]}
|
|
1085
|
+
claims: { sub: userId, ent: [`user:default/${userId}`] }
|
|
1075
1086
|
});
|
|
1076
|
-
return {id: userId, token};
|
|
1087
|
+
return { id: userId, token };
|
|
1077
1088
|
};
|
|
1078
1089
|
const createMicrosoftProvider = (options) => {
|
|
1079
1090
|
return ({
|
|
@@ -1095,7 +1106,7 @@ const createMicrosoftProvider = (options) => {
|
|
|
1095
1106
|
catalogApi,
|
|
1096
1107
|
tokenIssuer
|
|
1097
1108
|
});
|
|
1098
|
-
const authHandler = (options == null ? void 0 : options.authHandler) ? options.authHandler : async ({fullProfile, params}) => ({
|
|
1109
|
+
const authHandler = (options == null ? void 0 : options.authHandler) ? options.authHandler : async ({ fullProfile, params }) => ({
|
|
1099
1110
|
profile: makeProfileInfo(fullProfile, params.id_token)
|
|
1100
1111
|
});
|
|
1101
1112
|
const signInResolverFn = (_b = (_a = options == null ? void 0 : options.signIn) == null ? void 0 : _a.resolver) != null ? _b : microsoftDefaultSignInResolver;
|
|
@@ -1138,7 +1149,10 @@ class OAuth2AuthProvider {
|
|
|
1138
1149
|
authorizationURL: options.authorizationUrl,
|
|
1139
1150
|
tokenURL: options.tokenUrl,
|
|
1140
1151
|
passReqToCallback: false,
|
|
1141
|
-
scope: options.scope
|
|
1152
|
+
scope: options.scope,
|
|
1153
|
+
customHeaders: options.includeBasicAuth ? {
|
|
1154
|
+
Authorization: `Basic ${this.encodeClientCredentials(options.clientId, options.clientSecret)}`
|
|
1155
|
+
} : void 0
|
|
1142
1156
|
}, (accessToken, refreshToken, params, fullProfile, done) => {
|
|
1143
1157
|
done(void 0, {
|
|
1144
1158
|
fullProfile,
|
|
@@ -1159,7 +1173,7 @@ class OAuth2AuthProvider {
|
|
|
1159
1173
|
});
|
|
1160
1174
|
}
|
|
1161
1175
|
async handler(req) {
|
|
1162
|
-
const {result, privateInfo} = await executeFrameHandlerStrategy(req, this._strategy);
|
|
1176
|
+
const { result, privateInfo } = await executeFrameHandlerStrategy(req, this._strategy);
|
|
1163
1177
|
return {
|
|
1164
1178
|
response: await this.handleResult(result),
|
|
1165
1179
|
refreshToken: privateInfo.refreshToken
|
|
@@ -1181,7 +1195,7 @@ class OAuth2AuthProvider {
|
|
|
1181
1195
|
});
|
|
1182
1196
|
}
|
|
1183
1197
|
async handleResult(result) {
|
|
1184
|
-
const {profile} = await this.authHandler(result);
|
|
1198
|
+
const { profile } = await this.authHandler(result);
|
|
1185
1199
|
const response = {
|
|
1186
1200
|
providerInfo: {
|
|
1187
1201
|
idToken: result.params.id_token,
|
|
@@ -1204,17 +1218,20 @@ class OAuth2AuthProvider {
|
|
|
1204
1218
|
}
|
|
1205
1219
|
return response;
|
|
1206
1220
|
}
|
|
1221
|
+
encodeClientCredentials(clientID, clientSecret) {
|
|
1222
|
+
return Buffer.from(`${clientID}:${clientSecret}`).toString("base64");
|
|
1223
|
+
}
|
|
1207
1224
|
}
|
|
1208
|
-
const oAuth2DefaultSignInResolver = async (info, ctx) => {
|
|
1209
|
-
const {profile} = info;
|
|
1225
|
+
const oAuth2DefaultSignInResolver$1 = async (info, ctx) => {
|
|
1226
|
+
const { profile } = info;
|
|
1210
1227
|
if (!profile.email) {
|
|
1211
1228
|
throw new Error("Profile contained no email");
|
|
1212
1229
|
}
|
|
1213
1230
|
const userId = profile.email.split("@")[0];
|
|
1214
1231
|
const token = await ctx.tokenIssuer.issueToken({
|
|
1215
|
-
claims: {sub: userId, ent: [`user:default/${userId}`]}
|
|
1232
|
+
claims: { sub: userId, ent: [`user:default/${userId}`] }
|
|
1216
1233
|
});
|
|
1217
|
-
return {id: userId, token};
|
|
1234
|
+
return { id: userId, token };
|
|
1218
1235
|
};
|
|
1219
1236
|
const createOAuth2Provider = (options) => {
|
|
1220
1237
|
return ({
|
|
@@ -1232,15 +1249,16 @@ const createOAuth2Provider = (options) => {
|
|
|
1232
1249
|
const authorizationUrl = envConfig.getString("authorizationUrl");
|
|
1233
1250
|
const tokenUrl = envConfig.getString("tokenUrl");
|
|
1234
1251
|
const scope = envConfig.getOptionalString("scope");
|
|
1252
|
+
const includeBasicAuth = envConfig.getOptionalBoolean("includeBasicAuth");
|
|
1235
1253
|
const disableRefresh = (_a = envConfig.getOptionalBoolean("disableRefresh")) != null ? _a : false;
|
|
1236
1254
|
const catalogIdentityClient = new CatalogIdentityClient({
|
|
1237
1255
|
catalogApi,
|
|
1238
1256
|
tokenIssuer
|
|
1239
1257
|
});
|
|
1240
|
-
const authHandler = (options == null ? void 0 : options.authHandler) ? options.authHandler : async ({fullProfile, params}) => ({
|
|
1258
|
+
const authHandler = (options == null ? void 0 : options.authHandler) ? options.authHandler : async ({ fullProfile, params }) => ({
|
|
1241
1259
|
profile: makeProfileInfo(fullProfile, params.id_token)
|
|
1242
1260
|
});
|
|
1243
|
-
const signInResolverFn = (_c = (_b = options == null ? void 0 : options.signIn) == null ? void 0 : _b.resolver) != null ? _c : oAuth2DefaultSignInResolver;
|
|
1261
|
+
const signInResolverFn = (_c = (_b = options == null ? void 0 : options.signIn) == null ? void 0 : _b.resolver) != null ? _c : oAuth2DefaultSignInResolver$1;
|
|
1244
1262
|
const signInResolver = (info) => signInResolverFn(info, {
|
|
1245
1263
|
catalogIdentityClient,
|
|
1246
1264
|
tokenIssuer,
|
|
@@ -1257,7 +1275,8 @@ const createOAuth2Provider = (options) => {
|
|
|
1257
1275
|
authorizationUrl,
|
|
1258
1276
|
tokenUrl,
|
|
1259
1277
|
scope,
|
|
1260
|
-
logger
|
|
1278
|
+
logger,
|
|
1279
|
+
includeBasicAuth
|
|
1261
1280
|
});
|
|
1262
1281
|
return OAuthAdapter.fromConfig(globalConfig, provider, {
|
|
1263
1282
|
disableRefresh,
|
|
@@ -1267,6 +1286,168 @@ const createOAuth2Provider = (options) => {
|
|
|
1267
1286
|
});
|
|
1268
1287
|
};
|
|
1269
1288
|
|
|
1289
|
+
class OidcAuthProvider {
|
|
1290
|
+
constructor(options) {
|
|
1291
|
+
this.implementation = this.setupStrategy(options);
|
|
1292
|
+
this.scope = options.scope;
|
|
1293
|
+
this.prompt = options.prompt;
|
|
1294
|
+
this.signInResolver = options.signInResolver;
|
|
1295
|
+
this.authHandler = options.authHandler;
|
|
1296
|
+
this.tokenIssuer = options.tokenIssuer;
|
|
1297
|
+
this.catalogIdentityClient = options.catalogIdentityClient;
|
|
1298
|
+
this.logger = options.logger;
|
|
1299
|
+
}
|
|
1300
|
+
async start(req) {
|
|
1301
|
+
const { strategy } = await this.implementation;
|
|
1302
|
+
const options = {
|
|
1303
|
+
scope: req.scope || this.scope || "openid profile email",
|
|
1304
|
+
state: encodeState(req.state)
|
|
1305
|
+
};
|
|
1306
|
+
const prompt = this.prompt || "none";
|
|
1307
|
+
if (prompt !== "auto") {
|
|
1308
|
+
options.prompt = prompt;
|
|
1309
|
+
}
|
|
1310
|
+
return await executeRedirectStrategy(req, strategy, options);
|
|
1311
|
+
}
|
|
1312
|
+
async handler(req) {
|
|
1313
|
+
const { strategy } = await this.implementation;
|
|
1314
|
+
const strategyResponse = await executeFrameHandlerStrategy(req, strategy);
|
|
1315
|
+
const {
|
|
1316
|
+
result: { userinfo, tokenset },
|
|
1317
|
+
privateInfo
|
|
1318
|
+
} = strategyResponse;
|
|
1319
|
+
const identityResponse = await this.handleResult({ tokenset, userinfo });
|
|
1320
|
+
return {
|
|
1321
|
+
response: identityResponse,
|
|
1322
|
+
refreshToken: privateInfo.refreshToken
|
|
1323
|
+
};
|
|
1324
|
+
}
|
|
1325
|
+
async refresh(req) {
|
|
1326
|
+
const { client } = await this.implementation;
|
|
1327
|
+
const tokenset = await client.refresh(req.refreshToken);
|
|
1328
|
+
if (!tokenset.access_token) {
|
|
1329
|
+
throw new Error("Refresh failed");
|
|
1330
|
+
}
|
|
1331
|
+
const profile = await client.userinfo(tokenset.access_token);
|
|
1332
|
+
return this.handleResult({ tokenset, userinfo: profile });
|
|
1333
|
+
}
|
|
1334
|
+
async setupStrategy(options) {
|
|
1335
|
+
const issuer = await openidClient.Issuer.discover(options.metadataUrl);
|
|
1336
|
+
const client = new issuer.Client({
|
|
1337
|
+
access_type: "offline",
|
|
1338
|
+
client_id: options.clientId,
|
|
1339
|
+
client_secret: options.clientSecret,
|
|
1340
|
+
redirect_uris: [options.callbackUrl],
|
|
1341
|
+
response_types: ["code"],
|
|
1342
|
+
id_token_signed_response_alg: options.tokenSignedResponseAlg || "RS256",
|
|
1343
|
+
scope: options.scope || ""
|
|
1344
|
+
});
|
|
1345
|
+
const strategy = new openidClient.Strategy({
|
|
1346
|
+
client,
|
|
1347
|
+
passReqToCallback: false
|
|
1348
|
+
}, (tokenset, userinfo, done) => {
|
|
1349
|
+
if (typeof done !== "function") {
|
|
1350
|
+
throw new Error("OIDC IdP must provide a userinfo_endpoint in the metadata response");
|
|
1351
|
+
}
|
|
1352
|
+
done(void 0, { tokenset, userinfo }, {
|
|
1353
|
+
refreshToken: tokenset.refresh_token
|
|
1354
|
+
});
|
|
1355
|
+
});
|
|
1356
|
+
strategy.error = console.error;
|
|
1357
|
+
return { strategy, client };
|
|
1358
|
+
}
|
|
1359
|
+
async handleResult(result) {
|
|
1360
|
+
const { profile } = await this.authHandler(result);
|
|
1361
|
+
const response = {
|
|
1362
|
+
providerInfo: {
|
|
1363
|
+
idToken: result.tokenset.id_token,
|
|
1364
|
+
accessToken: result.tokenset.access_token,
|
|
1365
|
+
refreshToken: result.tokenset.refresh_token,
|
|
1366
|
+
scope: result.tokenset.scope,
|
|
1367
|
+
expiresInSeconds: result.tokenset.expires_in
|
|
1368
|
+
},
|
|
1369
|
+
profile
|
|
1370
|
+
};
|
|
1371
|
+
if (this.signInResolver) {
|
|
1372
|
+
response.backstageIdentity = await this.signInResolver({
|
|
1373
|
+
result,
|
|
1374
|
+
profile
|
|
1375
|
+
}, {
|
|
1376
|
+
tokenIssuer: this.tokenIssuer,
|
|
1377
|
+
catalogIdentityClient: this.catalogIdentityClient,
|
|
1378
|
+
logger: this.logger
|
|
1379
|
+
});
|
|
1380
|
+
}
|
|
1381
|
+
return response;
|
|
1382
|
+
}
|
|
1383
|
+
}
|
|
1384
|
+
const oAuth2DefaultSignInResolver = async (info, ctx) => {
|
|
1385
|
+
const { profile } = info;
|
|
1386
|
+
if (!profile.email) {
|
|
1387
|
+
throw new Error("Profile contained no email");
|
|
1388
|
+
}
|
|
1389
|
+
const userId = profile.email.split("@")[0];
|
|
1390
|
+
const token = await ctx.tokenIssuer.issueToken({
|
|
1391
|
+
claims: { sub: userId, ent: [`user:default/${userId}`] }
|
|
1392
|
+
});
|
|
1393
|
+
return { id: userId, token };
|
|
1394
|
+
};
|
|
1395
|
+
const createOidcProvider = (options) => {
|
|
1396
|
+
return ({
|
|
1397
|
+
providerId,
|
|
1398
|
+
globalConfig,
|
|
1399
|
+
config,
|
|
1400
|
+
tokenIssuer,
|
|
1401
|
+
catalogApi,
|
|
1402
|
+
logger
|
|
1403
|
+
}) => OAuthEnvironmentHandler.mapConfig(config, (envConfig) => {
|
|
1404
|
+
var _a, _b;
|
|
1405
|
+
const clientId = envConfig.getString("clientId");
|
|
1406
|
+
const clientSecret = envConfig.getString("clientSecret");
|
|
1407
|
+
const callbackUrl = `${globalConfig.baseUrl}/${providerId}/handler/frame`;
|
|
1408
|
+
const metadataUrl = envConfig.getString("metadataUrl");
|
|
1409
|
+
const tokenSignedResponseAlg = envConfig.getOptionalString("tokenSignedResponseAlg");
|
|
1410
|
+
const scope = envConfig.getOptionalString("scope");
|
|
1411
|
+
const prompt = envConfig.getOptionalString("prompt");
|
|
1412
|
+
const catalogIdentityClient = new CatalogIdentityClient({
|
|
1413
|
+
catalogApi,
|
|
1414
|
+
tokenIssuer
|
|
1415
|
+
});
|
|
1416
|
+
const authHandler = (options == null ? void 0 : options.authHandler) ? options.authHandler : async ({ userinfo }) => ({
|
|
1417
|
+
profile: {
|
|
1418
|
+
displayName: userinfo.name,
|
|
1419
|
+
email: userinfo.email,
|
|
1420
|
+
picture: userinfo.picture
|
|
1421
|
+
}
|
|
1422
|
+
});
|
|
1423
|
+
const signInResolverFn = (_b = (_a = options == null ? void 0 : options.signIn) == null ? void 0 : _a.resolver) != null ? _b : oAuth2DefaultSignInResolver;
|
|
1424
|
+
const signInResolver = (info) => signInResolverFn(info, {
|
|
1425
|
+
catalogIdentityClient,
|
|
1426
|
+
tokenIssuer,
|
|
1427
|
+
logger
|
|
1428
|
+
});
|
|
1429
|
+
const provider = new OidcAuthProvider({
|
|
1430
|
+
clientId,
|
|
1431
|
+
clientSecret,
|
|
1432
|
+
callbackUrl,
|
|
1433
|
+
tokenSignedResponseAlg,
|
|
1434
|
+
metadataUrl,
|
|
1435
|
+
scope,
|
|
1436
|
+
prompt,
|
|
1437
|
+
signInResolver,
|
|
1438
|
+
authHandler,
|
|
1439
|
+
logger,
|
|
1440
|
+
tokenIssuer,
|
|
1441
|
+
catalogIdentityClient
|
|
1442
|
+
});
|
|
1443
|
+
return OAuthAdapter.fromConfig(globalConfig, provider, {
|
|
1444
|
+
disableRefresh: false,
|
|
1445
|
+
providerId,
|
|
1446
|
+
tokenIssuer
|
|
1447
|
+
});
|
|
1448
|
+
});
|
|
1449
|
+
};
|
|
1450
|
+
|
|
1270
1451
|
class OktaAuthProvider {
|
|
1271
1452
|
constructor(options) {
|
|
1272
1453
|
this._store = {
|
|
@@ -1310,14 +1491,14 @@ class OktaAuthProvider {
|
|
|
1310
1491
|
});
|
|
1311
1492
|
}
|
|
1312
1493
|
async handler(req) {
|
|
1313
|
-
const {result, privateInfo} = await executeFrameHandlerStrategy(req, this._strategy);
|
|
1494
|
+
const { result, privateInfo } = await executeFrameHandlerStrategy(req, this._strategy);
|
|
1314
1495
|
return {
|
|
1315
1496
|
response: await this.handleResult(result),
|
|
1316
1497
|
refreshToken: privateInfo.refreshToken
|
|
1317
1498
|
};
|
|
1318
1499
|
}
|
|
1319
1500
|
async refresh(req) {
|
|
1320
|
-
const {accessToken, params} = await executeRefreshTokenStrategy(this._strategy, req.refreshToken, req.scope);
|
|
1501
|
+
const { accessToken, params } = await executeRefreshTokenStrategy(this._strategy, req.refreshToken, req.scope);
|
|
1321
1502
|
const fullProfile = await executeFetchUserProfileStrategy(this._strategy, accessToken);
|
|
1322
1503
|
return this.handleResult({
|
|
1323
1504
|
fullProfile,
|
|
@@ -1327,7 +1508,7 @@ class OktaAuthProvider {
|
|
|
1327
1508
|
});
|
|
1328
1509
|
}
|
|
1329
1510
|
async handleResult(result) {
|
|
1330
|
-
const {profile} = await this._authHandler(result);
|
|
1511
|
+
const { profile } = await this._authHandler(result);
|
|
1331
1512
|
const response = {
|
|
1332
1513
|
providerInfo: {
|
|
1333
1514
|
idToken: result.params.id_token,
|
|
@@ -1351,7 +1532,7 @@ class OktaAuthProvider {
|
|
|
1351
1532
|
}
|
|
1352
1533
|
}
|
|
1353
1534
|
const oktaEmailSignInResolver = async (info, ctx) => {
|
|
1354
|
-
const {profile} = info;
|
|
1535
|
+
const { profile } = info;
|
|
1355
1536
|
if (!profile.email) {
|
|
1356
1537
|
throw new Error("Okta profile contained no email");
|
|
1357
1538
|
}
|
|
@@ -1361,19 +1542,19 @@ const oktaEmailSignInResolver = async (info, ctx) => {
|
|
|
1361
1542
|
}
|
|
1362
1543
|
});
|
|
1363
1544
|
const claims = getEntityClaims(entity);
|
|
1364
|
-
const token = await ctx.tokenIssuer.issueToken({claims});
|
|
1365
|
-
return {id: entity.metadata.name, entity, token};
|
|
1545
|
+
const token = await ctx.tokenIssuer.issueToken({ claims });
|
|
1546
|
+
return { id: entity.metadata.name, entity, token };
|
|
1366
1547
|
};
|
|
1367
1548
|
const oktaDefaultSignInResolver = async (info, ctx) => {
|
|
1368
|
-
const {profile} = info;
|
|
1549
|
+
const { profile } = info;
|
|
1369
1550
|
if (!profile.email) {
|
|
1370
1551
|
throw new Error("Okta profile contained no email");
|
|
1371
1552
|
}
|
|
1372
1553
|
const userId = profile.email.split("@")[0];
|
|
1373
1554
|
const token = await ctx.tokenIssuer.issueToken({
|
|
1374
|
-
claims: {sub: userId, ent: [`user:default/${userId}`]}
|
|
1555
|
+
claims: { sub: userId, ent: [`user:default/${userId}`] }
|
|
1375
1556
|
});
|
|
1376
|
-
return {id: userId, token};
|
|
1557
|
+
return { id: userId, token };
|
|
1377
1558
|
};
|
|
1378
1559
|
const createOktaProvider = (_options) => {
|
|
1379
1560
|
return ({
|
|
@@ -1396,7 +1577,7 @@ const createOktaProvider = (_options) => {
|
|
|
1396
1577
|
catalogApi,
|
|
1397
1578
|
tokenIssuer
|
|
1398
1579
|
});
|
|
1399
|
-
const authHandler = (_options == null ? void 0 : _options.authHandler) ? _options.authHandler : async ({fullProfile, params}) => ({
|
|
1580
|
+
const authHandler = (_options == null ? void 0 : _options.authHandler) ? _options.authHandler : async ({ fullProfile, params }) => ({
|
|
1400
1581
|
profile: makeProfileInfo(fullProfile, params.id_token)
|
|
1401
1582
|
});
|
|
1402
1583
|
const signInResolverFn = (_b = (_a = _options == null ? void 0 : _options.signIn) == null ? void 0 : _a.resolver) != null ? _b : oktaDefaultSignInResolver;
|
|
@@ -1456,14 +1637,14 @@ class BitbucketAuthProvider {
|
|
|
1456
1637
|
});
|
|
1457
1638
|
}
|
|
1458
1639
|
async handler(req) {
|
|
1459
|
-
const {result, privateInfo} = await executeFrameHandlerStrategy(req, this._strategy);
|
|
1640
|
+
const { result, privateInfo } = await executeFrameHandlerStrategy(req, this._strategy);
|
|
1460
1641
|
return {
|
|
1461
1642
|
response: await this.handleResult(result),
|
|
1462
1643
|
refreshToken: privateInfo.refreshToken
|
|
1463
1644
|
};
|
|
1464
1645
|
}
|
|
1465
1646
|
async refresh(req) {
|
|
1466
|
-
const {accessToken, params} = await executeRefreshTokenStrategy(this._strategy, req.refreshToken, req.scope);
|
|
1647
|
+
const { accessToken, params } = await executeRefreshTokenStrategy(this._strategy, req.refreshToken, req.scope);
|
|
1467
1648
|
const fullProfile = await executeFetchUserProfileStrategy(this._strategy, accessToken);
|
|
1468
1649
|
return this.handleResult({
|
|
1469
1650
|
fullProfile,
|
|
@@ -1474,7 +1655,7 @@ class BitbucketAuthProvider {
|
|
|
1474
1655
|
}
|
|
1475
1656
|
async handleResult(result) {
|
|
1476
1657
|
result.fullProfile.avatarUrl = result.fullProfile._json.links.avatar.href;
|
|
1477
|
-
const {profile} = await this.authHandler(result);
|
|
1658
|
+
const { profile } = await this.authHandler(result);
|
|
1478
1659
|
const response = {
|
|
1479
1660
|
providerInfo: {
|
|
1480
1661
|
idToken: result.params.id_token,
|
|
@@ -1498,7 +1679,7 @@ class BitbucketAuthProvider {
|
|
|
1498
1679
|
}
|
|
1499
1680
|
}
|
|
1500
1681
|
const bitbucketUsernameSignInResolver = async (info, ctx) => {
|
|
1501
|
-
const {result} = info;
|
|
1682
|
+
const { result } = info;
|
|
1502
1683
|
if (!result.fullProfile.username) {
|
|
1503
1684
|
throw new Error("Bitbucket profile contained no Username");
|
|
1504
1685
|
}
|
|
@@ -1508,11 +1689,11 @@ const bitbucketUsernameSignInResolver = async (info, ctx) => {
|
|
|
1508
1689
|
}
|
|
1509
1690
|
});
|
|
1510
1691
|
const claims = getEntityClaims(entity);
|
|
1511
|
-
const token = await ctx.tokenIssuer.issueToken({claims});
|
|
1512
|
-
return {id: entity.metadata.name, entity, token};
|
|
1692
|
+
const token = await ctx.tokenIssuer.issueToken({ claims });
|
|
1693
|
+
return { id: entity.metadata.name, entity, token };
|
|
1513
1694
|
};
|
|
1514
1695
|
const bitbucketUserIdSignInResolver = async (info, ctx) => {
|
|
1515
|
-
const {result} = info;
|
|
1696
|
+
const { result } = info;
|
|
1516
1697
|
if (!result.fullProfile.id) {
|
|
1517
1698
|
throw new Error("Bitbucket profile contained no User ID");
|
|
1518
1699
|
}
|
|
@@ -1522,8 +1703,8 @@ const bitbucketUserIdSignInResolver = async (info, ctx) => {
|
|
|
1522
1703
|
}
|
|
1523
1704
|
});
|
|
1524
1705
|
const claims = getEntityClaims(entity);
|
|
1525
|
-
const token = await ctx.tokenIssuer.issueToken({claims});
|
|
1526
|
-
return {id: entity.metadata.name, entity, token};
|
|
1706
|
+
const token = await ctx.tokenIssuer.issueToken({ claims });
|
|
1707
|
+
return { id: entity.metadata.name, entity, token };
|
|
1527
1708
|
};
|
|
1528
1709
|
const createBitbucketProvider = (options) => {
|
|
1529
1710
|
return ({
|
|
@@ -1542,7 +1723,7 @@ const createBitbucketProvider = (options) => {
|
|
|
1542
1723
|
catalogApi,
|
|
1543
1724
|
tokenIssuer
|
|
1544
1725
|
});
|
|
1545
|
-
const authHandler = (options == null ? void 0 : options.authHandler) ? options.authHandler : async ({fullProfile, params}) => ({
|
|
1726
|
+
const authHandler = (options == null ? void 0 : options.authHandler) ? options.authHandler : async ({ fullProfile, params }) => ({
|
|
1546
1727
|
profile: makeProfileInfo(fullProfile, params.id_token)
|
|
1547
1728
|
});
|
|
1548
1729
|
const provider = new BitbucketAuthProvider({
|
|
@@ -1564,7 +1745,7 @@ const createBitbucketProvider = (options) => {
|
|
|
1564
1745
|
};
|
|
1565
1746
|
|
|
1566
1747
|
const defaultScopes = ["offline_access", "read:me"];
|
|
1567
|
-
class AtlassianStrategy extends OAuth2Strategy__default[
|
|
1748
|
+
class AtlassianStrategy extends OAuth2Strategy__default["default"] {
|
|
1568
1749
|
constructor(options, verify) {
|
|
1569
1750
|
if (!options.scope) {
|
|
1570
1751
|
throw new TypeError("Atlassian requires a scope option");
|
|
@@ -1574,7 +1755,7 @@ class AtlassianStrategy extends OAuth2Strategy__default['default'] {
|
|
|
1574
1755
|
...options,
|
|
1575
1756
|
authorizationURL: `https://auth.atlassian.com/authorize`,
|
|
1576
1757
|
tokenURL: `https://auth.atlassian.com/oauth/token`,
|
|
1577
|
-
scope: Array.from(new Set([...defaultScopes, ...scopes]))
|
|
1758
|
+
scope: Array.from(/* @__PURE__ */ new Set([...defaultScopes, ...scopes]))
|
|
1578
1759
|
};
|
|
1579
1760
|
super(optionsWithURLs, verify);
|
|
1580
1761
|
this.profileURL = "https://api.atlassian.com/me";
|
|
@@ -1611,8 +1792,8 @@ class AtlassianStrategy extends OAuth2Strategy__default['default'] {
|
|
|
1611
1792
|
provider: "atlassian",
|
|
1612
1793
|
username: resp.nickname,
|
|
1613
1794
|
displayName: resp.name,
|
|
1614
|
-
emails: [{value: resp.email}],
|
|
1615
|
-
photos: [{value: resp.picture}]
|
|
1795
|
+
emails: [{ value: resp.email }],
|
|
1796
|
+
photos: [{ value: resp.picture }]
|
|
1616
1797
|
};
|
|
1617
1798
|
}
|
|
1618
1799
|
}
|
|
@@ -1651,14 +1832,14 @@ class AtlassianAuthProvider {
|
|
|
1651
1832
|
}
|
|
1652
1833
|
async handler(req) {
|
|
1653
1834
|
var _a;
|
|
1654
|
-
const {result} = await executeFrameHandlerStrategy(req, this._strategy);
|
|
1835
|
+
const { result } = await executeFrameHandlerStrategy(req, this._strategy);
|
|
1655
1836
|
return {
|
|
1656
1837
|
response: await this.handleResult(result),
|
|
1657
1838
|
refreshToken: (_a = result.refreshToken) != null ? _a : ""
|
|
1658
1839
|
};
|
|
1659
1840
|
}
|
|
1660
1841
|
async handleResult(result) {
|
|
1661
|
-
const {profile} = await this.authHandler(result);
|
|
1842
|
+
const { profile } = await this.authHandler(result);
|
|
1662
1843
|
const response = {
|
|
1663
1844
|
providerInfo: {
|
|
1664
1845
|
idToken: result.params.id_token,
|
|
@@ -1749,7 +1930,7 @@ class AwsAlbAuthProvider {
|
|
|
1749
1930
|
this.tokenIssuer = options.tokenIssuer;
|
|
1750
1931
|
this.catalogIdentityClient = options.catalogIdentityClient;
|
|
1751
1932
|
this.logger = options.logger;
|
|
1752
|
-
this.keyCache = new NodeCache__default[
|
|
1933
|
+
this.keyCache = new NodeCache__default["default"]({ stdTTL: 3600 });
|
|
1753
1934
|
}
|
|
1754
1935
|
frameHandler() {
|
|
1755
1936
|
return Promise.resolve(void 0);
|
|
@@ -1793,8 +1974,8 @@ class AwsAlbAuthProvider {
|
|
|
1793
1974
|
familyName: claims.family_name,
|
|
1794
1975
|
givenName: claims.given_name
|
|
1795
1976
|
},
|
|
1796
|
-
emails: [{value: claims.email.toLowerCase()}],
|
|
1797
|
-
photos: [{value: claims.picture}]
|
|
1977
|
+
emails: [{ value: claims.email.toLowerCase() }],
|
|
1978
|
+
photos: [{ value: claims.picture }]
|
|
1798
1979
|
};
|
|
1799
1980
|
return {
|
|
1800
1981
|
fullProfile,
|
|
@@ -1806,7 +1987,7 @@ class AwsAlbAuthProvider {
|
|
|
1806
1987
|
}
|
|
1807
1988
|
}
|
|
1808
1989
|
async handleResult(result) {
|
|
1809
|
-
const {profile} = await this.authHandler(result);
|
|
1990
|
+
const { profile } = await this.authHandler(result);
|
|
1810
1991
|
const backstageIdentity = await this.signInResolver({
|
|
1811
1992
|
result,
|
|
1812
1993
|
profile
|
|
@@ -1820,7 +2001,7 @@ class AwsAlbAuthProvider {
|
|
|
1820
2001
|
accessToken: result.accessToken,
|
|
1821
2002
|
expiresInSeconds: result.expiresInSeconds
|
|
1822
2003
|
},
|
|
1823
|
-
backstageIdentity,
|
|
2004
|
+
backstageIdentity: prepareBackstageIdentityResponse(backstageIdentity),
|
|
1824
2005
|
profile
|
|
1825
2006
|
};
|
|
1826
2007
|
}
|
|
@@ -1829,14 +2010,14 @@ class AwsAlbAuthProvider {
|
|
|
1829
2010
|
if (optionalCacheKey) {
|
|
1830
2011
|
return crypto__namespace.createPublicKey(optionalCacheKey);
|
|
1831
2012
|
}
|
|
1832
|
-
const keyText = await fetch__default[
|
|
2013
|
+
const keyText = await fetch__default["default"](`https://public-keys.auth.elb.${this.region}.amazonaws.com/${keyId}`).then((response) => response.text());
|
|
1833
2014
|
const keyValue = crypto__namespace.createPublicKey(keyText);
|
|
1834
|
-
this.keyCache.set(keyId, keyValue.export({format: "pem", type: "spki"}));
|
|
2015
|
+
this.keyCache.set(keyId, keyValue.export({ format: "pem", type: "spki" }));
|
|
1835
2016
|
return keyValue;
|
|
1836
2017
|
}
|
|
1837
2018
|
}
|
|
1838
2019
|
const createAwsAlbProvider = (options) => {
|
|
1839
|
-
return ({config, tokenIssuer, catalogApi, logger}) => {
|
|
2020
|
+
return ({ config, tokenIssuer, catalogApi, logger }) => {
|
|
1840
2021
|
const region = config.getString("region");
|
|
1841
2022
|
const issuer = config.getOptionalString("iss");
|
|
1842
2023
|
if ((options == null ? void 0 : options.signIn.resolver) === void 0) {
|
|
@@ -1846,7 +2027,7 @@ const createAwsAlbProvider = (options) => {
|
|
|
1846
2027
|
catalogApi,
|
|
1847
2028
|
tokenIssuer
|
|
1848
2029
|
});
|
|
1849
|
-
const authHandler = (options == null ? void 0 : options.authHandler) ? options.authHandler : async ({fullProfile}) => ({
|
|
2030
|
+
const authHandler = (options == null ? void 0 : options.authHandler) ? options.authHandler : async ({ fullProfile }) => ({
|
|
1850
2031
|
profile: makeProfileInfo(fullProfile)
|
|
1851
2032
|
});
|
|
1852
2033
|
const signInResolver = options == null ? void 0 : options.signIn.resolver;
|
|
@@ -1862,182 +2043,98 @@ const createAwsAlbProvider = (options) => {
|
|
|
1862
2043
|
};
|
|
1863
2044
|
};
|
|
1864
2045
|
|
|
1865
|
-
class OidcAuthProvider {
|
|
1866
|
-
constructor(options) {
|
|
1867
|
-
this.implementation = this.setupStrategy(options);
|
|
1868
|
-
this.scope = options.scope;
|
|
1869
|
-
this.prompt = options.prompt;
|
|
1870
|
-
}
|
|
1871
|
-
async start(req) {
|
|
1872
|
-
const {strategy} = await this.implementation;
|
|
1873
|
-
const options = {
|
|
1874
|
-
accessType: "offline",
|
|
1875
|
-
scope: req.scope || this.scope || "openid profile email",
|
|
1876
|
-
state: encodeState(req.state)
|
|
1877
|
-
};
|
|
1878
|
-
const prompt = this.prompt || "none";
|
|
1879
|
-
if (prompt !== "auto") {
|
|
1880
|
-
options.prompt = prompt;
|
|
1881
|
-
}
|
|
1882
|
-
return await executeRedirectStrategy(req, strategy, options);
|
|
1883
|
-
}
|
|
1884
|
-
async handler(req) {
|
|
1885
|
-
const {strategy} = await this.implementation;
|
|
1886
|
-
const strategyResponse = await executeFrameHandlerStrategy(req, strategy);
|
|
1887
|
-
const {
|
|
1888
|
-
result: {userinfo, tokenset},
|
|
1889
|
-
privateInfo
|
|
1890
|
-
} = strategyResponse;
|
|
1891
|
-
const identityResponse = await this.populateIdentity({
|
|
1892
|
-
profile: {
|
|
1893
|
-
displayName: userinfo.name,
|
|
1894
|
-
email: userinfo.email,
|
|
1895
|
-
picture: userinfo.picture
|
|
1896
|
-
},
|
|
1897
|
-
providerInfo: {
|
|
1898
|
-
idToken: tokenset.id_token,
|
|
1899
|
-
accessToken: tokenset.access_token || "",
|
|
1900
|
-
scope: tokenset.scope || "",
|
|
1901
|
-
expiresInSeconds: tokenset.expires_in
|
|
1902
|
-
}
|
|
1903
|
-
});
|
|
1904
|
-
return {
|
|
1905
|
-
response: identityResponse,
|
|
1906
|
-
refreshToken: privateInfo.refreshToken
|
|
1907
|
-
};
|
|
1908
|
-
}
|
|
1909
|
-
async refresh(req) {
|
|
1910
|
-
const {client} = await this.implementation;
|
|
1911
|
-
const tokenset = await client.refresh(req.refreshToken);
|
|
1912
|
-
if (!tokenset.access_token) {
|
|
1913
|
-
throw new Error("Refresh failed");
|
|
1914
|
-
}
|
|
1915
|
-
const profile = await client.userinfo(tokenset.access_token);
|
|
1916
|
-
return this.populateIdentity({
|
|
1917
|
-
providerInfo: {
|
|
1918
|
-
accessToken: tokenset.access_token,
|
|
1919
|
-
refreshToken: tokenset.refresh_token,
|
|
1920
|
-
expiresInSeconds: tokenset.expires_in,
|
|
1921
|
-
idToken: tokenset.id_token,
|
|
1922
|
-
scope: tokenset.scope || ""
|
|
1923
|
-
},
|
|
1924
|
-
profile
|
|
1925
|
-
});
|
|
1926
|
-
}
|
|
1927
|
-
async setupStrategy(options) {
|
|
1928
|
-
const issuer = await openidClient.Issuer.discover(options.metadataUrl);
|
|
1929
|
-
const client = new issuer.Client({
|
|
1930
|
-
client_id: options.clientId,
|
|
1931
|
-
client_secret: options.clientSecret,
|
|
1932
|
-
redirect_uris: [options.callbackUrl],
|
|
1933
|
-
response_types: ["code"],
|
|
1934
|
-
id_token_signed_response_alg: options.tokenSignedResponseAlg || "RS256",
|
|
1935
|
-
scope: options.scope || ""
|
|
1936
|
-
});
|
|
1937
|
-
const strategy = new openidClient.Strategy({
|
|
1938
|
-
client,
|
|
1939
|
-
passReqToCallback: false
|
|
1940
|
-
}, (tokenset, userinfo, done) => {
|
|
1941
|
-
if (typeof done !== "function") {
|
|
1942
|
-
throw new Error("OIDC IdP must provide a userinfo_endpoint in the metadata response");
|
|
1943
|
-
}
|
|
1944
|
-
done(void 0, {tokenset, userinfo}, {
|
|
1945
|
-
refreshToken: tokenset.refresh_token
|
|
1946
|
-
});
|
|
1947
|
-
});
|
|
1948
|
-
strategy.error = console.error;
|
|
1949
|
-
return {strategy, client};
|
|
1950
|
-
}
|
|
1951
|
-
async populateIdentity(response) {
|
|
1952
|
-
const {profile} = response;
|
|
1953
|
-
if (!profile.email) {
|
|
1954
|
-
throw new Error("Profile does not contain an email");
|
|
1955
|
-
}
|
|
1956
|
-
const id = profile.email.split("@")[0];
|
|
1957
|
-
return {...response, backstageIdentity: {id}};
|
|
1958
|
-
}
|
|
1959
|
-
}
|
|
1960
|
-
const createOidcProvider = (_options) => {
|
|
1961
|
-
return ({providerId, globalConfig, config, tokenIssuer}) => OAuthEnvironmentHandler.mapConfig(config, (envConfig) => {
|
|
1962
|
-
const clientId = envConfig.getString("clientId");
|
|
1963
|
-
const clientSecret = envConfig.getString("clientSecret");
|
|
1964
|
-
const callbackUrl = `${globalConfig.baseUrl}/${providerId}/handler/frame`;
|
|
1965
|
-
const metadataUrl = envConfig.getString("metadataUrl");
|
|
1966
|
-
const tokenSignedResponseAlg = envConfig.getOptionalString("tokenSignedResponseAlg");
|
|
1967
|
-
const scope = envConfig.getOptionalString("scope");
|
|
1968
|
-
const prompt = envConfig.getOptionalString("prompt");
|
|
1969
|
-
const provider = new OidcAuthProvider({
|
|
1970
|
-
clientId,
|
|
1971
|
-
clientSecret,
|
|
1972
|
-
callbackUrl,
|
|
1973
|
-
tokenSignedResponseAlg,
|
|
1974
|
-
metadataUrl,
|
|
1975
|
-
scope,
|
|
1976
|
-
prompt
|
|
1977
|
-
});
|
|
1978
|
-
return OAuthAdapter.fromConfig(globalConfig, provider, {
|
|
1979
|
-
disableRefresh: false,
|
|
1980
|
-
providerId,
|
|
1981
|
-
tokenIssuer
|
|
1982
|
-
});
|
|
1983
|
-
});
|
|
1984
|
-
};
|
|
1985
|
-
|
|
1986
2046
|
class SamlAuthProvider {
|
|
1987
2047
|
constructor(options) {
|
|
1988
2048
|
this.appUrl = options.appUrl;
|
|
2049
|
+
this.signInResolver = options.signInResolver;
|
|
2050
|
+
this.authHandler = options.authHandler;
|
|
1989
2051
|
this.tokenIssuer = options.tokenIssuer;
|
|
1990
|
-
this.
|
|
1991
|
-
|
|
2052
|
+
this.catalogIdentityClient = options.catalogIdentityClient;
|
|
2053
|
+
this.logger = options.logger;
|
|
2054
|
+
this.strategy = new passportSaml.Strategy({ ...options }, (fullProfile, done) => {
|
|
2055
|
+
done(void 0, { fullProfile });
|
|
1992
2056
|
});
|
|
1993
2057
|
}
|
|
1994
2058
|
async start(req, res) {
|
|
1995
|
-
const {url} = await executeRedirectStrategy(req, this.strategy, {});
|
|
2059
|
+
const { url } = await executeRedirectStrategy(req, this.strategy, {});
|
|
1996
2060
|
res.redirect(url);
|
|
1997
2061
|
}
|
|
1998
2062
|
async frameHandler(req, res) {
|
|
1999
2063
|
try {
|
|
2000
|
-
const {result} = await executeFrameHandlerStrategy(req, this.strategy);
|
|
2001
|
-
const
|
|
2002
|
-
const
|
|
2003
|
-
|
|
2004
|
-
|
|
2064
|
+
const { result } = await executeFrameHandlerStrategy(req, this.strategy);
|
|
2065
|
+
const { profile } = await this.authHandler(result);
|
|
2066
|
+
const response = {
|
|
2067
|
+
profile,
|
|
2068
|
+
providerInfo: {}
|
|
2069
|
+
};
|
|
2070
|
+
if (this.signInResolver) {
|
|
2071
|
+
const signInResponse = await this.signInResolver({
|
|
2072
|
+
result,
|
|
2073
|
+
profile
|
|
2074
|
+
}, {
|
|
2075
|
+
tokenIssuer: this.tokenIssuer,
|
|
2076
|
+
catalogIdentityClient: this.catalogIdentityClient,
|
|
2077
|
+
logger: this.logger
|
|
2078
|
+
});
|
|
2079
|
+
response.backstageIdentity = prepareBackstageIdentityResponse(signInResponse);
|
|
2080
|
+
}
|
|
2005
2081
|
return postMessageResponse(res, this.appUrl, {
|
|
2006
2082
|
type: "authorization_response",
|
|
2007
|
-
response
|
|
2008
|
-
profile: {
|
|
2009
|
-
email: result.fullProfile.email,
|
|
2010
|
-
displayName: result.fullProfile.displayName
|
|
2011
|
-
},
|
|
2012
|
-
providerInfo: {},
|
|
2013
|
-
backstageIdentity: {id, idToken}
|
|
2014
|
-
}
|
|
2083
|
+
response
|
|
2015
2084
|
});
|
|
2016
2085
|
} catch (error) {
|
|
2017
|
-
const {name, message} = errors.isError(error) ? error : new Error("Encountered invalid error");
|
|
2086
|
+
const { name, message } = errors.isError(error) ? error : new Error("Encountered invalid error");
|
|
2018
2087
|
return postMessageResponse(res, this.appUrl, {
|
|
2019
2088
|
type: "authorization_response",
|
|
2020
|
-
error: {name, message}
|
|
2089
|
+
error: { name, message }
|
|
2021
2090
|
});
|
|
2022
2091
|
}
|
|
2023
2092
|
}
|
|
2024
2093
|
async logout(_req, res) {
|
|
2025
|
-
res.
|
|
2026
|
-
}
|
|
2027
|
-
identifyEnv() {
|
|
2028
|
-
return void 0;
|
|
2094
|
+
res.end();
|
|
2029
2095
|
}
|
|
2030
2096
|
}
|
|
2031
|
-
const
|
|
2032
|
-
|
|
2033
|
-
|
|
2097
|
+
const samlDefaultSignInResolver = async (info, ctx) => {
|
|
2098
|
+
const id = info.result.fullProfile.nameID;
|
|
2099
|
+
const token = await ctx.tokenIssuer.issueToken({
|
|
2100
|
+
claims: { sub: id }
|
|
2101
|
+
});
|
|
2102
|
+
return { id, token };
|
|
2103
|
+
};
|
|
2104
|
+
const createSamlProvider = (options) => {
|
|
2105
|
+
return ({
|
|
2106
|
+
providerId,
|
|
2107
|
+
globalConfig,
|
|
2108
|
+
config,
|
|
2109
|
+
tokenIssuer,
|
|
2110
|
+
catalogApi,
|
|
2111
|
+
logger
|
|
2112
|
+
}) => {
|
|
2113
|
+
var _a, _b;
|
|
2114
|
+
const catalogIdentityClient = new CatalogIdentityClient({
|
|
2115
|
+
catalogApi,
|
|
2116
|
+
tokenIssuer
|
|
2117
|
+
});
|
|
2118
|
+
const authHandler = (options == null ? void 0 : options.authHandler) ? options.authHandler : async ({ fullProfile }) => ({
|
|
2119
|
+
profile: {
|
|
2120
|
+
email: fullProfile.email,
|
|
2121
|
+
displayName: fullProfile.displayName
|
|
2122
|
+
}
|
|
2123
|
+
});
|
|
2124
|
+
const signInResolverFn = (_b = (_a = options == null ? void 0 : options.signIn) == null ? void 0 : _a.resolver) != null ? _b : samlDefaultSignInResolver;
|
|
2125
|
+
const signInResolver = (info) => signInResolverFn(info, {
|
|
2126
|
+
catalogIdentityClient,
|
|
2127
|
+
tokenIssuer,
|
|
2128
|
+
logger
|
|
2129
|
+
});
|
|
2130
|
+
return new SamlAuthProvider({
|
|
2034
2131
|
callbackUrl: `${globalConfig.baseUrl}/${providerId}/handler/frame`,
|
|
2035
2132
|
entryPoint: config.getString("entryPoint"),
|
|
2036
2133
|
logoutUrl: config.getOptionalString("logoutUrl"),
|
|
2037
2134
|
audience: config.getOptionalString("audience"),
|
|
2038
2135
|
issuer: config.getString("issuer"),
|
|
2039
2136
|
cert: config.getString("cert"),
|
|
2040
|
-
|
|
2137
|
+
privateKey: config.getOptionalString("privateKey"),
|
|
2041
2138
|
authnContext: config.getOptionalStringArray("authnContext"),
|
|
2042
2139
|
identifierFormat: config.getOptionalString("identifierFormat"),
|
|
2043
2140
|
decryptionPvk: config.getOptionalString("decryptionPvk"),
|
|
@@ -2045,13 +2142,16 @@ const createSamlProvider = (_options) => {
|
|
|
2045
2142
|
digestAlgorithm: config.getOptionalString("digestAlgorithm"),
|
|
2046
2143
|
acceptedClockSkewMs: config.getOptionalNumber("acceptedClockSkewMs"),
|
|
2047
2144
|
tokenIssuer,
|
|
2048
|
-
appUrl: globalConfig.appUrl
|
|
2049
|
-
|
|
2050
|
-
|
|
2145
|
+
appUrl: globalConfig.appUrl,
|
|
2146
|
+
authHandler,
|
|
2147
|
+
signInResolver,
|
|
2148
|
+
logger,
|
|
2149
|
+
catalogIdentityClient
|
|
2150
|
+
});
|
|
2051
2151
|
};
|
|
2052
2152
|
};
|
|
2053
2153
|
|
|
2054
|
-
class Auth0Strategy extends OAuth2Strategy__default[
|
|
2154
|
+
class Auth0Strategy extends OAuth2Strategy__default["default"] {
|
|
2055
2155
|
constructor(options, verify) {
|
|
2056
2156
|
const optionsWithURLs = {
|
|
2057
2157
|
...options,
|
|
@@ -2092,7 +2192,7 @@ class Auth0AuthProvider {
|
|
|
2092
2192
|
});
|
|
2093
2193
|
}
|
|
2094
2194
|
async handler(req) {
|
|
2095
|
-
const {result, privateInfo} = await executeFrameHandlerStrategy(req, this._strategy);
|
|
2195
|
+
const { result, privateInfo } = await executeFrameHandlerStrategy(req, this._strategy);
|
|
2096
2196
|
const profile = makeProfileInfo(result.fullProfile, result.params.id_token);
|
|
2097
2197
|
return {
|
|
2098
2198
|
response: await this.populateIdentity({
|
|
@@ -2108,7 +2208,7 @@ class Auth0AuthProvider {
|
|
|
2108
2208
|
};
|
|
2109
2209
|
}
|
|
2110
2210
|
async refresh(req) {
|
|
2111
|
-
const {accessToken, params} = await executeRefreshTokenStrategy(this._strategy, req.refreshToken, req.scope);
|
|
2211
|
+
const { accessToken, params } = await executeRefreshTokenStrategy(this._strategy, req.refreshToken, req.scope);
|
|
2112
2212
|
const fullProfile = await executeFetchUserProfileStrategy(this._strategy, accessToken);
|
|
2113
2213
|
const profile = makeProfileInfo(fullProfile, params.id_token);
|
|
2114
2214
|
return this.populateIdentity({
|
|
@@ -2122,16 +2222,16 @@ class Auth0AuthProvider {
|
|
|
2122
2222
|
});
|
|
2123
2223
|
}
|
|
2124
2224
|
async populateIdentity(response) {
|
|
2125
|
-
const {profile} = response;
|
|
2225
|
+
const { profile } = response;
|
|
2126
2226
|
if (!profile.email) {
|
|
2127
2227
|
throw new Error("Profile does not contain an email");
|
|
2128
2228
|
}
|
|
2129
2229
|
const id = profile.email.split("@")[0];
|
|
2130
|
-
return {...response, backstageIdentity: {id}};
|
|
2230
|
+
return { ...response, backstageIdentity: { id, token: "" } };
|
|
2131
2231
|
}
|
|
2132
2232
|
}
|
|
2133
2233
|
const createAuth0Provider = (_options) => {
|
|
2134
|
-
return ({providerId, globalConfig, config, tokenIssuer}) => OAuthEnvironmentHandler.mapConfig(config, (envConfig) => {
|
|
2234
|
+
return ({ providerId, globalConfig, config, tokenIssuer }) => OAuthEnvironmentHandler.mapConfig(config, (envConfig) => {
|
|
2135
2235
|
const clientId = envConfig.getString("clientId");
|
|
2136
2236
|
const clientSecret = envConfig.getString("clientSecret");
|
|
2137
2237
|
const domain = envConfig.getString("domain");
|
|
@@ -2178,7 +2278,7 @@ class OneLoginProvider {
|
|
|
2178
2278
|
});
|
|
2179
2279
|
}
|
|
2180
2280
|
async handler(req) {
|
|
2181
|
-
const {result, privateInfo} = await executeFrameHandlerStrategy(req, this._strategy);
|
|
2281
|
+
const { result, privateInfo } = await executeFrameHandlerStrategy(req, this._strategy);
|
|
2182
2282
|
const profile = makeProfileInfo(result.fullProfile, result.params.id_token);
|
|
2183
2283
|
return {
|
|
2184
2284
|
response: await this.populateIdentity({
|
|
@@ -2194,7 +2294,7 @@ class OneLoginProvider {
|
|
|
2194
2294
|
};
|
|
2195
2295
|
}
|
|
2196
2296
|
async refresh(req) {
|
|
2197
|
-
const {accessToken, params} = await executeRefreshTokenStrategy(this._strategy, req.refreshToken, req.scope);
|
|
2297
|
+
const { accessToken, params } = await executeRefreshTokenStrategy(this._strategy, req.refreshToken, req.scope);
|
|
2198
2298
|
const fullProfile = await executeFetchUserProfileStrategy(this._strategy, accessToken);
|
|
2199
2299
|
const profile = makeProfileInfo(fullProfile, params.id_token);
|
|
2200
2300
|
return this.populateIdentity({
|
|
@@ -2208,16 +2308,16 @@ class OneLoginProvider {
|
|
|
2208
2308
|
});
|
|
2209
2309
|
}
|
|
2210
2310
|
async populateIdentity(response) {
|
|
2211
|
-
const {profile} = response;
|
|
2311
|
+
const { profile } = response;
|
|
2212
2312
|
if (!profile.email) {
|
|
2213
2313
|
throw new Error("OIDC profile contained no email");
|
|
2214
2314
|
}
|
|
2215
2315
|
const id = profile.email.split("@")[0];
|
|
2216
|
-
return {...response, backstageIdentity: {id}};
|
|
2316
|
+
return { ...response, backstageIdentity: { id, token: "" } };
|
|
2217
2317
|
}
|
|
2218
2318
|
}
|
|
2219
2319
|
const createOneLoginProvider = (_options) => {
|
|
2220
|
-
return ({providerId, globalConfig, config, tokenIssuer}) => OAuthEnvironmentHandler.mapConfig(config, (envConfig) => {
|
|
2320
|
+
return ({ providerId, globalConfig, config, tokenIssuer }) => OAuthEnvironmentHandler.mapConfig(config, (envConfig) => {
|
|
2221
2321
|
const clientId = envConfig.getString("clientId");
|
|
2222
2322
|
const clientSecret = envConfig.getString("clientSecret");
|
|
2223
2323
|
const issuer = envConfig.getString("issuer");
|
|
@@ -2253,8 +2353,8 @@ const factories = {
|
|
|
2253
2353
|
};
|
|
2254
2354
|
|
|
2255
2355
|
function createOidcRouter(options) {
|
|
2256
|
-
const {baseUrl, tokenIssuer} = options;
|
|
2257
|
-
const router = Router__default[
|
|
2356
|
+
const { baseUrl, tokenIssuer } = options;
|
|
2357
|
+
const router = Router__default["default"]();
|
|
2258
2358
|
const config = {
|
|
2259
2359
|
issuer: baseUrl,
|
|
2260
2360
|
token_endpoint: `${baseUrl}/v1/token`,
|
|
@@ -2272,8 +2372,8 @@ function createOidcRouter(options) {
|
|
|
2272
2372
|
res.json(config);
|
|
2273
2373
|
});
|
|
2274
2374
|
router.get("/.well-known/jwks.json", async (_req, res) => {
|
|
2275
|
-
const {keys} = await tokenIssuer.listPublicKeys();
|
|
2276
|
-
res.json({keys});
|
|
2375
|
+
const { keys } = await tokenIssuer.listPublicKeys();
|
|
2376
|
+
res.json({ keys });
|
|
2277
2377
|
});
|
|
2278
2378
|
router.get("/v1/token", (_req, res) => {
|
|
2279
2379
|
res.status(501).send("Not Implemented");
|
|
@@ -2293,21 +2393,30 @@ class IdentityClient {
|
|
|
2293
2393
|
this.keyStoreUpdated = 0;
|
|
2294
2394
|
}
|
|
2295
2395
|
async authenticate(token) {
|
|
2396
|
+
var _a;
|
|
2296
2397
|
if (!token) {
|
|
2297
|
-
throw new
|
|
2398
|
+
throw new errors.AuthenticationError("No token specified");
|
|
2298
2399
|
}
|
|
2299
2400
|
const key = await this.getKey(token);
|
|
2300
2401
|
if (!key) {
|
|
2301
|
-
throw new
|
|
2402
|
+
throw new errors.AuthenticationError("No signing key matching token found");
|
|
2302
2403
|
}
|
|
2303
2404
|
const decoded = jose.JWT.IdToken.verify(token, key, {
|
|
2304
2405
|
algorithms: ["ES256"],
|
|
2305
2406
|
audience: "backstage",
|
|
2306
2407
|
issuer: this.issuer
|
|
2307
2408
|
});
|
|
2409
|
+
if (!decoded.sub) {
|
|
2410
|
+
throw new errors.AuthenticationError("No user sub found in token");
|
|
2411
|
+
}
|
|
2308
2412
|
const user = {
|
|
2309
2413
|
id: decoded.sub,
|
|
2310
|
-
|
|
2414
|
+
token,
|
|
2415
|
+
identity: {
|
|
2416
|
+
type: "user",
|
|
2417
|
+
userEntityRef: decoded.sub,
|
|
2418
|
+
ownershipEntityRefs: (_a = decoded.ent) != null ? _a : []
|
|
2419
|
+
}
|
|
2311
2420
|
};
|
|
2312
2421
|
return user;
|
|
2313
2422
|
}
|
|
@@ -2319,19 +2428,19 @@ class IdentityClient {
|
|
|
2319
2428
|
return matches == null ? void 0 : matches[1];
|
|
2320
2429
|
}
|
|
2321
2430
|
async getKey(rawJwtToken) {
|
|
2322
|
-
const {header, payload} = jose.JWT.decode(rawJwtToken, {
|
|
2431
|
+
const { header, payload } = jose.JWT.decode(rawJwtToken, {
|
|
2323
2432
|
complete: true
|
|
2324
2433
|
});
|
|
2325
|
-
const keyStoreHasKey = !!this.keyStore.get({kid: header.kid});
|
|
2434
|
+
const keyStoreHasKey = !!this.keyStore.get({ kid: header.kid });
|
|
2326
2435
|
const issuedAfterLastRefresh = (payload == null ? void 0 : payload.iat) && payload.iat > this.keyStoreUpdated - CLOCK_MARGIN_S;
|
|
2327
2436
|
if (!keyStoreHasKey && issuedAfterLastRefresh) {
|
|
2328
2437
|
await this.refreshKeyStore();
|
|
2329
2438
|
}
|
|
2330
|
-
return this.keyStore.get({kid: header.kid});
|
|
2439
|
+
return this.keyStore.get({ kid: header.kid });
|
|
2331
2440
|
}
|
|
2332
2441
|
async listPublicKeys() {
|
|
2333
2442
|
const url = `${await this.discovery.getBaseUrl("auth")}/.well-known/jwks.json`;
|
|
2334
|
-
const response = await fetch__default[
|
|
2443
|
+
const response = await fetch__default["default"](url);
|
|
2335
2444
|
if (!response.ok) {
|
|
2336
2445
|
const payload = await response.text();
|
|
2337
2446
|
const message = `Request failed with ${response.status} ${response.statusText}, ${payload}`;
|
|
@@ -2367,13 +2476,13 @@ class TokenFactory {
|
|
|
2367
2476
|
const iat = Math.floor(Date.now() / MS_IN_S);
|
|
2368
2477
|
const exp = iat + this.keyDurationSeconds;
|
|
2369
2478
|
this.logger.info(`Issuing token for ${sub}, with entities ${ent != null ? ent : []}`);
|
|
2370
|
-
return jose.JWS.sign({iss, sub, aud, iat, exp, ent}, key, {
|
|
2479
|
+
return jose.JWS.sign({ iss, sub, aud, iat, exp, ent }, key, {
|
|
2371
2480
|
alg: key.alg,
|
|
2372
2481
|
kid: key.kid
|
|
2373
2482
|
});
|
|
2374
2483
|
}
|
|
2375
2484
|
async listPublicKeys() {
|
|
2376
|
-
const {items: keys} = await this.keyStore.listKeys();
|
|
2485
|
+
const { items: keys } = await this.keyStore.listKeys();
|
|
2377
2486
|
const validKeys = [];
|
|
2378
2487
|
const expiredKeys = [];
|
|
2379
2488
|
for (const key of keys) {
|
|
@@ -2387,13 +2496,13 @@ class TokenFactory {
|
|
|
2387
2496
|
}
|
|
2388
2497
|
}
|
|
2389
2498
|
if (expiredKeys.length > 0) {
|
|
2390
|
-
const kids = expiredKeys.map(({key}) => key.kid);
|
|
2499
|
+
const kids = expiredKeys.map(({ key }) => key.kid);
|
|
2391
2500
|
this.logger.info(`Removing expired signing keys, '${kids.join("', '")}'`);
|
|
2392
2501
|
this.keyStore.removeKeys(kids).catch((error) => {
|
|
2393
2502
|
this.logger.error(`Failed to remove expired keys, ${error}`);
|
|
2394
2503
|
});
|
|
2395
2504
|
}
|
|
2396
|
-
return {keys: validKeys.map(({key}) => key)};
|
|
2505
|
+
return { keys: validKeys.map(({ key }) => key) };
|
|
2397
2506
|
}
|
|
2398
2507
|
async getKey() {
|
|
2399
2508
|
if (this.privateKeyPromise) {
|
|
@@ -2431,7 +2540,7 @@ class TokenFactory {
|
|
|
2431
2540
|
const migrationsDir = backendCommon.resolvePackagePath("@backstage/plugin-auth-backend", "migrations");
|
|
2432
2541
|
const TABLE = "signing_keys";
|
|
2433
2542
|
const parseDate = (date) => {
|
|
2434
|
-
const parsedDate = typeof date === "string" ? luxon.DateTime.fromSQL(date, {zone: "UTC"}) : luxon.DateTime.fromJSDate(date);
|
|
2543
|
+
const parsedDate = typeof date === "string" ? luxon.DateTime.fromSQL(date, { zone: "UTC" }) : luxon.DateTime.fromJSDate(date);
|
|
2435
2544
|
if (!parsedDate.isValid) {
|
|
2436
2545
|
throw new Error(`Failed to parse date, reason: ${parsedDate.invalidReason}, explanation: ${parsedDate.invalidExplanation}`);
|
|
2437
2546
|
}
|
|
@@ -2439,7 +2548,7 @@ const parseDate = (date) => {
|
|
|
2439
2548
|
};
|
|
2440
2549
|
class DatabaseKeyStore {
|
|
2441
2550
|
static async create(options) {
|
|
2442
|
-
const {database} = options;
|
|
2551
|
+
const { database } = options;
|
|
2443
2552
|
await database.migrate.latest({
|
|
2444
2553
|
directory: migrationsDir
|
|
2445
2554
|
});
|
|
@@ -2470,7 +2579,7 @@ class DatabaseKeyStore {
|
|
|
2470
2579
|
|
|
2471
2580
|
class MemoryKeyStore {
|
|
2472
2581
|
constructor() {
|
|
2473
|
-
this.keys = new Map();
|
|
2582
|
+
this.keys = /* @__PURE__ */ new Map();
|
|
2474
2583
|
}
|
|
2475
2584
|
async addKey(key) {
|
|
2476
2585
|
this.keys.set(key.kid, {
|
|
@@ -2485,7 +2594,7 @@ class MemoryKeyStore {
|
|
|
2485
2594
|
}
|
|
2486
2595
|
async listKeys() {
|
|
2487
2596
|
return {
|
|
2488
|
-
items: Array.from(this.keys).map(([, {createdAt, key: keyStr}]) => ({
|
|
2597
|
+
items: Array.from(this.keys).map(([, { createdAt, key: keyStr }]) => ({
|
|
2489
2598
|
createdAt,
|
|
2490
2599
|
key: JSON.parse(keyStr)
|
|
2491
2600
|
}))
|
|
@@ -2502,7 +2611,7 @@ class FirestoreKeyStore {
|
|
|
2502
2611
|
this.timeout = timeout;
|
|
2503
2612
|
}
|
|
2504
2613
|
static async create(settings) {
|
|
2505
|
-
const {path, timeout, ...firestoreSettings} = settings != null ? settings : {};
|
|
2614
|
+
const { path, timeout, ...firestoreSettings } = settings != null ? settings : {};
|
|
2506
2615
|
const database = new firestore.Firestore(firestoreSettings);
|
|
2507
2616
|
return new FirestoreKeyStore(database, path != null ? path : DEFAULT_DOCUMENT_PATH, timeout != null ? timeout : DEFAULT_TIMEOUT_MS);
|
|
2508
2617
|
}
|
|
@@ -2550,7 +2659,7 @@ class FirestoreKeyStore {
|
|
|
2550
2659
|
class KeyStores {
|
|
2551
2660
|
static async fromConfig(config, options) {
|
|
2552
2661
|
var _a;
|
|
2553
|
-
const {logger, database} = options != null ? options : {};
|
|
2662
|
+
const { logger, database } = options != null ? options : {};
|
|
2554
2663
|
const ks = config.getOptionalConfig("auth.keyStore");
|
|
2555
2664
|
const provider = (_a = ks == null ? void 0 : ks.getOptionalString("provider")) != null ? _a : "database";
|
|
2556
2665
|
logger == null ? void 0 : logger.info(`Configuring "${provider}" as KeyStore provider`);
|
|
@@ -2583,36 +2692,31 @@ class KeyStores {
|
|
|
2583
2692
|
}
|
|
2584
2693
|
}
|
|
2585
2694
|
|
|
2586
|
-
async function createRouter({
|
|
2587
|
-
logger,
|
|
2588
|
-
|
|
2589
|
-
discovery,
|
|
2590
|
-
database,
|
|
2591
|
-
providerFactories
|
|
2592
|
-
}) {
|
|
2593
|
-
const router = Router__default['default']();
|
|
2695
|
+
async function createRouter(options) {
|
|
2696
|
+
const { logger, config, discovery, database, providerFactories } = options;
|
|
2697
|
+
const router = Router__default["default"]();
|
|
2594
2698
|
const appUrl = config.getString("app.baseUrl");
|
|
2595
2699
|
const authUrl = await discovery.getExternalBaseUrl("auth");
|
|
2596
|
-
const keyStore = await KeyStores.fromConfig(config, {logger, database});
|
|
2700
|
+
const keyStore = await KeyStores.fromConfig(config, { logger, database });
|
|
2597
2701
|
const keyDurationSeconds = 3600;
|
|
2598
2702
|
const tokenIssuer = new TokenFactory({
|
|
2599
2703
|
issuer: authUrl,
|
|
2600
2704
|
keyStore,
|
|
2601
2705
|
keyDurationSeconds,
|
|
2602
|
-
logger: logger.child({component: "token-factory"})
|
|
2706
|
+
logger: logger.child({ component: "token-factory" })
|
|
2603
2707
|
});
|
|
2604
|
-
const catalogApi = new catalogClient.CatalogClient({discoveryApi: discovery});
|
|
2708
|
+
const catalogApi = new catalogClient.CatalogClient({ discoveryApi: discovery });
|
|
2605
2709
|
const secret = config.getOptionalString("auth.session.secret");
|
|
2606
2710
|
if (secret) {
|
|
2607
|
-
router.use(cookieParser__default[
|
|
2608
|
-
router.use(session__default[
|
|
2609
|
-
router.use(passport__default[
|
|
2610
|
-
router.use(passport__default[
|
|
2711
|
+
router.use(cookieParser__default["default"](secret));
|
|
2712
|
+
router.use(session__default["default"]({ secret, saveUninitialized: false, resave: false }));
|
|
2713
|
+
router.use(passport__default["default"].initialize());
|
|
2714
|
+
router.use(passport__default["default"].session());
|
|
2611
2715
|
} else {
|
|
2612
|
-
router.use(cookieParser__default[
|
|
2716
|
+
router.use(cookieParser__default["default"]());
|
|
2613
2717
|
}
|
|
2614
|
-
router.use(express__default[
|
|
2615
|
-
router.use(express__default[
|
|
2718
|
+
router.use(express__default["default"].urlencoded({ extended: false }));
|
|
2719
|
+
router.use(express__default["default"].json());
|
|
2616
2720
|
const allProviderFactories = {
|
|
2617
2721
|
...factories,
|
|
2618
2722
|
...providerFactories
|
|
@@ -2626,14 +2730,14 @@ async function createRouter({
|
|
|
2626
2730
|
try {
|
|
2627
2731
|
const provider = providerFactory({
|
|
2628
2732
|
providerId,
|
|
2629
|
-
globalConfig: {baseUrl: authUrl, appUrl, isOriginAllowed},
|
|
2733
|
+
globalConfig: { baseUrl: authUrl, appUrl, isOriginAllowed },
|
|
2630
2734
|
config: providersConfig.getConfig(providerId),
|
|
2631
2735
|
logger,
|
|
2632
2736
|
tokenIssuer,
|
|
2633
2737
|
discovery,
|
|
2634
2738
|
catalogApi
|
|
2635
2739
|
});
|
|
2636
|
-
const r = Router__default[
|
|
2740
|
+
const r = Router__default["default"]();
|
|
2637
2741
|
r.get("/start", provider.start.bind(provider));
|
|
2638
2742
|
r.get("/handler/frame", provider.frameHandler.bind(provider));
|
|
2639
2743
|
r.post("/handler/frame", provider.frameHandler.bind(provider));
|
|
@@ -2665,7 +2769,7 @@ async function createRouter({
|
|
|
2665
2769
|
baseUrl: authUrl
|
|
2666
2770
|
}));
|
|
2667
2771
|
router.use("/:provider/", (req) => {
|
|
2668
|
-
const {provider} = req.params;
|
|
2772
|
+
const { provider } = req.params;
|
|
2669
2773
|
throw new errors.NotFoundError(`Unknown auth provider '${provider}'`);
|
|
2670
2774
|
});
|
|
2671
2775
|
return router;
|
|
@@ -2673,9 +2777,9 @@ async function createRouter({
|
|
|
2673
2777
|
function createOriginFilter(config) {
|
|
2674
2778
|
var _a;
|
|
2675
2779
|
const appUrl = config.getString("app.baseUrl");
|
|
2676
|
-
const {origin: appOrigin} = new URL(appUrl);
|
|
2780
|
+
const { origin: appOrigin } = new URL(appUrl);
|
|
2677
2781
|
const allowedOrigins = config.getOptionalStringArray("auth.experimentalExtraAllowedOrigins");
|
|
2678
|
-
const allowedOriginPatterns = (_a = allowedOrigins == null ? void 0 : allowedOrigins.map((pattern) => new minimatch.Minimatch(pattern, {nocase: true, noglobstar: true}))) != null ? _a : [];
|
|
2782
|
+
const allowedOriginPatterns = (_a = allowedOrigins == null ? void 0 : allowedOrigins.map((pattern) => new minimatch.Minimatch(pattern, { nocase: true, noglobstar: true }))) != null ? _a : [];
|
|
2679
2783
|
return (origin) => {
|
|
2680
2784
|
if (origin === appOrigin) {
|
|
2681
2785
|
return true;
|
|
@@ -2684,6 +2788,7 @@ function createOriginFilter(config) {
|
|
|
2684
2788
|
};
|
|
2685
2789
|
}
|
|
2686
2790
|
|
|
2791
|
+
exports.CatalogIdentityClient = CatalogIdentityClient;
|
|
2687
2792
|
exports.IdentityClient = IdentityClient;
|
|
2688
2793
|
exports.OAuthAdapter = OAuthAdapter;
|
|
2689
2794
|
exports.OAuthEnvironmentHandler = OAuthEnvironmentHandler;
|
|
@@ -2697,16 +2802,20 @@ exports.createGitlabProvider = createGitlabProvider;
|
|
|
2697
2802
|
exports.createGoogleProvider = createGoogleProvider;
|
|
2698
2803
|
exports.createMicrosoftProvider = createMicrosoftProvider;
|
|
2699
2804
|
exports.createOAuth2Provider = createOAuth2Provider;
|
|
2805
|
+
exports.createOidcProvider = createOidcProvider;
|
|
2700
2806
|
exports.createOktaProvider = createOktaProvider;
|
|
2701
2807
|
exports.createOriginFilter = createOriginFilter;
|
|
2702
2808
|
exports.createRouter = createRouter;
|
|
2809
|
+
exports.createSamlProvider = createSamlProvider;
|
|
2703
2810
|
exports.defaultAuthProviderFactories = factories;
|
|
2704
2811
|
exports.encodeState = encodeState;
|
|
2705
2812
|
exports.ensuresXRequestedWith = ensuresXRequestedWith;
|
|
2813
|
+
exports.getEntityClaims = getEntityClaims;
|
|
2706
2814
|
exports.googleEmailSignInResolver = googleEmailSignInResolver;
|
|
2707
2815
|
exports.microsoftEmailSignInResolver = microsoftEmailSignInResolver;
|
|
2708
2816
|
exports.oktaEmailSignInResolver = oktaEmailSignInResolver;
|
|
2709
2817
|
exports.postMessageResponse = postMessageResponse;
|
|
2818
|
+
exports.prepareBackstageIdentityResponse = prepareBackstageIdentityResponse;
|
|
2710
2819
|
exports.readState = readState;
|
|
2711
2820
|
exports.verifyNonce = verifyNonce;
|
|
2712
2821
|
//# sourceMappingURL=index.cjs.js.map
|