@backstage/plugin-auth-backend 0.4.10 → 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/dist/index.cjs.js CHANGED
@@ -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);
@@ -287,11 +285,11 @@ const postMessageResponse = (res, appOrigin, response) => {
287
285
  window.close();
288
286
  }, 100); // same as the interval of the core-app-api lib/loginPopup.ts (to address race conditions)
289
287
  `;
290
- const hash = crypto__default['default'].createHash("sha256").update(script).digest("base64");
288
+ const hash = crypto__default["default"].createHash("sha256").update(script).digest("base64");
291
289
  res.setHeader("Content-Type", "text/html");
292
290
  res.setHeader("X-Frame-Options", "sameorigin");
293
291
  res.setHeader("Content-Security-Policy", `script-src 'sha256-${hash}'`);
294
- res.end(`<html><body><script>${script}</script></body></html>`);
292
+ res.end(`<html><body><script>${script}<\/script></body></html>`);
295
293
  };
296
294
  const ensuresXRequestedWith = (req) => {
297
295
  const requiredHeader = req.header("X-Requested-With");
@@ -301,6 +299,25 @@ const ensuresXRequestedWith = (req) => {
301
299
  return true;
302
300
  };
303
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
+
304
321
  const THOUSAND_DAYS_MS = 1e3 * 24 * 60 * 60 * 1e3;
305
322
  const TEN_MINUTES_MS = 600 * 1e3;
306
323
  class OAuthAdapter {
@@ -352,7 +369,7 @@ class OAuthAdapter {
352
369
  };
353
370
  }
354
371
  static fromConfig(config, handlers, options) {
355
- const {origin: appOrigin} = new url.URL(config.appUrl);
372
+ const { origin: appOrigin } = new url.URL(config.appUrl);
356
373
  const secure = config.baseUrl.startsWith("https://");
357
374
  const url$1 = new url.URL(config.baseUrl);
358
375
  const cookiePath = `${url$1.pathname}/${options.providerId}`;
@@ -376,11 +393,11 @@ class OAuthAdapter {
376
393
  if (this.options.persistScopes) {
377
394
  this.setScopesCookie(res, scope);
378
395
  }
379
- const nonce = crypto__default['default'].randomBytes(16).toString("base64");
396
+ const nonce = crypto__default["default"].randomBytes(16).toString("base64");
380
397
  this.setNonceCookie(res, nonce);
381
- const state = {nonce, env, origin};
382
- const forwardReq = Object.assign(req, {scope, state});
383
- 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);
384
401
  res.statusCode = status || 302;
385
402
  res.setHeader("Location", url);
386
403
  res.setHeader("Content-Length", "0");
@@ -402,7 +419,7 @@ class OAuthAdapter {
402
419
  }
403
420
  }
404
421
  verifyNonce(req, this.options.providerId);
405
- const {response, refreshToken} = await this.handlers.handler(req);
422
+ const { response, refreshToken } = await this.handlers.handler(req);
406
423
  if (this.options.persistScopes) {
407
424
  const grantedScopes = this.getScopesFromCookie(req, this.options.providerId);
408
425
  response.providerInfo.scope = grantedScopes;
@@ -410,16 +427,16 @@ class OAuthAdapter {
410
427
  if (refreshToken && !this.options.disableRefresh) {
411
428
  this.setRefreshTokenCookie(res, refreshToken);
412
429
  }
413
- await this.populateIdentity(response.backstageIdentity);
430
+ const identity = await this.populateIdentity(response.backstageIdentity);
414
431
  return postMessageResponse(res, appOrigin, {
415
432
  type: "authorization_response",
416
- response
433
+ response: { ...response, backstageIdentity: identity }
417
434
  });
418
435
  } catch (error) {
419
- 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");
420
437
  return postMessageResponse(res, appOrigin, {
421
438
  type: "authorization_response",
422
- error: {name, message}
439
+ error: { name, message }
423
440
  });
424
441
  }
425
442
  }
@@ -444,28 +461,28 @@ class OAuthAdapter {
444
461
  throw new errors.InputError("Missing session cookie");
445
462
  }
446
463
  const scope = (_b = (_a = req.query.scope) == null ? void 0 : _a.toString()) != null ? _b : "";
447
- const forwardReq = Object.assign(req, {scope, refreshToken});
464
+ const forwardReq = Object.assign(req, { scope, refreshToken });
448
465
  const response = await this.handlers.refresh(forwardReq);
449
- await this.populateIdentity(response.backstageIdentity);
466
+ const backstageIdentity = await this.populateIdentity(response.backstageIdentity);
450
467
  if (response.providerInfo.refreshToken && response.providerInfo.refreshToken !== refreshToken) {
451
468
  this.setRefreshTokenCookie(res, response.providerInfo.refreshToken);
452
469
  }
453
- res.status(200).json(response);
470
+ res.status(200).json({ ...response, backstageIdentity });
454
471
  } catch (error) {
455
472
  throw new errors.AuthenticationError("Refresh failed", error);
456
473
  }
457
474
  }
458
475
  async populateIdentity(identity) {
459
476
  if (!identity) {
460
- return;
477
+ return void 0;
461
478
  }
462
- if (!(identity.token || identity.idToken)) {
463
- identity.token = await this.options.tokenIssuer.issueToken({
464
- claims: {sub: identity.id}
465
- });
466
- } else if (!identity.token && identity.idToken) {
467
- identity.token = identity.idToken;
479
+ if (identity.token) {
480
+ return prepareBackstageIdentityResponse(identity);
468
481
  }
482
+ const token = await this.options.tokenIssuer.issueToken({
483
+ claims: { sub: identity.id }
484
+ });
485
+ return prepareBackstageIdentityResponse({ ...identity, token });
469
486
  }
470
487
  }
471
488
 
@@ -482,9 +499,9 @@ class CatalogIdentityClient {
482
499
  filter[`metadata.annotations.${key}`] = value;
483
500
  }
484
501
  const token = await this.tokenIssuer.issueToken({
485
- claims: {sub: "backstage.io/auth-backend"}
502
+ claims: { sub: "backstage.io/auth-backend" }
486
503
  });
487
- const {items} = await this.catalogApi.getEntities({filter}, {token});
504
+ const { items } = await this.catalogApi.getEntities({ filter }, { token });
488
505
  if (items.length !== 1) {
489
506
  if (items.length > 1) {
490
507
  throw new errors.ConflictError("User lookup resulted in multiple matches");
@@ -494,10 +511,8 @@ class CatalogIdentityClient {
494
511
  }
495
512
  return items[0];
496
513
  }
497
- async resolveCatalogMembership({
498
- entityRefs,
499
- logger
500
- }) {
514
+ async resolveCatalogMembership(query) {
515
+ const { entityRefs, logger } = query;
501
516
  const resolvedEntityRefs = entityRefs.map((ref) => {
502
517
  try {
503
518
  const parsedRef = catalogModel.parseEntityRef(ref.toLocaleLowerCase("en-US"), {
@@ -515,7 +530,7 @@ class CatalogIdentityClient {
515
530
  "metadata.namespace": ref.namespace,
516
531
  "metadata.name": ref.name
517
532
  }));
518
- const entities = await this.catalogApi.getEntities({filter}).then((r) => r.items);
533
+ const entities = await this.catalogApi.getEntities({ filter }).then((r) => r.items);
519
534
  if (entityRefs.length !== entities.length) {
520
535
  const foundEntityNames = entities.map(catalogModel.stringifyEntityRef);
521
536
  const missingEntityNames = resolvedEntityRefs.map(catalogModel.stringifyEntityRef).filter((s) => !foundEntityNames.includes(s));
@@ -559,7 +574,7 @@ class GithubAuthProvider {
559
574
  userProfileURL: options.userProfileUrl,
560
575
  authorizationURL: options.authorizationUrl
561
576
  }, (accessToken, refreshToken, params, fullProfile, done) => {
562
- done(void 0, {fullProfile, params, accessToken}, {refreshToken});
577
+ done(void 0, { fullProfile, params, accessToken }, { refreshToken });
563
578
  });
564
579
  }
565
580
  async start(req) {
@@ -569,7 +584,7 @@ class GithubAuthProvider {
569
584
  });
570
585
  }
571
586
  async handler(req) {
572
- const {result, privateInfo} = await executeFrameHandlerStrategy(req, this._strategy);
587
+ const { result, privateInfo } = await executeFrameHandlerStrategy(req, this._strategy);
573
588
  return {
574
589
  response: await this.handleResult(result),
575
590
  refreshToken: privateInfo.refreshToken
@@ -590,7 +605,7 @@ class GithubAuthProvider {
590
605
  });
591
606
  }
592
607
  async handleResult(result) {
593
- const {profile} = await this.authHandler(result);
608
+ const { profile } = await this.authHandler(result);
594
609
  const expiresInStr = result.params.expires_in;
595
610
  const response = {
596
611
  providerInfo: {
@@ -615,12 +630,12 @@ class GithubAuthProvider {
615
630
  }
616
631
  }
617
632
  const githubDefaultSignInResolver = async (info, ctx) => {
618
- const {fullProfile} = info.result;
633
+ const { fullProfile } = info.result;
619
634
  const userId = fullProfile.username || fullProfile.id;
620
635
  const token = await ctx.tokenIssuer.issueToken({
621
- claims: {sub: userId, ent: [`user:default/${userId}`]}
636
+ claims: { sub: userId, ent: [`user:default/${userId}`] }
622
637
  });
623
- return {id: userId, token};
638
+ return { id: userId, token };
624
639
  };
625
640
  const createGithubProvider = (options) => {
626
641
  return ({
@@ -644,7 +659,7 @@ const createGithubProvider = (options) => {
644
659
  catalogApi,
645
660
  tokenIssuer
646
661
  });
647
- 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 }) => ({
648
663
  profile: makeProfileInfo(fullProfile)
649
664
  });
650
665
  const signInResolverFn = (_b = (_a = options == null ? void 0 : options.signIn) == null ? void 0 : _a.resolver) != null ? _b : githubDefaultSignInResolver;
@@ -654,7 +669,7 @@ const createGithubProvider = (options) => {
654
669
  logger
655
670
  });
656
671
  const stateEncoder = (_c = options == null ? void 0 : options.stateEncoder) != null ? _c : async (req) => {
657
- return {encodedState: encodeState(req.state)};
672
+ return { encodedState: encodeState(req.state) };
658
673
  };
659
674
  const provider = new GithubAuthProvider({
660
675
  clientId,
@@ -679,15 +694,15 @@ const createGithubProvider = (options) => {
679
694
  };
680
695
 
681
696
  const gitlabDefaultSignInResolver = async (info, ctx) => {
682
- const {profile, result} = info;
697
+ const { profile, result } = info;
683
698
  let id = result.fullProfile.id;
684
699
  if (profile.email) {
685
700
  id = profile.email.split("@")[0];
686
701
  }
687
702
  const token = await ctx.tokenIssuer.issueToken({
688
- claims: {sub: id, ent: [`user:default/${id}`]}
703
+ claims: { sub: id, ent: [`user:default/${id}`] }
689
704
  });
690
- return {id, token};
705
+ return { id, token };
691
706
  };
692
707
  const gitlabDefaultAuthHandler = async ({
693
708
  fullProfile,
@@ -708,7 +723,7 @@ class GitlabAuthProvider {
708
723
  callbackURL: options.callbackUrl,
709
724
  baseURL: options.baseUrl
710
725
  }, (accessToken, refreshToken, params, fullProfile, done) => {
711
- done(void 0, {fullProfile, params, accessToken}, {
726
+ done(void 0, { fullProfile, params, accessToken }, {
712
727
  refreshToken
713
728
  });
714
729
  });
@@ -720,7 +735,7 @@ class GitlabAuthProvider {
720
735
  });
721
736
  }
722
737
  async handler(req) {
723
- const {result, privateInfo} = await executeFrameHandlerStrategy(req, this._strategy);
738
+ const { result, privateInfo } = await executeFrameHandlerStrategy(req, this._strategy);
724
739
  return {
725
740
  response: await this.handleResult(result),
726
741
  refreshToken: privateInfo.refreshToken
@@ -741,7 +756,7 @@ class GitlabAuthProvider {
741
756
  });
742
757
  }
743
758
  async handleResult(result) {
744
- const {profile} = await this.authHandler(result);
759
+ const { profile } = await this.authHandler(result);
745
760
  const response = {
746
761
  providerInfo: {
747
762
  idToken: result.params.id_token,
@@ -842,14 +857,14 @@ class GoogleAuthProvider {
842
857
  });
843
858
  }
844
859
  async handler(req) {
845
- const {result, privateInfo} = await executeFrameHandlerStrategy(req, this._strategy);
860
+ const { result, privateInfo } = await executeFrameHandlerStrategy(req, this._strategy);
846
861
  return {
847
862
  response: await this.handleResult(result),
848
863
  refreshToken: privateInfo.refreshToken
849
864
  };
850
865
  }
851
866
  async refresh(req) {
852
- const {accessToken, params} = await executeRefreshTokenStrategy(this._strategy, req.refreshToken, req.scope);
867
+ const { accessToken, params } = await executeRefreshTokenStrategy(this._strategy, req.refreshToken, req.scope);
853
868
  const fullProfile = await executeFetchUserProfileStrategy(this._strategy, accessToken);
854
869
  return this.handleResult({
855
870
  fullProfile,
@@ -859,7 +874,7 @@ class GoogleAuthProvider {
859
874
  });
860
875
  }
861
876
  async handleResult(result) {
862
- const {profile} = await this.authHandler(result);
877
+ const { profile } = await this.authHandler(result);
863
878
  const response = {
864
879
  providerInfo: {
865
880
  idToken: result.params.id_token,
@@ -883,7 +898,7 @@ class GoogleAuthProvider {
883
898
  }
884
899
  }
885
900
  const googleEmailSignInResolver = async (info, ctx) => {
886
- const {profile} = info;
901
+ const { profile } = info;
887
902
  if (!profile.email) {
888
903
  throw new Error("Google profile contained no email");
889
904
  }
@@ -893,11 +908,11 @@ const googleEmailSignInResolver = async (info, ctx) => {
893
908
  }
894
909
  });
895
910
  const claims = getEntityClaims(entity);
896
- const token = await ctx.tokenIssuer.issueToken({claims});
897
- return {id: entity.metadata.name, entity, token};
911
+ const token = await ctx.tokenIssuer.issueToken({ claims });
912
+ return { id: entity.metadata.name, entity, token };
898
913
  };
899
914
  const googleDefaultSignInResolver = async (info, ctx) => {
900
- const {profile} = info;
915
+ const { profile } = info;
901
916
  if (!profile.email) {
902
917
  throw new Error("Google profile contained no email");
903
918
  }
@@ -914,9 +929,9 @@ const googleDefaultSignInResolver = async (info, ctx) => {
914
929
  userId = profile.email.split("@")[0];
915
930
  }
916
931
  const token = await ctx.tokenIssuer.issueToken({
917
- claims: {sub: userId, ent: [`user:default/${userId}`]}
932
+ claims: { sub: userId, ent: [`user:default/${userId}`] }
918
933
  });
919
- return {id: userId, token};
934
+ return { id: userId, token };
920
935
  };
921
936
  const createGoogleProvider = (options) => {
922
937
  return ({
@@ -935,7 +950,7 @@ const createGoogleProvider = (options) => {
935
950
  catalogApi,
936
951
  tokenIssuer
937
952
  });
938
- 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 }) => ({
939
954
  profile: makeProfileInfo(fullProfile, params.id_token)
940
955
  });
941
956
  const signInResolverFn = (_b = (_a = options == null ? void 0 : options.signIn) == null ? void 0 : _a.resolver) != null ? _b : googleDefaultSignInResolver;
@@ -977,7 +992,7 @@ class MicrosoftAuthProvider {
977
992
  tokenURL: options.tokenUrl,
978
993
  passReqToCallback: false
979
994
  }, (accessToken, refreshToken, params, fullProfile, done) => {
980
- done(void 0, {fullProfile, accessToken, params}, {refreshToken});
995
+ done(void 0, { fullProfile, accessToken, params }, { refreshToken });
981
996
  });
982
997
  }
983
998
  async start(req) {
@@ -987,14 +1002,14 @@ class MicrosoftAuthProvider {
987
1002
  });
988
1003
  }
989
1004
  async handler(req) {
990
- const {result, privateInfo} = await executeFrameHandlerStrategy(req, this._strategy);
1005
+ const { result, privateInfo } = await executeFrameHandlerStrategy(req, this._strategy);
991
1006
  return {
992
1007
  response: await this.handleResult(result),
993
1008
  refreshToken: privateInfo.refreshToken
994
1009
  };
995
1010
  }
996
1011
  async refresh(req) {
997
- const {accessToken, params} = await executeRefreshTokenStrategy(this._strategy, req.refreshToken, req.scope);
1012
+ const { accessToken, params } = await executeRefreshTokenStrategy(this._strategy, req.refreshToken, req.scope);
998
1013
  const fullProfile = await executeFetchUserProfileStrategy(this._strategy, accessToken);
999
1014
  return this.handleResult({
1000
1015
  fullProfile,
@@ -1005,8 +1020,8 @@ class MicrosoftAuthProvider {
1005
1020
  }
1006
1021
  async handleResult(result) {
1007
1022
  const photo = await this.getUserPhoto(result.accessToken);
1008
- result.fullProfile.photos = photo ? [{value: photo}] : void 0;
1009
- const {profile} = await this.authHandler(result);
1023
+ result.fullProfile.photos = photo ? [{ value: photo }] : void 0;
1024
+ const { profile } = await this.authHandler(result);
1010
1025
  const response = {
1011
1026
  providerInfo: {
1012
1027
  idToken: result.params.id_token,
@@ -1030,7 +1045,7 @@ class MicrosoftAuthProvider {
1030
1045
  }
1031
1046
  getUserPhoto(accessToken) {
1032
1047
  return new Promise((resolve) => {
1033
- 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", {
1034
1049
  encoding: "binary",
1035
1050
  responseType: "buffer",
1036
1051
  headers: {
@@ -1047,7 +1062,7 @@ class MicrosoftAuthProvider {
1047
1062
  }
1048
1063
  }
1049
1064
  const microsoftEmailSignInResolver = async (info, ctx) => {
1050
- const {profile} = info;
1065
+ const { profile } = info;
1051
1066
  if (!profile.email) {
1052
1067
  throw new Error("Microsoft profile contained no email");
1053
1068
  }
@@ -1057,19 +1072,19 @@ const microsoftEmailSignInResolver = async (info, ctx) => {
1057
1072
  }
1058
1073
  });
1059
1074
  const claims = getEntityClaims(entity);
1060
- const token = await ctx.tokenIssuer.issueToken({claims});
1061
- return {id: entity.metadata.name, entity, token};
1075
+ const token = await ctx.tokenIssuer.issueToken({ claims });
1076
+ return { id: entity.metadata.name, entity, token };
1062
1077
  };
1063
1078
  const microsoftDefaultSignInResolver = async (info, ctx) => {
1064
- const {profile} = info;
1079
+ const { profile } = info;
1065
1080
  if (!profile.email) {
1066
1081
  throw new Error("Profile contained no email");
1067
1082
  }
1068
1083
  const userId = profile.email.split("@")[0];
1069
1084
  const token = await ctx.tokenIssuer.issueToken({
1070
- claims: {sub: userId, ent: [`user:default/${userId}`]}
1085
+ claims: { sub: userId, ent: [`user:default/${userId}`] }
1071
1086
  });
1072
- return {id: userId, token};
1087
+ return { id: userId, token };
1073
1088
  };
1074
1089
  const createMicrosoftProvider = (options) => {
1075
1090
  return ({
@@ -1091,7 +1106,7 @@ const createMicrosoftProvider = (options) => {
1091
1106
  catalogApi,
1092
1107
  tokenIssuer
1093
1108
  });
1094
- 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 }) => ({
1095
1110
  profile: makeProfileInfo(fullProfile, params.id_token)
1096
1111
  });
1097
1112
  const signInResolverFn = (_b = (_a = options == null ? void 0 : options.signIn) == null ? void 0 : _a.resolver) != null ? _b : microsoftDefaultSignInResolver;
@@ -1135,9 +1150,9 @@ class OAuth2AuthProvider {
1135
1150
  tokenURL: options.tokenUrl,
1136
1151
  passReqToCallback: false,
1137
1152
  scope: options.scope,
1138
- customHeaders: {
1153
+ customHeaders: options.includeBasicAuth ? {
1139
1154
  Authorization: `Basic ${this.encodeClientCredentials(options.clientId, options.clientSecret)}`
1140
- }
1155
+ } : void 0
1141
1156
  }, (accessToken, refreshToken, params, fullProfile, done) => {
1142
1157
  done(void 0, {
1143
1158
  fullProfile,
@@ -1158,7 +1173,7 @@ class OAuth2AuthProvider {
1158
1173
  });
1159
1174
  }
1160
1175
  async handler(req) {
1161
- const {result, privateInfo} = await executeFrameHandlerStrategy(req, this._strategy);
1176
+ const { result, privateInfo } = await executeFrameHandlerStrategy(req, this._strategy);
1162
1177
  return {
1163
1178
  response: await this.handleResult(result),
1164
1179
  refreshToken: privateInfo.refreshToken
@@ -1180,7 +1195,7 @@ class OAuth2AuthProvider {
1180
1195
  });
1181
1196
  }
1182
1197
  async handleResult(result) {
1183
- const {profile} = await this.authHandler(result);
1198
+ const { profile } = await this.authHandler(result);
1184
1199
  const response = {
1185
1200
  providerInfo: {
1186
1201
  idToken: result.params.id_token,
@@ -1208,15 +1223,15 @@ class OAuth2AuthProvider {
1208
1223
  }
1209
1224
  }
1210
1225
  const oAuth2DefaultSignInResolver$1 = async (info, ctx) => {
1211
- const {profile} = info;
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,12 +1249,13 @@ 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
1261
  const signInResolverFn = (_c = (_b = options == null ? void 0 : options.signIn) == null ? void 0 : _b.resolver) != null ? _c : oAuth2DefaultSignInResolver$1;
@@ -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,
@@ -1281,7 +1298,7 @@ class OidcAuthProvider {
1281
1298
  this.logger = options.logger;
1282
1299
  }
1283
1300
  async start(req) {
1284
- const {strategy} = await this.implementation;
1301
+ const { strategy } = await this.implementation;
1285
1302
  const options = {
1286
1303
  scope: req.scope || this.scope || "openid profile email",
1287
1304
  state: encodeState(req.state)
@@ -1293,26 +1310,26 @@ class OidcAuthProvider {
1293
1310
  return await executeRedirectStrategy(req, strategy, options);
1294
1311
  }
1295
1312
  async handler(req) {
1296
- const {strategy} = await this.implementation;
1313
+ const { strategy } = await this.implementation;
1297
1314
  const strategyResponse = await executeFrameHandlerStrategy(req, strategy);
1298
1315
  const {
1299
- result: {userinfo, tokenset},
1316
+ result: { userinfo, tokenset },
1300
1317
  privateInfo
1301
1318
  } = strategyResponse;
1302
- const identityResponse = await this.handleResult({tokenset, userinfo});
1319
+ const identityResponse = await this.handleResult({ tokenset, userinfo });
1303
1320
  return {
1304
1321
  response: identityResponse,
1305
1322
  refreshToken: privateInfo.refreshToken
1306
1323
  };
1307
1324
  }
1308
1325
  async refresh(req) {
1309
- const {client} = await this.implementation;
1326
+ const { client } = await this.implementation;
1310
1327
  const tokenset = await client.refresh(req.refreshToken);
1311
1328
  if (!tokenset.access_token) {
1312
1329
  throw new Error("Refresh failed");
1313
1330
  }
1314
1331
  const profile = await client.userinfo(tokenset.access_token);
1315
- return this.handleResult({tokenset, userinfo: profile});
1332
+ return this.handleResult({ tokenset, userinfo: profile });
1316
1333
  }
1317
1334
  async setupStrategy(options) {
1318
1335
  const issuer = await openidClient.Issuer.discover(options.metadataUrl);
@@ -1332,15 +1349,15 @@ class OidcAuthProvider {
1332
1349
  if (typeof done !== "function") {
1333
1350
  throw new Error("OIDC IdP must provide a userinfo_endpoint in the metadata response");
1334
1351
  }
1335
- done(void 0, {tokenset, userinfo}, {
1352
+ done(void 0, { tokenset, userinfo }, {
1336
1353
  refreshToken: tokenset.refresh_token
1337
1354
  });
1338
1355
  });
1339
1356
  strategy.error = console.error;
1340
- return {strategy, client};
1357
+ return { strategy, client };
1341
1358
  }
1342
1359
  async handleResult(result) {
1343
- const {profile} = await this.authHandler(result);
1360
+ const { profile } = await this.authHandler(result);
1344
1361
  const response = {
1345
1362
  providerInfo: {
1346
1363
  idToken: result.tokenset.id_token,
@@ -1365,15 +1382,15 @@ class OidcAuthProvider {
1365
1382
  }
1366
1383
  }
1367
1384
  const oAuth2DefaultSignInResolver = async (info, ctx) => {
1368
- const {profile} = info;
1385
+ const { profile } = info;
1369
1386
  if (!profile.email) {
1370
1387
  throw new Error("Profile contained no email");
1371
1388
  }
1372
1389
  const userId = profile.email.split("@")[0];
1373
1390
  const token = await ctx.tokenIssuer.issueToken({
1374
- claims: {sub: userId, ent: [`user:default/${userId}`]}
1391
+ claims: { sub: userId, ent: [`user:default/${userId}`] }
1375
1392
  });
1376
- return {id: userId, token};
1393
+ return { id: userId, token };
1377
1394
  };
1378
1395
  const createOidcProvider = (options) => {
1379
1396
  return ({
@@ -1396,7 +1413,7 @@ const createOidcProvider = (options) => {
1396
1413
  catalogApi,
1397
1414
  tokenIssuer
1398
1415
  });
1399
- const authHandler = (options == null ? void 0 : options.authHandler) ? options.authHandler : async ({userinfo}) => ({
1416
+ const authHandler = (options == null ? void 0 : options.authHandler) ? options.authHandler : async ({ userinfo }) => ({
1400
1417
  profile: {
1401
1418
  displayName: userinfo.name,
1402
1419
  email: userinfo.email,
@@ -1474,14 +1491,14 @@ class OktaAuthProvider {
1474
1491
  });
1475
1492
  }
1476
1493
  async handler(req) {
1477
- const {result, privateInfo} = await executeFrameHandlerStrategy(req, this._strategy);
1494
+ const { result, privateInfo } = await executeFrameHandlerStrategy(req, this._strategy);
1478
1495
  return {
1479
1496
  response: await this.handleResult(result),
1480
1497
  refreshToken: privateInfo.refreshToken
1481
1498
  };
1482
1499
  }
1483
1500
  async refresh(req) {
1484
- const {accessToken, params} = await executeRefreshTokenStrategy(this._strategy, req.refreshToken, req.scope);
1501
+ const { accessToken, params } = await executeRefreshTokenStrategy(this._strategy, req.refreshToken, req.scope);
1485
1502
  const fullProfile = await executeFetchUserProfileStrategy(this._strategy, accessToken);
1486
1503
  return this.handleResult({
1487
1504
  fullProfile,
@@ -1491,7 +1508,7 @@ class OktaAuthProvider {
1491
1508
  });
1492
1509
  }
1493
1510
  async handleResult(result) {
1494
- const {profile} = await this._authHandler(result);
1511
+ const { profile } = await this._authHandler(result);
1495
1512
  const response = {
1496
1513
  providerInfo: {
1497
1514
  idToken: result.params.id_token,
@@ -1515,7 +1532,7 @@ class OktaAuthProvider {
1515
1532
  }
1516
1533
  }
1517
1534
  const oktaEmailSignInResolver = async (info, ctx) => {
1518
- const {profile} = info;
1535
+ const { profile } = info;
1519
1536
  if (!profile.email) {
1520
1537
  throw new Error("Okta profile contained no email");
1521
1538
  }
@@ -1525,19 +1542,19 @@ const oktaEmailSignInResolver = async (info, ctx) => {
1525
1542
  }
1526
1543
  });
1527
1544
  const claims = getEntityClaims(entity);
1528
- const token = await ctx.tokenIssuer.issueToken({claims});
1529
- return {id: entity.metadata.name, entity, token};
1545
+ const token = await ctx.tokenIssuer.issueToken({ claims });
1546
+ return { id: entity.metadata.name, entity, token };
1530
1547
  };
1531
1548
  const oktaDefaultSignInResolver = async (info, ctx) => {
1532
- const {profile} = info;
1549
+ const { profile } = info;
1533
1550
  if (!profile.email) {
1534
1551
  throw new Error("Okta profile contained no email");
1535
1552
  }
1536
1553
  const userId = profile.email.split("@")[0];
1537
1554
  const token = await ctx.tokenIssuer.issueToken({
1538
- claims: {sub: userId, ent: [`user:default/${userId}`]}
1555
+ claims: { sub: userId, ent: [`user:default/${userId}`] }
1539
1556
  });
1540
- return {id: userId, token};
1557
+ return { id: userId, token };
1541
1558
  };
1542
1559
  const createOktaProvider = (_options) => {
1543
1560
  return ({
@@ -1560,7 +1577,7 @@ const createOktaProvider = (_options) => {
1560
1577
  catalogApi,
1561
1578
  tokenIssuer
1562
1579
  });
1563
- 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 }) => ({
1564
1581
  profile: makeProfileInfo(fullProfile, params.id_token)
1565
1582
  });
1566
1583
  const signInResolverFn = (_b = (_a = _options == null ? void 0 : _options.signIn) == null ? void 0 : _a.resolver) != null ? _b : oktaDefaultSignInResolver;
@@ -1620,14 +1637,14 @@ class BitbucketAuthProvider {
1620
1637
  });
1621
1638
  }
1622
1639
  async handler(req) {
1623
- const {result, privateInfo} = await executeFrameHandlerStrategy(req, this._strategy);
1640
+ const { result, privateInfo } = await executeFrameHandlerStrategy(req, this._strategy);
1624
1641
  return {
1625
1642
  response: await this.handleResult(result),
1626
1643
  refreshToken: privateInfo.refreshToken
1627
1644
  };
1628
1645
  }
1629
1646
  async refresh(req) {
1630
- const {accessToken, params} = await executeRefreshTokenStrategy(this._strategy, req.refreshToken, req.scope);
1647
+ const { accessToken, params } = await executeRefreshTokenStrategy(this._strategy, req.refreshToken, req.scope);
1631
1648
  const fullProfile = await executeFetchUserProfileStrategy(this._strategy, accessToken);
1632
1649
  return this.handleResult({
1633
1650
  fullProfile,
@@ -1638,7 +1655,7 @@ class BitbucketAuthProvider {
1638
1655
  }
1639
1656
  async handleResult(result) {
1640
1657
  result.fullProfile.avatarUrl = result.fullProfile._json.links.avatar.href;
1641
- const {profile} = await this.authHandler(result);
1658
+ const { profile } = await this.authHandler(result);
1642
1659
  const response = {
1643
1660
  providerInfo: {
1644
1661
  idToken: result.params.id_token,
@@ -1662,7 +1679,7 @@ class BitbucketAuthProvider {
1662
1679
  }
1663
1680
  }
1664
1681
  const bitbucketUsernameSignInResolver = async (info, ctx) => {
1665
- const {result} = info;
1682
+ const { result } = info;
1666
1683
  if (!result.fullProfile.username) {
1667
1684
  throw new Error("Bitbucket profile contained no Username");
1668
1685
  }
@@ -1672,11 +1689,11 @@ const bitbucketUsernameSignInResolver = async (info, ctx) => {
1672
1689
  }
1673
1690
  });
1674
1691
  const claims = getEntityClaims(entity);
1675
- const token = await ctx.tokenIssuer.issueToken({claims});
1676
- return {id: entity.metadata.name, entity, token};
1692
+ const token = await ctx.tokenIssuer.issueToken({ claims });
1693
+ return { id: entity.metadata.name, entity, token };
1677
1694
  };
1678
1695
  const bitbucketUserIdSignInResolver = async (info, ctx) => {
1679
- const {result} = info;
1696
+ const { result } = info;
1680
1697
  if (!result.fullProfile.id) {
1681
1698
  throw new Error("Bitbucket profile contained no User ID");
1682
1699
  }
@@ -1686,8 +1703,8 @@ const bitbucketUserIdSignInResolver = async (info, ctx) => {
1686
1703
  }
1687
1704
  });
1688
1705
  const claims = getEntityClaims(entity);
1689
- const token = await ctx.tokenIssuer.issueToken({claims});
1690
- return {id: entity.metadata.name, entity, token};
1706
+ const token = await ctx.tokenIssuer.issueToken({ claims });
1707
+ return { id: entity.metadata.name, entity, token };
1691
1708
  };
1692
1709
  const createBitbucketProvider = (options) => {
1693
1710
  return ({
@@ -1706,7 +1723,7 @@ const createBitbucketProvider = (options) => {
1706
1723
  catalogApi,
1707
1724
  tokenIssuer
1708
1725
  });
1709
- 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 }) => ({
1710
1727
  profile: makeProfileInfo(fullProfile, params.id_token)
1711
1728
  });
1712
1729
  const provider = new BitbucketAuthProvider({
@@ -1728,7 +1745,7 @@ const createBitbucketProvider = (options) => {
1728
1745
  };
1729
1746
 
1730
1747
  const defaultScopes = ["offline_access", "read:me"];
1731
- class AtlassianStrategy extends OAuth2Strategy__default['default'] {
1748
+ class AtlassianStrategy extends OAuth2Strategy__default["default"] {
1732
1749
  constructor(options, verify) {
1733
1750
  if (!options.scope) {
1734
1751
  throw new TypeError("Atlassian requires a scope option");
@@ -1738,7 +1755,7 @@ class AtlassianStrategy extends OAuth2Strategy__default['default'] {
1738
1755
  ...options,
1739
1756
  authorizationURL: `https://auth.atlassian.com/authorize`,
1740
1757
  tokenURL: `https://auth.atlassian.com/oauth/token`,
1741
- scope: Array.from(new Set([...defaultScopes, ...scopes]))
1758
+ scope: Array.from(/* @__PURE__ */ new Set([...defaultScopes, ...scopes]))
1742
1759
  };
1743
1760
  super(optionsWithURLs, verify);
1744
1761
  this.profileURL = "https://api.atlassian.com/me";
@@ -1775,8 +1792,8 @@ class AtlassianStrategy extends OAuth2Strategy__default['default'] {
1775
1792
  provider: "atlassian",
1776
1793
  username: resp.nickname,
1777
1794
  displayName: resp.name,
1778
- emails: [{value: resp.email}],
1779
- photos: [{value: resp.picture}]
1795
+ emails: [{ value: resp.email }],
1796
+ photos: [{ value: resp.picture }]
1780
1797
  };
1781
1798
  }
1782
1799
  }
@@ -1815,14 +1832,14 @@ class AtlassianAuthProvider {
1815
1832
  }
1816
1833
  async handler(req) {
1817
1834
  var _a;
1818
- const {result} = await executeFrameHandlerStrategy(req, this._strategy);
1835
+ const { result } = await executeFrameHandlerStrategy(req, this._strategy);
1819
1836
  return {
1820
1837
  response: await this.handleResult(result),
1821
1838
  refreshToken: (_a = result.refreshToken) != null ? _a : ""
1822
1839
  };
1823
1840
  }
1824
1841
  async handleResult(result) {
1825
- const {profile} = await this.authHandler(result);
1842
+ const { profile } = await this.authHandler(result);
1826
1843
  const response = {
1827
1844
  providerInfo: {
1828
1845
  idToken: result.params.id_token,
@@ -1913,7 +1930,7 @@ class AwsAlbAuthProvider {
1913
1930
  this.tokenIssuer = options.tokenIssuer;
1914
1931
  this.catalogIdentityClient = options.catalogIdentityClient;
1915
1932
  this.logger = options.logger;
1916
- this.keyCache = new NodeCache__default['default']({stdTTL: 3600});
1933
+ this.keyCache = new NodeCache__default["default"]({ stdTTL: 3600 });
1917
1934
  }
1918
1935
  frameHandler() {
1919
1936
  return Promise.resolve(void 0);
@@ -1957,8 +1974,8 @@ class AwsAlbAuthProvider {
1957
1974
  familyName: claims.family_name,
1958
1975
  givenName: claims.given_name
1959
1976
  },
1960
- emails: [{value: claims.email.toLowerCase()}],
1961
- photos: [{value: claims.picture}]
1977
+ emails: [{ value: claims.email.toLowerCase() }],
1978
+ photos: [{ value: claims.picture }]
1962
1979
  };
1963
1980
  return {
1964
1981
  fullProfile,
@@ -1970,7 +1987,7 @@ class AwsAlbAuthProvider {
1970
1987
  }
1971
1988
  }
1972
1989
  async handleResult(result) {
1973
- const {profile} = await this.authHandler(result);
1990
+ const { profile } = await this.authHandler(result);
1974
1991
  const backstageIdentity = await this.signInResolver({
1975
1992
  result,
1976
1993
  profile
@@ -1984,7 +2001,7 @@ class AwsAlbAuthProvider {
1984
2001
  accessToken: result.accessToken,
1985
2002
  expiresInSeconds: result.expiresInSeconds
1986
2003
  },
1987
- backstageIdentity,
2004
+ backstageIdentity: prepareBackstageIdentityResponse(backstageIdentity),
1988
2005
  profile
1989
2006
  };
1990
2007
  }
@@ -1993,14 +2010,14 @@ class AwsAlbAuthProvider {
1993
2010
  if (optionalCacheKey) {
1994
2011
  return crypto__namespace.createPublicKey(optionalCacheKey);
1995
2012
  }
1996
- 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());
1997
2014
  const keyValue = crypto__namespace.createPublicKey(keyText);
1998
- this.keyCache.set(keyId, keyValue.export({format: "pem", type: "spki"}));
2015
+ this.keyCache.set(keyId, keyValue.export({ format: "pem", type: "spki" }));
1999
2016
  return keyValue;
2000
2017
  }
2001
2018
  }
2002
2019
  const createAwsAlbProvider = (options) => {
2003
- return ({config, tokenIssuer, catalogApi, logger}) => {
2020
+ return ({ config, tokenIssuer, catalogApi, logger }) => {
2004
2021
  const region = config.getString("region");
2005
2022
  const issuer = config.getOptionalString("iss");
2006
2023
  if ((options == null ? void 0 : options.signIn.resolver) === void 0) {
@@ -2010,7 +2027,7 @@ const createAwsAlbProvider = (options) => {
2010
2027
  catalogApi,
2011
2028
  tokenIssuer
2012
2029
  });
2013
- 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 }) => ({
2014
2031
  profile: makeProfileInfo(fullProfile)
2015
2032
  });
2016
2033
  const signInResolver = options == null ? void 0 : options.signIn.resolver;
@@ -2034,24 +2051,24 @@ class SamlAuthProvider {
2034
2051
  this.tokenIssuer = options.tokenIssuer;
2035
2052
  this.catalogIdentityClient = options.catalogIdentityClient;
2036
2053
  this.logger = options.logger;
2037
- this.strategy = new passportSaml.Strategy({...options}, (fullProfile, done) => {
2038
- done(void 0, {fullProfile});
2054
+ this.strategy = new passportSaml.Strategy({ ...options }, (fullProfile, done) => {
2055
+ done(void 0, { fullProfile });
2039
2056
  });
2040
2057
  }
2041
2058
  async start(req, res) {
2042
- const {url} = await executeRedirectStrategy(req, this.strategy, {});
2059
+ const { url } = await executeRedirectStrategy(req, this.strategy, {});
2043
2060
  res.redirect(url);
2044
2061
  }
2045
2062
  async frameHandler(req, res) {
2046
2063
  try {
2047
- const {result} = await executeFrameHandlerStrategy(req, this.strategy);
2048
- const {profile} = await this.authHandler(result);
2064
+ const { result } = await executeFrameHandlerStrategy(req, this.strategy);
2065
+ const { profile } = await this.authHandler(result);
2049
2066
  const response = {
2050
2067
  profile,
2051
2068
  providerInfo: {}
2052
2069
  };
2053
2070
  if (this.signInResolver) {
2054
- response.backstageIdentity = await this.signInResolver({
2071
+ const signInResponse = await this.signInResolver({
2055
2072
  result,
2056
2073
  profile
2057
2074
  }, {
@@ -2059,16 +2076,17 @@ class SamlAuthProvider {
2059
2076
  catalogIdentityClient: this.catalogIdentityClient,
2060
2077
  logger: this.logger
2061
2078
  });
2079
+ response.backstageIdentity = prepareBackstageIdentityResponse(signInResponse);
2062
2080
  }
2063
2081
  return postMessageResponse(res, this.appUrl, {
2064
2082
  type: "authorization_response",
2065
2083
  response
2066
2084
  });
2067
2085
  } catch (error) {
2068
- 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");
2069
2087
  return postMessageResponse(res, this.appUrl, {
2070
2088
  type: "authorization_response",
2071
- error: {name, message}
2089
+ error: { name, message }
2072
2090
  });
2073
2091
  }
2074
2092
  }
@@ -2079,9 +2097,9 @@ class SamlAuthProvider {
2079
2097
  const samlDefaultSignInResolver = async (info, ctx) => {
2080
2098
  const id = info.result.fullProfile.nameID;
2081
2099
  const token = await ctx.tokenIssuer.issueToken({
2082
- claims: {sub: id}
2100
+ claims: { sub: id }
2083
2101
  });
2084
- return {id, token};
2102
+ return { id, token };
2085
2103
  };
2086
2104
  const createSamlProvider = (options) => {
2087
2105
  return ({
@@ -2097,7 +2115,7 @@ const createSamlProvider = (options) => {
2097
2115
  catalogApi,
2098
2116
  tokenIssuer
2099
2117
  });
2100
- const authHandler = (options == null ? void 0 : options.authHandler) ? options.authHandler : async ({fullProfile}) => ({
2118
+ const authHandler = (options == null ? void 0 : options.authHandler) ? options.authHandler : async ({ fullProfile }) => ({
2101
2119
  profile: {
2102
2120
  email: fullProfile.email,
2103
2121
  displayName: fullProfile.displayName
@@ -2133,7 +2151,7 @@ const createSamlProvider = (options) => {
2133
2151
  };
2134
2152
  };
2135
2153
 
2136
- class Auth0Strategy extends OAuth2Strategy__default['default'] {
2154
+ class Auth0Strategy extends OAuth2Strategy__default["default"] {
2137
2155
  constructor(options, verify) {
2138
2156
  const optionsWithURLs = {
2139
2157
  ...options,
@@ -2174,7 +2192,7 @@ class Auth0AuthProvider {
2174
2192
  });
2175
2193
  }
2176
2194
  async handler(req) {
2177
- const {result, privateInfo} = await executeFrameHandlerStrategy(req, this._strategy);
2195
+ const { result, privateInfo } = await executeFrameHandlerStrategy(req, this._strategy);
2178
2196
  const profile = makeProfileInfo(result.fullProfile, result.params.id_token);
2179
2197
  return {
2180
2198
  response: await this.populateIdentity({
@@ -2190,7 +2208,7 @@ class Auth0AuthProvider {
2190
2208
  };
2191
2209
  }
2192
2210
  async refresh(req) {
2193
- const {accessToken, params} = await executeRefreshTokenStrategy(this._strategy, req.refreshToken, req.scope);
2211
+ const { accessToken, params } = await executeRefreshTokenStrategy(this._strategy, req.refreshToken, req.scope);
2194
2212
  const fullProfile = await executeFetchUserProfileStrategy(this._strategy, accessToken);
2195
2213
  const profile = makeProfileInfo(fullProfile, params.id_token);
2196
2214
  return this.populateIdentity({
@@ -2204,16 +2222,16 @@ class Auth0AuthProvider {
2204
2222
  });
2205
2223
  }
2206
2224
  async populateIdentity(response) {
2207
- const {profile} = response;
2225
+ const { profile } = response;
2208
2226
  if (!profile.email) {
2209
2227
  throw new Error("Profile does not contain an email");
2210
2228
  }
2211
2229
  const id = profile.email.split("@")[0];
2212
- return {...response, backstageIdentity: {id}};
2230
+ return { ...response, backstageIdentity: { id, token: "" } };
2213
2231
  }
2214
2232
  }
2215
2233
  const createAuth0Provider = (_options) => {
2216
- return ({providerId, globalConfig, config, tokenIssuer}) => OAuthEnvironmentHandler.mapConfig(config, (envConfig) => {
2234
+ return ({ providerId, globalConfig, config, tokenIssuer }) => OAuthEnvironmentHandler.mapConfig(config, (envConfig) => {
2217
2235
  const clientId = envConfig.getString("clientId");
2218
2236
  const clientSecret = envConfig.getString("clientSecret");
2219
2237
  const domain = envConfig.getString("domain");
@@ -2260,7 +2278,7 @@ class OneLoginProvider {
2260
2278
  });
2261
2279
  }
2262
2280
  async handler(req) {
2263
- const {result, privateInfo} = await executeFrameHandlerStrategy(req, this._strategy);
2281
+ const { result, privateInfo } = await executeFrameHandlerStrategy(req, this._strategy);
2264
2282
  const profile = makeProfileInfo(result.fullProfile, result.params.id_token);
2265
2283
  return {
2266
2284
  response: await this.populateIdentity({
@@ -2276,7 +2294,7 @@ class OneLoginProvider {
2276
2294
  };
2277
2295
  }
2278
2296
  async refresh(req) {
2279
- const {accessToken, params} = await executeRefreshTokenStrategy(this._strategy, req.refreshToken, req.scope);
2297
+ const { accessToken, params } = await executeRefreshTokenStrategy(this._strategy, req.refreshToken, req.scope);
2280
2298
  const fullProfile = await executeFetchUserProfileStrategy(this._strategy, accessToken);
2281
2299
  const profile = makeProfileInfo(fullProfile, params.id_token);
2282
2300
  return this.populateIdentity({
@@ -2290,16 +2308,16 @@ class OneLoginProvider {
2290
2308
  });
2291
2309
  }
2292
2310
  async populateIdentity(response) {
2293
- const {profile} = response;
2311
+ const { profile } = response;
2294
2312
  if (!profile.email) {
2295
2313
  throw new Error("OIDC profile contained no email");
2296
2314
  }
2297
2315
  const id = profile.email.split("@")[0];
2298
- return {...response, backstageIdentity: {id}};
2316
+ return { ...response, backstageIdentity: { id, token: "" } };
2299
2317
  }
2300
2318
  }
2301
2319
  const createOneLoginProvider = (_options) => {
2302
- return ({providerId, globalConfig, config, tokenIssuer}) => OAuthEnvironmentHandler.mapConfig(config, (envConfig) => {
2320
+ return ({ providerId, globalConfig, config, tokenIssuer }) => OAuthEnvironmentHandler.mapConfig(config, (envConfig) => {
2303
2321
  const clientId = envConfig.getString("clientId");
2304
2322
  const clientSecret = envConfig.getString("clientSecret");
2305
2323
  const issuer = envConfig.getString("issuer");
@@ -2335,8 +2353,8 @@ const factories = {
2335
2353
  };
2336
2354
 
2337
2355
  function createOidcRouter(options) {
2338
- const {baseUrl, tokenIssuer} = options;
2339
- const router = Router__default['default']();
2356
+ const { baseUrl, tokenIssuer } = options;
2357
+ const router = Router__default["default"]();
2340
2358
  const config = {
2341
2359
  issuer: baseUrl,
2342
2360
  token_endpoint: `${baseUrl}/v1/token`,
@@ -2354,8 +2372,8 @@ function createOidcRouter(options) {
2354
2372
  res.json(config);
2355
2373
  });
2356
2374
  router.get("/.well-known/jwks.json", async (_req, res) => {
2357
- const {keys} = await tokenIssuer.listPublicKeys();
2358
- res.json({keys});
2375
+ const { keys } = await tokenIssuer.listPublicKeys();
2376
+ res.json({ keys });
2359
2377
  });
2360
2378
  router.get("/v1/token", (_req, res) => {
2361
2379
  res.status(501).send("Not Implemented");
@@ -2375,21 +2393,30 @@ class IdentityClient {
2375
2393
  this.keyStoreUpdated = 0;
2376
2394
  }
2377
2395
  async authenticate(token) {
2396
+ var _a;
2378
2397
  if (!token) {
2379
- throw new Error("No token specified");
2398
+ throw new errors.AuthenticationError("No token specified");
2380
2399
  }
2381
2400
  const key = await this.getKey(token);
2382
2401
  if (!key) {
2383
- throw new Error("No signing key matching token found");
2402
+ throw new errors.AuthenticationError("No signing key matching token found");
2384
2403
  }
2385
2404
  const decoded = jose.JWT.IdToken.verify(token, key, {
2386
2405
  algorithms: ["ES256"],
2387
2406
  audience: "backstage",
2388
2407
  issuer: this.issuer
2389
2408
  });
2409
+ if (!decoded.sub) {
2410
+ throw new errors.AuthenticationError("No user sub found in token");
2411
+ }
2390
2412
  const user = {
2391
2413
  id: decoded.sub,
2392
- idToken: token
2414
+ token,
2415
+ identity: {
2416
+ type: "user",
2417
+ userEntityRef: decoded.sub,
2418
+ ownershipEntityRefs: (_a = decoded.ent) != null ? _a : []
2419
+ }
2393
2420
  };
2394
2421
  return user;
2395
2422
  }
@@ -2401,19 +2428,19 @@ class IdentityClient {
2401
2428
  return matches == null ? void 0 : matches[1];
2402
2429
  }
2403
2430
  async getKey(rawJwtToken) {
2404
- const {header, payload} = jose.JWT.decode(rawJwtToken, {
2431
+ const { header, payload } = jose.JWT.decode(rawJwtToken, {
2405
2432
  complete: true
2406
2433
  });
2407
- const keyStoreHasKey = !!this.keyStore.get({kid: header.kid});
2434
+ const keyStoreHasKey = !!this.keyStore.get({ kid: header.kid });
2408
2435
  const issuedAfterLastRefresh = (payload == null ? void 0 : payload.iat) && payload.iat > this.keyStoreUpdated - CLOCK_MARGIN_S;
2409
2436
  if (!keyStoreHasKey && issuedAfterLastRefresh) {
2410
2437
  await this.refreshKeyStore();
2411
2438
  }
2412
- return this.keyStore.get({kid: header.kid});
2439
+ return this.keyStore.get({ kid: header.kid });
2413
2440
  }
2414
2441
  async listPublicKeys() {
2415
2442
  const url = `${await this.discovery.getBaseUrl("auth")}/.well-known/jwks.json`;
2416
- const response = await fetch__default['default'](url);
2443
+ const response = await fetch__default["default"](url);
2417
2444
  if (!response.ok) {
2418
2445
  const payload = await response.text();
2419
2446
  const message = `Request failed with ${response.status} ${response.statusText}, ${payload}`;
@@ -2449,13 +2476,13 @@ class TokenFactory {
2449
2476
  const iat = Math.floor(Date.now() / MS_IN_S);
2450
2477
  const exp = iat + this.keyDurationSeconds;
2451
2478
  this.logger.info(`Issuing token for ${sub}, with entities ${ent != null ? ent : []}`);
2452
- return jose.JWS.sign({iss, sub, aud, iat, exp, ent}, key, {
2479
+ return jose.JWS.sign({ iss, sub, aud, iat, exp, ent }, key, {
2453
2480
  alg: key.alg,
2454
2481
  kid: key.kid
2455
2482
  });
2456
2483
  }
2457
2484
  async listPublicKeys() {
2458
- const {items: keys} = await this.keyStore.listKeys();
2485
+ const { items: keys } = await this.keyStore.listKeys();
2459
2486
  const validKeys = [];
2460
2487
  const expiredKeys = [];
2461
2488
  for (const key of keys) {
@@ -2469,13 +2496,13 @@ class TokenFactory {
2469
2496
  }
2470
2497
  }
2471
2498
  if (expiredKeys.length > 0) {
2472
- const kids = expiredKeys.map(({key}) => key.kid);
2499
+ const kids = expiredKeys.map(({ key }) => key.kid);
2473
2500
  this.logger.info(`Removing expired signing keys, '${kids.join("', '")}'`);
2474
2501
  this.keyStore.removeKeys(kids).catch((error) => {
2475
2502
  this.logger.error(`Failed to remove expired keys, ${error}`);
2476
2503
  });
2477
2504
  }
2478
- return {keys: validKeys.map(({key}) => key)};
2505
+ return { keys: validKeys.map(({ key }) => key) };
2479
2506
  }
2480
2507
  async getKey() {
2481
2508
  if (this.privateKeyPromise) {
@@ -2513,7 +2540,7 @@ class TokenFactory {
2513
2540
  const migrationsDir = backendCommon.resolvePackagePath("@backstage/plugin-auth-backend", "migrations");
2514
2541
  const TABLE = "signing_keys";
2515
2542
  const parseDate = (date) => {
2516
- 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);
2517
2544
  if (!parsedDate.isValid) {
2518
2545
  throw new Error(`Failed to parse date, reason: ${parsedDate.invalidReason}, explanation: ${parsedDate.invalidExplanation}`);
2519
2546
  }
@@ -2521,7 +2548,7 @@ const parseDate = (date) => {
2521
2548
  };
2522
2549
  class DatabaseKeyStore {
2523
2550
  static async create(options) {
2524
- const {database} = options;
2551
+ const { database } = options;
2525
2552
  await database.migrate.latest({
2526
2553
  directory: migrationsDir
2527
2554
  });
@@ -2552,7 +2579,7 @@ class DatabaseKeyStore {
2552
2579
 
2553
2580
  class MemoryKeyStore {
2554
2581
  constructor() {
2555
- this.keys = new Map();
2582
+ this.keys = /* @__PURE__ */ new Map();
2556
2583
  }
2557
2584
  async addKey(key) {
2558
2585
  this.keys.set(key.kid, {
@@ -2567,7 +2594,7 @@ class MemoryKeyStore {
2567
2594
  }
2568
2595
  async listKeys() {
2569
2596
  return {
2570
- items: Array.from(this.keys).map(([, {createdAt, key: keyStr}]) => ({
2597
+ items: Array.from(this.keys).map(([, { createdAt, key: keyStr }]) => ({
2571
2598
  createdAt,
2572
2599
  key: JSON.parse(keyStr)
2573
2600
  }))
@@ -2584,7 +2611,7 @@ class FirestoreKeyStore {
2584
2611
  this.timeout = timeout;
2585
2612
  }
2586
2613
  static async create(settings) {
2587
- const {path, timeout, ...firestoreSettings} = settings != null ? settings : {};
2614
+ const { path, timeout, ...firestoreSettings } = settings != null ? settings : {};
2588
2615
  const database = new firestore.Firestore(firestoreSettings);
2589
2616
  return new FirestoreKeyStore(database, path != null ? path : DEFAULT_DOCUMENT_PATH, timeout != null ? timeout : DEFAULT_TIMEOUT_MS);
2590
2617
  }
@@ -2632,7 +2659,7 @@ class FirestoreKeyStore {
2632
2659
  class KeyStores {
2633
2660
  static async fromConfig(config, options) {
2634
2661
  var _a;
2635
- const {logger, database} = options != null ? options : {};
2662
+ const { logger, database } = options != null ? options : {};
2636
2663
  const ks = config.getOptionalConfig("auth.keyStore");
2637
2664
  const provider = (_a = ks == null ? void 0 : ks.getOptionalString("provider")) != null ? _a : "database";
2638
2665
  logger == null ? void 0 : logger.info(`Configuring "${provider}" as KeyStore provider`);
@@ -2665,36 +2692,31 @@ class KeyStores {
2665
2692
  }
2666
2693
  }
2667
2694
 
2668
- async function createRouter({
2669
- logger,
2670
- config,
2671
- discovery,
2672
- database,
2673
- providerFactories
2674
- }) {
2675
- const router = Router__default['default']();
2695
+ async function createRouter(options) {
2696
+ const { logger, config, discovery, database, providerFactories } = options;
2697
+ const router = Router__default["default"]();
2676
2698
  const appUrl = config.getString("app.baseUrl");
2677
2699
  const authUrl = await discovery.getExternalBaseUrl("auth");
2678
- const keyStore = await KeyStores.fromConfig(config, {logger, database});
2700
+ const keyStore = await KeyStores.fromConfig(config, { logger, database });
2679
2701
  const keyDurationSeconds = 3600;
2680
2702
  const tokenIssuer = new TokenFactory({
2681
2703
  issuer: authUrl,
2682
2704
  keyStore,
2683
2705
  keyDurationSeconds,
2684
- logger: logger.child({component: "token-factory"})
2706
+ logger: logger.child({ component: "token-factory" })
2685
2707
  });
2686
- const catalogApi = new catalogClient.CatalogClient({discoveryApi: discovery});
2708
+ const catalogApi = new catalogClient.CatalogClient({ discoveryApi: discovery });
2687
2709
  const secret = config.getOptionalString("auth.session.secret");
2688
2710
  if (secret) {
2689
- router.use(cookieParser__default['default'](secret));
2690
- router.use(session__default['default']({secret, saveUninitialized: false, resave: false}));
2691
- router.use(passport__default['default'].initialize());
2692
- 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());
2693
2715
  } else {
2694
- router.use(cookieParser__default['default']());
2716
+ router.use(cookieParser__default["default"]());
2695
2717
  }
2696
- router.use(express__default['default'].urlencoded({extended: false}));
2697
- router.use(express__default['default'].json());
2718
+ router.use(express__default["default"].urlencoded({ extended: false }));
2719
+ router.use(express__default["default"].json());
2698
2720
  const allProviderFactories = {
2699
2721
  ...factories,
2700
2722
  ...providerFactories
@@ -2708,14 +2730,14 @@ async function createRouter({
2708
2730
  try {
2709
2731
  const provider = providerFactory({
2710
2732
  providerId,
2711
- globalConfig: {baseUrl: authUrl, appUrl, isOriginAllowed},
2733
+ globalConfig: { baseUrl: authUrl, appUrl, isOriginAllowed },
2712
2734
  config: providersConfig.getConfig(providerId),
2713
2735
  logger,
2714
2736
  tokenIssuer,
2715
2737
  discovery,
2716
2738
  catalogApi
2717
2739
  });
2718
- const r = Router__default['default']();
2740
+ const r = Router__default["default"]();
2719
2741
  r.get("/start", provider.start.bind(provider));
2720
2742
  r.get("/handler/frame", provider.frameHandler.bind(provider));
2721
2743
  r.post("/handler/frame", provider.frameHandler.bind(provider));
@@ -2747,7 +2769,7 @@ async function createRouter({
2747
2769
  baseUrl: authUrl
2748
2770
  }));
2749
2771
  router.use("/:provider/", (req) => {
2750
- const {provider} = req.params;
2772
+ const { provider } = req.params;
2751
2773
  throw new errors.NotFoundError(`Unknown auth provider '${provider}'`);
2752
2774
  });
2753
2775
  return router;
@@ -2755,9 +2777,9 @@ async function createRouter({
2755
2777
  function createOriginFilter(config) {
2756
2778
  var _a;
2757
2779
  const appUrl = config.getString("app.baseUrl");
2758
- const {origin: appOrigin} = new URL(appUrl);
2780
+ const { origin: appOrigin } = new URL(appUrl);
2759
2781
  const allowedOrigins = config.getOptionalStringArray("auth.experimentalExtraAllowedOrigins");
2760
- 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 : [];
2761
2783
  return (origin) => {
2762
2784
  if (origin === appOrigin) {
2763
2785
  return true;
@@ -2793,6 +2815,7 @@ exports.googleEmailSignInResolver = googleEmailSignInResolver;
2793
2815
  exports.microsoftEmailSignInResolver = microsoftEmailSignInResolver;
2794
2816
  exports.oktaEmailSignInResolver = oktaEmailSignInResolver;
2795
2817
  exports.postMessageResponse = postMessageResponse;
2818
+ exports.prepareBackstageIdentityResponse = prepareBackstageIdentityResponse;
2796
2819
  exports.readState = readState;
2797
2820
  exports.verifyNonce = verifyNonce;
2798
2821
  //# sourceMappingURL=index.cjs.js.map