@backstage/plugin-auth-backend 0.8.0 → 0.10.0-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
@@ -149,15 +149,14 @@ const verifyNonce = (req, providerId) => {
149
149
  throw new Error("Invalid nonce");
150
150
  }
151
151
  };
152
- const getCookieConfig = (authUrl, providerId) => {
153
- const { hostname: cookieDomain, pathname, protocol } = authUrl;
152
+ const defaultCookieConfigurer = ({
153
+ callbackUrl,
154
+ providerId
155
+ }) => {
156
+ const { hostname: domain, pathname, protocol } = new URL(callbackUrl);
154
157
  const secure = protocol === "https:";
155
- const cookiePath = pathname.endsWith(`${providerId}/handler/frame`) ? pathname.slice(0, -"/handler/frame".length) : `${pathname}/${providerId}`;
156
- return {
157
- cookieDomain,
158
- cookiePath,
159
- secure
160
- };
158
+ const path = pathname.endsWith(`${providerId}/handler/frame`) ? pathname.slice(0, -"/handler/frame".length) : `${pathname}/${providerId}`;
159
+ return { domain, path, secure };
161
160
  };
162
161
 
163
162
  class OAuthEnvironmentHandler {
@@ -281,58 +280,54 @@ class OAuthAdapter {
281
280
  this.setNonceCookie = (res, nonce) => {
282
281
  res.cookie(`${this.options.providerId}-nonce`, nonce, {
283
282
  maxAge: TEN_MINUTES_MS,
284
- secure: this.options.secure,
285
- sameSite: "lax",
286
- domain: this.options.cookieDomain,
287
- path: `${this.options.cookiePath}/handler`,
288
- httpOnly: true
283
+ ...this.baseCookieOptions,
284
+ path: `${this.options.cookiePath}/handler`
289
285
  });
290
286
  };
291
- this.setScopesCookie = (res, scope) => {
292
- res.cookie(`${this.options.providerId}-scope`, scope, {
293
- maxAge: TEN_MINUTES_MS,
294
- secure: this.options.secure,
295
- sameSite: "lax",
296
- domain: this.options.cookieDomain,
297
- path: `${this.options.cookiePath}/handler`,
298
- httpOnly: true
287
+ this.setGrantedScopeCookie = (res, scope) => {
288
+ res.cookie(`${this.options.providerId}-granted-scope`, scope, {
289
+ maxAge: THOUSAND_DAYS_MS,
290
+ ...this.baseCookieOptions
299
291
  });
300
292
  };
301
- this.getScopesFromCookie = (req, providerId) => {
302
- return req.cookies[`${providerId}-scope`];
293
+ this.getGrantedScopeFromCookie = (req) => {
294
+ return req.cookies[`${this.options.providerId}-granted-scope`];
303
295
  };
304
296
  this.setRefreshTokenCookie = (res, refreshToken) => {
305
297
  res.cookie(`${this.options.providerId}-refresh-token`, refreshToken, {
306
298
  maxAge: THOUSAND_DAYS_MS,
307
- secure: this.options.secure,
308
- sameSite: "lax",
309
- domain: this.options.cookieDomain,
310
- path: this.options.cookiePath,
311
- httpOnly: true
299
+ ...this.baseCookieOptions
312
300
  });
313
301
  };
314
302
  this.removeRefreshTokenCookie = (res) => {
315
303
  res.cookie(`${this.options.providerId}-refresh-token`, "", {
316
304
  maxAge: 0,
317
- secure: this.options.secure,
318
- sameSite: "lax",
319
- domain: this.options.cookieDomain,
320
- path: this.options.cookiePath,
321
- httpOnly: true
305
+ ...this.baseCookieOptions
322
306
  });
323
307
  };
308
+ this.baseCookieOptions = {
309
+ httpOnly: true,
310
+ sameSite: "lax",
311
+ secure: this.options.secure,
312
+ path: this.options.cookiePath,
313
+ domain: this.options.cookieDomain
314
+ };
324
315
  }
325
316
  static fromConfig(config, handlers, options) {
326
317
  var _a;
327
318
  const { origin: appOrigin } = new url.URL(config.appUrl);
328
- const authUrl = new url.URL((_a = options.callbackUrl) != null ? _a : config.baseUrl);
329
- const { cookieDomain, cookiePath, secure } = getCookieConfig(authUrl, options.providerId);
319
+ const cookieConfigurer = (_a = config.cookieConfigurer) != null ? _a : defaultCookieConfigurer;
320
+ const cookieConfig = cookieConfigurer({
321
+ providerId: options.providerId,
322
+ baseUrl: config.baseUrl,
323
+ callbackUrl: options.callbackUrl
324
+ });
330
325
  return new OAuthAdapter(handlers, {
331
326
  ...options,
332
327
  appOrigin,
333
- cookieDomain,
334
- cookiePath,
335
- secure,
328
+ cookieDomain: cookieConfig.domain,
329
+ cookiePath: cookieConfig.path,
330
+ secure: cookieConfig.secure,
336
331
  isOriginAllowed: config.isOriginAllowed
337
332
  });
338
333
  }
@@ -344,12 +339,12 @@ class OAuthAdapter {
344
339
  if (!env) {
345
340
  throw new errors.InputError("No env provided in request query parameters");
346
341
  }
347
- if (this.options.persistScopes) {
348
- this.setScopesCookie(res, scope);
349
- }
350
342
  const nonce = crypto__default["default"].randomBytes(16).toString("base64");
351
343
  this.setNonceCookie(res, nonce);
352
344
  const state = { nonce, env, origin };
345
+ if (this.options.persistScopes) {
346
+ state.scope = scope;
347
+ }
353
348
  const forwardReq = Object.assign(req, { scope, state });
354
349
  const { url, status } = await this.handlers.start(forwardReq);
355
350
  res.statusCode = status || 302;
@@ -374,9 +369,9 @@ class OAuthAdapter {
374
369
  }
375
370
  verifyNonce(req, this.options.providerId);
376
371
  const { response, refreshToken } = await this.handlers.handler(req);
377
- if (this.options.persistScopes) {
378
- const grantedScopes = this.getScopesFromCookie(req, this.options.providerId);
379
- response.providerInfo.scope = grantedScopes;
372
+ if (this.options.persistScopes && state.scope) {
373
+ this.setGrantedScopeCookie(res, state.scope);
374
+ response.providerInfo.scope = state.scope;
380
375
  }
381
376
  if (refreshToken && !this.options.disableRefresh) {
382
377
  this.setRefreshTokenCookie(res, refreshToken);
@@ -414,7 +409,10 @@ class OAuthAdapter {
414
409
  if (!refreshToken) {
415
410
  throw new errors.InputError("Missing session cookie");
416
411
  }
417
- const scope = (_b = (_a = req.query.scope) == null ? void 0 : _a.toString()) != null ? _b : "";
412
+ let scope = (_b = (_a = req.query.scope) == null ? void 0 : _a.toString()) != null ? _b : "";
413
+ if (this.options.persistScopes) {
414
+ scope = this.getGrantedScopeFromCookie(req);
415
+ }
418
416
  const forwardReq = Object.assign(req, { scope, refreshToken });
419
417
  const { response, refreshToken: newRefreshToken } = await this.handlers.refresh(forwardReq);
420
418
  const backstageIdentity = await this.populateIdentity(response.backstageIdentity);
@@ -560,7 +558,7 @@ const executeFetchUserProfileStrategy = async (providerStrategy, accessToken) =>
560
558
  class CatalogIdentityClient {
561
559
  constructor(options) {
562
560
  this.catalogApi = options.catalogApi;
563
- this.tokenIssuer = options.tokenIssuer;
561
+ this.tokenManager = options.tokenManager;
564
562
  }
565
563
  async findUser(query) {
566
564
  const filter = {
@@ -569,9 +567,7 @@ class CatalogIdentityClient {
569
567
  for (const [key, value] of Object.entries(query.annotations)) {
570
568
  filter[`metadata.annotations.${key}`] = value;
571
569
  }
572
- const token = await this.tokenIssuer.issueToken({
573
- claims: { sub: "backstage.io/auth-backend" }
574
- });
570
+ const { token } = await this.tokenManager.getToken();
575
571
  const { items } = await this.catalogApi.getEntities({ filter }, { token });
576
572
  if (items.length !== 1) {
577
573
  if (items.length > 1) {
@@ -601,7 +597,8 @@ class CatalogIdentityClient {
601
597
  "metadata.namespace": ref.namespace,
602
598
  "metadata.name": ref.name
603
599
  }));
604
- const entities = await this.catalogApi.getEntities({ filter }).then((r) => r.items);
600
+ const { token } = await this.tokenManager.getToken();
601
+ const entities = await this.catalogApi.getEntities({ filter }, { token }).then((r) => r.items);
605
602
  if (entityRefs.length !== entities.length) {
606
603
  const foundEntityNames = entities.map(catalogModel.stringifyEntityRef);
607
604
  const missingEntityNames = resolvedEntityRefs.map(catalogModel.stringifyEntityRef).filter((s) => !foundEntityNames.includes(s));
@@ -711,6 +708,7 @@ const createAtlassianProvider = (options) => {
711
708
  globalConfig,
712
709
  config,
713
710
  tokenIssuer,
711
+ tokenManager,
714
712
  catalogApi,
715
713
  logger
716
714
  }) => OAuthEnvironmentHandler.mapConfig(config, (envConfig) => {
@@ -718,10 +716,11 @@ const createAtlassianProvider = (options) => {
718
716
  const clientId = envConfig.getString("clientId");
719
717
  const clientSecret = envConfig.getString("clientSecret");
720
718
  const scopes = envConfig.getString("scopes");
721
- const callbackUrl = `${globalConfig.baseUrl}/${providerId}/handler/frame`;
719
+ const customCallbackUrl = envConfig.getOptionalString("callbackUrl");
720
+ const callbackUrl = customCallbackUrl || `${globalConfig.baseUrl}/${providerId}/handler/frame`;
722
721
  const catalogIdentityClient = new CatalogIdentityClient({
723
722
  catalogApi,
724
- tokenIssuer
723
+ tokenManager
725
724
  });
726
725
  const authHandler = (_a = options == null ? void 0 : options.authHandler) != null ? _a : atlassianDefaultAuthHandler;
727
726
  const provider = new AtlassianAuthProvider({
@@ -736,9 +735,9 @@ const createAtlassianProvider = (options) => {
736
735
  tokenIssuer
737
736
  });
738
737
  return OAuthAdapter.fromConfig(globalConfig, provider, {
739
- disableRefresh: true,
740
738
  providerId,
741
- tokenIssuer
739
+ tokenIssuer,
740
+ callbackUrl
742
741
  });
743
742
  });
744
743
  };
@@ -846,6 +845,7 @@ const createAuth0Provider = (options) => {
846
845
  globalConfig,
847
846
  config,
848
847
  tokenIssuer,
848
+ tokenManager,
849
849
  catalogApi,
850
850
  logger
851
851
  }) => OAuthEnvironmentHandler.mapConfig(config, (envConfig) => {
@@ -853,10 +853,11 @@ const createAuth0Provider = (options) => {
853
853
  const clientId = envConfig.getString("clientId");
854
854
  const clientSecret = envConfig.getString("clientSecret");
855
855
  const domain = envConfig.getString("domain");
856
- const callbackUrl = `${globalConfig.baseUrl}/${providerId}/handler/frame`;
856
+ const customCallbackUrl = envConfig.getOptionalString("callbackUrl");
857
+ const callbackUrl = customCallbackUrl || `${globalConfig.baseUrl}/${providerId}/handler/frame`;
857
858
  const catalogIdentityClient = new CatalogIdentityClient({
858
859
  catalogApi,
859
- tokenIssuer
860
+ tokenManager
860
861
  });
861
862
  const authHandler = (options == null ? void 0 : options.authHandler) ? options.authHandler : async ({ fullProfile, params }) => ({
862
863
  profile: makeProfileInfo(fullProfile, params.id_token)
@@ -876,7 +877,8 @@ const createAuth0Provider = (options) => {
876
877
  return OAuthAdapter.fromConfig(globalConfig, provider, {
877
878
  disableRefresh: true,
878
879
  providerId,
879
- tokenIssuer
880
+ tokenIssuer,
881
+ callbackUrl
880
882
  });
881
883
  });
882
884
  };
@@ -984,7 +986,7 @@ class AwsAlbAuthProvider {
984
986
  }
985
987
  }
986
988
  const createAwsAlbProvider = (options) => {
987
- return ({ config, tokenIssuer, catalogApi, logger }) => {
989
+ return ({ config, tokenIssuer, catalogApi, logger, tokenManager }) => {
988
990
  const region = config.getString("region");
989
991
  const issuer = config.getOptionalString("iss");
990
992
  if ((options == null ? void 0 : options.signIn.resolver) === void 0) {
@@ -992,7 +994,7 @@ const createAwsAlbProvider = (options) => {
992
994
  }
993
995
  const catalogIdentityClient = new CatalogIdentityClient({
994
996
  catalogApi,
995
- tokenIssuer
997
+ tokenManager
996
998
  });
997
999
  const authHandler = (options == null ? void 0 : options.authHandler) ? options.authHandler : async ({ fullProfile }) => ({
998
1000
  profile: makeProfileInfo(fullProfile)
@@ -1120,16 +1122,18 @@ const createBitbucketProvider = (options) => {
1120
1122
  globalConfig,
1121
1123
  config,
1122
1124
  tokenIssuer,
1125
+ tokenManager,
1123
1126
  catalogApi,
1124
1127
  logger
1125
1128
  }) => OAuthEnvironmentHandler.mapConfig(config, (envConfig) => {
1126
1129
  var _a;
1127
1130
  const clientId = envConfig.getString("clientId");
1128
1131
  const clientSecret = envConfig.getString("clientSecret");
1129
- const callbackUrl = `${globalConfig.baseUrl}/${providerId}/handler/frame`;
1132
+ const customCallbackUrl = envConfig.getOptionalString("callbackUrl");
1133
+ const callbackUrl = customCallbackUrl || `${globalConfig.baseUrl}/${providerId}/handler/frame`;
1130
1134
  const catalogIdentityClient = new CatalogIdentityClient({
1131
1135
  catalogApi,
1132
- tokenIssuer
1136
+ tokenManager
1133
1137
  });
1134
1138
  const authHandler = (options == null ? void 0 : options.authHandler) ? options.authHandler : async ({ fullProfile, params }) => ({
1135
1139
  profile: makeProfileInfo(fullProfile, params.id_token)
@@ -1147,11 +1151,14 @@ const createBitbucketProvider = (options) => {
1147
1151
  return OAuthAdapter.fromConfig(globalConfig, provider, {
1148
1152
  disableRefresh: false,
1149
1153
  providerId,
1150
- tokenIssuer
1154
+ tokenIssuer,
1155
+ callbackUrl
1151
1156
  });
1152
1157
  });
1153
1158
  };
1154
1159
 
1160
+ const ACCESS_TOKEN_PREFIX = "access-token.";
1161
+ const BACKSTAGE_SESSION_EXPIRATION = 3600;
1155
1162
  class GithubAuthProvider {
1156
1163
  constructor(options) {
1157
1164
  this.signInResolver = options.signInResolver;
@@ -1179,21 +1186,43 @@ class GithubAuthProvider {
1179
1186
  }
1180
1187
  async handler(req) {
1181
1188
  const { result, privateInfo } = await executeFrameHandlerStrategy(req, this._strategy);
1189
+ let refreshToken = privateInfo.refreshToken;
1190
+ if (!refreshToken && !result.params.expires_in) {
1191
+ refreshToken = ACCESS_TOKEN_PREFIX + result.accessToken;
1192
+ }
1182
1193
  return {
1183
1194
  response: await this.handleResult(result),
1184
- refreshToken: privateInfo.refreshToken
1195
+ refreshToken
1185
1196
  };
1186
1197
  }
1187
1198
  async refresh(req) {
1188
- const { accessToken, refreshToken, params } = await executeRefreshTokenStrategy(this._strategy, req.refreshToken, req.scope);
1189
- const fullProfile = await executeFetchUserProfileStrategy(this._strategy, accessToken);
1199
+ const { scope, refreshToken } = req;
1200
+ if (refreshToken == null ? void 0 : refreshToken.startsWith(ACCESS_TOKEN_PREFIX)) {
1201
+ const accessToken = refreshToken.slice(ACCESS_TOKEN_PREFIX.length);
1202
+ const fullProfile = await executeFetchUserProfileStrategy(this._strategy, accessToken).catch((error) => {
1203
+ var _a;
1204
+ if (((_a = error.oauthError) == null ? void 0 : _a.statusCode) === 401) {
1205
+ throw new Error("Invalid access token");
1206
+ }
1207
+ throw error;
1208
+ });
1209
+ return {
1210
+ response: await this.handleResult({
1211
+ fullProfile,
1212
+ params: { scope },
1213
+ accessToken
1214
+ }),
1215
+ refreshToken
1216
+ };
1217
+ }
1218
+ const result = await executeRefreshTokenStrategy(this._strategy, refreshToken, scope);
1190
1219
  return {
1191
1220
  response: await this.handleResult({
1192
- fullProfile,
1193
- params,
1194
- accessToken
1221
+ fullProfile: await executeFetchUserProfileStrategy(this._strategy, result.accessToken),
1222
+ params: { ...result.params, scope },
1223
+ accessToken: result.accessToken
1195
1224
  }),
1196
- refreshToken
1225
+ refreshToken: result.refreshToken
1197
1226
  };
1198
1227
  }
1199
1228
  async handleResult(result) {
@@ -1204,21 +1233,28 @@ class GithubAuthProvider {
1204
1233
  };
1205
1234
  const { profile } = await this.authHandler(result, context);
1206
1235
  const expiresInStr = result.params.expires_in;
1207
- const response = {
1236
+ let expiresInSeconds = expiresInStr === void 0 ? void 0 : Number(expiresInStr);
1237
+ let backstageIdentity = void 0;
1238
+ if (this.signInResolver) {
1239
+ backstageIdentity = await this.signInResolver({
1240
+ result,
1241
+ profile
1242
+ }, context);
1243
+ if (expiresInSeconds) {
1244
+ expiresInSeconds = Math.min(expiresInSeconds, BACKSTAGE_SESSION_EXPIRATION);
1245
+ } else {
1246
+ expiresInSeconds = BACKSTAGE_SESSION_EXPIRATION;
1247
+ }
1248
+ }
1249
+ return {
1250
+ backstageIdentity,
1208
1251
  providerInfo: {
1209
1252
  accessToken: result.accessToken,
1210
1253
  scope: result.params.scope,
1211
- expiresInSeconds: expiresInStr === void 0 ? void 0 : Number(expiresInStr)
1254
+ expiresInSeconds
1212
1255
  },
1213
1256
  profile
1214
1257
  };
1215
- if (this.signInResolver) {
1216
- response.backstageIdentity = await this.signInResolver({
1217
- result,
1218
- profile
1219
- }, context);
1220
- }
1221
- return response;
1222
1258
  }
1223
1259
  }
1224
1260
  const githubDefaultSignInResolver = async (info, ctx) => {
@@ -1238,6 +1274,7 @@ const createGithubProvider = (options) => {
1238
1274
  globalConfig,
1239
1275
  config,
1240
1276
  tokenIssuer,
1277
+ tokenManager,
1241
1278
  catalogApi,
1242
1279
  logger
1243
1280
  }) => OAuthEnvironmentHandler.mapConfig(config, (envConfig) => {
@@ -1252,7 +1289,7 @@ const createGithubProvider = (options) => {
1252
1289
  const callbackUrl = customCallbackUrl || `${globalConfig.baseUrl}/${providerId}/handler/frame`;
1253
1290
  const catalogIdentityClient = new CatalogIdentityClient({
1254
1291
  catalogApi,
1255
- tokenIssuer
1292
+ tokenManager
1256
1293
  });
1257
1294
  const authHandler = (options == null ? void 0 : options.authHandler) ? options.authHandler : async ({ fullProfile }) => ({
1258
1295
  profile: makeProfileInfo(fullProfile)
@@ -1380,6 +1417,7 @@ const createGitlabProvider = (options) => {
1380
1417
  globalConfig,
1381
1418
  config,
1382
1419
  tokenIssuer,
1420
+ tokenManager,
1383
1421
  catalogApi,
1384
1422
  logger
1385
1423
  }) => OAuthEnvironmentHandler.mapConfig(config, (envConfig) => {
@@ -1388,10 +1426,11 @@ const createGitlabProvider = (options) => {
1388
1426
  const clientSecret = envConfig.getString("clientSecret");
1389
1427
  const audience = envConfig.getOptionalString("audience");
1390
1428
  const baseUrl = audience || "https://gitlab.com";
1391
- const callbackUrl = `${globalConfig.baseUrl}/${providerId}/handler/frame`;
1429
+ const customCallbackUrl = envConfig.getOptionalString("callbackUrl");
1430
+ const callbackUrl = customCallbackUrl || `${globalConfig.baseUrl}/${providerId}/handler/frame`;
1392
1431
  const catalogIdentityClient = new CatalogIdentityClient({
1393
1432
  catalogApi,
1394
- tokenIssuer
1433
+ tokenManager
1395
1434
  });
1396
1435
  const authHandler = (_a = options == null ? void 0 : options.authHandler) != null ? _a : gitlabDefaultAuthHandler;
1397
1436
  const signInResolverFn = (_c = (_b = options == null ? void 0 : options.signIn) == null ? void 0 : _b.resolver) != null ? _c : gitlabDefaultSignInResolver;
@@ -1414,7 +1453,8 @@ const createGitlabProvider = (options) => {
1414
1453
  return OAuthAdapter.fromConfig(globalConfig, provider, {
1415
1454
  disableRefresh: false,
1416
1455
  providerId,
1417
- tokenIssuer
1456
+ tokenIssuer,
1457
+ callbackUrl
1418
1458
  });
1419
1459
  });
1420
1460
  };
@@ -1536,16 +1576,18 @@ const createGoogleProvider = (options) => {
1536
1576
  globalConfig,
1537
1577
  config,
1538
1578
  tokenIssuer,
1579
+ tokenManager,
1539
1580
  catalogApi,
1540
1581
  logger
1541
1582
  }) => OAuthEnvironmentHandler.mapConfig(config, (envConfig) => {
1542
1583
  var _a, _b;
1543
1584
  const clientId = envConfig.getString("clientId");
1544
1585
  const clientSecret = envConfig.getString("clientSecret");
1545
- const callbackUrl = `${globalConfig.baseUrl}/${providerId}/handler/frame`;
1586
+ const customCallbackUrl = envConfig.getOptionalString("callbackUrl");
1587
+ const callbackUrl = customCallbackUrl || `${globalConfig.baseUrl}/${providerId}/handler/frame`;
1546
1588
  const catalogIdentityClient = new CatalogIdentityClient({
1547
1589
  catalogApi,
1548
- tokenIssuer
1590
+ tokenManager
1549
1591
  });
1550
1592
  const authHandler = (options == null ? void 0 : options.authHandler) ? options.authHandler : async ({ fullProfile, params }) => ({
1551
1593
  profile: makeProfileInfo(fullProfile, params.id_token)
@@ -1569,7 +1611,8 @@ const createGoogleProvider = (options) => {
1569
1611
  return OAuthAdapter.fromConfig(globalConfig, provider, {
1570
1612
  disableRefresh: false,
1571
1613
  providerId,
1572
- tokenIssuer
1614
+ tokenIssuer,
1615
+ callbackUrl
1573
1616
  });
1574
1617
  });
1575
1618
  };
@@ -1693,6 +1736,7 @@ const createMicrosoftProvider = (options) => {
1693
1736
  globalConfig,
1694
1737
  config,
1695
1738
  tokenIssuer,
1739
+ tokenManager,
1696
1740
  catalogApi,
1697
1741
  logger
1698
1742
  }) => OAuthEnvironmentHandler.mapConfig(config, (envConfig) => {
@@ -1700,12 +1744,13 @@ const createMicrosoftProvider = (options) => {
1700
1744
  const clientId = envConfig.getString("clientId");
1701
1745
  const clientSecret = envConfig.getString("clientSecret");
1702
1746
  const tenantId = envConfig.getString("tenantId");
1703
- const callbackUrl = `${globalConfig.baseUrl}/${providerId}/handler/frame`;
1747
+ const customCallbackUrl = envConfig.getOptionalString("callbackUrl");
1748
+ const callbackUrl = customCallbackUrl || `${globalConfig.baseUrl}/${providerId}/handler/frame`;
1704
1749
  const authorizationUrl = `https://login.microsoftonline.com/${tenantId}/oauth2/v2.0/authorize`;
1705
1750
  const tokenUrl = `https://login.microsoftonline.com/${tenantId}/oauth2/v2.0/token`;
1706
1751
  const catalogIdentityClient = new CatalogIdentityClient({
1707
1752
  catalogApi,
1708
- tokenIssuer
1753
+ tokenManager
1709
1754
  });
1710
1755
  const authHandler = (options == null ? void 0 : options.authHandler) ? options.authHandler : async ({ fullProfile, params }) => ({
1711
1756
  profile: makeProfileInfo(fullProfile, params.id_token)
@@ -1731,7 +1776,8 @@ const createMicrosoftProvider = (options) => {
1731
1776
  return OAuthAdapter.fromConfig(globalConfig, provider, {
1732
1777
  disableRefresh: false,
1733
1778
  providerId,
1734
- tokenIssuer
1779
+ tokenIssuer,
1780
+ callbackUrl
1735
1781
  });
1736
1782
  });
1737
1783
  };
@@ -1838,13 +1884,15 @@ const createOAuth2Provider = (options) => {
1838
1884
  globalConfig,
1839
1885
  config,
1840
1886
  tokenIssuer,
1887
+ tokenManager,
1841
1888
  catalogApi,
1842
1889
  logger
1843
1890
  }) => OAuthEnvironmentHandler.mapConfig(config, (envConfig) => {
1844
1891
  var _a, _b, _c;
1845
1892
  const clientId = envConfig.getString("clientId");
1846
1893
  const clientSecret = envConfig.getString("clientSecret");
1847
- const callbackUrl = `${globalConfig.baseUrl}/${providerId}/handler/frame`;
1894
+ const customCallbackUrl = envConfig.getOptionalString("callbackUrl");
1895
+ const callbackUrl = customCallbackUrl || `${globalConfig.baseUrl}/${providerId}/handler/frame`;
1848
1896
  const authorizationUrl = envConfig.getString("authorizationUrl");
1849
1897
  const tokenUrl = envConfig.getString("tokenUrl");
1850
1898
  const scope = envConfig.getOptionalString("scope");
@@ -1852,7 +1900,7 @@ const createOAuth2Provider = (options) => {
1852
1900
  const disableRefresh = (_a = envConfig.getOptionalBoolean("disableRefresh")) != null ? _a : false;
1853
1901
  const catalogIdentityClient = new CatalogIdentityClient({
1854
1902
  catalogApi,
1855
- tokenIssuer
1903
+ tokenManager
1856
1904
  });
1857
1905
  const authHandler = (options == null ? void 0 : options.authHandler) ? options.authHandler : async ({ fullProfile, params }) => ({
1858
1906
  profile: makeProfileInfo(fullProfile, params.id_token)
@@ -1880,7 +1928,8 @@ const createOAuth2Provider = (options) => {
1880
1928
  return OAuthAdapter.fromConfig(globalConfig, provider, {
1881
1929
  disableRefresh,
1882
1930
  providerId,
1883
- tokenIssuer
1931
+ tokenIssuer,
1932
+ callbackUrl
1884
1933
  });
1885
1934
  });
1886
1935
  };
@@ -2283,12 +2332,12 @@ class Oauth2ProxyAuthProvider {
2283
2332
  };
2284
2333
  }
2285
2334
  }
2286
- const createOauth2ProxyProvider = (options) => ({ catalogApi, logger, tokenIssuer }) => {
2335
+ const createOauth2ProxyProvider = (options) => ({ catalogApi, logger, tokenIssuer, tokenManager }) => {
2287
2336
  const signInResolver = options.signIn.resolver;
2288
2337
  const authHandler = options.authHandler;
2289
2338
  const catalogIdentityClient = new CatalogIdentityClient({
2290
2339
  catalogApi,
2291
- tokenIssuer
2340
+ tokenManager
2292
2341
  });
2293
2342
  return new Oauth2ProxyAuthProvider({
2294
2343
  logger,
@@ -2412,20 +2461,22 @@ const createOidcProvider = (options) => {
2412
2461
  globalConfig,
2413
2462
  config,
2414
2463
  tokenIssuer,
2464
+ tokenManager,
2415
2465
  catalogApi,
2416
2466
  logger
2417
2467
  }) => OAuthEnvironmentHandler.mapConfig(config, (envConfig) => {
2418
2468
  var _a, _b;
2419
2469
  const clientId = envConfig.getString("clientId");
2420
2470
  const clientSecret = envConfig.getString("clientSecret");
2421
- const callbackUrl = `${globalConfig.baseUrl}/${providerId}/handler/frame`;
2471
+ const customCallbackUrl = envConfig.getOptionalString("callbackUrl");
2472
+ const callbackUrl = customCallbackUrl || `${globalConfig.baseUrl}/${providerId}/handler/frame`;
2422
2473
  const metadataUrl = envConfig.getString("metadataUrl");
2423
2474
  const tokenSignedResponseAlg = envConfig.getOptionalString("tokenSignedResponseAlg");
2424
2475
  const scope = envConfig.getOptionalString("scope");
2425
2476
  const prompt = envConfig.getOptionalString("prompt");
2426
2477
  const catalogIdentityClient = new CatalogIdentityClient({
2427
2478
  catalogApi,
2428
- tokenIssuer
2479
+ tokenManager
2429
2480
  });
2430
2481
  const authHandler = (options == null ? void 0 : options.authHandler) ? options.authHandler : async ({ userinfo }) => ({
2431
2482
  profile: {
@@ -2457,7 +2508,8 @@ const createOidcProvider = (options) => {
2457
2508
  return OAuthAdapter.fromConfig(globalConfig, provider, {
2458
2509
  disableRefresh: false,
2459
2510
  providerId,
2460
- tokenIssuer
2511
+ tokenIssuer,
2512
+ callbackUrl
2461
2513
  });
2462
2514
  });
2463
2515
  };
@@ -2579,6 +2631,7 @@ const createOktaProvider = (_options) => {
2579
2631
  globalConfig,
2580
2632
  config,
2581
2633
  tokenIssuer,
2634
+ tokenManager,
2582
2635
  catalogApi,
2583
2636
  logger
2584
2637
  }) => OAuthEnvironmentHandler.mapConfig(config, (envConfig) => {
@@ -2586,13 +2639,14 @@ const createOktaProvider = (_options) => {
2586
2639
  const clientId = envConfig.getString("clientId");
2587
2640
  const clientSecret = envConfig.getString("clientSecret");
2588
2641
  const audience = envConfig.getString("audience");
2589
- const callbackUrl = `${globalConfig.baseUrl}/${providerId}/handler/frame`;
2642
+ const customCallbackUrl = envConfig.getOptionalString("callbackUrl");
2643
+ const callbackUrl = customCallbackUrl || `${globalConfig.baseUrl}/${providerId}/handler/frame`;
2590
2644
  if (!audience.startsWith("https://")) {
2591
2645
  throw new Error("URL for 'audience' must start with 'https://'.");
2592
2646
  }
2593
2647
  const catalogIdentityClient = new CatalogIdentityClient({
2594
2648
  catalogApi,
2595
- tokenIssuer
2649
+ tokenManager
2596
2650
  });
2597
2651
  const authHandler = (_options == null ? void 0 : _options.authHandler) ? _options.authHandler : async ({ fullProfile, params }) => ({
2598
2652
  profile: makeProfileInfo(fullProfile, params.id_token)
@@ -2617,7 +2671,8 @@ const createOktaProvider = (_options) => {
2617
2671
  return OAuthAdapter.fromConfig(globalConfig, provider, {
2618
2672
  disableRefresh: false,
2619
2673
  providerId,
2620
- tokenIssuer
2674
+ tokenIssuer,
2675
+ callbackUrl
2621
2676
  });
2622
2677
  });
2623
2678
  };
@@ -2712,6 +2767,7 @@ const createOneLoginProvider = (options) => {
2712
2767
  globalConfig,
2713
2768
  config,
2714
2769
  tokenIssuer,
2770
+ tokenManager,
2715
2771
  catalogApi,
2716
2772
  logger
2717
2773
  }) => OAuthEnvironmentHandler.mapConfig(config, (envConfig) => {
@@ -2719,10 +2775,11 @@ const createOneLoginProvider = (options) => {
2719
2775
  const clientId = envConfig.getString("clientId");
2720
2776
  const clientSecret = envConfig.getString("clientSecret");
2721
2777
  const issuer = envConfig.getString("issuer");
2722
- const callbackUrl = `${globalConfig.baseUrl}/${providerId}/handler/frame`;
2778
+ const customCallbackUrl = envConfig.getOptionalString("callbackUrl");
2779
+ const callbackUrl = customCallbackUrl || `${globalConfig.baseUrl}/${providerId}/handler/frame`;
2723
2780
  const catalogIdentityClient = new CatalogIdentityClient({
2724
2781
  catalogApi,
2725
- tokenIssuer
2782
+ tokenManager
2726
2783
  });
2727
2784
  const authHandler = (options == null ? void 0 : options.authHandler) ? options.authHandler : async ({ fullProfile, params }) => ({
2728
2785
  profile: makeProfileInfo(fullProfile, params.id_token)
@@ -2742,7 +2799,8 @@ const createOneLoginProvider = (options) => {
2742
2799
  return OAuthAdapter.fromConfig(globalConfig, provider, {
2743
2800
  disableRefresh: false,
2744
2801
  providerId,
2745
- tokenIssuer
2802
+ tokenIssuer,
2803
+ callbackUrl
2746
2804
  });
2747
2805
  });
2748
2806
  };
@@ -2812,13 +2870,14 @@ const createSamlProvider = (options) => {
2812
2870
  globalConfig,
2813
2871
  config,
2814
2872
  tokenIssuer,
2873
+ tokenManager,
2815
2874
  catalogApi,
2816
2875
  logger
2817
2876
  }) => {
2818
2877
  var _a, _b;
2819
2878
  const catalogIdentityClient = new CatalogIdentityClient({
2820
2879
  catalogApi,
2821
- tokenIssuer
2880
+ tokenManager
2822
2881
  });
2823
2882
  const authHandler = (options == null ? void 0 : options.authHandler) ? options.authHandler : async ({ fullProfile }) => ({
2824
2883
  profile: {
@@ -2926,7 +2985,7 @@ class GcpIapProvider {
2926
2985
  }
2927
2986
  }
2928
2987
  function createGcpIapProvider(options) {
2929
- return ({ config, tokenIssuer, catalogApi, logger }) => {
2988
+ return ({ config, tokenIssuer, catalogApi, logger, tokenManager }) => {
2930
2989
  var _a;
2931
2990
  const audience = config.getString("audience");
2932
2991
  const authHandler = (_a = options.authHandler) != null ? _a : defaultAuthHandler;
@@ -2934,7 +2993,7 @@ function createGcpIapProvider(options) {
2934
2993
  const tokenValidator = createTokenValidator(audience);
2935
2994
  const catalogIdentityClient = new CatalogIdentityClient({
2936
2995
  catalogApi,
2937
- tokenIssuer
2996
+ tokenManager
2938
2997
  });
2939
2998
  return new GcpIapProvider({
2940
2999
  authHandler,
@@ -2964,7 +3023,14 @@ const factories = {
2964
3023
  };
2965
3024
 
2966
3025
  async function createRouter(options) {
2967
- const { logger, config, discovery, database, providerFactories } = options;
3026
+ const {
3027
+ logger,
3028
+ config,
3029
+ discovery,
3030
+ database,
3031
+ tokenManager,
3032
+ providerFactories
3033
+ } = options;
2968
3034
  const router = Router__default["default"]();
2969
3035
  const appUrl = config.getString("app.baseUrl");
2970
3036
  const authUrl = await discovery.getExternalBaseUrl("auth");
@@ -3007,9 +3073,14 @@ async function createRouter(options) {
3007
3073
  try {
3008
3074
  const provider = providerFactory({
3009
3075
  providerId,
3010
- globalConfig: { baseUrl: authUrl, appUrl, isOriginAllowed },
3076
+ globalConfig: {
3077
+ baseUrl: authUrl,
3078
+ appUrl,
3079
+ isOriginAllowed
3080
+ },
3011
3081
  config: providersConfig.getConfig(providerId),
3012
3082
  logger,
3083
+ tokenManager,
3013
3084
  tokenIssuer,
3014
3085
  discovery,
3015
3086
  catalogApi