@backstage/plugin-auth-backend 0.4.8 → 0.5.1

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/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('cross-fetch');
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['default'] = e;
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['default'](idToken);
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['default'](state, (value) => value !== void 0)).toString();
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, res);
231
- await (provider == null ? void 0 : provider.start(req, res));
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, res);
235
- await (provider == null ? void 0 : provider.frameHandler(req, res));
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, res);
240
- await ((_a = provider == null ? void 0 : provider.refresh) == null ? void 0 : _a.call(provider, req, res));
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, res);
245
- await ((_a = provider == null ? void 0 : provider.logout) == null ? void 0 : _a.call(provider, req, res));
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, res) {
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
- if (!this.handlers.has(env)) {
266
- res.status(404).send(`Missing configuration.
267
- <br>
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 this.handlers.get(env);
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['default'].createHash("sha256").update(script).digest("base64");
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}</script></body></html>`);
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['default'].randomBytes(16).toString("base64");
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,65 +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
- res.status(401).send("Invalid X-Requested-With header");
432
- return;
445
+ throw new errors.AuthenticationError("Invalid X-Requested-With header");
433
446
  }
434
447
  this.removeRefreshTokenCookie(res);
435
- res.status(200).send("logout!");
448
+ res.status(200).end();
436
449
  }
437
450
  async refresh(req, res) {
438
451
  var _a, _b;
439
452
  if (!ensuresXRequestedWith(req)) {
440
- res.status(401).send("Invalid X-Requested-With header");
441
- return;
453
+ throw new errors.AuthenticationError("Invalid X-Requested-With header");
442
454
  }
443
455
  if (!this.handlers.refresh || this.options.disableRefresh) {
444
- res.status(400).send(`Refresh token not supported for provider: ${this.options.providerId}`);
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 Error("Missing session cookie");
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
- res.status(401).send(String(error));
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 (!(identity.token || identity.idToken)) {
469
- identity.token = await this.options.tokenIssuer.issueToken({
470
- claims: {sub: identity.id}
471
- });
472
- } else if (!identity.token && identity.idToken) {
473
- identity.token = identity.idToken;
479
+ if (identity.token) {
480
+ return prepareBackstageIdentityResponse(identity);
474
481
  }
482
+ const token = await this.options.tokenIssuer.issueToken({
483
+ claims: { sub: identity.id }
484
+ });
485
+ return prepareBackstageIdentityResponse({ ...identity, token });
475
486
  }
476
487
  }
477
488
 
@@ -488,9 +499,9 @@ class CatalogIdentityClient {
488
499
  filter[`metadata.annotations.${key}`] = value;
489
500
  }
490
501
  const token = await this.tokenIssuer.issueToken({
491
- claims: {sub: "backstage.io/auth-backend"}
502
+ claims: { sub: "backstage.io/auth-backend" }
492
503
  });
493
- const {items} = await this.catalogApi.getEntities({filter}, {token});
504
+ const { items } = await this.catalogApi.getEntities({ filter }, { token });
494
505
  if (items.length !== 1) {
495
506
  if (items.length > 1) {
496
507
  throw new errors.ConflictError("User lookup resulted in multiple matches");
@@ -500,10 +511,8 @@ class CatalogIdentityClient {
500
511
  }
501
512
  return items[0];
502
513
  }
503
- async resolveCatalogMembership({
504
- entityRefs,
505
- logger
506
- }) {
514
+ async resolveCatalogMembership(query) {
515
+ const { entityRefs, logger } = query;
507
516
  const resolvedEntityRefs = entityRefs.map((ref) => {
508
517
  try {
509
518
  const parsedRef = catalogModel.parseEntityRef(ref.toLocaleLowerCase("en-US"), {
@@ -521,7 +530,7 @@ class CatalogIdentityClient {
521
530
  "metadata.namespace": ref.namespace,
522
531
  "metadata.name": ref.name
523
532
  }));
524
- const entities = await this.catalogApi.getEntities({filter}).then((r) => r.items);
533
+ const entities = await this.catalogApi.getEntities({ filter }).then((r) => r.items);
525
534
  if (entityRefs.length !== entities.length) {
526
535
  const foundEntityNames = entities.map(catalogModel.stringifyEntityRef);
527
536
  const missingEntityNames = resolvedEntityRefs.map(catalogModel.stringifyEntityRef).filter((s) => !foundEntityNames.includes(s));
@@ -565,7 +574,7 @@ class GithubAuthProvider {
565
574
  userProfileURL: options.userProfileUrl,
566
575
  authorizationURL: options.authorizationUrl
567
576
  }, (accessToken, refreshToken, params, fullProfile, done) => {
568
- done(void 0, {fullProfile, params, accessToken}, {refreshToken});
577
+ done(void 0, { fullProfile, params, accessToken }, { refreshToken });
569
578
  });
570
579
  }
571
580
  async start(req) {
@@ -575,7 +584,7 @@ class GithubAuthProvider {
575
584
  });
576
585
  }
577
586
  async handler(req) {
578
- const {result, privateInfo} = await executeFrameHandlerStrategy(req, this._strategy);
587
+ const { result, privateInfo } = await executeFrameHandlerStrategy(req, this._strategy);
579
588
  return {
580
589
  response: await this.handleResult(result),
581
590
  refreshToken: privateInfo.refreshToken
@@ -596,7 +605,7 @@ class GithubAuthProvider {
596
605
  });
597
606
  }
598
607
  async handleResult(result) {
599
- const {profile} = await this.authHandler(result);
608
+ const { profile } = await this.authHandler(result);
600
609
  const expiresInStr = result.params.expires_in;
601
610
  const response = {
602
611
  providerInfo: {
@@ -621,12 +630,12 @@ class GithubAuthProvider {
621
630
  }
622
631
  }
623
632
  const githubDefaultSignInResolver = async (info, ctx) => {
624
- const {fullProfile} = info.result;
633
+ const { fullProfile } = info.result;
625
634
  const userId = fullProfile.username || fullProfile.id;
626
635
  const token = await ctx.tokenIssuer.issueToken({
627
- claims: {sub: userId, ent: [`user:default/${userId}`]}
636
+ claims: { sub: userId, ent: [`user:default/${userId}`] }
628
637
  });
629
- return {id: userId, token};
638
+ return { id: userId, token };
630
639
  };
631
640
  const createGithubProvider = (options) => {
632
641
  return ({
@@ -650,7 +659,7 @@ const createGithubProvider = (options) => {
650
659
  catalogApi,
651
660
  tokenIssuer
652
661
  });
653
- 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 }) => ({
654
663
  profile: makeProfileInfo(fullProfile)
655
664
  });
656
665
  const signInResolverFn = (_b = (_a = options == null ? void 0 : options.signIn) == null ? void 0 : _a.resolver) != null ? _b : githubDefaultSignInResolver;
@@ -660,7 +669,7 @@ const createGithubProvider = (options) => {
660
669
  logger
661
670
  });
662
671
  const stateEncoder = (_c = options == null ? void 0 : options.stateEncoder) != null ? _c : async (req) => {
663
- return {encodedState: encodeState(req.state)};
672
+ return { encodedState: encodeState(req.state) };
664
673
  };
665
674
  const provider = new GithubAuthProvider({
666
675
  clientId,
@@ -685,15 +694,15 @@ const createGithubProvider = (options) => {
685
694
  };
686
695
 
687
696
  const gitlabDefaultSignInResolver = async (info, ctx) => {
688
- const {profile, result} = info;
697
+ const { profile, result } = info;
689
698
  let id = result.fullProfile.id;
690
699
  if (profile.email) {
691
700
  id = profile.email.split("@")[0];
692
701
  }
693
702
  const token = await ctx.tokenIssuer.issueToken({
694
- claims: {sub: id, ent: [`user:default/${id}`]}
703
+ claims: { sub: id, ent: [`user:default/${id}`] }
695
704
  });
696
- return {id, token};
705
+ return { id, token };
697
706
  };
698
707
  const gitlabDefaultAuthHandler = async ({
699
708
  fullProfile,
@@ -714,7 +723,7 @@ class GitlabAuthProvider {
714
723
  callbackURL: options.callbackUrl,
715
724
  baseURL: options.baseUrl
716
725
  }, (accessToken, refreshToken, params, fullProfile, done) => {
717
- done(void 0, {fullProfile, params, accessToken}, {
726
+ done(void 0, { fullProfile, params, accessToken }, {
718
727
  refreshToken
719
728
  });
720
729
  });
@@ -726,7 +735,7 @@ class GitlabAuthProvider {
726
735
  });
727
736
  }
728
737
  async handler(req) {
729
- const {result, privateInfo} = await executeFrameHandlerStrategy(req, this._strategy);
738
+ const { result, privateInfo } = await executeFrameHandlerStrategy(req, this._strategy);
730
739
  return {
731
740
  response: await this.handleResult(result),
732
741
  refreshToken: privateInfo.refreshToken
@@ -747,7 +756,7 @@ class GitlabAuthProvider {
747
756
  });
748
757
  }
749
758
  async handleResult(result) {
750
- const {profile} = await this.authHandler(result);
759
+ const { profile } = await this.authHandler(result);
751
760
  const response = {
752
761
  providerInfo: {
753
762
  idToken: result.params.id_token,
@@ -848,14 +857,14 @@ class GoogleAuthProvider {
848
857
  });
849
858
  }
850
859
  async handler(req) {
851
- const {result, privateInfo} = await executeFrameHandlerStrategy(req, this._strategy);
860
+ const { result, privateInfo } = await executeFrameHandlerStrategy(req, this._strategy);
852
861
  return {
853
862
  response: await this.handleResult(result),
854
863
  refreshToken: privateInfo.refreshToken
855
864
  };
856
865
  }
857
866
  async refresh(req) {
858
- const {accessToken, params} = await executeRefreshTokenStrategy(this._strategy, req.refreshToken, req.scope);
867
+ const { accessToken, params } = await executeRefreshTokenStrategy(this._strategy, req.refreshToken, req.scope);
859
868
  const fullProfile = await executeFetchUserProfileStrategy(this._strategy, accessToken);
860
869
  return this.handleResult({
861
870
  fullProfile,
@@ -865,7 +874,7 @@ class GoogleAuthProvider {
865
874
  });
866
875
  }
867
876
  async handleResult(result) {
868
- const {profile} = await this.authHandler(result);
877
+ const { profile } = await this.authHandler(result);
869
878
  const response = {
870
879
  providerInfo: {
871
880
  idToken: result.params.id_token,
@@ -889,7 +898,7 @@ class GoogleAuthProvider {
889
898
  }
890
899
  }
891
900
  const googleEmailSignInResolver = async (info, ctx) => {
892
- const {profile} = info;
901
+ const { profile } = info;
893
902
  if (!profile.email) {
894
903
  throw new Error("Google profile contained no email");
895
904
  }
@@ -899,11 +908,11 @@ const googleEmailSignInResolver = async (info, ctx) => {
899
908
  }
900
909
  });
901
910
  const claims = getEntityClaims(entity);
902
- const token = await ctx.tokenIssuer.issueToken({claims});
903
- return {id: entity.metadata.name, entity, token};
911
+ const token = await ctx.tokenIssuer.issueToken({ claims });
912
+ return { id: entity.metadata.name, entity, token };
904
913
  };
905
914
  const googleDefaultSignInResolver = async (info, ctx) => {
906
- const {profile} = info;
915
+ const { profile } = info;
907
916
  if (!profile.email) {
908
917
  throw new Error("Google profile contained no email");
909
918
  }
@@ -920,9 +929,9 @@ const googleDefaultSignInResolver = async (info, ctx) => {
920
929
  userId = profile.email.split("@")[0];
921
930
  }
922
931
  const token = await ctx.tokenIssuer.issueToken({
923
- claims: {sub: userId, ent: [`user:default/${userId}`]}
932
+ claims: { sub: userId, ent: [`user:default/${userId}`] }
924
933
  });
925
- return {id: userId, token};
934
+ return { id: userId, token };
926
935
  };
927
936
  const createGoogleProvider = (options) => {
928
937
  return ({
@@ -941,7 +950,7 @@ const createGoogleProvider = (options) => {
941
950
  catalogApi,
942
951
  tokenIssuer
943
952
  });
944
- 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 }) => ({
945
954
  profile: makeProfileInfo(fullProfile, params.id_token)
946
955
  });
947
956
  const signInResolverFn = (_b = (_a = options == null ? void 0 : options.signIn) == null ? void 0 : _a.resolver) != null ? _b : googleDefaultSignInResolver;
@@ -983,7 +992,7 @@ class MicrosoftAuthProvider {
983
992
  tokenURL: options.tokenUrl,
984
993
  passReqToCallback: false
985
994
  }, (accessToken, refreshToken, params, fullProfile, done) => {
986
- done(void 0, {fullProfile, accessToken, params}, {refreshToken});
995
+ done(void 0, { fullProfile, accessToken, params }, { refreshToken });
987
996
  });
988
997
  }
989
998
  async start(req) {
@@ -993,14 +1002,14 @@ class MicrosoftAuthProvider {
993
1002
  });
994
1003
  }
995
1004
  async handler(req) {
996
- const {result, privateInfo} = await executeFrameHandlerStrategy(req, this._strategy);
1005
+ const { result, privateInfo } = await executeFrameHandlerStrategy(req, this._strategy);
997
1006
  return {
998
1007
  response: await this.handleResult(result),
999
1008
  refreshToken: privateInfo.refreshToken
1000
1009
  };
1001
1010
  }
1002
1011
  async refresh(req) {
1003
- const {accessToken, params} = await executeRefreshTokenStrategy(this._strategy, req.refreshToken, req.scope);
1012
+ const { accessToken, params } = await executeRefreshTokenStrategy(this._strategy, req.refreshToken, req.scope);
1004
1013
  const fullProfile = await executeFetchUserProfileStrategy(this._strategy, accessToken);
1005
1014
  return this.handleResult({
1006
1015
  fullProfile,
@@ -1011,8 +1020,8 @@ class MicrosoftAuthProvider {
1011
1020
  }
1012
1021
  async handleResult(result) {
1013
1022
  const photo = await this.getUserPhoto(result.accessToken);
1014
- result.fullProfile.photos = photo ? [{value: photo}] : void 0;
1015
- const {profile} = await this.authHandler(result);
1023
+ result.fullProfile.photos = photo ? [{ value: photo }] : void 0;
1024
+ const { profile } = await this.authHandler(result);
1016
1025
  const response = {
1017
1026
  providerInfo: {
1018
1027
  idToken: result.params.id_token,
@@ -1036,7 +1045,7 @@ class MicrosoftAuthProvider {
1036
1045
  }
1037
1046
  getUserPhoto(accessToken) {
1038
1047
  return new Promise((resolve) => {
1039
- got__default['default'].get("https://graph.microsoft.com/v1.0/me/photos/48x48/$value", {
1048
+ got__default["default"].get("https://graph.microsoft.com/v1.0/me/photos/48x48/$value", {
1040
1049
  encoding: "binary",
1041
1050
  responseType: "buffer",
1042
1051
  headers: {
@@ -1053,7 +1062,7 @@ class MicrosoftAuthProvider {
1053
1062
  }
1054
1063
  }
1055
1064
  const microsoftEmailSignInResolver = async (info, ctx) => {
1056
- const {profile} = info;
1065
+ const { profile } = info;
1057
1066
  if (!profile.email) {
1058
1067
  throw new Error("Microsoft profile contained no email");
1059
1068
  }
@@ -1063,19 +1072,19 @@ const microsoftEmailSignInResolver = async (info, ctx) => {
1063
1072
  }
1064
1073
  });
1065
1074
  const claims = getEntityClaims(entity);
1066
- const token = await ctx.tokenIssuer.issueToken({claims});
1067
- return {id: entity.metadata.name, entity, token};
1075
+ const token = await ctx.tokenIssuer.issueToken({ claims });
1076
+ return { id: entity.metadata.name, entity, token };
1068
1077
  };
1069
1078
  const microsoftDefaultSignInResolver = async (info, ctx) => {
1070
- const {profile} = info;
1079
+ const { profile } = info;
1071
1080
  if (!profile.email) {
1072
1081
  throw new Error("Profile contained no email");
1073
1082
  }
1074
1083
  const userId = profile.email.split("@")[0];
1075
1084
  const token = await ctx.tokenIssuer.issueToken({
1076
- claims: {sub: userId, ent: [`user:default/${userId}`]}
1085
+ claims: { sub: userId, ent: [`user:default/${userId}`] }
1077
1086
  });
1078
- return {id: userId, token};
1087
+ return { id: userId, token };
1079
1088
  };
1080
1089
  const createMicrosoftProvider = (options) => {
1081
1090
  return ({
@@ -1097,7 +1106,7 @@ const createMicrosoftProvider = (options) => {
1097
1106
  catalogApi,
1098
1107
  tokenIssuer
1099
1108
  });
1100
- 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 }) => ({
1101
1110
  profile: makeProfileInfo(fullProfile, params.id_token)
1102
1111
  });
1103
1112
  const signInResolverFn = (_b = (_a = options == null ? void 0 : options.signIn) == null ? void 0 : _a.resolver) != null ? _b : microsoftDefaultSignInResolver;
@@ -1140,7 +1149,10 @@ class OAuth2AuthProvider {
1140
1149
  authorizationURL: options.authorizationUrl,
1141
1150
  tokenURL: options.tokenUrl,
1142
1151
  passReqToCallback: false,
1143
- scope: options.scope
1152
+ scope: options.scope,
1153
+ customHeaders: options.includeBasicAuth ? {
1154
+ Authorization: `Basic ${this.encodeClientCredentials(options.clientId, options.clientSecret)}`
1155
+ } : void 0
1144
1156
  }, (accessToken, refreshToken, params, fullProfile, done) => {
1145
1157
  done(void 0, {
1146
1158
  fullProfile,
@@ -1161,7 +1173,7 @@ class OAuth2AuthProvider {
1161
1173
  });
1162
1174
  }
1163
1175
  async handler(req) {
1164
- const {result, privateInfo} = await executeFrameHandlerStrategy(req, this._strategy);
1176
+ const { result, privateInfo } = await executeFrameHandlerStrategy(req, this._strategy);
1165
1177
  return {
1166
1178
  response: await this.handleResult(result),
1167
1179
  refreshToken: privateInfo.refreshToken
@@ -1183,7 +1195,7 @@ class OAuth2AuthProvider {
1183
1195
  });
1184
1196
  }
1185
1197
  async handleResult(result) {
1186
- const {profile} = await this.authHandler(result);
1198
+ const { profile } = await this.authHandler(result);
1187
1199
  const response = {
1188
1200
  providerInfo: {
1189
1201
  idToken: result.params.id_token,
@@ -1206,17 +1218,20 @@ class OAuth2AuthProvider {
1206
1218
  }
1207
1219
  return response;
1208
1220
  }
1221
+ encodeClientCredentials(clientID, clientSecret) {
1222
+ return Buffer.from(`${clientID}:${clientSecret}`).toString("base64");
1223
+ }
1209
1224
  }
1210
- const oAuth2DefaultSignInResolver = async (info, ctx) => {
1211
- const {profile} = info;
1225
+ const oAuth2DefaultSignInResolver$1 = async (info, ctx) => {
1226
+ const { profile } = info;
1212
1227
  if (!profile.email) {
1213
1228
  throw new Error("Profile contained no email");
1214
1229
  }
1215
1230
  const userId = profile.email.split("@")[0];
1216
1231
  const token = await ctx.tokenIssuer.issueToken({
1217
- claims: {sub: userId, ent: [`user:default/${userId}`]}
1232
+ claims: { sub: userId, ent: [`user:default/${userId}`] }
1218
1233
  });
1219
- return {id: userId, token};
1234
+ return { id: userId, token };
1220
1235
  };
1221
1236
  const createOAuth2Provider = (options) => {
1222
1237
  return ({
@@ -1234,15 +1249,16 @@ const createOAuth2Provider = (options) => {
1234
1249
  const authorizationUrl = envConfig.getString("authorizationUrl");
1235
1250
  const tokenUrl = envConfig.getString("tokenUrl");
1236
1251
  const scope = envConfig.getOptionalString("scope");
1252
+ const includeBasicAuth = envConfig.getOptionalBoolean("includeBasicAuth");
1237
1253
  const disableRefresh = (_a = envConfig.getOptionalBoolean("disableRefresh")) != null ? _a : false;
1238
1254
  const catalogIdentityClient = new CatalogIdentityClient({
1239
1255
  catalogApi,
1240
1256
  tokenIssuer
1241
1257
  });
1242
- 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 }) => ({
1243
1259
  profile: makeProfileInfo(fullProfile, params.id_token)
1244
1260
  });
1245
- 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;
1246
1262
  const signInResolver = (info) => signInResolverFn(info, {
1247
1263
  catalogIdentityClient,
1248
1264
  tokenIssuer,
@@ -1259,7 +1275,8 @@ const createOAuth2Provider = (options) => {
1259
1275
  authorizationUrl,
1260
1276
  tokenUrl,
1261
1277
  scope,
1262
- logger
1278
+ logger,
1279
+ includeBasicAuth
1263
1280
  });
1264
1281
  return OAuthAdapter.fromConfig(globalConfig, provider, {
1265
1282
  disableRefresh,
@@ -1269,6 +1286,168 @@ const createOAuth2Provider = (options) => {
1269
1286
  });
1270
1287
  };
1271
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
+
1272
1451
  class OktaAuthProvider {
1273
1452
  constructor(options) {
1274
1453
  this._store = {
@@ -1312,14 +1491,14 @@ class OktaAuthProvider {
1312
1491
  });
1313
1492
  }
1314
1493
  async handler(req) {
1315
- const {result, privateInfo} = await executeFrameHandlerStrategy(req, this._strategy);
1494
+ const { result, privateInfo } = await executeFrameHandlerStrategy(req, this._strategy);
1316
1495
  return {
1317
1496
  response: await this.handleResult(result),
1318
1497
  refreshToken: privateInfo.refreshToken
1319
1498
  };
1320
1499
  }
1321
1500
  async refresh(req) {
1322
- const {accessToken, params} = await executeRefreshTokenStrategy(this._strategy, req.refreshToken, req.scope);
1501
+ const { accessToken, params } = await executeRefreshTokenStrategy(this._strategy, req.refreshToken, req.scope);
1323
1502
  const fullProfile = await executeFetchUserProfileStrategy(this._strategy, accessToken);
1324
1503
  return this.handleResult({
1325
1504
  fullProfile,
@@ -1329,7 +1508,7 @@ class OktaAuthProvider {
1329
1508
  });
1330
1509
  }
1331
1510
  async handleResult(result) {
1332
- const {profile} = await this._authHandler(result);
1511
+ const { profile } = await this._authHandler(result);
1333
1512
  const response = {
1334
1513
  providerInfo: {
1335
1514
  idToken: result.params.id_token,
@@ -1353,7 +1532,7 @@ class OktaAuthProvider {
1353
1532
  }
1354
1533
  }
1355
1534
  const oktaEmailSignInResolver = async (info, ctx) => {
1356
- const {profile} = info;
1535
+ const { profile } = info;
1357
1536
  if (!profile.email) {
1358
1537
  throw new Error("Okta profile contained no email");
1359
1538
  }
@@ -1363,19 +1542,19 @@ const oktaEmailSignInResolver = async (info, ctx) => {
1363
1542
  }
1364
1543
  });
1365
1544
  const claims = getEntityClaims(entity);
1366
- const token = await ctx.tokenIssuer.issueToken({claims});
1367
- return {id: entity.metadata.name, entity, token};
1545
+ const token = await ctx.tokenIssuer.issueToken({ claims });
1546
+ return { id: entity.metadata.name, entity, token };
1368
1547
  };
1369
1548
  const oktaDefaultSignInResolver = async (info, ctx) => {
1370
- const {profile} = info;
1549
+ const { profile } = info;
1371
1550
  if (!profile.email) {
1372
1551
  throw new Error("Okta profile contained no email");
1373
1552
  }
1374
1553
  const userId = profile.email.split("@")[0];
1375
1554
  const token = await ctx.tokenIssuer.issueToken({
1376
- claims: {sub: userId, ent: [`user:default/${userId}`]}
1555
+ claims: { sub: userId, ent: [`user:default/${userId}`] }
1377
1556
  });
1378
- return {id: userId, token};
1557
+ return { id: userId, token };
1379
1558
  };
1380
1559
  const createOktaProvider = (_options) => {
1381
1560
  return ({
@@ -1398,7 +1577,7 @@ const createOktaProvider = (_options) => {
1398
1577
  catalogApi,
1399
1578
  tokenIssuer
1400
1579
  });
1401
- 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 }) => ({
1402
1581
  profile: makeProfileInfo(fullProfile, params.id_token)
1403
1582
  });
1404
1583
  const signInResolverFn = (_b = (_a = _options == null ? void 0 : _options.signIn) == null ? void 0 : _a.resolver) != null ? _b : oktaDefaultSignInResolver;
@@ -1458,14 +1637,14 @@ class BitbucketAuthProvider {
1458
1637
  });
1459
1638
  }
1460
1639
  async handler(req) {
1461
- const {result, privateInfo} = await executeFrameHandlerStrategy(req, this._strategy);
1640
+ const { result, privateInfo } = await executeFrameHandlerStrategy(req, this._strategy);
1462
1641
  return {
1463
1642
  response: await this.handleResult(result),
1464
1643
  refreshToken: privateInfo.refreshToken
1465
1644
  };
1466
1645
  }
1467
1646
  async refresh(req) {
1468
- const {accessToken, params} = await executeRefreshTokenStrategy(this._strategy, req.refreshToken, req.scope);
1647
+ const { accessToken, params } = await executeRefreshTokenStrategy(this._strategy, req.refreshToken, req.scope);
1469
1648
  const fullProfile = await executeFetchUserProfileStrategy(this._strategy, accessToken);
1470
1649
  return this.handleResult({
1471
1650
  fullProfile,
@@ -1476,7 +1655,7 @@ class BitbucketAuthProvider {
1476
1655
  }
1477
1656
  async handleResult(result) {
1478
1657
  result.fullProfile.avatarUrl = result.fullProfile._json.links.avatar.href;
1479
- const {profile} = await this.authHandler(result);
1658
+ const { profile } = await this.authHandler(result);
1480
1659
  const response = {
1481
1660
  providerInfo: {
1482
1661
  idToken: result.params.id_token,
@@ -1500,7 +1679,7 @@ class BitbucketAuthProvider {
1500
1679
  }
1501
1680
  }
1502
1681
  const bitbucketUsernameSignInResolver = async (info, ctx) => {
1503
- const {result} = info;
1682
+ const { result } = info;
1504
1683
  if (!result.fullProfile.username) {
1505
1684
  throw new Error("Bitbucket profile contained no Username");
1506
1685
  }
@@ -1510,11 +1689,11 @@ const bitbucketUsernameSignInResolver = async (info, ctx) => {
1510
1689
  }
1511
1690
  });
1512
1691
  const claims = getEntityClaims(entity);
1513
- const token = await ctx.tokenIssuer.issueToken({claims});
1514
- return {id: entity.metadata.name, entity, token};
1692
+ const token = await ctx.tokenIssuer.issueToken({ claims });
1693
+ return { id: entity.metadata.name, entity, token };
1515
1694
  };
1516
1695
  const bitbucketUserIdSignInResolver = async (info, ctx) => {
1517
- const {result} = info;
1696
+ const { result } = info;
1518
1697
  if (!result.fullProfile.id) {
1519
1698
  throw new Error("Bitbucket profile contained no User ID");
1520
1699
  }
@@ -1524,8 +1703,8 @@ const bitbucketUserIdSignInResolver = async (info, ctx) => {
1524
1703
  }
1525
1704
  });
1526
1705
  const claims = getEntityClaims(entity);
1527
- const token = await ctx.tokenIssuer.issueToken({claims});
1528
- return {id: entity.metadata.name, entity, token};
1706
+ const token = await ctx.tokenIssuer.issueToken({ claims });
1707
+ return { id: entity.metadata.name, entity, token };
1529
1708
  };
1530
1709
  const createBitbucketProvider = (options) => {
1531
1710
  return ({
@@ -1544,7 +1723,7 @@ const createBitbucketProvider = (options) => {
1544
1723
  catalogApi,
1545
1724
  tokenIssuer
1546
1725
  });
1547
- 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 }) => ({
1548
1727
  profile: makeProfileInfo(fullProfile, params.id_token)
1549
1728
  });
1550
1729
  const provider = new BitbucketAuthProvider({
@@ -1566,7 +1745,7 @@ const createBitbucketProvider = (options) => {
1566
1745
  };
1567
1746
 
1568
1747
  const defaultScopes = ["offline_access", "read:me"];
1569
- class AtlassianStrategy extends OAuth2Strategy__default['default'] {
1748
+ class AtlassianStrategy extends OAuth2Strategy__default["default"] {
1570
1749
  constructor(options, verify) {
1571
1750
  if (!options.scope) {
1572
1751
  throw new TypeError("Atlassian requires a scope option");
@@ -1576,7 +1755,7 @@ class AtlassianStrategy extends OAuth2Strategy__default['default'] {
1576
1755
  ...options,
1577
1756
  authorizationURL: `https://auth.atlassian.com/authorize`,
1578
1757
  tokenURL: `https://auth.atlassian.com/oauth/token`,
1579
- scope: Array.from(new Set([...defaultScopes, ...scopes]))
1758
+ scope: Array.from(/* @__PURE__ */ new Set([...defaultScopes, ...scopes]))
1580
1759
  };
1581
1760
  super(optionsWithURLs, verify);
1582
1761
  this.profileURL = "https://api.atlassian.com/me";
@@ -1613,8 +1792,8 @@ class AtlassianStrategy extends OAuth2Strategy__default['default'] {
1613
1792
  provider: "atlassian",
1614
1793
  username: resp.nickname,
1615
1794
  displayName: resp.name,
1616
- emails: [{value: resp.email}],
1617
- photos: [{value: resp.picture}]
1795
+ emails: [{ value: resp.email }],
1796
+ photos: [{ value: resp.picture }]
1618
1797
  };
1619
1798
  }
1620
1799
  }
@@ -1653,14 +1832,14 @@ class AtlassianAuthProvider {
1653
1832
  }
1654
1833
  async handler(req) {
1655
1834
  var _a;
1656
- const {result} = await executeFrameHandlerStrategy(req, this._strategy);
1835
+ const { result } = await executeFrameHandlerStrategy(req, this._strategy);
1657
1836
  return {
1658
1837
  response: await this.handleResult(result),
1659
1838
  refreshToken: (_a = result.refreshToken) != null ? _a : ""
1660
1839
  };
1661
1840
  }
1662
1841
  async handleResult(result) {
1663
- const {profile} = await this.authHandler(result);
1842
+ const { profile } = await this.authHandler(result);
1664
1843
  const response = {
1665
1844
  providerInfo: {
1666
1845
  idToken: result.params.id_token,
@@ -1751,7 +1930,7 @@ class AwsAlbAuthProvider {
1751
1930
  this.tokenIssuer = options.tokenIssuer;
1752
1931
  this.catalogIdentityClient = options.catalogIdentityClient;
1753
1932
  this.logger = options.logger;
1754
- this.keyCache = new NodeCache__default['default']({stdTTL: 3600});
1933
+ this.keyCache = new NodeCache__default["default"]({ stdTTL: 3600 });
1755
1934
  }
1756
1935
  frameHandler() {
1757
1936
  return Promise.resolve(void 0);
@@ -1795,8 +1974,8 @@ class AwsAlbAuthProvider {
1795
1974
  familyName: claims.family_name,
1796
1975
  givenName: claims.given_name
1797
1976
  },
1798
- emails: [{value: claims.email.toLowerCase()}],
1799
- photos: [{value: claims.picture}]
1977
+ emails: [{ value: claims.email.toLowerCase() }],
1978
+ photos: [{ value: claims.picture }]
1800
1979
  };
1801
1980
  return {
1802
1981
  fullProfile,
@@ -1808,7 +1987,7 @@ class AwsAlbAuthProvider {
1808
1987
  }
1809
1988
  }
1810
1989
  async handleResult(result) {
1811
- const {profile} = await this.authHandler(result);
1990
+ const { profile } = await this.authHandler(result);
1812
1991
  const backstageIdentity = await this.signInResolver({
1813
1992
  result,
1814
1993
  profile
@@ -1822,7 +2001,7 @@ class AwsAlbAuthProvider {
1822
2001
  accessToken: result.accessToken,
1823
2002
  expiresInSeconds: result.expiresInSeconds
1824
2003
  },
1825
- backstageIdentity,
2004
+ backstageIdentity: prepareBackstageIdentityResponse(backstageIdentity),
1826
2005
  profile
1827
2006
  };
1828
2007
  }
@@ -1831,14 +2010,14 @@ class AwsAlbAuthProvider {
1831
2010
  if (optionalCacheKey) {
1832
2011
  return crypto__namespace.createPublicKey(optionalCacheKey);
1833
2012
  }
1834
- const keyText = await fetch__default['default'](`https://public-keys.auth.elb.${this.region}.amazonaws.com/${keyId}`).then((response) => response.text());
2013
+ const keyText = await fetch__default["default"](`https://public-keys.auth.elb.${this.region}.amazonaws.com/${keyId}`).then((response) => response.text());
1835
2014
  const keyValue = crypto__namespace.createPublicKey(keyText);
1836
- this.keyCache.set(keyId, keyValue.export({format: "pem", type: "spki"}));
2015
+ this.keyCache.set(keyId, keyValue.export({ format: "pem", type: "spki" }));
1837
2016
  return keyValue;
1838
2017
  }
1839
2018
  }
1840
2019
  const createAwsAlbProvider = (options) => {
1841
- return ({config, tokenIssuer, catalogApi, logger}) => {
2020
+ return ({ config, tokenIssuer, catalogApi, logger }) => {
1842
2021
  const region = config.getString("region");
1843
2022
  const issuer = config.getOptionalString("iss");
1844
2023
  if ((options == null ? void 0 : options.signIn.resolver) === void 0) {
@@ -1848,7 +2027,7 @@ const createAwsAlbProvider = (options) => {
1848
2027
  catalogApi,
1849
2028
  tokenIssuer
1850
2029
  });
1851
- 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 }) => ({
1852
2031
  profile: makeProfileInfo(fullProfile)
1853
2032
  });
1854
2033
  const signInResolver = options == null ? void 0 : options.signIn.resolver;
@@ -1864,182 +2043,98 @@ const createAwsAlbProvider = (options) => {
1864
2043
  };
1865
2044
  };
1866
2045
 
1867
- class OidcAuthProvider {
1868
- constructor(options) {
1869
- this.implementation = this.setupStrategy(options);
1870
- this.scope = options.scope;
1871
- this.prompt = options.prompt;
1872
- }
1873
- async start(req) {
1874
- const {strategy} = await this.implementation;
1875
- const options = {
1876
- accessType: "offline",
1877
- scope: req.scope || this.scope || "openid profile email",
1878
- state: encodeState(req.state)
1879
- };
1880
- const prompt = this.prompt || "none";
1881
- if (prompt !== "auto") {
1882
- options.prompt = prompt;
1883
- }
1884
- return await executeRedirectStrategy(req, strategy, options);
1885
- }
1886
- async handler(req) {
1887
- const {strategy} = await this.implementation;
1888
- const strategyResponse = await executeFrameHandlerStrategy(req, strategy);
1889
- const {
1890
- result: {userinfo, tokenset},
1891
- privateInfo
1892
- } = strategyResponse;
1893
- const identityResponse = await this.populateIdentity({
1894
- profile: {
1895
- displayName: userinfo.name,
1896
- email: userinfo.email,
1897
- picture: userinfo.picture
1898
- },
1899
- providerInfo: {
1900
- idToken: tokenset.id_token,
1901
- accessToken: tokenset.access_token || "",
1902
- scope: tokenset.scope || "",
1903
- expiresInSeconds: tokenset.expires_in
1904
- }
1905
- });
1906
- return {
1907
- response: identityResponse,
1908
- refreshToken: privateInfo.refreshToken
1909
- };
1910
- }
1911
- async refresh(req) {
1912
- const {client} = await this.implementation;
1913
- const tokenset = await client.refresh(req.refreshToken);
1914
- if (!tokenset.access_token) {
1915
- throw new Error("Refresh failed");
1916
- }
1917
- const profile = await client.userinfo(tokenset.access_token);
1918
- return this.populateIdentity({
1919
- providerInfo: {
1920
- accessToken: tokenset.access_token,
1921
- refreshToken: tokenset.refresh_token,
1922
- expiresInSeconds: tokenset.expires_in,
1923
- idToken: tokenset.id_token,
1924
- scope: tokenset.scope || ""
1925
- },
1926
- profile
1927
- });
1928
- }
1929
- async setupStrategy(options) {
1930
- const issuer = await openidClient.Issuer.discover(options.metadataUrl);
1931
- const client = new issuer.Client({
1932
- client_id: options.clientId,
1933
- client_secret: options.clientSecret,
1934
- redirect_uris: [options.callbackUrl],
1935
- response_types: ["code"],
1936
- id_token_signed_response_alg: options.tokenSignedResponseAlg || "RS256",
1937
- scope: options.scope || ""
1938
- });
1939
- const strategy = new openidClient.Strategy({
1940
- client,
1941
- passReqToCallback: false
1942
- }, (tokenset, userinfo, done) => {
1943
- if (typeof done !== "function") {
1944
- throw new Error("OIDC IdP must provide a userinfo_endpoint in the metadata response");
1945
- }
1946
- done(void 0, {tokenset, userinfo}, {
1947
- refreshToken: tokenset.refresh_token
1948
- });
1949
- });
1950
- strategy.error = console.error;
1951
- return {strategy, client};
1952
- }
1953
- async populateIdentity(response) {
1954
- const {profile} = response;
1955
- if (!profile.email) {
1956
- throw new Error("Profile does not contain an email");
1957
- }
1958
- const id = profile.email.split("@")[0];
1959
- return {...response, backstageIdentity: {id}};
1960
- }
1961
- }
1962
- const createOidcProvider = (_options) => {
1963
- return ({providerId, globalConfig, config, tokenIssuer}) => OAuthEnvironmentHandler.mapConfig(config, (envConfig) => {
1964
- const clientId = envConfig.getString("clientId");
1965
- const clientSecret = envConfig.getString("clientSecret");
1966
- const callbackUrl = `${globalConfig.baseUrl}/${providerId}/handler/frame`;
1967
- const metadataUrl = envConfig.getString("metadataUrl");
1968
- const tokenSignedResponseAlg = envConfig.getOptionalString("tokenSignedResponseAlg");
1969
- const scope = envConfig.getOptionalString("scope");
1970
- const prompt = envConfig.getOptionalString("prompt");
1971
- const provider = new OidcAuthProvider({
1972
- clientId,
1973
- clientSecret,
1974
- callbackUrl,
1975
- tokenSignedResponseAlg,
1976
- metadataUrl,
1977
- scope,
1978
- prompt
1979
- });
1980
- return OAuthAdapter.fromConfig(globalConfig, provider, {
1981
- disableRefresh: false,
1982
- providerId,
1983
- tokenIssuer
1984
- });
1985
- });
1986
- };
1987
-
1988
2046
  class SamlAuthProvider {
1989
2047
  constructor(options) {
1990
2048
  this.appUrl = options.appUrl;
2049
+ this.signInResolver = options.signInResolver;
2050
+ this.authHandler = options.authHandler;
1991
2051
  this.tokenIssuer = options.tokenIssuer;
1992
- this.strategy = new passportSaml.Strategy({...options}, (fullProfile, done) => {
1993
- done(void 0, {fullProfile});
2052
+ this.catalogIdentityClient = options.catalogIdentityClient;
2053
+ this.logger = options.logger;
2054
+ this.strategy = new passportSaml.Strategy({ ...options }, (fullProfile, done) => {
2055
+ done(void 0, { fullProfile });
1994
2056
  });
1995
2057
  }
1996
2058
  async start(req, res) {
1997
- const {url} = await executeRedirectStrategy(req, this.strategy, {});
2059
+ const { url } = await executeRedirectStrategy(req, this.strategy, {});
1998
2060
  res.redirect(url);
1999
2061
  }
2000
2062
  async frameHandler(req, res) {
2001
2063
  try {
2002
- const {result} = await executeFrameHandlerStrategy(req, this.strategy);
2003
- const id = result.fullProfile.nameID;
2004
- const idToken = await this.tokenIssuer.issueToken({
2005
- claims: {sub: id}
2006
- });
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
+ }
2007
2081
  return postMessageResponse(res, this.appUrl, {
2008
2082
  type: "authorization_response",
2009
- response: {
2010
- profile: {
2011
- email: result.fullProfile.email,
2012
- displayName: result.fullProfile.displayName
2013
- },
2014
- providerInfo: {},
2015
- backstageIdentity: {id, idToken}
2016
- }
2083
+ response
2017
2084
  });
2018
2085
  } catch (error) {
2019
- 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");
2020
2087
  return postMessageResponse(res, this.appUrl, {
2021
2088
  type: "authorization_response",
2022
- error: {name, message}
2089
+ error: { name, message }
2023
2090
  });
2024
2091
  }
2025
2092
  }
2026
2093
  async logout(_req, res) {
2027
- res.send("noop");
2028
- }
2029
- identifyEnv() {
2030
- return void 0;
2094
+ res.end();
2031
2095
  }
2032
2096
  }
2033
- const createSamlProvider = (_options) => {
2034
- return ({providerId, globalConfig, config, tokenIssuer}) => {
2035
- const opts = {
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({
2036
2131
  callbackUrl: `${globalConfig.baseUrl}/${providerId}/handler/frame`,
2037
2132
  entryPoint: config.getString("entryPoint"),
2038
2133
  logoutUrl: config.getOptionalString("logoutUrl"),
2039
2134
  audience: config.getOptionalString("audience"),
2040
2135
  issuer: config.getString("issuer"),
2041
2136
  cert: config.getString("cert"),
2042
- privateCert: config.getOptionalString("privateKey"),
2137
+ privateKey: config.getOptionalString("privateKey"),
2043
2138
  authnContext: config.getOptionalStringArray("authnContext"),
2044
2139
  identifierFormat: config.getOptionalString("identifierFormat"),
2045
2140
  decryptionPvk: config.getOptionalString("decryptionPvk"),
@@ -2047,13 +2142,16 @@ const createSamlProvider = (_options) => {
2047
2142
  digestAlgorithm: config.getOptionalString("digestAlgorithm"),
2048
2143
  acceptedClockSkewMs: config.getOptionalNumber("acceptedClockSkewMs"),
2049
2144
  tokenIssuer,
2050
- appUrl: globalConfig.appUrl
2051
- };
2052
- return new SamlAuthProvider(opts);
2145
+ appUrl: globalConfig.appUrl,
2146
+ authHandler,
2147
+ signInResolver,
2148
+ logger,
2149
+ catalogIdentityClient
2150
+ });
2053
2151
  };
2054
2152
  };
2055
2153
 
2056
- class Auth0Strategy extends OAuth2Strategy__default['default'] {
2154
+ class Auth0Strategy extends OAuth2Strategy__default["default"] {
2057
2155
  constructor(options, verify) {
2058
2156
  const optionsWithURLs = {
2059
2157
  ...options,
@@ -2094,7 +2192,7 @@ class Auth0AuthProvider {
2094
2192
  });
2095
2193
  }
2096
2194
  async handler(req) {
2097
- const {result, privateInfo} = await executeFrameHandlerStrategy(req, this._strategy);
2195
+ const { result, privateInfo } = await executeFrameHandlerStrategy(req, this._strategy);
2098
2196
  const profile = makeProfileInfo(result.fullProfile, result.params.id_token);
2099
2197
  return {
2100
2198
  response: await this.populateIdentity({
@@ -2110,7 +2208,7 @@ class Auth0AuthProvider {
2110
2208
  };
2111
2209
  }
2112
2210
  async refresh(req) {
2113
- const {accessToken, params} = await executeRefreshTokenStrategy(this._strategy, req.refreshToken, req.scope);
2211
+ const { accessToken, params } = await executeRefreshTokenStrategy(this._strategy, req.refreshToken, req.scope);
2114
2212
  const fullProfile = await executeFetchUserProfileStrategy(this._strategy, accessToken);
2115
2213
  const profile = makeProfileInfo(fullProfile, params.id_token);
2116
2214
  return this.populateIdentity({
@@ -2124,16 +2222,16 @@ class Auth0AuthProvider {
2124
2222
  });
2125
2223
  }
2126
2224
  async populateIdentity(response) {
2127
- const {profile} = response;
2225
+ const { profile } = response;
2128
2226
  if (!profile.email) {
2129
2227
  throw new Error("Profile does not contain an email");
2130
2228
  }
2131
2229
  const id = profile.email.split("@")[0];
2132
- return {...response, backstageIdentity: {id}};
2230
+ return { ...response, backstageIdentity: { id, token: "" } };
2133
2231
  }
2134
2232
  }
2135
2233
  const createAuth0Provider = (_options) => {
2136
- return ({providerId, globalConfig, config, tokenIssuer}) => OAuthEnvironmentHandler.mapConfig(config, (envConfig) => {
2234
+ return ({ providerId, globalConfig, config, tokenIssuer }) => OAuthEnvironmentHandler.mapConfig(config, (envConfig) => {
2137
2235
  const clientId = envConfig.getString("clientId");
2138
2236
  const clientSecret = envConfig.getString("clientSecret");
2139
2237
  const domain = envConfig.getString("domain");
@@ -2180,7 +2278,7 @@ class OneLoginProvider {
2180
2278
  });
2181
2279
  }
2182
2280
  async handler(req) {
2183
- const {result, privateInfo} = await executeFrameHandlerStrategy(req, this._strategy);
2281
+ const { result, privateInfo } = await executeFrameHandlerStrategy(req, this._strategy);
2184
2282
  const profile = makeProfileInfo(result.fullProfile, result.params.id_token);
2185
2283
  return {
2186
2284
  response: await this.populateIdentity({
@@ -2196,7 +2294,7 @@ class OneLoginProvider {
2196
2294
  };
2197
2295
  }
2198
2296
  async refresh(req) {
2199
- const {accessToken, params} = await executeRefreshTokenStrategy(this._strategy, req.refreshToken, req.scope);
2297
+ const { accessToken, params } = await executeRefreshTokenStrategy(this._strategy, req.refreshToken, req.scope);
2200
2298
  const fullProfile = await executeFetchUserProfileStrategy(this._strategy, accessToken);
2201
2299
  const profile = makeProfileInfo(fullProfile, params.id_token);
2202
2300
  return this.populateIdentity({
@@ -2210,16 +2308,16 @@ class OneLoginProvider {
2210
2308
  });
2211
2309
  }
2212
2310
  async populateIdentity(response) {
2213
- const {profile} = response;
2311
+ const { profile } = response;
2214
2312
  if (!profile.email) {
2215
2313
  throw new Error("OIDC profile contained no email");
2216
2314
  }
2217
2315
  const id = profile.email.split("@")[0];
2218
- return {...response, backstageIdentity: {id}};
2316
+ return { ...response, backstageIdentity: { id, token: "" } };
2219
2317
  }
2220
2318
  }
2221
2319
  const createOneLoginProvider = (_options) => {
2222
- return ({providerId, globalConfig, config, tokenIssuer}) => OAuthEnvironmentHandler.mapConfig(config, (envConfig) => {
2320
+ return ({ providerId, globalConfig, config, tokenIssuer }) => OAuthEnvironmentHandler.mapConfig(config, (envConfig) => {
2223
2321
  const clientId = envConfig.getString("clientId");
2224
2322
  const clientSecret = envConfig.getString("clientSecret");
2225
2323
  const issuer = envConfig.getString("issuer");
@@ -2255,8 +2353,8 @@ const factories = {
2255
2353
  };
2256
2354
 
2257
2355
  function createOidcRouter(options) {
2258
- const {baseUrl, tokenIssuer} = options;
2259
- const router = Router__default['default']();
2356
+ const { baseUrl, tokenIssuer } = options;
2357
+ const router = Router__default["default"]();
2260
2358
  const config = {
2261
2359
  issuer: baseUrl,
2262
2360
  token_endpoint: `${baseUrl}/v1/token`,
@@ -2274,8 +2372,8 @@ function createOidcRouter(options) {
2274
2372
  res.json(config);
2275
2373
  });
2276
2374
  router.get("/.well-known/jwks.json", async (_req, res) => {
2277
- const {keys} = await tokenIssuer.listPublicKeys();
2278
- res.json({keys});
2375
+ const { keys } = await tokenIssuer.listPublicKeys();
2376
+ res.json({ keys });
2279
2377
  });
2280
2378
  router.get("/v1/token", (_req, res) => {
2281
2379
  res.status(501).send("Not Implemented");
@@ -2295,21 +2393,30 @@ class IdentityClient {
2295
2393
  this.keyStoreUpdated = 0;
2296
2394
  }
2297
2395
  async authenticate(token) {
2396
+ var _a;
2298
2397
  if (!token) {
2299
- throw new Error("No token specified");
2398
+ throw new errors.AuthenticationError("No token specified");
2300
2399
  }
2301
2400
  const key = await this.getKey(token);
2302
2401
  if (!key) {
2303
- throw new Error("No signing key matching token found");
2402
+ throw new errors.AuthenticationError("No signing key matching token found");
2304
2403
  }
2305
2404
  const decoded = jose.JWT.IdToken.verify(token, key, {
2306
2405
  algorithms: ["ES256"],
2307
2406
  audience: "backstage",
2308
2407
  issuer: this.issuer
2309
2408
  });
2409
+ if (!decoded.sub) {
2410
+ throw new errors.AuthenticationError("No user sub found in token");
2411
+ }
2310
2412
  const user = {
2311
2413
  id: decoded.sub,
2312
- idToken: token
2414
+ token,
2415
+ identity: {
2416
+ type: "user",
2417
+ userEntityRef: decoded.sub,
2418
+ ownershipEntityRefs: (_a = decoded.ent) != null ? _a : []
2419
+ }
2313
2420
  };
2314
2421
  return user;
2315
2422
  }
@@ -2321,19 +2428,19 @@ class IdentityClient {
2321
2428
  return matches == null ? void 0 : matches[1];
2322
2429
  }
2323
2430
  async getKey(rawJwtToken) {
2324
- const {header, payload} = jose.JWT.decode(rawJwtToken, {
2431
+ const { header, payload } = jose.JWT.decode(rawJwtToken, {
2325
2432
  complete: true
2326
2433
  });
2327
- const keyStoreHasKey = !!this.keyStore.get({kid: header.kid});
2434
+ const keyStoreHasKey = !!this.keyStore.get({ kid: header.kid });
2328
2435
  const issuedAfterLastRefresh = (payload == null ? void 0 : payload.iat) && payload.iat > this.keyStoreUpdated - CLOCK_MARGIN_S;
2329
2436
  if (!keyStoreHasKey && issuedAfterLastRefresh) {
2330
2437
  await this.refreshKeyStore();
2331
2438
  }
2332
- return this.keyStore.get({kid: header.kid});
2439
+ return this.keyStore.get({ kid: header.kid });
2333
2440
  }
2334
2441
  async listPublicKeys() {
2335
2442
  const url = `${await this.discovery.getBaseUrl("auth")}/.well-known/jwks.json`;
2336
- const response = await fetch__default['default'](url);
2443
+ const response = await fetch__default["default"](url);
2337
2444
  if (!response.ok) {
2338
2445
  const payload = await response.text();
2339
2446
  const message = `Request failed with ${response.status} ${response.statusText}, ${payload}`;
@@ -2369,13 +2476,13 @@ class TokenFactory {
2369
2476
  const iat = Math.floor(Date.now() / MS_IN_S);
2370
2477
  const exp = iat + this.keyDurationSeconds;
2371
2478
  this.logger.info(`Issuing token for ${sub}, with entities ${ent != null ? ent : []}`);
2372
- return jose.JWS.sign({iss, sub, aud, iat, exp, ent}, key, {
2479
+ return jose.JWS.sign({ iss, sub, aud, iat, exp, ent }, key, {
2373
2480
  alg: key.alg,
2374
2481
  kid: key.kid
2375
2482
  });
2376
2483
  }
2377
2484
  async listPublicKeys() {
2378
- const {items: keys} = await this.keyStore.listKeys();
2485
+ const { items: keys } = await this.keyStore.listKeys();
2379
2486
  const validKeys = [];
2380
2487
  const expiredKeys = [];
2381
2488
  for (const key of keys) {
@@ -2389,13 +2496,13 @@ class TokenFactory {
2389
2496
  }
2390
2497
  }
2391
2498
  if (expiredKeys.length > 0) {
2392
- const kids = expiredKeys.map(({key}) => key.kid);
2499
+ const kids = expiredKeys.map(({ key }) => key.kid);
2393
2500
  this.logger.info(`Removing expired signing keys, '${kids.join("', '")}'`);
2394
2501
  this.keyStore.removeKeys(kids).catch((error) => {
2395
2502
  this.logger.error(`Failed to remove expired keys, ${error}`);
2396
2503
  });
2397
2504
  }
2398
- return {keys: validKeys.map(({key}) => key)};
2505
+ return { keys: validKeys.map(({ key }) => key) };
2399
2506
  }
2400
2507
  async getKey() {
2401
2508
  if (this.privateKeyPromise) {
@@ -2433,7 +2540,7 @@ class TokenFactory {
2433
2540
  const migrationsDir = backendCommon.resolvePackagePath("@backstage/plugin-auth-backend", "migrations");
2434
2541
  const TABLE = "signing_keys";
2435
2542
  const parseDate = (date) => {
2436
- 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);
2437
2544
  if (!parsedDate.isValid) {
2438
2545
  throw new Error(`Failed to parse date, reason: ${parsedDate.invalidReason}, explanation: ${parsedDate.invalidExplanation}`);
2439
2546
  }
@@ -2441,7 +2548,7 @@ const parseDate = (date) => {
2441
2548
  };
2442
2549
  class DatabaseKeyStore {
2443
2550
  static async create(options) {
2444
- const {database} = options;
2551
+ const { database } = options;
2445
2552
  await database.migrate.latest({
2446
2553
  directory: migrationsDir
2447
2554
  });
@@ -2472,7 +2579,7 @@ class DatabaseKeyStore {
2472
2579
 
2473
2580
  class MemoryKeyStore {
2474
2581
  constructor() {
2475
- this.keys = new Map();
2582
+ this.keys = /* @__PURE__ */ new Map();
2476
2583
  }
2477
2584
  async addKey(key) {
2478
2585
  this.keys.set(key.kid, {
@@ -2487,7 +2594,7 @@ class MemoryKeyStore {
2487
2594
  }
2488
2595
  async listKeys() {
2489
2596
  return {
2490
- items: Array.from(this.keys).map(([, {createdAt, key: keyStr}]) => ({
2597
+ items: Array.from(this.keys).map(([, { createdAt, key: keyStr }]) => ({
2491
2598
  createdAt,
2492
2599
  key: JSON.parse(keyStr)
2493
2600
  }))
@@ -2504,7 +2611,7 @@ class FirestoreKeyStore {
2504
2611
  this.timeout = timeout;
2505
2612
  }
2506
2613
  static async create(settings) {
2507
- const {path, timeout, ...firestoreSettings} = settings != null ? settings : {};
2614
+ const { path, timeout, ...firestoreSettings } = settings != null ? settings : {};
2508
2615
  const database = new firestore.Firestore(firestoreSettings);
2509
2616
  return new FirestoreKeyStore(database, path != null ? path : DEFAULT_DOCUMENT_PATH, timeout != null ? timeout : DEFAULT_TIMEOUT_MS);
2510
2617
  }
@@ -2552,7 +2659,7 @@ class FirestoreKeyStore {
2552
2659
  class KeyStores {
2553
2660
  static async fromConfig(config, options) {
2554
2661
  var _a;
2555
- const {logger, database} = options != null ? options : {};
2662
+ const { logger, database } = options != null ? options : {};
2556
2663
  const ks = config.getOptionalConfig("auth.keyStore");
2557
2664
  const provider = (_a = ks == null ? void 0 : ks.getOptionalString("provider")) != null ? _a : "database";
2558
2665
  logger == null ? void 0 : logger.info(`Configuring "${provider}" as KeyStore provider`);
@@ -2585,36 +2692,31 @@ class KeyStores {
2585
2692
  }
2586
2693
  }
2587
2694
 
2588
- async function createRouter({
2589
- logger,
2590
- config,
2591
- discovery,
2592
- database,
2593
- providerFactories
2594
- }) {
2595
- const router = Router__default['default']();
2695
+ async function createRouter(options) {
2696
+ const { logger, config, discovery, database, providerFactories } = options;
2697
+ const router = Router__default["default"]();
2596
2698
  const appUrl = config.getString("app.baseUrl");
2597
2699
  const authUrl = await discovery.getExternalBaseUrl("auth");
2598
- const keyStore = await KeyStores.fromConfig(config, {logger, database});
2700
+ const keyStore = await KeyStores.fromConfig(config, { logger, database });
2599
2701
  const keyDurationSeconds = 3600;
2600
2702
  const tokenIssuer = new TokenFactory({
2601
2703
  issuer: authUrl,
2602
2704
  keyStore,
2603
2705
  keyDurationSeconds,
2604
- logger: logger.child({component: "token-factory"})
2706
+ logger: logger.child({ component: "token-factory" })
2605
2707
  });
2606
- const catalogApi = new catalogClient.CatalogClient({discoveryApi: discovery});
2708
+ const catalogApi = new catalogClient.CatalogClient({ discoveryApi: discovery });
2607
2709
  const secret = config.getOptionalString("auth.session.secret");
2608
2710
  if (secret) {
2609
- router.use(cookieParser__default['default'](secret));
2610
- router.use(session__default['default']({secret, saveUninitialized: false, resave: false}));
2611
- router.use(passport__default['default'].initialize());
2612
- router.use(passport__default['default'].session());
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());
2613
2715
  } else {
2614
- router.use(cookieParser__default['default']());
2716
+ router.use(cookieParser__default["default"]());
2615
2717
  }
2616
- router.use(express__default['default'].urlencoded({extended: false}));
2617
- router.use(express__default['default'].json());
2718
+ router.use(express__default["default"].urlencoded({ extended: false }));
2719
+ router.use(express__default["default"].json());
2618
2720
  const allProviderFactories = {
2619
2721
  ...factories,
2620
2722
  ...providerFactories
@@ -2628,14 +2730,14 @@ async function createRouter({
2628
2730
  try {
2629
2731
  const provider = providerFactory({
2630
2732
  providerId,
2631
- globalConfig: {baseUrl: authUrl, appUrl, isOriginAllowed},
2733
+ globalConfig: { baseUrl: authUrl, appUrl, isOriginAllowed },
2632
2734
  config: providersConfig.getConfig(providerId),
2633
2735
  logger,
2634
2736
  tokenIssuer,
2635
2737
  discovery,
2636
2738
  catalogApi
2637
2739
  });
2638
- const r = Router__default['default']();
2740
+ const r = Router__default["default"]();
2639
2741
  r.get("/start", provider.start.bind(provider));
2640
2742
  r.get("/handler/frame", provider.frameHandler.bind(provider));
2641
2743
  r.post("/handler/frame", provider.frameHandler.bind(provider));
@@ -2667,7 +2769,7 @@ async function createRouter({
2667
2769
  baseUrl: authUrl
2668
2770
  }));
2669
2771
  router.use("/:provider/", (req) => {
2670
- const {provider} = req.params;
2772
+ const { provider } = req.params;
2671
2773
  throw new errors.NotFoundError(`Unknown auth provider '${provider}'`);
2672
2774
  });
2673
2775
  return router;
@@ -2675,9 +2777,9 @@ async function createRouter({
2675
2777
  function createOriginFilter(config) {
2676
2778
  var _a;
2677
2779
  const appUrl = config.getString("app.baseUrl");
2678
- const {origin: appOrigin} = new URL(appUrl);
2780
+ const { origin: appOrigin } = new URL(appUrl);
2679
2781
  const allowedOrigins = config.getOptionalStringArray("auth.experimentalExtraAllowedOrigins");
2680
- 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 : [];
2681
2783
  return (origin) => {
2682
2784
  if (origin === appOrigin) {
2683
2785
  return true;
@@ -2686,6 +2788,7 @@ function createOriginFilter(config) {
2686
2788
  };
2687
2789
  }
2688
2790
 
2791
+ exports.CatalogIdentityClient = CatalogIdentityClient;
2689
2792
  exports.IdentityClient = IdentityClient;
2690
2793
  exports.OAuthAdapter = OAuthAdapter;
2691
2794
  exports.OAuthEnvironmentHandler = OAuthEnvironmentHandler;
@@ -2699,16 +2802,20 @@ exports.createGitlabProvider = createGitlabProvider;
2699
2802
  exports.createGoogleProvider = createGoogleProvider;
2700
2803
  exports.createMicrosoftProvider = createMicrosoftProvider;
2701
2804
  exports.createOAuth2Provider = createOAuth2Provider;
2805
+ exports.createOidcProvider = createOidcProvider;
2702
2806
  exports.createOktaProvider = createOktaProvider;
2703
2807
  exports.createOriginFilter = createOriginFilter;
2704
2808
  exports.createRouter = createRouter;
2809
+ exports.createSamlProvider = createSamlProvider;
2705
2810
  exports.defaultAuthProviderFactories = factories;
2706
2811
  exports.encodeState = encodeState;
2707
2812
  exports.ensuresXRequestedWith = ensuresXRequestedWith;
2813
+ exports.getEntityClaims = getEntityClaims;
2708
2814
  exports.googleEmailSignInResolver = googleEmailSignInResolver;
2709
2815
  exports.microsoftEmailSignInResolver = microsoftEmailSignInResolver;
2710
2816
  exports.oktaEmailSignInResolver = oktaEmailSignInResolver;
2711
2817
  exports.postMessageResponse = postMessageResponse;
2818
+ exports.prepareBackstageIdentityResponse = prepareBackstageIdentityResponse;
2712
2819
  exports.readState = readState;
2713
2820
  exports.verifyNonce = verifyNonce;
2714
2821
  //# sourceMappingURL=index.cjs.js.map