@backstage/plugin-auth-backend 0.22.4-next.1 → 0.22.5-next.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
@@ -15,8 +15,8 @@ var url = require('url');
15
15
  var errors = require('@backstage/errors');
16
16
  var jose = require('jose');
17
17
  var pluginAuthBackendModuleAwsAlbProvider = require('@backstage/plugin-auth-backend-module-aws-alb-provider');
18
- var passportBitbucketOauth2 = require('passport-bitbucket-oauth2');
19
- var fetch = require('node-fetch');
18
+ var pluginAuthBackendModuleBitbucketProvider = require('@backstage/plugin-auth-backend-module-bitbucket-provider');
19
+ var pluginAuthBackendModuleCloudflareAccessProvider = require('@backstage/plugin-auth-backend-module-cloudflare-access-provider');
20
20
  var pluginAuthBackendModuleGcpIapProvider = require('@backstage/plugin-auth-backend-module-gcp-iap-provider');
21
21
  var pluginAuthBackendModuleGithubProvider = require('@backstage/plugin-auth-backend-module-github-provider');
22
22
  var pluginAuthBackendModuleGitlabProvider = require('@backstage/plugin-auth-backend-module-gitlab-provider');
@@ -29,6 +29,8 @@ var pluginAuthBackendModuleOktaProvider = require('@backstage/plugin-auth-backen
29
29
  var passportOneloginOauth = require('passport-onelogin-oauth');
30
30
  var passportSaml = require('@node-saml/passport-saml');
31
31
  var passportOauth2 = require('passport-oauth2');
32
+ var fetch = require('node-fetch');
33
+ var pluginAuthBackendModuleAzureEasyauthProvider = require('@backstage/plugin-auth-backend-module-azure-easyauth-provider');
32
34
  var catalogClient = require('@backstage/catalog-client');
33
35
  var minimatch = require('minimatch');
34
36
  var catalogModel = require('@backstage/catalog-model');
@@ -219,10 +221,10 @@ const ensuresXRequestedWith = (req) => {
219
221
 
220
222
  const prepareBackstageIdentityResponse = pluginAuthNode.prepareBackstageIdentityResponse;
221
223
 
222
- var __defProp$c = Object.defineProperty;
223
- var __defNormalProp$c = (obj, key, value) => key in obj ? __defProp$c(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
224
- var __publicField$c = (obj, key, value) => {
225
- __defNormalProp$c(obj, typeof key !== "symbol" ? key + "" : key, value);
224
+ var __defProp$9 = Object.defineProperty;
225
+ var __defNormalProp$9 = (obj, key, value) => key in obj ? __defProp$9(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
226
+ var __publicField$9 = (obj, key, value) => {
227
+ __defNormalProp$9(obj, typeof key !== "symbol" ? key + "" : key, value);
226
228
  return value;
227
229
  };
228
230
  const THOUSAND_DAYS_MS = 1e3 * 24 * 60 * 60 * 1e3;
@@ -231,8 +233,8 @@ class OAuthAdapter {
231
233
  constructor(handlers, options) {
232
234
  this.handlers = handlers;
233
235
  this.options = options;
234
- __publicField$c(this, "baseCookieOptions");
235
- __publicField$c(this, "setNonceCookie", (res, nonce, cookieConfig) => {
236
+ __publicField$9(this, "baseCookieOptions");
237
+ __publicField$9(this, "setNonceCookie", (res, nonce, cookieConfig) => {
236
238
  res.cookie(`${this.options.providerId}-nonce`, nonce, {
237
239
  maxAge: TEN_MINUTES_MS,
238
240
  ...this.baseCookieOptions,
@@ -240,34 +242,34 @@ class OAuthAdapter {
240
242
  path: `${cookieConfig.path}/handler`
241
243
  });
242
244
  });
243
- __publicField$c(this, "setGrantedScopeCookie", (res, scope, cookieConfig) => {
245
+ __publicField$9(this, "setGrantedScopeCookie", (res, scope, cookieConfig) => {
244
246
  res.cookie(`${this.options.providerId}-granted-scope`, scope, {
245
247
  maxAge: THOUSAND_DAYS_MS,
246
248
  ...this.baseCookieOptions,
247
249
  ...cookieConfig
248
250
  });
249
251
  });
250
- __publicField$c(this, "getRefreshTokenFromCookie", (req) => {
252
+ __publicField$9(this, "getRefreshTokenFromCookie", (req) => {
251
253
  return req.cookies[`${this.options.providerId}-refresh-token`];
252
254
  });
253
- __publicField$c(this, "getGrantedScopeFromCookie", (req) => {
255
+ __publicField$9(this, "getGrantedScopeFromCookie", (req) => {
254
256
  return req.cookies[`${this.options.providerId}-granted-scope`];
255
257
  });
256
- __publicField$c(this, "setRefreshTokenCookie", (res, refreshToken, cookieConfig) => {
258
+ __publicField$9(this, "setRefreshTokenCookie", (res, refreshToken, cookieConfig) => {
257
259
  res.cookie(`${this.options.providerId}-refresh-token`, refreshToken, {
258
260
  maxAge: THOUSAND_DAYS_MS,
259
261
  ...this.baseCookieOptions,
260
262
  ...cookieConfig
261
263
  });
262
264
  });
263
- __publicField$c(this, "removeRefreshTokenCookie", (res, cookieConfig) => {
265
+ __publicField$9(this, "removeRefreshTokenCookie", (res, cookieConfig) => {
264
266
  res.cookie(`${this.options.providerId}-refresh-token`, "", {
265
267
  maxAge: 0,
266
268
  ...this.baseCookieOptions,
267
269
  ...cookieConfig
268
270
  });
269
271
  });
270
- __publicField$c(this, "getCookieConfig", (origin) => {
272
+ __publicField$9(this, "getCookieConfig", (origin) => {
271
273
  return this.options.cookieConfigurer({
272
274
  providerId: this.options.providerId,
273
275
  baseUrl: this.options.baseUrl,
@@ -565,21 +567,21 @@ const executeFetchUserProfileStrategy = async (providerStrategy, accessToken) =>
565
567
  });
566
568
  };
567
569
 
568
- var __defProp$b = Object.defineProperty;
569
- var __defNormalProp$b = (obj, key, value) => key in obj ? __defProp$b(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
570
- var __publicField$b = (obj, key, value) => {
571
- __defNormalProp$b(obj, typeof key !== "symbol" ? key + "" : key, value);
570
+ var __defProp$8 = Object.defineProperty;
571
+ var __defNormalProp$8 = (obj, key, value) => key in obj ? __defProp$8(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
572
+ var __publicField$8 = (obj, key, value) => {
573
+ __defNormalProp$8(obj, typeof key !== "symbol" ? key + "" : key, value);
572
574
  return value;
573
575
  };
574
576
  class Auth0AuthProvider {
575
577
  constructor(options) {
576
- __publicField$b(this, "_strategy");
577
- __publicField$b(this, "signInResolver");
578
- __publicField$b(this, "authHandler");
579
- __publicField$b(this, "resolverContext");
580
- __publicField$b(this, "audience");
581
- __publicField$b(this, "connection");
582
- __publicField$b(this, "connectionScope");
578
+ __publicField$8(this, "_strategy");
579
+ __publicField$8(this, "signInResolver");
580
+ __publicField$8(this, "authHandler");
581
+ __publicField$8(this, "resolverContext");
582
+ __publicField$8(this, "audience");
583
+ __publicField$8(this, "connection");
584
+ __publicField$8(this, "connectionScope");
583
585
  /**
584
586
  * Due to passport-auth0 forcing options.state = true,
585
587
  * passport-oauth2 requires express-session to be installed
@@ -588,7 +590,7 @@ class Auth0AuthProvider {
588
590
  * passport-oauth2, which is the StateStore implementation used when options.state = false,
589
591
  * allowing us to avoid using express-session in order to integrate with auth0.
590
592
  */
591
- __publicField$b(this, "store", {
593
+ __publicField$8(this, "store", {
592
594
  store(_req, cb) {
593
595
  cb(null, null);
594
596
  },
@@ -740,370 +742,34 @@ const awsAlb = createAuthProviderIntegration({
740
742
  }
741
743
  });
742
744
 
743
- var __defProp$a = Object.defineProperty;
744
- var __defNormalProp$a = (obj, key, value) => key in obj ? __defProp$a(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
745
- var __publicField$a = (obj, key, value) => {
746
- __defNormalProp$a(obj, typeof key !== "symbol" ? key + "" : key, value);
747
- return value;
748
- };
749
- class BitbucketAuthProvider {
750
- constructor(options) {
751
- __publicField$a(this, "_strategy");
752
- __publicField$a(this, "signInResolver");
753
- __publicField$a(this, "authHandler");
754
- __publicField$a(this, "resolverContext");
755
- this.signInResolver = options.signInResolver;
756
- this.authHandler = options.authHandler;
757
- this.resolverContext = options.resolverContext;
758
- this._strategy = new passportBitbucketOauth2.Strategy(
759
- {
760
- clientID: options.clientId,
761
- clientSecret: options.clientSecret,
762
- callbackURL: options.callbackUrl,
763
- passReqToCallback: false
764
- },
765
- (accessToken, refreshToken, params, fullProfile, done) => {
766
- done(
767
- void 0,
768
- {
769
- fullProfile,
770
- params,
771
- accessToken,
772
- refreshToken
773
- },
774
- {
775
- refreshToken
776
- }
777
- );
778
- }
779
- );
780
- }
781
- async start(req) {
782
- return await executeRedirectStrategy(req, this._strategy, {
783
- accessType: "offline",
784
- prompt: "consent",
785
- scope: req.scope,
786
- state: encodeState(req.state)
787
- });
788
- }
789
- async handler(req) {
790
- const { result, privateInfo } = await executeFrameHandlerStrategy(req, this._strategy);
791
- return {
792
- response: await this.handleResult(result),
793
- refreshToken: privateInfo.refreshToken
794
- };
795
- }
796
- async refresh(req) {
797
- const { accessToken, refreshToken, params } = await executeRefreshTokenStrategy(
798
- this._strategy,
799
- req.refreshToken,
800
- req.scope
801
- );
802
- const fullProfile = await executeFetchUserProfileStrategy(
803
- this._strategy,
804
- accessToken
805
- );
806
- return {
807
- response: await this.handleResult({
808
- fullProfile,
809
- params,
810
- accessToken
811
- }),
812
- refreshToken
813
- };
814
- }
815
- async handleResult(result) {
816
- result.fullProfile.avatarUrl = result.fullProfile._json.links.avatar.href;
817
- const { profile } = await this.authHandler(result, this.resolverContext);
818
- const response = {
819
- providerInfo: {
820
- idToken: result.params.id_token,
821
- accessToken: result.accessToken,
822
- scope: result.params.scope,
823
- expiresInSeconds: result.params.expires_in
824
- },
825
- profile
826
- };
827
- if (this.signInResolver) {
828
- response.backstageIdentity = await this.signInResolver(
829
- {
830
- result,
831
- profile
832
- },
833
- this.resolverContext
834
- );
835
- }
836
- return response;
837
- }
838
- }
839
745
  const bitbucket = createAuthProviderIntegration({
840
746
  create(options) {
841
- return ({ providerId, globalConfig, config, resolverContext }) => OAuthEnvironmentHandler.mapConfig(config, (envConfig) => {
842
- var _a;
843
- const clientId = envConfig.getString("clientId");
844
- const clientSecret = envConfig.getString("clientSecret");
845
- const customCallbackUrl = envConfig.getOptionalString("callbackUrl");
846
- const callbackUrl = customCallbackUrl || `${globalConfig.baseUrl}/${providerId}/handler/frame`;
847
- const authHandler = (options == null ? void 0 : options.authHandler) ? options.authHandler : async ({ fullProfile, params }) => ({
848
- profile: makeProfileInfo(fullProfile, params.id_token)
849
- });
850
- const provider = new BitbucketAuthProvider({
851
- clientId,
852
- clientSecret,
853
- callbackUrl,
854
- signInResolver: (_a = options == null ? void 0 : options.signIn) == null ? void 0 : _a.resolver,
855
- authHandler,
856
- resolverContext
857
- });
858
- return OAuthAdapter.fromConfig(globalConfig, provider, {
859
- providerId,
860
- callbackUrl
861
- });
747
+ var _a;
748
+ return pluginAuthNode.createOAuthProviderFactory({
749
+ authenticator: pluginAuthBackendModuleBitbucketProvider.bitbucketAuthenticator,
750
+ profileTransform: adaptLegacyOAuthHandler(options == null ? void 0 : options.authHandler),
751
+ signInResolver: adaptLegacyOAuthSignInResolver((_a = options == null ? void 0 : options.signIn) == null ? void 0 : _a.resolver)
862
752
  });
863
753
  },
864
- resolvers: {
865
- /**
866
- * Looks up the user by matching their username to the `bitbucket.org/username` annotation.
867
- */
868
- usernameMatchingUserEntityAnnotation() {
869
- return async (info, ctx) => {
870
- const { result } = info;
871
- if (!result.fullProfile.username) {
872
- throw new Error("Bitbucket profile contained no Username");
873
- }
874
- return ctx.signInWithCatalogUser({
875
- annotations: {
876
- "bitbucket.org/username": result.fullProfile.username
877
- }
878
- });
879
- };
880
- },
881
- /**
882
- * Looks up the user by matching their user ID to the `bitbucket.org/user-id` annotation.
883
- */
884
- userIdMatchingUserEntityAnnotation() {
885
- return async (info, ctx) => {
886
- const { result } = info;
887
- if (!result.fullProfile.id) {
888
- throw new Error("Bitbucket profile contained no User ID");
889
- }
890
- return ctx.signInWithCatalogUser({
891
- annotations: {
892
- "bitbucket.org/user-id": result.fullProfile.id
893
- }
894
- });
895
- };
896
- }
897
- }
754
+ resolvers: adaptOAuthSignInResolverToLegacy({
755
+ userIdMatchingUserEntityAnnotation: pluginAuthBackendModuleBitbucketProvider.bitbucketSignInResolvers.userIdMatchingUserEntityAnnotation(),
756
+ usernameMatchingUserEntityAnnotation: pluginAuthBackendModuleBitbucketProvider.bitbucketSignInResolvers.usernameMatchingUserEntityAnnotation()
757
+ })
898
758
  });
899
759
 
900
- const commonByEmailLocalPartResolver = async (info, ctx) => {
901
- const { profile } = info;
902
- if (!profile.email) {
903
- throw new Error("Login failed, user profile does not contain an email");
904
- }
905
- const [localPart] = profile.email.split("@");
906
- return ctx.signInWithCatalogUser({
907
- entityRef: { name: localPart }
908
- });
909
- };
910
- const commonByEmailResolver = async (info, ctx) => {
911
- const { profile } = info;
912
- if (!profile.email) {
913
- throw new Error("Login failed, user profile does not contain an email");
914
- }
915
- return ctx.signInWithCatalogUser({
916
- filter: {
917
- "spec.profile.email": profile.email
918
- }
919
- });
920
- };
921
-
922
- var __defProp$9 = Object.defineProperty;
923
- var __defNormalProp$9 = (obj, key, value) => key in obj ? __defProp$9(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
924
- var __publicField$9 = (obj, key, value) => {
925
- __defNormalProp$9(obj, typeof key !== "symbol" ? key + "" : key, value);
926
- return value;
927
- };
928
- const CF_JWT_HEADER = "cf-access-jwt-assertion";
929
- const COOKIE_AUTH_NAME = "CF_Authorization";
930
- const CACHE_PREFIX = "providers/cloudflare-access/profile-v1";
931
- class CloudflareAccessAuthProvider {
932
- constructor(options) {
933
- __publicField$9(this, "teamName");
934
- __publicField$9(this, "serviceTokens");
935
- __publicField$9(this, "resolverContext");
936
- __publicField$9(this, "authHandler");
937
- __publicField$9(this, "signInResolver");
938
- __publicField$9(this, "jwtKeySet");
939
- __publicField$9(this, "cache");
940
- this.teamName = options.teamName;
941
- this.serviceTokens = options.serviceTokens;
942
- this.authHandler = options.authHandler;
943
- this.signInResolver = options.signInResolver;
944
- this.resolverContext = options.resolverContext;
945
- this.jwtKeySet = jose.createRemoteJWKSet(
946
- new URL(
947
- `https://${this.teamName}.cloudflareaccess.com/cdn-cgi/access/certs`
948
- )
949
- );
950
- this.cache = options.cache;
951
- }
952
- frameHandler() {
953
- return Promise.resolve();
954
- }
955
- async refresh(req, res) {
956
- const result = await this.getResult(req);
957
- const response = await this.handleResult(result);
958
- res.json(response);
959
- }
960
- start() {
961
- return Promise.resolve();
962
- }
963
- async getIdentityProfile(jwt) {
964
- const headers = new fetch.Headers();
965
- headers.set(CF_JWT_HEADER, jwt);
966
- headers.set("cookie", `${COOKIE_AUTH_NAME}=${jwt}`);
967
- try {
968
- const res = await fetch__default.default(
969
- `https://${this.teamName}.cloudflareaccess.com/cdn-cgi/access/get-identity`,
970
- { headers }
971
- );
972
- if (!res.ok) {
973
- throw await errors.ResponseError.fromResponse(res);
974
- }
975
- const cfIdentity = await res.json();
976
- return cfIdentity;
977
- } catch (err) {
978
- throw new errors.ForwardedError("getIdentityProfile failed", err);
979
- }
980
- }
981
- async getResult(req) {
982
- var _a, _b;
983
- let jwt = req.header(CF_JWT_HEADER);
984
- if (!jwt) {
985
- jwt = req.cookies.CF_Authorization;
986
- }
987
- if (!jwt) {
988
- throw new errors.AuthenticationError(
989
- `Missing ${CF_JWT_HEADER} from Cloudflare Access`
990
- );
991
- }
992
- const verifyResult = await jose.jwtVerify(jwt, this.jwtKeySet, {
993
- issuer: `https://${this.teamName}.cloudflareaccess.com`
994
- });
995
- const isServiceToken = !verifyResult.payload.sub;
996
- const subject = isServiceToken ? verifyResult.payload.common_name : verifyResult.payload.sub;
997
- if (!subject) {
998
- throw new errors.AuthenticationError(
999
- `Missing both sub and common_name from Cloudflare Access JWT`
1000
- );
1001
- }
1002
- const serviceToken = this.serviceTokens.find((st) => st.token === subject);
1003
- if (isServiceToken && !serviceToken) {
1004
- throw new errors.AuthenticationError(
1005
- `${subject} is not a permitted Service Token.`
1006
- );
1007
- }
1008
- const cacheKey = `${CACHE_PREFIX}/${subject}`;
1009
- const cfAccessResultStr = await ((_a = this.cache) == null ? void 0 : _a.get(cacheKey));
1010
- if (typeof cfAccessResultStr === "string") {
1011
- const result = JSON.parse(cfAccessResultStr);
1012
- return {
1013
- ...result,
1014
- token: jwt
1015
- };
1016
- }
1017
- const claims = verifyResult.payload;
1018
- try {
1019
- let cfIdentity;
1020
- if (serviceToken) {
1021
- cfIdentity = {
1022
- id: subject,
1023
- name: "Bot",
1024
- email: serviceToken.subject,
1025
- groups: []
1026
- };
1027
- } else {
1028
- cfIdentity = await this.getIdentityProfile(jwt);
1029
- }
1030
- const cfAccessResult = {
1031
- claims,
1032
- cfIdentity,
1033
- expiresInSeconds: claims.exp - claims.iat
1034
- };
1035
- (_b = this.cache) == null ? void 0 : _b.set(cacheKey, JSON.stringify(cfAccessResult));
1036
- return {
1037
- ...cfAccessResult,
1038
- token: jwt
1039
- };
1040
- } catch (err) {
1041
- throw new errors.ForwardedError(
1042
- "Failed to populate access identity information",
1043
- err
1044
- );
1045
- }
1046
- }
1047
- async handleResult(result) {
1048
- const { profile } = await this.authHandler(result, this.resolverContext);
1049
- const backstageIdentity = await this.signInResolver(
1050
- {
1051
- result,
1052
- profile
1053
- },
1054
- this.resolverContext
1055
- );
1056
- return {
1057
- providerInfo: {
1058
- expiresInSeconds: result.expiresInSeconds,
1059
- claims: result.claims,
1060
- cfAccessIdentityProfile: result.cfIdentity
1061
- },
1062
- backstageIdentity: prepareBackstageIdentityResponse(backstageIdentity),
1063
- profile
1064
- };
1065
- }
1066
- }
1067
760
  const cfAccess = createAuthProviderIntegration({
1068
761
  create(options) {
1069
- return ({ config, resolverContext }) => {
1070
- const teamName = config.getString("teamName");
1071
- const serviceTokensConfig = config.getOptionalConfigArray("serviceTokens");
1072
- const serviceTokens = (serviceTokensConfig == null ? void 0 : serviceTokensConfig.map((cfg) => {
1073
- return {
1074
- token: cfg.getString("token"),
1075
- subject: cfg.getString("subject")
1076
- };
1077
- })) || [];
1078
- if (!options.signIn.resolver) {
1079
- throw new Error(
1080
- "SignInResolver is required to use this authentication provider"
1081
- );
1082
- }
1083
- const authHandler = (options == null ? void 0 : options.authHandler) ? options.authHandler : async ({ claims, cfIdentity }) => {
1084
- return {
1085
- profile: {
1086
- email: claims.email,
1087
- displayName: cfIdentity.name
1088
- }
1089
- };
1090
- };
1091
- return new CloudflareAccessAuthProvider({
1092
- teamName,
1093
- serviceTokens,
1094
- signInResolver: options == null ? void 0 : options.signIn.resolver,
1095
- authHandler,
1096
- resolverContext,
1097
- ...options.cache && { cache: options.cache }
1098
- });
1099
- };
762
+ var _a;
763
+ return pluginAuthNode.createProxyAuthProviderFactory({
764
+ authenticator: pluginAuthBackendModuleCloudflareAccessProvider.createCloudflareAccessAuthenticator({
765
+ cache: options.cache
766
+ }),
767
+ profileTransform: options == null ? void 0 : options.authHandler,
768
+ signInResolver: (_a = options == null ? void 0 : options.signIn) == null ? void 0 : _a.resolver,
769
+ signInResolverFactories: pluginAuthBackendModuleCloudflareAccessProvider.cloudflareAccessSignInResolvers
770
+ });
1100
771
  },
1101
- resolvers: {
1102
- /**
1103
- * Looks up the user by matching their email to the entity email.
1104
- */
1105
- emailMatchingUserEntityProfileEmail: () => commonByEmailResolver
1106
- }
772
+ resolvers: pluginAuthBackendModuleCloudflareAccessProvider.cloudflareAccessSignInResolvers
1107
773
  });
1108
774
 
1109
775
  const gcpIap = createAuthProviderIntegration({
@@ -1236,6 +902,28 @@ const oauth2Proxy = createAuthProviderIntegration({
1236
902
  }
1237
903
  });
1238
904
 
905
+ const commonByEmailLocalPartResolver = async (info, ctx) => {
906
+ const { profile } = info;
907
+ if (!profile.email) {
908
+ throw new Error("Login failed, user profile does not contain an email");
909
+ }
910
+ const [localPart] = profile.email.split("@");
911
+ return ctx.signInWithCatalogUser({
912
+ entityRef: { name: localPart }
913
+ });
914
+ };
915
+ const commonByEmailResolver = async (info, ctx) => {
916
+ const { profile } = info;
917
+ if (!profile.email) {
918
+ throw new Error("Login failed, user profile does not contain an email");
919
+ }
920
+ return ctx.signInWithCatalogUser({
921
+ filter: {
922
+ "spec.profile.email": profile.email
923
+ }
924
+ });
925
+ };
926
+
1239
927
  const oidc = createAuthProviderIntegration({
1240
928
  create(options) {
1241
929
  var _a;
@@ -1302,18 +990,18 @@ const okta = createAuthProviderIntegration({
1302
990
  }
1303
991
  });
1304
992
 
1305
- var __defProp$8 = Object.defineProperty;
1306
- var __defNormalProp$8 = (obj, key, value) => key in obj ? __defProp$8(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
1307
- var __publicField$8 = (obj, key, value) => {
1308
- __defNormalProp$8(obj, typeof key !== "symbol" ? key + "" : key, value);
993
+ var __defProp$7 = Object.defineProperty;
994
+ var __defNormalProp$7 = (obj, key, value) => key in obj ? __defProp$7(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
995
+ var __publicField$7 = (obj, key, value) => {
996
+ __defNormalProp$7(obj, typeof key !== "symbol" ? key + "" : key, value);
1309
997
  return value;
1310
998
  };
1311
999
  class OneLoginProvider {
1312
1000
  constructor(options) {
1313
- __publicField$8(this, "_strategy");
1314
- __publicField$8(this, "signInResolver");
1315
- __publicField$8(this, "authHandler");
1316
- __publicField$8(this, "resolverContext");
1001
+ __publicField$7(this, "_strategy");
1002
+ __publicField$7(this, "signInResolver");
1003
+ __publicField$7(this, "authHandler");
1004
+ __publicField$7(this, "resolverContext");
1317
1005
  this.signInResolver = options.signInResolver;
1318
1006
  this.authHandler = options.authHandler;
1319
1007
  this.resolverContext = options.resolverContext;
@@ -1427,19 +1115,19 @@ const onelogin = createAuthProviderIntegration({
1427
1115
  }
1428
1116
  });
1429
1117
 
1430
- var __defProp$7 = Object.defineProperty;
1431
- var __defNormalProp$7 = (obj, key, value) => key in obj ? __defProp$7(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
1432
- var __publicField$7 = (obj, key, value) => {
1433
- __defNormalProp$7(obj, typeof key !== "symbol" ? key + "" : key, value);
1118
+ var __defProp$6 = Object.defineProperty;
1119
+ var __defNormalProp$6 = (obj, key, value) => key in obj ? __defProp$6(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
1120
+ var __publicField$6 = (obj, key, value) => {
1121
+ __defNormalProp$6(obj, typeof key !== "symbol" ? key + "" : key, value);
1434
1122
  return value;
1435
1123
  };
1436
1124
  class SamlAuthProvider {
1437
1125
  constructor(options) {
1438
- __publicField$7(this, "strategy");
1439
- __publicField$7(this, "signInResolver");
1440
- __publicField$7(this, "authHandler");
1441
- __publicField$7(this, "resolverContext");
1442
- __publicField$7(this, "appUrl");
1126
+ __publicField$6(this, "strategy");
1127
+ __publicField$6(this, "signInResolver");
1128
+ __publicField$6(this, "authHandler");
1129
+ __publicField$6(this, "resolverContext");
1130
+ __publicField$6(this, "appUrl");
1443
1131
  this.appUrl = options.appUrl;
1444
1132
  this.signInResolver = options.signInResolver;
1445
1133
  this.authHandler = options.authHandler;
@@ -1543,19 +1231,19 @@ const saml = createAuthProviderIntegration({
1543
1231
  }
1544
1232
  });
1545
1233
 
1546
- var __defProp$6 = Object.defineProperty;
1547
- var __defNormalProp$6 = (obj, key, value) => key in obj ? __defProp$6(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
1548
- var __publicField$6 = (obj, key, value) => {
1549
- __defNormalProp$6(obj, typeof key !== "symbol" ? key + "" : key, value);
1234
+ var __defProp$5 = Object.defineProperty;
1235
+ var __defNormalProp$5 = (obj, key, value) => key in obj ? __defProp$5(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
1236
+ var __publicField$5 = (obj, key, value) => {
1237
+ __defNormalProp$5(obj, typeof key !== "symbol" ? key + "" : key, value);
1550
1238
  return value;
1551
1239
  };
1552
1240
  class BitbucketServerAuthProvider {
1553
1241
  constructor(options) {
1554
- __publicField$6(this, "signInResolver");
1555
- __publicField$6(this, "authHandler");
1556
- __publicField$6(this, "resolverContext");
1557
- __publicField$6(this, "strategy");
1558
- __publicField$6(this, "host");
1242
+ __publicField$5(this, "signInResolver");
1243
+ __publicField$5(this, "authHandler");
1244
+ __publicField$5(this, "resolverContext");
1245
+ __publicField$5(this, "strategy");
1246
+ __publicField$5(this, "host");
1559
1247
  this.signInResolver = options.signInResolver;
1560
1248
  this.authHandler = options.authHandler;
1561
1249
  this.resolverContext = options.resolverContext;
@@ -1720,112 +1408,16 @@ const bitbucketServer = createAuthProviderIntegration({
1720
1408
  }
1721
1409
  });
1722
1410
 
1723
- var __defProp$5 = Object.defineProperty;
1724
- var __defNormalProp$5 = (obj, key, value) => key in obj ? __defProp$5(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
1725
- var __publicField$5 = (obj, key, value) => {
1726
- __defNormalProp$5(obj, typeof key !== "symbol" ? key + "" : key, value);
1727
- return value;
1728
- };
1729
- const ID_TOKEN_HEADER = "x-ms-token-aad-id-token";
1730
- const ACCESS_TOKEN_HEADER = "x-ms-token-aad-access-token";
1731
- class EasyAuthAuthProvider {
1732
- constructor(options) {
1733
- __publicField$5(this, "resolverContext");
1734
- __publicField$5(this, "authHandler");
1735
- __publicField$5(this, "signInResolver");
1736
- this.authHandler = options.authHandler;
1737
- this.signInResolver = options.signInResolver;
1738
- this.resolverContext = options.resolverContext;
1739
- }
1740
- frameHandler() {
1741
- return Promise.resolve(void 0);
1742
- }
1743
- async refresh(req, res) {
1744
- const result = await this.getResult(req);
1745
- const response = await this.handleResult(result);
1746
- res.json(response);
1747
- }
1748
- start() {
1749
- return Promise.resolve(void 0);
1750
- }
1751
- async getResult(req) {
1752
- const idToken = req.header(ID_TOKEN_HEADER);
1753
- const accessToken = req.header(ACCESS_TOKEN_HEADER);
1754
- if (idToken === void 0) {
1755
- throw new errors.AuthenticationError(`Missing ${ID_TOKEN_HEADER} header`);
1756
- }
1757
- return {
1758
- fullProfile: this.idTokenToProfile(idToken),
1759
- accessToken
1760
- };
1761
- }
1762
- idTokenToProfile(idToken) {
1763
- const claims = jose.decodeJwt(idToken);
1764
- if (claims.ver !== "2.0") {
1765
- throw new Error("id_token is not version 2.0 ");
1766
- }
1767
- return {
1768
- id: claims.oid,
1769
- displayName: claims.name,
1770
- provider: "easyauth",
1771
- emails: [{ value: claims.email }],
1772
- username: claims.preferred_username
1773
- };
1774
- }
1775
- async handleResult(result) {
1776
- const { profile } = await this.authHandler(result, this.resolverContext);
1777
- const backstageIdentity = await this.signInResolver(
1778
- {
1779
- result,
1780
- profile
1781
- },
1782
- this.resolverContext
1783
- );
1784
- return {
1785
- providerInfo: {
1786
- accessToken: result.accessToken
1787
- },
1788
- backstageIdentity: prepareBackstageIdentityResponse(backstageIdentity),
1789
- profile
1790
- };
1791
- }
1792
- }
1793
1411
  const easyAuth = createAuthProviderIntegration({
1794
1412
  create(options) {
1795
- return ({ resolverContext }) => {
1796
- var _a;
1797
- validateAppServiceConfiguration(process.env);
1798
- if ((options == null ? void 0 : options.signIn.resolver) === void 0) {
1799
- throw new Error(
1800
- "SignInResolver is required to use this authentication provider"
1801
- );
1802
- }
1803
- const authHandler = (_a = options.authHandler) != null ? _a : async ({ fullProfile }) => ({
1804
- profile: makeProfileInfo(fullProfile)
1805
- });
1806
- return new EasyAuthAuthProvider({
1807
- signInResolver: options.signIn.resolver,
1808
- authHandler,
1809
- resolverContext
1810
- });
1811
- };
1413
+ var _a;
1414
+ return pluginAuthNode.createProxyAuthProviderFactory({
1415
+ authenticator: pluginAuthBackendModuleAzureEasyauthProvider.azureEasyAuthAuthenticator,
1416
+ profileTransform: options == null ? void 0 : options.authHandler,
1417
+ signInResolver: (_a = options == null ? void 0 : options.signIn) == null ? void 0 : _a.resolver
1418
+ });
1812
1419
  }
1813
1420
  });
1814
- function validateAppServiceConfiguration(env) {
1815
- var _a, _b, _c;
1816
- if (env.WEBSITE_SKU === void 0) {
1817
- throw new Error("Backstage is not running on Azure App Services");
1818
- }
1819
- if (((_a = env.WEBSITE_AUTH_ENABLED) == null ? void 0 : _a.toLowerCase()) !== "true") {
1820
- throw new Error("Azure App Services does not have authentication enabled");
1821
- }
1822
- if (((_b = env.WEBSITE_AUTH_DEFAULT_PROVIDER) == null ? void 0 : _b.toLowerCase()) !== "azureactivedirectory") {
1823
- throw new Error("Authentication provider is not Entra ID");
1824
- }
1825
- if (((_c = process.env.WEBSITE_AUTH_TOKEN_STORE) == null ? void 0 : _c.toLowerCase()) !== "true") {
1826
- throw new Error("Token Store is not enabled");
1827
- }
1828
- }
1829
1421
 
1830
1422
  const providers = Object.freeze({
1831
1423
  atlassian,
@@ -1968,12 +1560,13 @@ function getDefaultOwnershipEntityRefs(entity) {
1968
1560
  return Array.from(/* @__PURE__ */ new Set([catalogModel.stringifyEntityRef(entity), ...membershipRefs]));
1969
1561
  }
1970
1562
  class CatalogAuthResolverContext {
1971
- constructor(logger, tokenIssuer, catalogIdentityClient, catalogApi, auth) {
1563
+ constructor(logger, tokenIssuer, catalogIdentityClient, catalogApi, auth, ownershipResolver) {
1972
1564
  this.logger = logger;
1973
1565
  this.tokenIssuer = tokenIssuer;
1974
1566
  this.catalogIdentityClient = catalogIdentityClient;
1975
1567
  this.catalogApi = catalogApi;
1976
1568
  this.auth = auth;
1569
+ this.ownershipResolver = ownershipResolver;
1977
1570
  }
1978
1571
  static create(options) {
1979
1572
  const catalogIdentityClient = new CatalogIdentityClient({
@@ -1988,7 +1581,8 @@ class CatalogAuthResolverContext {
1988
1581
  options.tokenIssuer,
1989
1582
  catalogIdentityClient,
1990
1583
  options.catalogApi,
1991
- options.auth
1584
+ options.auth,
1585
+ options.ownershipResolver
1992
1586
  );
1993
1587
  }
1994
1588
  async issueToken(params) {
@@ -2049,11 +1643,17 @@ class CatalogAuthResolverContext {
2049
1643
  }
2050
1644
  async signInWithCatalogUser(query) {
2051
1645
  const { entity } = await this.findCatalogUser(query);
2052
- const ownershipRefs = getDefaultOwnershipEntityRefs(entity);
1646
+ let ent;
1647
+ if (this.ownershipResolver) {
1648
+ const { ownershipEntityRefs } = await this.ownershipResolver.resolveOwnershipEntityRefs(entity);
1649
+ ent = ownershipEntityRefs;
1650
+ } else {
1651
+ ent = getDefaultOwnershipEntityRefs(entity);
1652
+ }
2053
1653
  const token = await this.tokenIssuer.issueToken({
2054
1654
  claims: {
2055
1655
  sub: catalogModel.stringifyEntityRef(entity),
2056
- ent: ownershipRefs
1656
+ ent
2057
1657
  }
2058
1658
  });
2059
1659
  return { token };
@@ -2072,7 +1672,8 @@ function bindProviderRouters(targetRouter, options) {
2072
1672
  httpAuth,
2073
1673
  tokenManager,
2074
1674
  tokenIssuer,
2075
- catalogApi
1675
+ catalogApi,
1676
+ ownershipResolver
2076
1677
  } = options;
2077
1678
  const providersConfig = config.getOptionalConfig("auth.providers");
2078
1679
  const isOriginAllowed = createOriginFilter(config);
@@ -2099,7 +1700,8 @@ function bindProviderRouters(targetRouter, options) {
2099
1700
  tokenManager,
2100
1701
  discovery,
2101
1702
  auth,
2102
- httpAuth
1703
+ httpAuth,
1704
+ ownershipResolver
2103
1705
  })
2104
1706
  });
2105
1707
  const r = Router__default.default();
@@ -2413,7 +2015,7 @@ class DatabaseKeyStore {
2413
2015
  var __defProp$2 = Object.defineProperty;
2414
2016
  var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
2415
2017
  var __publicField$2 = (obj, key, value) => {
2416
- __defNormalProp$2(obj, typeof key !== "symbol" ? key + "" : key, value);
2018
+ __defNormalProp$2(obj, key + "" , value);
2417
2019
  return value;
2418
2020
  };
2419
2021
  class MemoryKeyStore {
@@ -2665,7 +2267,7 @@ var __accessCheck = (obj, member, msg) => {
2665
2267
  };
2666
2268
  var __privateGet = (obj, member, getter) => {
2667
2269
  __accessCheck(obj, member, "read from private field");
2668
- return getter ? getter.call(obj) : member.get(obj);
2270
+ return member.get(obj);
2669
2271
  };
2670
2272
  var __privateAdd = (obj, member, value) => {
2671
2273
  if (member.has(obj))
@@ -2674,7 +2276,7 @@ var __privateAdd = (obj, member, value) => {
2674
2276
  };
2675
2277
  var __privateSet = (obj, member, value, setter) => {
2676
2278
  __accessCheck(obj, member, "write to private field");
2677
- setter ? setter.call(obj, value) : member.set(obj, value);
2279
+ member.set(obj, value);
2678
2280
  return value;
2679
2281
  };
2680
2282
  var _database, _promise;
@@ -2888,6 +2490,7 @@ const authPlugin = backendPluginApi.createBackendPlugin({
2888
2490
  pluginId: "auth",
2889
2491
  register(reg) {
2890
2492
  const providers = /* @__PURE__ */ new Map();
2493
+ let ownershipResolver = void 0;
2891
2494
  reg.registerExtensionPoint(pluginAuthNode.authProvidersExtensionPoint, {
2892
2495
  registerProvider({ providerId, factory }) {
2893
2496
  if (providers.has(providerId)) {
@@ -2898,6 +2501,14 @@ const authPlugin = backendPluginApi.createBackendPlugin({
2898
2501
  providers.set(providerId, factory);
2899
2502
  }
2900
2503
  });
2504
+ reg.registerExtensionPoint(pluginAuthNode.authOwnershipResolutionExtensionPoint, {
2505
+ setAuthOwnershipResolver(resolver) {
2506
+ if (ownershipResolver) {
2507
+ throw new Error("Auth ownership resolver is already set");
2508
+ }
2509
+ ownershipResolver = resolver;
2510
+ }
2511
+ });
2901
2512
  reg.registerInit({
2902
2513
  deps: {
2903
2514
  httpRouter: backendPluginApi.coreServices.httpRouter,
@@ -2931,7 +2542,8 @@ const authPlugin = backendPluginApi.createBackendPlugin({
2931
2542
  httpAuth,
2932
2543
  catalogApi,
2933
2544
  providerFactories: Object.fromEntries(providers),
2934
- disableDefaultProviderFactories: true
2545
+ disableDefaultProviderFactories: true,
2546
+ ownershipResolver
2935
2547
  });
2936
2548
  httpRouter.addAuthPolicy({
2937
2549
  path: "/",