@auth0/auth0-spa-js 2.7.0 → 2.9.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.
@@ -550,7 +550,7 @@ var browserTabsLock = createCommonjsModule((function(module, exports) {
550
550
 
551
551
  var Lock = unwrapExports(browserTabsLock);
552
552
 
553
- var version = "2.7.0";
553
+ var version = "2.9.0";
554
554
 
555
555
  const DEFAULT_AUTHORIZE_TIMEOUT_IN_SECONDS = 60;
556
556
 
@@ -581,6 +581,8 @@ const DEFAULT_AUTH0_CLIENT = {
581
581
 
582
582
  const DEFAULT_NOW_PROVIDER = () => Date.now();
583
583
 
584
+ const DEFAULT_AUDIENCE = "default";
585
+
584
586
  class GenericError extends Error {
585
587
  constructor(error, error_description) {
586
588
  super(error_description);
@@ -775,6 +777,25 @@ const stripUndefined = params => Object.keys(params).filter((k => typeof params[
775
777
  [key]: params[key]
776
778
  })), {});
777
779
 
780
+ const ALLOWED_AUTH0CLIENT_PROPERTIES = [ {
781
+ key: "name",
782
+ type: [ "string" ]
783
+ }, {
784
+ key: "version",
785
+ type: [ "string", "number" ]
786
+ }, {
787
+ key: "env",
788
+ type: [ "object" ]
789
+ } ];
790
+
791
+ const stripAuth0Client = auth0Client => Object.keys(auth0Client).reduce(((acc, key) => {
792
+ const allowedProperty = ALLOWED_AUTH0CLIENT_PROPERTIES.find((p => p.key === key));
793
+ if (allowedProperty && allowedProperty.type.includes(typeof auth0Client[key])) {
794
+ acc[key] = auth0Client[key];
795
+ }
796
+ return acc;
797
+ }), {});
798
+
778
799
  const createQueryParams = _a => {
779
800
  var {clientId: client_id} = _a, params = __rest(_a, [ "clientId" ]);
780
801
  return new URLSearchParams(stripUndefined(Object.assign({
@@ -1306,12 +1327,12 @@ async function oauthToken(_a, worker) {
1306
1327
  });
1307
1328
  const body = useFormData ? createQueryParams(allParams) : JSON.stringify(allParams);
1308
1329
  const isDpopSupported = isGrantTypeSupported(options.grant_type);
1309
- return await getJSON(`${baseUrl}/oauth/token`, timeout, audience || "default", scope, {
1330
+ return await getJSON(`${baseUrl}/oauth/token`, timeout, audience || DEFAULT_AUDIENCE, scope, {
1310
1331
  method: "POST",
1311
1332
  body: body,
1312
1333
  headers: {
1313
1334
  "Content-Type": useFormData ? "application/x-www-form-urlencoded" : "application/json",
1314
- "Auth0-Client": btoa(JSON.stringify(auth0Client || DEFAULT_AUTH0_CLIENT))
1335
+ "Auth0-Client": btoa(JSON.stringify(stripAuth0Client(auth0Client || DEFAULT_AUTH0_CLIENT)))
1315
1336
  }
1316
1337
  }, worker, useFormData, useMrrt, isDpopSupported ? dpop : undefined);
1317
1338
  }
@@ -1320,6 +1341,33 @@ const dedupe = arr => Array.from(new Set(arr));
1320
1341
 
1321
1342
  const getUniqueScopes = (...scopes) => dedupe(scopes.filter(Boolean).join(" ").trim().split(/\s+/)).join(" ");
1322
1343
 
1344
+ const injectDefaultScopes = (authScopes, openIdScope, ...extraScopes) => {
1345
+ if (typeof authScopes !== "object") {
1346
+ return {
1347
+ [DEFAULT_AUDIENCE]: getUniqueScopes(openIdScope, authScopes, ...extraScopes)
1348
+ };
1349
+ }
1350
+ let requestedScopes = {
1351
+ [DEFAULT_AUDIENCE]: getUniqueScopes(openIdScope, ...extraScopes)
1352
+ };
1353
+ Object.keys(authScopes).forEach((key => {
1354
+ const audienceScopes = authScopes[key];
1355
+ requestedScopes[key] = getUniqueScopes(openIdScope, audienceScopes, ...extraScopes);
1356
+ }));
1357
+ return requestedScopes;
1358
+ };
1359
+
1360
+ const scopesToRequest = (authScopes, methodScopes, audience) => {
1361
+ let scope;
1362
+ if (audience) {
1363
+ scope = authScopes[audience];
1364
+ }
1365
+ if (!scope) {
1366
+ scope = authScopes[DEFAULT_AUDIENCE];
1367
+ }
1368
+ return getUniqueScopes(scope, methodScopes);
1369
+ };
1370
+
1323
1371
  const CACHE_KEY_PREFIX = "@@auth0spajs@@";
1324
1372
 
1325
1373
  const CACHE_KEY_ID_TOKEN_SUFFIX = "@@user@@";
@@ -1494,6 +1542,14 @@ class CacheManager {
1494
1542
  await this.cache.set(cacheKey.toKey(), wrappedEntry);
1495
1543
  await ((_a = this.keyManifest) === null || _a === void 0 ? void 0 : _a.add(cacheKey.toKey()));
1496
1544
  }
1545
+ async remove(client_id, audience, scope) {
1546
+ const cacheKey = new CacheKey({
1547
+ clientId: client_id,
1548
+ scope: scope,
1549
+ audience: audience
1550
+ });
1551
+ await this.cache.remove(cacheKey.toKey());
1552
+ }
1497
1553
  async clear(clientId) {
1498
1554
  var _a;
1499
1555
  const keys = await this.getCacheKeys();
@@ -1999,6 +2055,8 @@ class CacheKeyManifest {
1999
2055
 
2000
2056
  const GET_TOKEN_SILENTLY_LOCK_KEY = "auth0.lock.getTokenSilently";
2001
2057
 
2058
+ const buildGetTokenSilentlyLockKey = (clientId, audience) => `${GET_TOKEN_SILENTLY_LOCK_KEY}.${clientId}.${audience}`;
2059
+
2002
2060
  const buildOrganizationHintCookieName = clientId => `auth0.${clientId}.organization_hint`;
2003
2061
 
2004
2062
  const OLD_IS_AUTHENTICATED_COOKIE_NAME = "auth0.is.authenticated";
@@ -2015,7 +2073,7 @@ const cacheFactory = location => cacheLocationBuilders[location];
2015
2073
  const getAuthorizeParams = (clientOptions, scope, authorizationParams, state, nonce, code_challenge, redirect_uri, response_mode, thumbprint) => Object.assign(Object.assign(Object.assign({
2016
2074
  client_id: clientOptions.clientId
2017
2075
  }, clientOptions.authorizationParams), authorizationParams), {
2018
- scope: getUniqueScopes(scope, authorizationParams.scope),
2076
+ scope: scopesToRequest(scope, authorizationParams.scope, authorizationParams.audience),
2019
2077
  response_type: "code",
2020
2078
  response_mode: response_mode || "query",
2021
2079
  state: state,
@@ -2369,6 +2427,7 @@ const lock = new Lock;
2369
2427
  class Auth0Client {
2370
2428
  constructor(options) {
2371
2429
  this.userCache = (new InMemoryCache).enclosedCache;
2430
+ this.activeLockKeys = new Set;
2372
2431
  this.defaultOptions = {
2373
2432
  authorizationParams: {
2374
2433
  scope: DEFAULT_SCOPE
@@ -2377,7 +2436,11 @@ class Auth0Client {
2377
2436
  useFormData: true
2378
2437
  };
2379
2438
  this._releaseLockOnPageHide = async () => {
2380
- await lock.releaseLock(GET_TOKEN_SILENTLY_LOCK_KEY);
2439
+ const lockKeysToRelease = Array.from(this.activeLockKeys);
2440
+ for (const lockKey of lockKeysToRelease) {
2441
+ await lock.releaseLock(lockKey);
2442
+ }
2443
+ this.activeLockKeys.clear();
2381
2444
  window.removeEventListener("pagehide", this._releaseLockOnPageHide);
2382
2445
  };
2383
2446
  this.options = Object.assign(Object.assign(Object.assign({}, this.defaultOptions), options), {
@@ -2404,7 +2467,7 @@ class Auth0Client {
2404
2467
  this.isAuthenticatedCookieName = buildIsAuthenticatedCookieName(this.options.clientId);
2405
2468
  this.sessionCheckExpiryDays = options.sessionCheckExpiryDays || DEFAULT_SESSION_CHECK_EXPIRY_DAYS;
2406
2469
  const transactionStorage = options.useCookiesForTransactions ? this.cookieStorage : SessionStorage;
2407
- this.scope = getUniqueScopes("openid", this.options.authorizationParams.scope, this.options.useRefreshTokens ? "offline_access" : "");
2470
+ this.scope = injectDefaultScopes(this.options.authorizationParams.scope, "openid", this.options.useRefreshTokens ? "offline_access" : "");
2408
2471
  this.transactionManager = new TransactionManager(transactionStorage, this.options.clientId, this.options.cookieDomain);
2409
2472
  this.nowProvider = this.options.nowProvider || DEFAULT_NOW_PROVIDER;
2410
2473
  this.cacheManager = new CacheManager(cache, !cache.allKeys ? new CacheKeyManifest(cache, this.options.clientId) : undefined, this.nowProvider);
@@ -2478,7 +2541,7 @@ class Auth0Client {
2478
2541
  nonce: nonce,
2479
2542
  code_verifier: code_verifier,
2480
2543
  scope: params.scope,
2481
- audience: params.audience || "default",
2544
+ audience: params.audience || DEFAULT_AUDIENCE,
2482
2545
  redirect_uri: params.redirect_uri,
2483
2546
  state: state,
2484
2547
  url: url
@@ -2628,12 +2691,12 @@ class Auth0Client {
2628
2691
  } catch (_) {}
2629
2692
  }
2630
2693
  async getTokenSilently(options = {}) {
2631
- var _a;
2694
+ var _a, _b;
2632
2695
  const localOptions = Object.assign(Object.assign({
2633
2696
  cacheMode: "on"
2634
2697
  }, options), {
2635
2698
  authorizationParams: Object.assign(Object.assign(Object.assign({}, this.options.authorizationParams), options.authorizationParams), {
2636
- scope: getUniqueScopes(this.scope, (_a = options.authorizationParams) === null || _a === void 0 ? void 0 : _a.scope)
2699
+ scope: scopesToRequest(this.scope, (_a = options.authorizationParams) === null || _a === void 0 ? void 0 : _a.scope, ((_b = options.authorizationParams) === null || _b === void 0 ? void 0 : _b.audience) || this.options.authorizationParams.audience)
2637
2700
  })
2638
2701
  });
2639
2702
  const result = await singlePromise((() => this._getTokenSilently(localOptions)), `${this.options.clientId}::${localOptions.authorizationParams.audience}::${localOptions.authorizationParams.scope}`);
@@ -2644,7 +2707,7 @@ class Auth0Client {
2644
2707
  if (cacheMode !== "off") {
2645
2708
  const entry = await this._getEntryFromCache({
2646
2709
  scope: getTokenOptions.authorizationParams.scope,
2647
- audience: getTokenOptions.authorizationParams.audience || "default",
2710
+ audience: getTokenOptions.authorizationParams.audience || DEFAULT_AUDIENCE,
2648
2711
  clientId: this.options.clientId,
2649
2712
  cacheMode: cacheMode
2650
2713
  });
@@ -2655,13 +2718,17 @@ class Auth0Client {
2655
2718
  if (cacheMode === "cache-only") {
2656
2719
  return;
2657
2720
  }
2658
- if (await retryPromise((() => lock.acquireLock(GET_TOKEN_SILENTLY_LOCK_KEY, 5e3)), 10)) {
2659
- try {
2721
+ const lockKey = buildGetTokenSilentlyLockKey(this.options.clientId, getTokenOptions.authorizationParams.audience || "default");
2722
+ if (await retryPromise((() => lock.acquireLock(lockKey, 5e3)), 10)) {
2723
+ this.activeLockKeys.add(lockKey);
2724
+ if (this.activeLockKeys.size === 1) {
2660
2725
  window.addEventListener("pagehide", this._releaseLockOnPageHide);
2726
+ }
2727
+ try {
2661
2728
  if (cacheMode !== "off") {
2662
2729
  const entry = await this._getEntryFromCache({
2663
2730
  scope: getTokenOptions.authorizationParams.scope,
2664
- audience: getTokenOptions.authorizationParams.audience || "default",
2731
+ audience: getTokenOptions.authorizationParams.audience || DEFAULT_AUDIENCE,
2665
2732
  clientId: this.options.clientId
2666
2733
  });
2667
2734
  if (entry) {
@@ -2680,25 +2747,28 @@ class Auth0Client {
2680
2747
  expires_in: expires_in
2681
2748
  });
2682
2749
  } finally {
2683
- await lock.releaseLock(GET_TOKEN_SILENTLY_LOCK_KEY);
2684
- window.removeEventListener("pagehide", this._releaseLockOnPageHide);
2750
+ await lock.releaseLock(lockKey);
2751
+ this.activeLockKeys.delete(lockKey);
2752
+ if (this.activeLockKeys.size === 0) {
2753
+ window.removeEventListener("pagehide", this._releaseLockOnPageHide);
2754
+ }
2685
2755
  }
2686
2756
  } else {
2687
2757
  throw new TimeoutError;
2688
2758
  }
2689
2759
  }
2690
2760
  async getTokenWithPopup(options = {}, config = {}) {
2691
- var _a;
2761
+ var _a, _b;
2692
2762
  const localOptions = Object.assign(Object.assign({}, options), {
2693
2763
  authorizationParams: Object.assign(Object.assign(Object.assign({}, this.options.authorizationParams), options.authorizationParams), {
2694
- scope: getUniqueScopes(this.scope, (_a = options.authorizationParams) === null || _a === void 0 ? void 0 : _a.scope)
2764
+ scope: scopesToRequest(this.scope, (_a = options.authorizationParams) === null || _a === void 0 ? void 0 : _a.scope, ((_b = options.authorizationParams) === null || _b === void 0 ? void 0 : _b.audience) || this.options.authorizationParams.audience)
2695
2765
  })
2696
2766
  });
2697
2767
  config = Object.assign(Object.assign({}, DEFAULT_POPUP_CONFIG_OPTIONS), config);
2698
2768
  await this.loginWithPopup(localOptions, config);
2699
2769
  const cache = await this.cacheManager.get(new CacheKey({
2700
2770
  scope: localOptions.authorizationParams.scope,
2701
- audience: localOptions.authorizationParams.audience || "default",
2771
+ audience: localOptions.authorizationParams.audience || DEFAULT_AUDIENCE,
2702
2772
  clientId: this.options.clientId
2703
2773
  }), undefined, this.options.useMrrt);
2704
2774
  return cache.access_token;
@@ -2796,14 +2866,14 @@ class Auth0Client {
2796
2866
  async _getTokenUsingRefreshToken(options) {
2797
2867
  const cache = await this.cacheManager.get(new CacheKey({
2798
2868
  scope: options.authorizationParams.scope,
2799
- audience: options.authorizationParams.audience || "default",
2869
+ audience: options.authorizationParams.audience || DEFAULT_AUDIENCE,
2800
2870
  clientId: this.options.clientId
2801
2871
  }), undefined, this.options.useMrrt);
2802
2872
  if ((!cache || !cache.refresh_token) && !this.worker) {
2803
2873
  if (this.options.useRefreshTokensFallback) {
2804
2874
  return await this._getTokenFromIFrame(options);
2805
2875
  }
2806
- throw new MissingRefreshTokenError(options.authorizationParams.audience || "default", options.authorizationParams.scope);
2876
+ throw new MissingRefreshTokenError(options.authorizationParams.audience || DEFAULT_AUDIENCE, options.authorizationParams.scope);
2807
2877
  }
2808
2878
  const redirect_uri = options.authorizationParams.redirect_uri || this.options.authorizationParams.redirect_uri || window.location.origin;
2809
2879
  const timeout = typeof options.timeoutInSeconds === "number" ? options.timeoutInSeconds * 1e3 : null;
@@ -2829,6 +2899,7 @@ class Auth0Client {
2829
2899
  if (this.options.useRefreshTokensFallback) {
2830
2900
  return await this._getTokenFromIFrame(options);
2831
2901
  }
2902
+ await this.cacheManager.remove(this.options.clientId, options.authorizationParams.audience, options.authorizationParams.scope);
2832
2903
  const missingScopes = getMissingScopes(scopesToRequest, tokenResult.scope);
2833
2904
  throw new MissingScopesError(options.authorizationParams.audience || "default", missingScopes);
2834
2905
  }
@@ -2837,7 +2908,7 @@ class Auth0Client {
2837
2908
  return Object.assign(Object.assign({}, tokenResult), {
2838
2909
  scope: options.authorizationParams.scope,
2839
2910
  oauthTokenScope: tokenResult.scope,
2840
- audience: options.authorizationParams.audience || "default"
2911
+ audience: options.authorizationParams.audience || DEFAULT_AUDIENCE
2841
2912
  });
2842
2913
  } catch (e) {
2843
2914
  if ((e.message.indexOf(MISSING_REFRESH_TOKEN_ERROR_MESSAGE) > -1 || e.message && e.message.indexOf(INVALID_REFRESH_TOKEN_ERROR_MESSAGE) > -1) && this.options.useRefreshTokensFallback) {
@@ -2856,11 +2927,12 @@ class Auth0Client {
2856
2927
  await this.cacheManager.set(entryWithoutIdToken);
2857
2928
  }
2858
2929
  async _getIdTokenFromCache() {
2859
- const audience = this.options.authorizationParams.audience || "default";
2930
+ const audience = this.options.authorizationParams.audience || DEFAULT_AUDIENCE;
2931
+ const scope = this.scope[audience];
2860
2932
  const cache = await this.cacheManager.getIdToken(new CacheKey({
2861
2933
  clientId: this.options.clientId,
2862
2934
  audience: audience,
2863
- scope: this.scope
2935
+ scope: scope
2864
2936
  }));
2865
2937
  const currentCache = this.userCache.get(CACHE_KEY_ID_TOKEN_SUFFIX);
2866
2938
  if (cache && cache.id_token === (currentCache === null || currentCache === void 0 ? void 0 : currentCache.id_token)) {
@@ -2906,7 +2978,7 @@ class Auth0Client {
2906
2978
  await this._saveEntryInCache(Object.assign(Object.assign(Object.assign(Object.assign({}, authResult), {
2907
2979
  decodedToken: decodedToken,
2908
2980
  scope: options.scope,
2909
- audience: options.audience || "default"
2981
+ audience: options.audience || DEFAULT_AUDIENCE
2910
2982
  }), authResult.scope ? {
2911
2983
  oauthTokenScope: authResult.scope
2912
2984
  } : null), {
@@ -2926,7 +2998,7 @@ class Auth0Client {
2926
2998
  grant_type: "urn:ietf:params:oauth:grant-type:token-exchange",
2927
2999
  subject_token: options.subject_token,
2928
3000
  subject_token_type: options.subject_token_type,
2929
- scope: getUniqueScopes(options.scope, this.scope),
3001
+ scope: scopesToRequest(this.scope, options.scope, options.audience || this.options.authorizationParams.audience),
2930
3002
  audience: options.audience || this.options.authorizationParams.audience
2931
3003
  });
2932
3004
  }
@@ -2966,7 +3038,7 @@ class Auth0Client {
2966
3038
  });
2967
3039
  }
2968
3040
  async connectAccountWithRedirect(options) {
2969
- const {openUrl: openUrl, appState: appState, connection: connection, authorization_params: authorization_params, redirectUri: redirectUri = this.options.authorizationParams.redirect_uri || window.location.origin} = options;
3041
+ const {openUrl: openUrl, appState: appState, connection: connection, scopes: scopes, authorization_params: authorization_params, redirectUri: redirectUri = this.options.authorizationParams.redirect_uri || window.location.origin} = options;
2970
3042
  if (!connection) {
2971
3043
  throw new Error("connection is required");
2972
3044
  }
@@ -2976,6 +3048,7 @@ class Auth0Client {
2976
3048
  const code_challenge = bufferToBase64UrlEncoded(code_challengeBuffer);
2977
3049
  const {connect_uri: connect_uri, connect_params: connect_params, auth_session: auth_session} = await this.myAccountApi.connectAccount({
2978
3050
  connection: connection,
3051
+ scopes: scopes,
2979
3052
  redirect_uri: redirectUri,
2980
3053
  state: state,
2981
3054
  code_challenge: code_challenge,