@auth0/auth0-spa-js 2.4.1 → 2.6.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.
Files changed (42) hide show
  1. package/README.md +1 -1
  2. package/dist/auth0-spa-js.development.js +298 -43
  3. package/dist/auth0-spa-js.development.js.map +1 -1
  4. package/dist/auth0-spa-js.production.esm.js +1 -1
  5. package/dist/auth0-spa-js.production.esm.js.map +1 -1
  6. package/dist/auth0-spa-js.production.js +1 -1
  7. package/dist/auth0-spa-js.production.js.map +1 -1
  8. package/dist/auth0-spa-js.worker.development.js +34 -2
  9. package/dist/auth0-spa-js.worker.development.js.map +1 -1
  10. package/dist/auth0-spa-js.worker.production.js +1 -1
  11. package/dist/auth0-spa-js.worker.production.js.map +1 -1
  12. package/dist/lib/auth0-spa-js.cjs.js +309 -44
  13. package/dist/lib/auth0-spa-js.cjs.js.map +1 -1
  14. package/dist/typings/Auth0Client.d.ts +42 -2
  15. package/dist/typings/Auth0Client.utils.d.ts +32 -0
  16. package/dist/typings/MyAccountApiClient.d.ts +92 -0
  17. package/dist/typings/api.d.ts +1 -1
  18. package/dist/typings/cache/cache-manager.d.ts +18 -1
  19. package/dist/typings/errors.d.ts +10 -0
  20. package/dist/typings/fetcher.d.ts +11 -7
  21. package/dist/typings/global.d.ts +97 -0
  22. package/dist/typings/http.d.ts +2 -2
  23. package/dist/typings/index.d.ts +2 -1
  24. package/dist/typings/transaction-manager.d.ts +15 -4
  25. package/dist/typings/version.d.ts +1 -1
  26. package/dist/typings/worker/worker.types.d.ts +1 -0
  27. package/package.json +1 -1
  28. package/src/Auth0Client.ts +282 -25
  29. package/src/Auth0Client.utils.ts +66 -0
  30. package/src/MyAccountApiClient.ts +158 -0
  31. package/src/api.ts +7 -1
  32. package/src/cache/cache-manager.ts +82 -7
  33. package/src/errors.ts +18 -0
  34. package/src/fetcher.ts +30 -18
  35. package/src/global.ts +112 -4
  36. package/src/http.ts +12 -5
  37. package/src/index.ts +5 -0
  38. package/src/transaction-manager.ts +17 -4
  39. package/src/utils.ts +1 -0
  40. package/src/version.ts +1 -1
  41. package/src/worker/token.worker.ts +60 -9
  42. package/src/worker/worker.types.ts +1 -0
@@ -31,10 +31,11 @@ import {
31
31
  DecodedToken
32
32
  } from './cache';
33
33
 
34
- import { TransactionManager } from './transaction-manager';
34
+ import { ConnectAccountTransaction, LoginTransaction, TransactionManager } from './transaction-manager';
35
35
  import { verify as verifyIdToken } from './jwt';
36
36
  import {
37
37
  AuthenticationError,
38
+ ConnectError,
38
39
  GenericError,
39
40
  MissingRefreshTokenError,
40
41
  TimeoutError
@@ -76,7 +77,11 @@ import {
76
77
  User,
77
78
  IdToken,
78
79
  GetTokenSilentlyVerboseResponse,
79
- TokenEndpointResponse
80
+ TokenEndpointResponse,
81
+ AuthenticationResult,
82
+ ConnectAccountRedirectResult,
83
+ RedirectConnectAccountOptions,
84
+ ResponseType
80
85
  } from './global';
81
86
 
82
87
  // @ts-ignore
@@ -90,7 +95,10 @@ import {
90
95
  getAuthorizeParams,
91
96
  GET_TOKEN_SILENTLY_LOCK_KEY,
92
97
  OLD_IS_AUTHENTICATED_COOKIE_NAME,
93
- patchOpenUrlWithOnRedirect
98
+ patchOpenUrlWithOnRedirect,
99
+ getScopeToRequest,
100
+ allScopesAreIncluded,
101
+ isRefreshWithMrrt
94
102
  } from './Auth0Client.utils';
95
103
  import { CustomTokenExchangeOptions } from './TokenExchange';
96
104
  import { Dpop } from './dpop/dpop';
@@ -99,6 +107,7 @@ import {
99
107
  type FetcherConfig,
100
108
  type CustomFetchMinimalOutput
101
109
  } from './fetcher';
110
+ import { MyAccountApiClient } from './MyAccountApiClient';
102
111
 
103
112
  /**
104
113
  * @ignore
@@ -135,6 +144,7 @@ export class Auth0Client {
135
144
  authorizationParams: AuthorizationParams;
136
145
  };
137
146
  private readonly userCache: ICache = new InMemoryCache().enclosedCache;
147
+ private readonly myAccountApi: MyAccountApiClient;
138
148
 
139
149
  private worker?: Worker;
140
150
  private readonly defaultOptions: Partial<Auth0ClientOptions> = {
@@ -235,6 +245,22 @@ export class Auth0Client {
235
245
  this.domainUrl = getDomain(this.options.domain);
236
246
  this.tokenIssuer = getTokenIssuer(this.options.issuer, this.domainUrl);
237
247
 
248
+ const myAccountApiIdentifier = `${this.domainUrl}/me/`;
249
+ const myAccountFetcher = this.createFetcher({
250
+ ...(this.options.useDpop && { dpopNonceId: '__auth0_my_account_api__' }),
251
+ getAccessToken: () =>
252
+ this.getTokenSilently({
253
+ authorizationParams: {
254
+ scope: 'create:me:connected_accounts',
255
+ audience: myAccountApiIdentifier
256
+ }
257
+ })
258
+ });
259
+ this.myAccountApi = new MyAccountApiClient(
260
+ myAccountFetcher,
261
+ myAccountApiIdentifier
262
+ );
263
+
238
264
  // Don't use web workers unless using refresh tokens in memory
239
265
  if (
240
266
  typeof window !== 'undefined' &&
@@ -321,8 +347,8 @@ export class Auth0Client {
321
347
  nonce,
322
348
  code_challenge,
323
349
  authorizationParams.redirect_uri ||
324
- this.options.authorizationParams.redirect_uri ||
325
- fallbackRedirectUri,
350
+ this.options.authorizationParams.redirect_uri ||
351
+ fallbackRedirectUri,
326
352
  authorizeOptions?.response_mode,
327
353
  thumbprint
328
354
  );
@@ -474,9 +500,10 @@ export class Auth0Client {
474
500
  urlOptions.authorizationParams || {}
475
501
  );
476
502
 
477
- this.transactionManager.create({
503
+ this.transactionManager.create<LoginTransaction>({
478
504
  ...transaction,
479
505
  appState,
506
+ response_type: ResponseType.Code,
480
507
  ...(organization && { organization })
481
508
  });
482
509
 
@@ -497,18 +524,18 @@ export class Auth0Client {
497
524
  */
498
525
  public async handleRedirectCallback<TAppState = any>(
499
526
  url: string = window.location.href
500
- ): Promise<RedirectLoginResult<TAppState>> {
527
+ ): Promise<
528
+ RedirectLoginResult<TAppState> | ConnectAccountRedirectResult<TAppState>
529
+ > {
501
530
  const queryStringFragments = url.split('?').slice(1);
502
531
 
503
532
  if (queryStringFragments.length === 0) {
504
533
  throw new Error('There are no query params available for parsing.');
505
534
  }
506
535
 
507
- const { state, code, error, error_description } = parseAuthenticationResult(
508
- queryStringFragments.join('')
509
- );
510
-
511
- const transaction = this.transactionManager.get();
536
+ const transaction = this.transactionManager.get<
537
+ LoginTransaction | ConnectAccountTransaction
538
+ >();
512
539
 
513
540
  if (!transaction) {
514
541
  throw new GenericError('missing_transaction', 'Invalid state');
@@ -516,6 +543,38 @@ export class Auth0Client {
516
543
 
517
544
  this.transactionManager.remove();
518
545
 
546
+ const authenticationResult = parseAuthenticationResult(
547
+ queryStringFragments.join('')
548
+ );
549
+
550
+ if (transaction.response_type === ResponseType.ConnectCode) {
551
+ return this._handleConnectAccountRedirectCallback<TAppState>(
552
+ authenticationResult,
553
+ transaction
554
+ );
555
+ }
556
+ return this._handleLoginRedirectCallback<TAppState>(
557
+ authenticationResult,
558
+ transaction
559
+ );
560
+ }
561
+
562
+ /**
563
+ * Handles the redirect callback from the login flow.
564
+ *
565
+ * @template AppState - The application state persisted from the /authorize redirect.
566
+ * @param {string} authenticationResult - The parsed authentication result from the URL.
567
+ * @param {string} transaction - The login transaction.
568
+ *
569
+ * @returns {RedirectLoginResult} Resolves with the persisted app state.
570
+ * @throws {GenericError | Error} If the transaction is missing, invalid, or the code exchange fails.
571
+ */
572
+ private async _handleLoginRedirectCallback<TAppState>(
573
+ authenticationResult: AuthenticationResult,
574
+ transaction: LoginTransaction
575
+ ): Promise<RedirectLoginResult<TAppState>> {
576
+ const { code, state, error, error_description } = authenticationResult;
577
+
519
578
  if (error) {
520
579
  throw new AuthenticationError(
521
580
  error,
@@ -550,7 +609,63 @@ export class Auth0Client {
550
609
  );
551
610
 
552
611
  return {
553
- appState: transaction.appState
612
+ appState: transaction.appState,
613
+ response_type: ResponseType.Code
614
+ };
615
+ }
616
+
617
+ /**
618
+ * Handles the redirect callback from the connect account flow.
619
+ * This works the same as the redirect from the login flow expect it verifies the `connect_code`
620
+ * with the My Account API rather than the `code` with the Authorization Server.
621
+ *
622
+ * @template AppState - The application state persisted from the connect redirect.
623
+ * @param {string} connectResult - The parsed connect accounts result from the URL.
624
+ * @param {string} transaction - The login transaction.
625
+ * @returns {Promise<ConnectAccountRedirectResult>} The result of the My Account API, including any persisted app state.
626
+ * @throws {GenericError | MyAccountApiError} If the transaction is missing, invalid, or an error is returned from the My Account API.
627
+ */
628
+ private async _handleConnectAccountRedirectCallback<TAppState>(
629
+ connectResult: AuthenticationResult,
630
+ transaction: ConnectAccountTransaction
631
+ ): Promise<ConnectAccountRedirectResult<TAppState>> {
632
+ const { connect_code, state, error, error_description } = connectResult;
633
+
634
+ if (error) {
635
+ throw new ConnectError(
636
+ error,
637
+ error_description || error,
638
+ transaction.connection,
639
+ state,
640
+ transaction.appState
641
+ );
642
+ }
643
+
644
+ if (!connect_code) {
645
+ throw new GenericError('missing_connect_code', 'Missing connect code');
646
+ }
647
+
648
+ if (
649
+ !transaction.code_verifier ||
650
+ !transaction.state ||
651
+ !transaction.auth_session ||
652
+ !transaction.redirect_uri ||
653
+ transaction.state !== state
654
+ ) {
655
+ throw new GenericError('state_mismatch', 'Invalid state');
656
+ }
657
+
658
+ const data = await this.myAccountApi.completeAccount({
659
+ auth_session: transaction.auth_session,
660
+ connect_code,
661
+ redirect_uri: transaction.redirect_uri,
662
+ code_verifier: transaction.code_verifier
663
+ });
664
+
665
+ return {
666
+ ...data,
667
+ appState: transaction.appState,
668
+ response_type: ResponseType.ConnectCode,
554
669
  };
555
670
  }
556
671
 
@@ -596,7 +711,7 @@ export class Auth0Client {
596
711
 
597
712
  try {
598
713
  await this.getTokenSilently(options);
599
- } catch (_) {}
714
+ } catch (_) { }
600
715
  }
601
716
 
602
717
  /**
@@ -689,7 +804,8 @@ export class Auth0Client {
689
804
  const entry = await this._getEntryFromCache({
690
805
  scope: getTokenOptions.authorizationParams.scope,
691
806
  audience: getTokenOptions.authorizationParams.audience || 'default',
692
- clientId: this.options.clientId
807
+ clientId: this.options.clientId,
808
+ cacheMode,
693
809
  });
694
810
 
695
811
  if (entry) {
@@ -789,7 +905,9 @@ export class Auth0Client {
789
905
  scope: localOptions.authorizationParams.scope,
790
906
  audience: localOptions.authorizationParams.audience || 'default',
791
907
  clientId: this.options.clientId
792
- })
908
+ }),
909
+ undefined,
910
+ this.options.useMrrt
793
911
  );
794
912
 
795
913
  return cache!.access_token;
@@ -976,7 +1094,9 @@ export class Auth0Client {
976
1094
  scope: options.authorizationParams.scope,
977
1095
  audience: options.authorizationParams.audience || 'default',
978
1096
  clientId: this.options.clientId
979
- })
1097
+ }),
1098
+ undefined,
1099
+ this.options.useMrrt
980
1100
  );
981
1101
 
982
1102
  // If you don't have a refresh token in memory
@@ -1004,6 +1124,13 @@ export class Auth0Client {
1004
1124
  ? options.timeoutInSeconds * 1000
1005
1125
  : null;
1006
1126
 
1127
+ const scopesToRequest = getScopeToRequest(
1128
+ this.options.useMrrt,
1129
+ options.authorizationParams,
1130
+ cache?.audience,
1131
+ cache?.scope,
1132
+ );
1133
+
1007
1134
  try {
1008
1135
  const tokenResult = await this._requestToken({
1009
1136
  ...options.authorizationParams,
@@ -1011,7 +1138,51 @@ export class Auth0Client {
1011
1138
  refresh_token: cache && cache.refresh_token,
1012
1139
  redirect_uri,
1013
1140
  ...(timeout && { timeout })
1014
- });
1141
+ },
1142
+ {
1143
+ scopesToRequest,
1144
+ }
1145
+ );
1146
+
1147
+ // If is refreshed with MRRT, we update all entries that have the old
1148
+ // refresh_token with the new one if the server responded with one
1149
+ if (tokenResult.refresh_token && this.options.useMrrt && cache?.refresh_token) {
1150
+ await this.cacheManager.updateEntry(
1151
+ cache.refresh_token,
1152
+ tokenResult.refresh_token
1153
+ );
1154
+ }
1155
+
1156
+ // Some scopes requested to the server might not be inside the refresh policies
1157
+ // In order to return a token with all requested scopes when using MRRT we should
1158
+ // check if all scopes are returned. If not, we will try to use an iframe to request
1159
+ // a token.
1160
+ if (this.options.useMrrt) {
1161
+ const isRefreshMrrt = isRefreshWithMrrt(
1162
+ cache?.audience,
1163
+ cache?.scope,
1164
+ options.authorizationParams.audience,
1165
+ options.authorizationParams.scope,
1166
+ );
1167
+
1168
+ if (isRefreshMrrt) {
1169
+ const tokenHasAllScopes = allScopesAreIncluded(
1170
+ scopesToRequest,
1171
+ tokenResult.scope,
1172
+ );
1173
+
1174
+ if (!tokenHasAllScopes) {
1175
+ if (this.options.useRefreshTokensFallback) {
1176
+ return await this._getTokenFromIFrame(options);
1177
+ }
1178
+
1179
+ throw new MissingRefreshTokenError(
1180
+ options.authorizationParams.audience || 'default',
1181
+ options.authorizationParams.scope,
1182
+ );
1183
+ }
1184
+ }
1185
+ }
1015
1186
 
1016
1187
  return {
1017
1188
  ...tokenResult,
@@ -1084,11 +1255,13 @@ export class Auth0Client {
1084
1255
  private async _getEntryFromCache({
1085
1256
  scope,
1086
1257
  audience,
1087
- clientId
1258
+ clientId,
1259
+ cacheMode,
1088
1260
  }: {
1089
1261
  scope: string;
1090
1262
  audience: string;
1091
1263
  clientId: string;
1264
+ cacheMode?: string;
1092
1265
  }): Promise<undefined | GetTokenSilentlyVerboseResponse> {
1093
1266
  const entry = await this.cacheManager.get(
1094
1267
  new CacheKey({
@@ -1096,7 +1269,9 @@ export class Auth0Client {
1096
1269
  audience,
1097
1270
  clientId
1098
1271
  }),
1099
- 60 // get a new token if within 60 seconds of expiring
1272
+ 60, // get a new token if within 60 seconds of expiring
1273
+ this.options.useMrrt,
1274
+ cacheMode,
1100
1275
  );
1101
1276
 
1102
1277
  if (entry && entry.access_token) {
@@ -1134,7 +1309,7 @@ export class Auth0Client {
1134
1309
  | TokenExchangeRequestOptions,
1135
1310
  additionalParameters?: RequestTokenAdditionalParameters
1136
1311
  ) {
1137
- const { nonceIn, organization } = additionalParameters || {};
1312
+ const { nonceIn, organization, scopesToRequest } = additionalParameters || {};
1138
1313
  const authResult = await oauthToken(
1139
1314
  {
1140
1315
  baseUrl: this.domainUrl,
@@ -1142,8 +1317,10 @@ export class Auth0Client {
1142
1317
  auth0Client: this.options.auth0Client,
1143
1318
  useFormData: this.options.useFormData,
1144
1319
  timeout: this.httpTimeoutMs,
1320
+ useMrrt: this.options.useMrrt,
1145
1321
  dpop: this.dpop,
1146
- ...options
1322
+ ...options,
1323
+ scope: scopesToRequest || options.scope,
1147
1324
  },
1148
1325
  this.worker
1149
1326
  );
@@ -1298,7 +1475,7 @@ export class Auth0Client {
1298
1475
  * This is a drop-in replacement for the Fetch API's `fetch()` method, but will
1299
1476
  * handle certain authentication logic for you, like building the proper auth
1300
1477
  * headers or managing DPoP nonces and retries automatically.
1301
- *
1478
+ *
1302
1479
  * Check the `EXAMPLES.md` file for a deeper look into this method.
1303
1480
  */
1304
1481
  public createFetcher<TOutput extends CustomFetchMinimalOutput = Response>(
@@ -1312,12 +1489,91 @@ export class Auth0Client {
1312
1489
 
1313
1490
  return new Fetcher(config, {
1314
1491
  isDpopEnabled: () => !!this.options.useDpop,
1315
- getAccessToken: () => this.getTokenSilently(),
1492
+ getAccessToken: authParams =>
1493
+ this.getTokenSilently({
1494
+ authorizationParams: {
1495
+ scope: authParams?.scope?.join(' '),
1496
+ audience: authParams?.audience
1497
+ }
1498
+ }),
1316
1499
  getDpopNonce: () => this.getDpopNonce(config.dpopNonceId),
1317
- setDpopNonce: nonce => this.setDpopNonce(nonce),
1500
+ setDpopNonce: nonce => this.setDpopNonce(nonce, config.dpopNonceId),
1318
1501
  generateDpopProof: params => this.generateDpopProof(params)
1319
1502
  });
1320
1503
  }
1504
+
1505
+ /**
1506
+ * Initiates a redirect to connect the user's account with a specified connection.
1507
+ * This method generates PKCE parameters, creates a transaction, and redirects to the /connect endpoint.
1508
+ *
1509
+ * @template TAppState - The application state to persist through the transaction.
1510
+ * @param {RedirectConnectAccountOptions<TAppState>} options - Options for the connect account redirect flow.
1511
+ * @param {string} options.connection - The name of the connection to link (e.g. 'google-oauth2').
1512
+ * @param {AuthorizationParams} [options.authorization_params] - Additional authorization parameters for the request to the upstream IdP.
1513
+ * @param {string} [options.redirectUri] - The URI to redirect back to after connecting the account.
1514
+ * @param {TAppState} [options.appState] - Application state to persist through the transaction.
1515
+ * @param {(url: string) => Promise<void>} [options.openUrl] - Custom function to open the URL.
1516
+ *
1517
+ * @returns {Promise<void>} Resolves when the redirect is initiated.
1518
+ * @throws {MyAccountApiError} If the connect request to the My Account API fails.
1519
+ */
1520
+ public async connectAccountWithRedirect<TAppState = any>(
1521
+ options: RedirectConnectAccountOptions<TAppState>
1522
+ ) {
1523
+ if (!this.options.useDpop) {
1524
+ throw new Error('`useDpop` option must be enabled before using connectAccountWithRedirect.');
1525
+ }
1526
+
1527
+ if (!this.options.useMrrt) {
1528
+ throw new Error('`useMrrt` option must be enabled before using connectAccountWithRedirect.');
1529
+ }
1530
+
1531
+ const {
1532
+ openUrl,
1533
+ appState,
1534
+ connection,
1535
+ authorization_params,
1536
+ redirectUri = this.options.authorizationParams.redirect_uri ||
1537
+ window.location.origin
1538
+ } = options;
1539
+
1540
+ if (!connection) {
1541
+ throw new Error('connection is required');
1542
+ }
1543
+
1544
+ const state = encode(createRandomString());
1545
+ const code_verifier = createRandomString();
1546
+ const code_challengeBuffer = await sha256(code_verifier);
1547
+ const code_challenge = bufferToBase64UrlEncoded(code_challengeBuffer);
1548
+
1549
+ const { connect_uri, connect_params, auth_session } =
1550
+ await this.myAccountApi.connectAccount({
1551
+ connection,
1552
+ redirect_uri: redirectUri,
1553
+ state,
1554
+ code_challenge,
1555
+ code_challenge_method: 'S256',
1556
+ authorization_params
1557
+ });
1558
+
1559
+ this.transactionManager.create<ConnectAccountTransaction>({
1560
+ state,
1561
+ code_verifier,
1562
+ auth_session,
1563
+ redirect_uri: redirectUri,
1564
+ appState,
1565
+ connection,
1566
+ response_type: ResponseType.ConnectCode
1567
+ });
1568
+
1569
+ const url = new URL(connect_uri);
1570
+ url.searchParams.set('ticket', connect_params.ticket);
1571
+ if (openUrl) {
1572
+ await openUrl(url.toString());
1573
+ } else {
1574
+ window.location.assign(url);
1575
+ }
1576
+ }
1321
1577
  }
1322
1578
 
1323
1579
  interface BaseRequestTokenOptions {
@@ -1349,4 +1605,5 @@ interface TokenExchangeRequestOptions extends BaseRequestTokenOptions {
1349
1605
  interface RequestTokenAdditionalParameters {
1350
1606
  nonceIn?: string;
1351
1607
  organization?: string;
1608
+ scopesToRequest?: string;
1352
1609
  }
@@ -96,3 +96,69 @@ export const patchOpenUrlWithOnRedirect = <
96
96
 
97
97
  return result as T;
98
98
  };
99
+
100
+ /**
101
+ * @ignore
102
+ *
103
+ * Checks if all scopes are included inside other array of scopes
104
+ */
105
+ export const allScopesAreIncluded = (scopeToInclude?: string, scopes?: string): boolean => {
106
+ const scopeGroup = scopes?.split(" ") || [];
107
+ const scopesToInclude = scopeToInclude?.split(" ") || [];
108
+ return scopesToInclude.every((key) => scopeGroup.includes(key));
109
+ }
110
+
111
+ /**
112
+ * @ignore
113
+ *
114
+ * For backward compatibility we are going to check if we are going to downscope while doing a refresh request
115
+ * while MRRT is allowed. If the audience is the same for the refresh_token we are going to use and it has
116
+ * lower scopes than the ones originally in the token, we are going to return the scopes that were stored
117
+ * with the refresh_token in the tokenset.
118
+ * @param useMrrt Setting that the user can activate to use MRRT in their requests
119
+ * @param authorizationParams Contains the audience and scope that the user requested to obtain a token
120
+ * @param cachedAudience Audience stored with the refresh_token wich we are going to use in the request
121
+ * @param cachedScope Scope stored with the refresh_token wich we are going to use in the request
122
+ */
123
+ export const getScopeToRequest = (
124
+ useMrrt: boolean | undefined,
125
+ authorizationParams: { audience?: string, scope: string },
126
+ cachedAudience?: string,
127
+ cachedScope?: string
128
+ ): string => {
129
+ if (useMrrt && cachedAudience && cachedScope) {
130
+ if (authorizationParams.audience !== cachedAudience) {
131
+ return authorizationParams.scope;
132
+ }
133
+
134
+ const cachedScopes = cachedScope.split(" ");
135
+ const newScopes = authorizationParams.scope?.split(" ") || [];
136
+ const newScopesAreIncluded = newScopes.every((scope) => cachedScopes.includes(scope));
137
+
138
+ return cachedScopes.length >= newScopes.length && newScopesAreIncluded ? cachedScope : authorizationParams.scope;
139
+ }
140
+
141
+ return authorizationParams.scope;
142
+ }
143
+
144
+ /**
145
+ * @ignore
146
+ *
147
+ * Checks if the refresh request has been done using MRRT
148
+ * @param cachedAudience Audience from the refresh token used to refresh
149
+ * @param cachedScope Scopes from the refresh token used to refresh
150
+ * @param requestAudience Audience sent to the server
151
+ * @param requestScope Scopes sent to the server
152
+ */
153
+ export const isRefreshWithMrrt = (
154
+ cachedAudience: string | undefined,
155
+ cachedScope: string | undefined,
156
+ requestAudience: string | undefined,
157
+ requestScope: string,
158
+ ): boolean => {
159
+ if (cachedAudience !== requestAudience) {
160
+ return true;
161
+ }
162
+
163
+ return !allScopesAreIncluded(requestScope, cachedScope);
164
+ }