From 3fe465a19e0ec89116a17adfc95c53e2a30c103b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mart=C3=ADn=20Melado?=
<217925+martinml@users.noreply.github.com>
Date: Wed, 30 Jul 2025 20:46:11 +0200
Subject: [PATCH 1/9] Add support for DPoP
---
EXAMPLES.md | 173 +++++++++++++++++++++++++++++-
__mocks__/@auth0/auth0-spa-js.tsx | 6 ++
__tests__/auth-provider.test.tsx | 47 ++++++++
src/auth0-context.tsx | 43 ++++++++
src/auth0-provider.tsx | 23 ++++
5 files changed, 288 insertions(+), 4 deletions(-)
diff --git a/EXAMPLES.md b/EXAMPLES.md
index cd29491f..98e16975 100644
--- a/EXAMPLES.md
+++ b/EXAMPLES.md
@@ -8,6 +8,7 @@
- [Protecting a route in a Next.js app (in SPA mode)](#protecting-a-route-in-a-nextjs-app-in-spa-mode)
- [Use with Auth0 organizations](#use-with-auth0-organizations)
- [Protecting a route with a claims check](#protecting-a-route-with-a-claims-check)
+- [Device-bound tokens with DPoP](#device-bound-tokens-with-dpop)
## Use with a Class Component
@@ -325,17 +326,181 @@ In order to protect a route with a claims check alongside an authentication requ
```jsx
const withClaimCheck = (Component, myClaimCheckFunction, returnTo) => {
- const { user } = useAuth0();
+ const { user } = useAuth0();
if (myClaimCheckFunction(user)) {
- return
+ return ;
}
Router.push(returnTo);
-}
+};
const checkClaims = (claim?: User) => claim?.['https://my.app.io/jwt/claims']?.ROLE?.includes('ADMIN');
// Usage
const Page = withAuthenticationRequired(
- withClaimCheck(Component, checkClaims, '/missing-roles' )
+ withClaimCheck(Component, checkClaims, '/missing-roles')
);
```
+
+## Device-bound tokens with DPoP
+
+**Demonstrating Proof-of-Possession** –or just **DPoP**– is an OAuth 2.0 extension defined in [RFC9449](https://datatracker.ietf.org/doc/html/rfc9449).
+
+It defines a mechanism for securely binding tokens to a specific device by means of cryptographic signatures. Without it, **a token leak caused by XSS or other vulnerability could result in an attacker impersonating the real user.**
+
+In order to support DPoP in `auth0-spa-js`, we require some APIs found in modern browsers:
+
+- [Crypto API](https://developer.mozilla.org/en-US/docs/Web/API/Crypto): it allows to create and use cryptographic keys that will be used for creating the proofs (i.e. signatures) used in DPoP.
+
+- [IndexedDB](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API): it allows to use cryptographic keys [without giving access to the private material](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto#storing_keys).
+
+The following OAuth 2.0 flows are currently supported by `auth0-spa-js`:
+
+- [Authorization Code Flow](https://auth0.com/docs/get-started/authentication-and-authorization-flow/authorization-code-flow) (`authorization_code`).
+
+- [Refresh Token Flow](https://auth0.com/docs/secure/tokens/refresh-tokens) (`refresh_token`).
+
+- [Custom Token Exchange Flow](https://auth0.com/docs/authenticate/custom-token-exchange) (`urn:ietf:params:oauth:grant-type:token-exchange`).
+
+Currently, only the `ES256` algorithm is supported.
+
+### Enabling DPoP
+
+Currently, DPoP is disabled by default. To enable it, set the `useDpop` option to `true` when invoking the provider. For example:
+
+```jsx
+
+```
+
+After enabling DPoP, supported OAuth 2.0 flows in Auth0 will start transparently issuing tokens that will be cryptographically bound to the current browser.
+
+Note that a DPoP token will have to be sent to a resource server with an `Authorization: DPoP ` header instead of `Authorization: Bearer ` as usual.
+
+If you're using both types at the same time, you can use the `detailedResponse` option in `getAccessTokenSilently()` to get access to the `token_type` property and know what kind of token you got:
+
+```js
+const headers = {
+ Authorization: `${token.token_type} ${token.access_token}`,
+};
+```
+
+If all your clients are already using DPoP, you may want to increase security and make Auth0 reject non-DPoP interactions by enabling the "Require Token Sender-Constraining" option in your Auth0's application settings. Check [the docs](https://auth0.com/docs/get-started/applications/configure-sender-constraining) for details.
+
+### Clearing DPoP data
+
+When using DPoP some temporary data is stored in the user's browser. When you log the user out with `logout()`, it will be deleted.
+
+### Using DPoP in your own requests
+
+Enabling `useDpop` **protects every internal request that the SDK sends to Auth0** (i.e. the authorization server).
+
+However, if you want to use a DPoP access token to authenticate against a custom API (i.e. a resource server), some extra work is required. `Auth0Provider` has some methods that will provide the needed pieces:
+
+- `getDpopNonce()`
+- `setDpopNonce()`
+- `generateDpopProof()`
+
+This example shows how these coould be used:
+
+```jsx
+import { useEffect, useState } from 'react';
+import { useAuth0 } from '@auth0/auth0-react';
+
+const Posts = () => {
+ const {
+ getAccessTokenSilently,
+ getDpopNonce,
+ setDpopNonce,
+ generateDpopProof,
+ } = useAuth0();
+
+ const [posts, setPosts] = useState(null);
+
+ useEffect(() => {
+ (async () => {
+ // Define an identifier that the SDK will use to reference the nonces.
+ const nonceId = 'my_api_request';
+
+ // Get an access token as usual.
+ const accessToken = await getAccessTokenSilently();
+
+ // Get the current DPoP nonce (if any) and do the request with it.
+ const nonce = await getDpopNonce(nonceId);
+
+ const response = await fetchWithDpop({
+ url: 'https://api.example.com/posts',
+ method: 'GET',
+ accessToken,
+ nonce,
+ });
+
+ setPosts(await response.json());
+
+ async function fetchWithDpop({
+ url,
+ method,
+ body,
+ accessToken,
+ nonce,
+ isDpopNonceRetry,
+ }) {
+ const headers = {
+ // A DPoP access token has the type `DPoP` and not `Bearer`.
+ Authorization: `DPoP ${accessToken}`,
+
+ // Include the DPoP proof, which is cryptographic evidence that we
+ // are in possession of the same key that was used to get the token.
+ DPoP: await generateDpopProof({ url, method, nonce, accessToken }),
+ };
+
+ // Make the request.
+ const response = await fetch(url, { method, headers, body });
+
+ // If there was a nonce in the response, save it.
+ const newNonce = response.headers.get('dpop-nonce');
+
+ if (newNonce) {
+ setDpopNonce(newNonce, nonceId);
+ }
+
+ // If the server rejects the DPoP nonce but it provides a new one, try
+ // the request one last time with the correct nonce.
+ if (
+ response.status === 401 &&
+ response.headers.get('www-authenticate')?.includes('use_dpop_nonce')
+ ) {
+ if (isDpopNonceRetry) {
+ throw new Error('DPoP nonce was rejected twice, giving up');
+ }
+
+ return fetchWithDpop({
+ ...params,
+ nonce: newNonce ?? nonce,
+ isDpopNonceRetry: true,
+ });
+ }
+
+ return response;
+ }
+ })();
+ }, []);
+
+ if (!posts) {
+ return Loading...
;
+ }
+
+ return (
+
+ {posts.map((post, index) => {
+ return - {post}
;
+ })}
+
+ );
+};
+
+export default Posts;
+```
diff --git a/__mocks__/@auth0/auth0-spa-js.tsx b/__mocks__/@auth0/auth0-spa-js.tsx
index b19548ad..20bd0fd6 100644
--- a/__mocks__/@auth0/auth0-spa-js.tsx
+++ b/__mocks__/@auth0/auth0-spa-js.tsx
@@ -10,6 +10,9 @@ const isAuthenticated = jest.fn(() => false);
const loginWithPopup = jest.fn();
const loginWithRedirect = jest.fn();
const logout = jest.fn();
+const getDpopNonce = jest.fn();
+const setDpopNonce = jest.fn();
+const generateDpopProof = jest.fn();
export const Auth0Client = jest.fn(() => {
return {
@@ -25,5 +28,8 @@ export const Auth0Client = jest.fn(() => {
loginWithPopup,
loginWithRedirect,
logout,
+ getDpopNonce,
+ setDpopNonce,
+ generateDpopProof,
};
});
diff --git a/__tests__/auth-provider.test.tsx b/__tests__/auth-provider.test.tsx
index ee506f8b..b224c148 100644
--- a/__tests__/auth-provider.test.tsx
+++ b/__tests__/auth-provider.test.tsx
@@ -522,6 +522,7 @@ describe('Auth0Provider', () => {
access_token: '123',
id_token: '456',
expires_in: 2,
+ token_type: 'Bearer',
};
(clientMock.getTokenSilently as jest.Mock).mockResolvedValue(tokenResponse);
const wrapper = createWrapper();
@@ -940,6 +941,52 @@ describe('Auth0Provider', () => {
});
});
+ it('should provide a getDpopNonce method', async () => {
+ const wrapper = createWrapper();
+ const { result } = renderHook(
+ () => useContext(Auth0Context),
+ { wrapper }
+ );
+
+ expect(result.current.getDpopNonce).toBeInstanceOf(Function);
+ await act(() => result.current.getDpopNonce())
+ expect(clientMock.getDpopNonce).toHaveBeenCalled();
+ });
+
+ it('should provide a setDpopNonce method', async () => {
+ const wrapper = createWrapper();
+ const { result } = renderHook(
+ () => useContext(Auth0Context),
+ { wrapper }
+ );
+
+ const nonce = 'n-123456';
+ const id = 'my-nonce';
+
+ expect(result.current.setDpopNonce).toBeInstanceOf(Function);
+ await act(() => result.current.setDpopNonce(nonce, id))
+ expect(clientMock.setDpopNonce).toHaveBeenCalledWith(nonce, id);
+ });
+
+ it('should provide a generateDpopProof method', async () => {
+ const wrapper = createWrapper();
+ const { result } = renderHook(
+ () => useContext(Auth0Context),
+ { wrapper }
+ );
+
+ const params = {
+ url: 'https://api.example.com/foo',
+ method: 'GET',
+ nonce: 'n-123456',
+ accessToken: 'at-123456',
+ };
+
+ expect(result.current.generateDpopProof).toBeInstanceOf(Function);
+ await act(() => result.current.generateDpopProof(params))
+ expect(clientMock.generateDpopProof).toHaveBeenCalledWith(params);
+ });
+
it('should not update context value after rerender with no state change', async () => {
clientMock.getTokenSilently.mockReturnThis();
clientMock.getUser.mockResolvedValue({ name: 'foo' });
diff --git a/src/auth0-context.tsx b/src/auth0-context.tsx
index 62d74d1e..ae4e1408 100644
--- a/src/auth0-context.tsx
+++ b/src/auth0-context.tsx
@@ -140,6 +140,46 @@ export interface Auth0ContextInterface
* @param url The URL to that should be used to retrieve the `state` and `code` values. Defaults to `window.location.href` if not given.
*/
handleRedirectCallback: (url?: string) => Promise;
+
+ /**
+ * Returns the current DPoP nonce used for making requests to Auth0.
+ *
+ * It can return `undefined` because when starting fresh it will not
+ * be populated until after the first response from the server.
+ *
+ * It requires enabling the {@link Auth0ClientOptions.useDpop} option.
+ *
+ * @param nonce The nonce value.
+ * @param id The identifier of a nonce: if absent, it will set the nonce
+ * used for requests to Auth0. Otherwise, it will be used to
+ * select a specific non-Auth0 nonce.
+ */
+ getDpopNonce(id?: string): Promise;
+
+ /**
+ * Gets the current DPoP nonce used for making requests to Auth0.
+ *
+ * It requires enabling the {@link Auth0ClientOptions.useDpop} option.
+ *
+ * @param nonce The nonce value.
+ * @param id The identifier of a nonce: if absent, it will set the nonce
+ * used for requests to Auth0. Otherwise, it will be used to
+ * select a specific non-Auth0 nonce.
+ */
+ setDpopNonce(nonce: string, id?: string): Promise;
+
+ /**
+ * Returns a string to be used to demonstrate possession of the private
+ * key used to cryptographically bind access tokens with DPoP.
+ *
+ * It requires enabling the {@link Auth0ClientOptions.useDpop} option.
+ */
+ generateDpopProof(params: {
+ url: string;
+ method: string;
+ nonce?: string;
+ accessToken: string;
+ }): Promise;
}
/**
@@ -163,6 +203,9 @@ export const initialContext = {
loginWithPopup: stub,
logout: stub,
handleRedirectCallback: stub,
+ getDpopNonce: stub,
+ setDpopNonce: stub,
+ generateDpopProof: stub,
};
/**
diff --git a/src/auth0-provider.tsx b/src/auth0-provider.tsx
index 47df9472..b7b26557 100644
--- a/src/auth0-provider.tsx
+++ b/src/auth0-provider.tsx
@@ -272,6 +272,23 @@ const Auth0Provider = (opts: Auth0ProviderOptions client.getDpopNonce(), [client]);
+
+ const setDpopNonce = useCallback(
+ (nonce: string, nonceId?: string) => client.setDpopNonce(nonce, nonceId),
+ [client]
+ );
+
+ const generateDpopProof = useCallback(
+ (params: {
+ url: string;
+ method: string;
+ nonce?: string;
+ accessToken: string;
+ }) => client.generateDpopProof(params),
+ [client]
+ );
+
const contextValue = useMemo>(() => {
return {
...state,
@@ -282,6 +299,9 @@ const Auth0Provider = (opts: Auth0ProviderOptions(opts: Auth0ProviderOptions{children};
From 1b4c2632cd9c3c9ddced7d0b36fe2ba8ee65d260 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mart=C3=ADn=20Melado?=
<217925+martinml@users.noreply.github.com>
Date: Wed, 30 Jul 2025 21:46:39 +0200
Subject: [PATCH 2/9] Revert accidental auto-formatting changes
---
EXAMPLES.md | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/EXAMPLES.md b/EXAMPLES.md
index 98e16975..35ec91c7 100644
--- a/EXAMPLES.md
+++ b/EXAMPLES.md
@@ -326,18 +326,18 @@ In order to protect a route with a claims check alongside an authentication requ
```jsx
const withClaimCheck = (Component, myClaimCheckFunction, returnTo) => {
- const { user } = useAuth0();
+ const { user } = useAuth0();
if (myClaimCheckFunction(user)) {
- return ;
+ return
}
Router.push(returnTo);
-};
+}
const checkClaims = (claim?: User) => claim?.['https://my.app.io/jwt/claims']?.ROLE?.includes('ADMIN');
// Usage
const Page = withAuthenticationRequired(
- withClaimCheck(Component, checkClaims, '/missing-roles')
+ withClaimCheck(Component, checkClaims, '/missing-roles' )
);
```
From 1a6f0dbf088fcfba9679ce250c6e73040b6842b1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mart=C3=ADn=20Melado?=
<217925+martinml@users.noreply.github.com>
Date: Thu, 31 Jul 2025 13:00:08 +0200
Subject: [PATCH 3/9] Fix bad parameter syntax in example
---
EXAMPLES.md | 12 ++++--------
1 file changed, 4 insertions(+), 8 deletions(-)
diff --git a/EXAMPLES.md b/EXAMPLES.md
index 35ec91c7..6651abe4 100644
--- a/EXAMPLES.md
+++ b/EXAMPLES.md
@@ -440,14 +440,10 @@ const Posts = () => {
setPosts(await response.json());
- async function fetchWithDpop({
- url,
- method,
- body,
- accessToken,
- nonce,
- isDpopNonceRetry,
- }) {
+ async function fetchWithDpop(params) {
+ const { url, method, body, accessToken, nonce, isDpopNonceRetry } =
+ params;
+
const headers = {
// A DPoP access token has the type `DPoP` and not `Bearer`.
Authorization: `DPoP ${accessToken}`,
From a97412acdd2cbeed9a7e6ad543e0e1a92520be46 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mart=C3=ADn=20Melado?=
<217925+martinml@users.noreply.github.com>
Date: Wed, 13 Aug 2025 19:22:08 +0200
Subject: [PATCH 4/9] Add fetcher support and docs and simplify types
---
EXAMPLES.md | 293 +++++++++++++++++++-----------
__mocks__/@auth0/auth0-spa-js.tsx | 2 +
__tests__/auth-provider.test.tsx | 32 ++--
src/auth0-context.tsx | 17 +-
src/auth0-provider.tsx | 25 ++-
src/index.tsx | 4 +-
6 files changed, 227 insertions(+), 146 deletions(-)
diff --git a/EXAMPLES.md b/EXAMPLES.md
index 6651abe4..85b39320 100644
--- a/EXAMPLES.md
+++ b/EXAMPLES.md
@@ -343,17 +343,17 @@ const Page = withAuthenticationRequired(
## Device-bound tokens with DPoP
-**Demonstrating Proof-of-Possession** –or just **DPoP**– is an OAuth 2.0 extension defined in [RFC9449](https://datatracker.ietf.org/doc/html/rfc9449).
+**Demonstrating Proof-of-Possession** —or simply **DPoP**— is a recent OAuth 2.0 extension defined in [RFC9449](https://datatracker.ietf.org/doc/html/rfc9449).
-It defines a mechanism for securely binding tokens to a specific device by means of cryptographic signatures. Without it, **a token leak caused by XSS or other vulnerability could result in an attacker impersonating the real user.**
+It defines a mechanism for securely binding tokens to a specific device using cryptographic signatures. Without it, **a token leak caused by XSS or other vulnerabilities could allow an attacker to impersonate the real user.**
-In order to support DPoP in `auth0-spa-js`, we require some APIs found in modern browsers:
+To support DPoP in `auth0-react`, some APIs available in modern browsers are required:
-- [Crypto API](https://developer.mozilla.org/en-US/docs/Web/API/Crypto): it allows to create and use cryptographic keys that will be used for creating the proofs (i.e. signatures) used in DPoP.
+- [Crypto API](https://developer.mozilla.org/en-US/docs/Web/API/Crypto): allows to create and use cryptographic keys, which are used to generate the proofs (i.e. signatures) required for DPoP.
-- [IndexedDB](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API): it allows to use cryptographic keys [without giving access to the private material](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto#storing_keys).
+- [IndexedDB](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API): enables the use of cryptographic keys [without exposing the private material](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto#storing_keys).
-The following OAuth 2.0 flows are currently supported by `auth0-spa-js`:
+The following OAuth 2.0 flows are currently supported by `auth0-react`:
- [Authorization Code Flow](https://auth0.com/docs/get-started/authentication-and-authorization-flow/authorization-code-flow) (`authorization_code`).
@@ -361,11 +361,12 @@ The following OAuth 2.0 flows are currently supported by `auth0-spa-js`:
- [Custom Token Exchange Flow](https://auth0.com/docs/authenticate/custom-token-exchange) (`urn:ietf:params:oauth:grant-type:token-exchange`).
-Currently, only the `ES256` algorithm is supported.
+> [!IMPORTANT]
+> Currently, only the `ES256` algorithm is supported.
### Enabling DPoP
-Currently, DPoP is disabled by default. To enable it, set the `useDpop` option to `true` when invoking the provider. For example:
+DPoP is disabled by default. To enable it, set the `useDpop` option to `true` when invoking the provider. For example:
```jsx
```
-After enabling DPoP, supported OAuth 2.0 flows in Auth0 will start transparently issuing tokens that will be cryptographically bound to the current browser.
+After enabling DPoP, **every new session using a supported OAuth 2.0 flow in Auth0 will begin transparently to use tokens that are cryptographically bound to the current browser**.
-Note that a DPoP token will have to be sent to a resource server with an `Authorization: DPoP ` header instead of `Authorization: Bearer ` as usual.
-
-If you're using both types at the same time, you can use the `detailedResponse` option in `getAccessTokenSilently()` to get access to the `token_type` property and know what kind of token you got:
+> [!IMPORTANT]
+> DPoP will only be used for new user sessions created after enabling it. Any previously existing sessions will continue using non-DPoP tokens until the user logs in again.
+>
+> You decide how to handle this transition. For example, you might require users to log in again the next time they use your application.
-```js
-const headers = {
- Authorization: `${token.token_type} ${token.access_token}`,
-};
-```
+> [!IMPORTANT]
+> Using DPoP requires storing some temporary data in the user's browser. When you log the user out with `logout()`, this data is deleted.
-If all your clients are already using DPoP, you may want to increase security and make Auth0 reject non-DPoP interactions by enabling the "Require Token Sender-Constraining" option in your Auth0's application settings. Check [the docs](https://auth0.com/docs/get-started/applications/configure-sender-constraining) for details.
+> [!IMPORTANT]
+> If all your clients are already using DPoP, you may want to increase security by making Auth0 reject any non-DPoP interactions. See [the docs on Sender Constraining](https://auth0.com/docs/secure/sender-constraining/configure-sender-constraining) for details.
-### Clearing DPoP data
+### Using DPoP in your own requests
-When using DPoP some temporary data is stored in the user's browser. When you log the user out with `logout()`, it will be deleted.
+You use a DPoP token the same way as a "traditional" access token, except it must be sent to the server with an `Authorization: DPoP ` header instead of the usual `Authorization: Bearer `.
-### Using DPoP in your own requests
+To determine the type of a token, use the `detailedResponse` option in `getAccessTokenSilently()` to access the `token_type` property, which will be either `DPoP` or `Bearer`.
-Enabling `useDpop` **protects every internal request that the SDK sends to Auth0** (i.e. the authorization server).
+For internal requests sent by `auth0-react` to Auth0, simply enable the `useDpop` option and **every interaction with Auth0 will be protected**.
-However, if you want to use a DPoP access token to authenticate against a custom API (i.e. a resource server), some extra work is required. `Auth0Provider` has some methods that will provide the needed pieces:
+However, **to use DPoP with a custom, external API, some additional work is required**. The `useAuth()` hook provides some low-level methods to help with this:
- `getDpopNonce()`
- `setDpopNonce()`
- `generateDpopProof()`
-This example shows how these coould be used:
+However, due to the nature of how DPoP works, **this is not a trivial task**:
-```jsx
-import { useEffect, useState } from 'react';
-import { useAuth0 } from '@auth0/auth0-react';
+- When a nonce is missing or expired, the request may need to be retried.
+- Received nonces must be stored and managed.
+- DPoP headers must be generated and included in every request, and regenerated for retries.
-const Posts = () => {
- const {
- getAccessTokenSilently,
- getDpopNonce,
- setDpopNonce,
- generateDpopProof,
- } = useAuth0();
+Because of this, we recommend using the provided `fetchWithAuth()` method, which **handles all of this for you**.
- const [posts, setPosts] = useState(null);
+#### Simple usage
- useEffect(() => {
- (async () => {
- // Define an identifier that the SDK will use to reference the nonces.
- const nonceId = 'my_api_request';
-
- // Get an access token as usual.
- const accessToken = await getAccessTokenSilently();
-
- // Get the current DPoP nonce (if any) and do the request with it.
- const nonce = await getDpopNonce(nonceId);
-
- const response = await fetchWithDpop({
- url: 'https://api.example.com/posts',
- method: 'GET',
- accessToken,
- nonce,
- });
-
- setPosts(await response.json());
-
- async function fetchWithDpop(params) {
- const { url, method, body, accessToken, nonce, isDpopNonceRetry } =
- params;
-
- const headers = {
- // A DPoP access token has the type `DPoP` and not `Bearer`.
- Authorization: `DPoP ${accessToken}`,
-
- // Include the DPoP proof, which is cryptographic evidence that we
- // are in possession of the same key that was used to get the token.
- DPoP: await generateDpopProof({ url, method, nonce, accessToken }),
- };
-
- // Make the request.
- const response = await fetch(url, { method, headers, body });
-
- // If there was a nonce in the response, save it.
- const newNonce = response.headers.get('dpop-nonce');
-
- if (newNonce) {
- setDpopNonce(newNonce, nonceId);
- }
-
- // If the server rejects the DPoP nonce but it provides a new one, try
- // the request one last time with the correct nonce.
- if (
- response.status === 401 &&
- response.headers.get('www-authenticate')?.includes('use_dpop_nonce')
- ) {
- if (isDpopNonceRetry) {
- throw new Error('DPoP nonce was rejected twice, giving up');
- }
-
- return fetchWithDpop({
- ...params,
- nonce: newNonce ?? nonce,
- isDpopNonceRetry: true,
- });
- }
-
- return response;
- }
- })();
- }, []);
+The `fetchWithAuth()` method is a drop-in replacement for the native `fetch()` function from the Fetch API, so if you're already using it, the change will be minimal.
- if (!posts) {
- return Loading...
;
- }
+For example, if you had this code:
- return (
-
- {posts.map((post, index) => {
- return - {post}
;
- })}
-
- );
-};
+```js
+await fetch('https://api.example.com/foo', {
+ method: 'GET',
+ headers: { 'user-agent': 'My Client 1.0' }
+});
-export default Posts;
+console.log(response.status);
+console.log(response.headers);
+console.log(await response.json());
+```
+
+You would change it as follows:
+
+```js
+const { createFetcher } = useAuth0();
+
+const fetcher = createFetcher({
+ dpopNonceId: 'my_api_request'
+});
+
+await fetcher.fetchWithAuth('https://api.example.com/foo', {
+ method: 'GET',
+ headers: { 'user-agent': 'My Client 1.0' }
+});
+
+console.log(response.status);
+console.log(response.headers);
+console.log(await response.json());
+```
+
+When using `fetchWithAuth()`, the following will be handled for you automatically:
+
+- Use `getAccessTokenSilently()` to get the access token to inject in the headers.
+- Generate and inject DPoP headers when needed.
+- Store and update any DPoP nonces.
+- Handle retries caused by a rejected nonce.
+
+> [!IMPORTANT]
+> If DPoP is enabled in the provider, a `dpopNonceId` **must** be present in the `createFetcher()` parameters, since it’s used to keep track of the DPoP nonces for each request.
+
+#### Advanced usage
+
+If you need something more complex than the example above, you can provide a custom implementation in the `fetch` property.
+
+However, since `auth0-react` needs to make decisions based on HTTP responses, your implementation **must return an object with _at least_ two properties**:
+
+1. `status`: the response status code as a number.
+2. `headers`: the response headers as a plain object or as a Fetch API’s Headers-like interface.
+
+Whatever it returns, it will be passed as the output of the `fetchWithAuth()` method.
+
+Your implementation will be called with a standard, ready-to-use [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object, which will contain any headers needed for authorization and DPoP usage (if enabled). Depending on your needs, you can use this object directly or treat it as a container with everything required to make the request your own way.
+
+##### Example with `axios`
+
+```js
+const { createFetcher } = useAuth0();
+
+const fetcher = createFetcher({
+ dpopNonceId: 'my_api_request',
+ fetch: (request) =>
+ // The `Request` object has everything you need to do a request in a
+ // different library. Make sure that your output meets the requirements
+ // about the `status` and `headers` properties.
+ axios.request({
+ url: request.url,
+ method: request.method,
+ data: request.body,
+ headers: Object.fromEntries(request.headers),
+ timeout: 2000,
+ // etc.
+ }),
+ },
+});
+
+const response = await fetcher.fetchWithAuth('https://api.example.com/foo', {
+ method: 'POST',
+ body: JSON.stringify({ name: 'John Doe' }),
+ headers: { 'user-agent': 'My Client 1.0' },
+});
+
+console.log(response.status);
+console.log(response.headers);
+console.log(response.data);
+```
+
+##### Timeouts with native `fetch()`
+
+The Fetch API doesn’t support passing a timeout value directly; instead, you’re expected to use an [AbortSignal](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal). For example:
+
+```js
+const { createFetcher } = useAuth0();
+
+const fetcher = createFetcher();
+
+await fetcher.fetchWithAuth('https://api.example.com/foo', {
+ signal: AbortSignal.timeout(2000)
+});
+```
+
+This works, but if you define your request parameters statically when your app starts and then call `fetchWithAuth()` after an indeterminate amount of time, you'll find that **the request will timeout immediately**. This happens because the `AbortSignal` **starts counting time as soon as it is created**.
+
+To work around this, you can pass a thin wrapper over the native `fetch()` so that a new `AbortSignal` is created each time a request is made:
+
+```js
+const { createFetcher } = useAuth0();
+
+const fetcher = createFetcher({
+ fetch: (request) => signal: AbortSignal.timeout(2000),
+});
+
+await fetcher.fetchWithAuth('https://api.example.com/foo');
+```
+
+##### Having a base URL
+
+If you need to make requests to different endpoints of the same API, passing a `baseUrl` to `createFetcher()` can be useful:
+
+```js
+const { createFetcher } = useAuth0();
+
+const fetcher = createFetcher({
+ baseUrl: 'https://api.example.com'
+});
+
+await fetcher.fetchWithAuth('/foo'); // => https://api.example.com/foo
+await fetcher.fetchWithAuth('/bar'); // => https://api.example.com/bar
+await fetcher.fetchWithAuth('/xyz'); // => https://api.example.com/xyz
+
+// If the passed URL is absolute, `baseUrl` will be ignored for convenience:
+await fetcher.fetchWithAuth('https://other-api.example.com/foo');
+```
+
+##### Passing an access token
+
+The `fetchWithAuth()` method assumes you’re using the SDK to get the access token for the request. This means that by default, it will always call `getAccessTokenSilently()` internally before making the request.
+
+However, if you already have an access token or need to pass specific parameters to `getAccessTokenSilently()`, you can override this behavior with a custom access token factory, like so:
+
+```js
+const { createFetcher, getAccessTokenSilently } = useAuth0();
+
+createFetcher({
+ getAccessToken: () =>
+ getAccessTokenSilently({
+ authorizationParams: {
+ audience: '',
+ scope: ''
+ // etc.
+ }
+ })
+});
```
diff --git a/__mocks__/@auth0/auth0-spa-js.tsx b/__mocks__/@auth0/auth0-spa-js.tsx
index 20bd0fd6..713e5d6d 100644
--- a/__mocks__/@auth0/auth0-spa-js.tsx
+++ b/__mocks__/@auth0/auth0-spa-js.tsx
@@ -13,6 +13,7 @@ const logout = jest.fn();
const getDpopNonce = jest.fn();
const setDpopNonce = jest.fn();
const generateDpopProof = jest.fn();
+const createFetcher = jest.fn();
export const Auth0Client = jest.fn(() => {
return {
@@ -31,5 +32,6 @@ export const Auth0Client = jest.fn(() => {
getDpopNonce,
setDpopNonce,
generateDpopProof,
+ createFetcher,
};
});
diff --git a/__tests__/auth-provider.test.tsx b/__tests__/auth-provider.test.tsx
index b224c148..143d6422 100644
--- a/__tests__/auth-provider.test.tsx
+++ b/__tests__/auth-provider.test.tsx
@@ -943,37 +943,28 @@ describe('Auth0Provider', () => {
it('should provide a getDpopNonce method', async () => {
const wrapper = createWrapper();
- const { result } = renderHook(
- () => useContext(Auth0Context),
- { wrapper }
- );
+ const { result } = renderHook(() => useContext(Auth0Context), { wrapper });
expect(result.current.getDpopNonce).toBeInstanceOf(Function);
- await act(() => result.current.getDpopNonce())
+ await act(() => result.current.getDpopNonce());
expect(clientMock.getDpopNonce).toHaveBeenCalled();
});
it('should provide a setDpopNonce method', async () => {
const wrapper = createWrapper();
- const { result } = renderHook(
- () => useContext(Auth0Context),
- { wrapper }
- );
+ const { result } = renderHook(() => useContext(Auth0Context), { wrapper });
const nonce = 'n-123456';
const id = 'my-nonce';
expect(result.current.setDpopNonce).toBeInstanceOf(Function);
- await act(() => result.current.setDpopNonce(nonce, id))
+ await act(() => result.current.setDpopNonce(nonce, id));
expect(clientMock.setDpopNonce).toHaveBeenCalledWith(nonce, id);
});
it('should provide a generateDpopProof method', async () => {
const wrapper = createWrapper();
- const { result } = renderHook(
- () => useContext(Auth0Context),
- { wrapper }
- );
+ const { result } = renderHook(() => useContext(Auth0Context), { wrapper });
const params = {
url: 'https://api.example.com/foo',
@@ -983,10 +974,21 @@ describe('Auth0Provider', () => {
};
expect(result.current.generateDpopProof).toBeInstanceOf(Function);
- await act(() => result.current.generateDpopProof(params))
+ await act(() => result.current.generateDpopProof(params));
expect(clientMock.generateDpopProof).toHaveBeenCalledWith(params);
});
+ it('should provide a createFetcher method', async () => {
+ const wrapper = createWrapper();
+ const { result } = renderHook(() => useContext(Auth0Context), { wrapper });
+
+ const config = { dpopNonceId: 'my_dpop_nonce_test_id' };
+
+ expect(result.current.createFetcher).toBeInstanceOf(Function);
+ await act(() => result.current.createFetcher(config));
+ expect(clientMock.createFetcher).toHaveBeenCalledWith(config);
+ });
+
it('should not update context value after rerender with no state change', async () => {
clientMock.getTokenSilently.mockReturnThis();
clientMock.getUser.mockResolvedValue({ name: 'foo' });
diff --git a/src/auth0-context.tsx b/src/auth0-context.tsx
index ae4e1408..e9cab796 100644
--- a/src/auth0-context.tsx
+++ b/src/auth0-context.tsx
@@ -9,6 +9,7 @@ import {
User,
GetTokenSilentlyVerboseResponse,
RedirectLoginOptions as SPARedirectLoginOptions,
+ type Auth0Client,
} from '@auth0/auth0-spa-js';
import { createContext } from 'react';
import { AuthState, initialAuthState } from './auth-state';
@@ -150,11 +151,11 @@ export interface Auth0ContextInterface
* It requires enabling the {@link Auth0ClientOptions.useDpop} option.
*
* @param nonce The nonce value.
- * @param id The identifier of a nonce: if absent, it will set the nonce
+ * @param id The identifier of a nonce: if absent, it will get the nonce
* used for requests to Auth0. Otherwise, it will be used to
* select a specific non-Auth0 nonce.
*/
- getDpopNonce(id?: string): Promise;
+ getDpopNonce: Auth0Client['getDpopNonce'];
/**
* Gets the current DPoP nonce used for making requests to Auth0.
@@ -166,7 +167,7 @@ export interface Auth0ContextInterface
* used for requests to Auth0. Otherwise, it will be used to
* select a specific non-Auth0 nonce.
*/
- setDpopNonce(nonce: string, id?: string): Promise;
+ setDpopNonce: Auth0Client['setDpopNonce'];
/**
* Returns a string to be used to demonstrate possession of the private
@@ -174,12 +175,9 @@ export interface Auth0ContextInterface
*
* It requires enabling the {@link Auth0ClientOptions.useDpop} option.
*/
- generateDpopProof(params: {
- url: string;
- method: string;
- nonce?: string;
- accessToken: string;
- }): Promise;
+ generateDpopProof: Auth0Client['generateDpopProof'];
+
+ createFetcher: Auth0Client['createFetcher'];
}
/**
@@ -206,6 +204,7 @@ export const initialContext = {
getDpopNonce: stub,
setDpopNonce: stub,
generateDpopProof: stub,
+ createFetcher: stub,
};
/**
diff --git a/src/auth0-provider.tsx b/src/auth0-provider.tsx
index b7b26557..c6bcd5aa 100644
--- a/src/auth0-provider.tsx
+++ b/src/auth0-provider.tsx
@@ -272,20 +272,23 @@ const Auth0Provider = (opts: Auth0ProviderOptions client.getDpopNonce(), [client]);
+ const getDpopNonce = useCallback(
+ (id) => client.getDpopNonce(id),
+ [client]
+ );
+
+ const setDpopNonce = useCallback(
+ (nonce, id) => client.setDpopNonce(nonce, id),
+ [client]
+ );
- const setDpopNonce = useCallback(
- (nonce: string, nonceId?: string) => client.setDpopNonce(nonce, nonceId),
+ const generateDpopProof = useCallback(
+ (params) => client.generateDpopProof(params),
[client]
);
- const generateDpopProof = useCallback(
- (params: {
- url: string;
- method: string;
- nonce?: string;
- accessToken: string;
- }) => client.generateDpopProof(params),
+ const createFetcher = useCallback(
+ (config) => client.createFetcher(config),
[client]
);
@@ -302,6 +305,7 @@ const Auth0Provider = (opts: Auth0ProviderOptions(opts: Auth0ProviderOptions{children};
diff --git a/src/index.tsx b/src/index.tsx
index 3b860ff1..94efde79 100644
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -36,6 +36,8 @@ export {
PopupTimeoutError,
AuthenticationError,
MissingRefreshTokenError,
- GenericError
+ GenericError,
+ UseDpopNonceError,
+ type FetcherConfig
} from '@auth0/auth0-spa-js';
export { OAuthError } from './errors';
From 9f672feececa3c776999e2ad37c415f9cf771933 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mart=C3=ADn=20Melado?=
<217925+martinml@users.noreply.github.com>
Date: Tue, 26 Aug 2025 10:43:29 +0200
Subject: [PATCH 5/9] Improve docs
---
EXAMPLES.md | 4 ++--
src/auth0-context.tsx | 10 +++++++++-
2 files changed, 11 insertions(+), 3 deletions(-)
diff --git a/EXAMPLES.md b/EXAMPLES.md
index 85b39320..2c568e6c 100644
--- a/EXAMPLES.md
+++ b/EXAMPLES.md
@@ -384,10 +384,10 @@ After enabling DPoP, **every new session using a supported OAuth 2.0 flow in Aut
>
> You decide how to handle this transition. For example, you might require users to log in again the next time they use your application.
-> [!IMPORTANT]
+> [!NOTE]
> Using DPoP requires storing some temporary data in the user's browser. When you log the user out with `logout()`, this data is deleted.
-> [!IMPORTANT]
+> [!TIP]
> If all your clients are already using DPoP, you may want to increase security by making Auth0 reject any non-DPoP interactions. See [the docs on Sender Constraining](https://auth0.com/docs/secure/sender-constraining/configure-sender-constraining) for details.
### Using DPoP in your own requests
diff --git a/src/auth0-context.tsx b/src/auth0-context.tsx
index e9cab796..8ddd046e 100644
--- a/src/auth0-context.tsx
+++ b/src/auth0-context.tsx
@@ -158,7 +158,7 @@ export interface Auth0ContextInterface
getDpopNonce: Auth0Client['getDpopNonce'];
/**
- * Gets the current DPoP nonce used for making requests to Auth0.
+ * Sets the current DPoP nonce used for making requests to Auth0.
*
* It requires enabling the {@link Auth0ClientOptions.useDpop} option.
*
@@ -177,6 +177,14 @@ export interface Auth0ContextInterface
*/
generateDpopProof: Auth0Client['generateDpopProof'];
+ /**
+ * Returns a new `Fetcher` class that will contain a `fetchWithAuth()` method.
+ * This is a drop-in replacement for the Fetch API's `fetch()` method, but will
+ * handle certain authentication logic for you, like building the proper auth
+ * headers or managing DPoP nonces and retries automatically.
+ *
+ * Check the `EXAMPLES.md` file for a deeper look into this method.
+ */
createFetcher: Auth0Client['createFetcher'];
}
From c88e0dc3cca9ea4b45e3ba0c6952062bc5e78071 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mart=C3=ADn=20Melado?=
<217925+martinml@users.noreply.github.com>
Date: Tue, 26 Aug 2025 11:04:15 +0200
Subject: [PATCH 6/9] Fix broken code in examples
---
EXAMPLES.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/EXAMPLES.md b/EXAMPLES.md
index 2c568e6c..0637ee52 100644
--- a/EXAMPLES.md
+++ b/EXAMPLES.md
@@ -526,7 +526,7 @@ To work around this, you can pass a thin wrapper over the native `fetch()` so th
const { createFetcher } = useAuth0();
const fetcher = createFetcher({
- fetch: (request) => signal: AbortSignal.timeout(2000),
+ fetch: (request) => fetch(request, { signal: AbortSignal.timeout(2000) })
});
await fetcher.fetchWithAuth('https://api.example.com/foo');
From 78f4bc49d50fe8b9c2df57e2bc0351f78a1c112d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mart=C3=ADn=20Melado?=
<217925+martinml@users.noreply.github.com>
Date: Mon, 8 Sep 2025 18:04:38 +0200
Subject: [PATCH 7/9] Bring in `auth0-spa-js` with DPoP support (2.3.0 ->
2.4.0)
---
package-lock.json | 8 ++++----
package.json | 2 +-
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index 52ad95af..42344612 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -9,7 +9,7 @@
"version": "2.4.0",
"license": "MIT",
"dependencies": {
- "@auth0/auth0-spa-js": "^2.2.0"
+ "@auth0/auth0-spa-js": "^2.4.0"
},
"devDependencies": {
"@rollup/plugin-node-resolve": "^15.0.1",
@@ -74,9 +74,9 @@
}
},
"node_modules/@auth0/auth0-spa-js": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/@auth0/auth0-spa-js/-/auth0-spa-js-2.3.0.tgz",
- "integrity": "sha512-zAW6w79UO+G1+3AxboVQIUIZy05xluSOb1ymGg2dqG0pIi0JxEtZGec05BOf2LJ9SehzW4WeCYUQsYD9BjrVpQ==",
+ "version": "2.4.0",
+ "resolved": "https://a0us.jfrog.io/artifactory/api/npm/npm/@auth0/auth0-spa-js/-/auth0-spa-js-2.4.0.tgz",
+ "integrity": "sha512-Hq37s9r2FYPAcP/WsslcjAeZhPStnfV2gRmXhIqWTSG/acxFt7eS2+yU5VM3KPxdwtv9ZzlZgoMFIsggpRV0Dw==",
"license": "MIT"
},
"node_modules/@babel/code-frame": {
diff --git a/package.json b/package.json
index 7d055e55..55628f9f 100644
--- a/package.json
+++ b/package.json
@@ -95,6 +95,6 @@
"react-dom": "^16.11.0 || ^17 || ^18 || ^19"
},
"dependencies": {
- "@auth0/auth0-spa-js": "^2.2.0"
+ "@auth0/auth0-spa-js": "^2.4.0"
}
}
From 001c30f6a3ac620eb98d86b80e189c085eecda6f Mon Sep 17 00:00:00 2001
From: Gyanesh Gouraw
Date: Wed, 10 Sep 2025 20:05:48 +0530
Subject: [PATCH 8/9] fix: update package-lock.json to use correct npm registry
---
package-lock.json | 394 +++++++++++-----------------------------------
1 file changed, 89 insertions(+), 305 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index 87466ac1..f3acbf50 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -74,10 +74,14 @@
}
},
"node_modules/@auth0/auth0-spa-js": {
- "version": "2.4.0",
- "resolved": "https://a0us.jfrog.io/artifactory/api/npm/npm/@auth0/auth0-spa-js/-/auth0-spa-js-2.4.0.tgz",
- "integrity": "sha512-Hq37s9r2FYPAcP/WsslcjAeZhPStnfV2gRmXhIqWTSG/acxFt7eS2+yU5VM3KPxdwtv9ZzlZgoMFIsggpRV0Dw==",
- "license": "MIT"
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/@auth0/auth0-spa-js/-/auth0-spa-js-2.4.1.tgz",
+ "integrity": "sha512-GE1XPLEgEUeqYBw5VcA52+3ubJDh4VKZFqdu0mr6h7anu+rFZb389cDbfpW145I23T1knZB/jvQtuRrkcLuT+Q==",
+ "dependencies": {
+ "browser-tabs-lock": "^1.2.15",
+ "dpop": "^2.1.1",
+ "es-cookie": "~1.3.2"
+ }
},
"node_modules/@babel/code-frame": {
"version": "7.26.2",
@@ -588,8 +592,6 @@
},
"node_modules/@eslint-community/eslint-utils": {
"version": "4.7.0",
- "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz",
- "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -645,8 +647,6 @@
},
"node_modules/@gerrit0/mini-shiki": {
"version": "3.7.0",
- "resolved": "https://registry.npmjs.org/@gerrit0/mini-shiki/-/mini-shiki-3.7.0.tgz",
- "integrity": "sha512-7iY9wg4FWXmeoFJpUL2u+tsmh0d0jcEJHAIzVxl3TG4KL493JNnisdLAILZ77zcD+z3J0keEXZ+lFzUgzQzPDg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -1338,8 +1338,6 @@
},
"node_modules/@shikijs/engine-oniguruma": {
"version": "3.7.0",
- "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-3.7.0.tgz",
- "integrity": "sha512-5BxcD6LjVWsGu4xyaBC5bu8LdNgPCVBnAkWTtOCs/CZxcB22L8rcoWfv7Hh/3WooVjBZmFtyxhgvkQFedPGnFw==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -1349,8 +1347,6 @@
},
"node_modules/@shikijs/langs": {
"version": "3.7.0",
- "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-3.7.0.tgz",
- "integrity": "sha512-1zYtdfXLr9xDKLTGy5kb7O0zDQsxXiIsw1iIBcNOO8Yi5/Y1qDbJ+0VsFoqTlzdmneO8Ij35g7QKF8kcLyznCQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -1359,8 +1355,6 @@
},
"node_modules/@shikijs/themes": {
"version": "3.7.0",
- "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-3.7.0.tgz",
- "integrity": "sha512-VJx8497iZPy5zLiiCTSIaOChIcKQwR0FebwE9S3rcN0+J/GTWwQ1v/bqhTbpbY3zybPKeO8wdammqkpXc4NVjQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -1369,8 +1363,6 @@
},
"node_modules/@shikijs/types": {
"version": "3.7.0",
- "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-3.7.0.tgz",
- "integrity": "sha512-MGaLeaRlSWpnP0XSAum3kP3a8vtcTsITqoEPYdt3lQG3YCdQH4DnEhodkYcNMcU0uW0RffhoD1O3e0vG5eSBBg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -1380,8 +1372,6 @@
},
"node_modules/@shikijs/vscode-textmate": {
"version": "10.0.2",
- "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz",
- "integrity": "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==",
"dev": true,
"license": "MIT"
},
@@ -1505,7 +1495,6 @@
"resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.3.0.tgz",
"integrity": "sha512-kFSyxiEDwv1WLl2fgsq6pPBbw5aWKrsY2/noi1Id0TK0UParSF62oFQFGHXIyaG4pp2tEub/Zlel+fjjZILDsw==",
"dev": true,
- "license": "MIT",
"dependencies": {
"@babel/runtime": "^7.12.5"
},
@@ -1583,6 +1572,15 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/@types/glob": {
+ "version": "7.2.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/minimatch": "*",
+ "@types/node": "*"
+ }
+ },
"node_modules/@types/graceful-fs": {
"version": "4.1.9",
"dev": true,
@@ -1593,8 +1591,6 @@
},
"node_modules/@types/hast": {
"version": "3.0.4",
- "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz",
- "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -1675,6 +1671,11 @@
"parse5": "^7.0.0"
}
},
+ "node_modules/@types/minimatch": {
+ "version": "5.1.2",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/@types/node": {
"version": "22.10.6",
"dev": true,
@@ -1685,8 +1686,6 @@
},
"node_modules/@types/react": {
"version": "19.1.8",
- "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.8.tgz",
- "integrity": "sha512-AwAfQ2Wa5bCx9WP8nZL2uMZWod7J7/JSplxbTmBQ5ms6QpqNYm672H0Vu9ZVKVngQ+ii4R/byguVEUZQyeg44g==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -1695,8 +1694,6 @@
},
"node_modules/@types/react-dom": {
"version": "19.1.6",
- "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.1.6.tgz",
- "integrity": "sha512-4hOiT/dwO8Ko0gV1m/TJZYk3y0KBnY9vzDh7W+DH17b2HFSOGgdj33dhihPeuy3l0q23+4e+hoXHV6hCC4dCXw==",
"dev": true,
"license": "MIT",
"peerDependencies": {
@@ -1730,8 +1727,6 @@
},
"node_modules/@types/unist": {
"version": "3.0.3",
- "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz",
- "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==",
"dev": true,
"license": "MIT"
},
@@ -1759,8 +1754,6 @@
},
"node_modules/@typescript-eslint/eslint-plugin": {
"version": "8.37.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.37.0.tgz",
- "integrity": "sha512-jsuVWeIkb6ggzB+wPCsR4e6loj+rM72ohW6IBn2C+5NCvfUVY8s33iFPySSVXqtm5Hu29Ne/9bnA0JmyLmgenA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -1789,8 +1782,6 @@
},
"node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": {
"version": "7.0.5",
- "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz",
- "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==",
"dev": true,
"license": "MIT",
"engines": {
@@ -1798,16 +1789,14 @@
}
},
"node_modules/@typescript-eslint/parser": {
- "version": "8.42.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.42.0.tgz",
- "integrity": "sha512-r1XG74QgShUgXph1BYseJ+KZd17bKQib/yF3SR+demvytiRXrwd12Blnz5eYGm8tXaeRdd4x88MlfwldHoudGg==",
+ "version": "8.37.0",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/scope-manager": "8.42.0",
- "@typescript-eslint/types": "8.42.0",
- "@typescript-eslint/typescript-estree": "8.42.0",
- "@typescript-eslint/visitor-keys": "8.42.0",
+ "@typescript-eslint/scope-manager": "8.37.0",
+ "@typescript-eslint/types": "8.37.0",
+ "@typescript-eslint/typescript-estree": "8.37.0",
+ "@typescript-eslint/visitor-keys": "8.37.0",
"debug": "^4.3.4"
},
"engines": {
@@ -1819,170 +1808,11 @@
},
"peerDependencies": {
"eslint": "^8.57.0 || ^9.0.0",
- "typescript": ">=4.8.4 <6.0.0"
- }
- },
- "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/project-service": {
- "version": "8.42.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.42.0.tgz",
- "integrity": "sha512-vfVpLHAhbPjilrabtOSNcUDmBboQNrJUiNAGoImkZKnMjs2TIcWG33s4Ds0wY3/50aZmTMqJa6PiwkwezaAklg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@typescript-eslint/tsconfig-utils": "^8.42.0",
- "@typescript-eslint/types": "^8.42.0",
- "debug": "^4.3.4"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "typescript": ">=4.8.4 <6.0.0"
- }
- },
- "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": {
- "version": "8.42.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.42.0.tgz",
- "integrity": "sha512-51+x9o78NBAVgQzOPd17DkNTnIzJ8T/O2dmMBLoK9qbY0Gm52XJcdJcCl18ExBMiHo6jPMErUQWUv5RLE51zJw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@typescript-eslint/types": "8.42.0",
- "@typescript-eslint/visitor-keys": "8.42.0"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- }
- },
- "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/tsconfig-utils": {
- "version": "8.42.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.42.0.tgz",
- "integrity": "sha512-kHeFUOdwAJfUmYKjR3CLgZSglGHjbNTi1H8sTYRYV2xX6eNz4RyJ2LIgsDLKf8Yi0/GL1WZAC/DgZBeBft8QAQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "typescript": ">=4.8.4 <6.0.0"
- }
- },
- "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": {
- "version": "8.42.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.42.0.tgz",
- "integrity": "sha512-LdtAWMiFmbRLNP7JNeY0SqEtJvGMYSzfiWBSmx+VSZ1CH+1zyl8Mmw1TT39OrtsRvIYShjJWzTDMPWZJCpwBlw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- }
- },
- "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": {
- "version": "8.42.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.42.0.tgz",
- "integrity": "sha512-ku/uYtT4QXY8sl9EDJETD27o3Ewdi72hcXg1ah/kkUgBvAYHLwj2ofswFFNXS+FL5G+AGkxBtvGt8pFBHKlHsQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@typescript-eslint/project-service": "8.42.0",
- "@typescript-eslint/tsconfig-utils": "8.42.0",
- "@typescript-eslint/types": "8.42.0",
- "@typescript-eslint/visitor-keys": "8.42.0",
- "debug": "^4.3.4",
- "fast-glob": "^3.3.2",
- "is-glob": "^4.0.3",
- "minimatch": "^9.0.4",
- "semver": "^7.6.0",
- "ts-api-utils": "^2.1.0"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "typescript": ">=4.8.4 <6.0.0"
- }
- },
- "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": {
- "version": "8.42.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.42.0.tgz",
- "integrity": "sha512-3WbiuzoEowaEn8RSnhJBrxSwX8ULYE9CXaPepS2C2W3NSA5NNIvBaslpBSBElPq0UGr0xVJlXFWOAKIkyylydQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@typescript-eslint/types": "8.42.0",
- "eslint-visitor-keys": "^4.2.1"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- }
- },
- "node_modules/@typescript-eslint/parser/node_modules/brace-expansion": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
- "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "balanced-match": "^1.0.0"
- }
- },
- "node_modules/@typescript-eslint/parser/node_modules/eslint-visitor-keys": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
- "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
- "dev": true,
- "license": "Apache-2.0",
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "url": "https://opencollective.com/eslint"
- }
- },
- "node_modules/@typescript-eslint/parser/node_modules/minimatch": {
- "version": "9.0.5",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
- "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "brace-expansion": "^2.0.1"
- },
- "engines": {
- "node": ">=16 || 14 >=14.17"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
+ "typescript": ">=4.8.4 <5.9.0"
}
},
"node_modules/@typescript-eslint/project-service": {
"version": "8.37.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.37.0.tgz",
- "integrity": "sha512-BIUXYsbkl5A1aJDdYJCBAo8rCEbAvdquQ8AnLb6z5Lp1u3x5PNgSSx9A/zqYc++Xnr/0DVpls8iQ2cJs/izTXA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -2003,8 +1833,6 @@
},
"node_modules/@typescript-eslint/scope-manager": {
"version": "8.37.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.37.0.tgz",
- "integrity": "sha512-0vGq0yiU1gbjKob2q691ybTg9JX6ShiVXAAfm2jGf3q0hdP6/BruaFjL/ManAR/lj05AvYCH+5bbVo0VtzmjOA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -2021,8 +1849,6 @@
},
"node_modules/@typescript-eslint/tsconfig-utils": {
"version": "8.37.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.37.0.tgz",
- "integrity": "sha512-1/YHvAVTimMM9mmlPvTec9NP4bobA1RkDbMydxG8omqwJJLEW/Iy2C4adsAESIXU3WGLXFHSZUU+C9EoFWl4Zg==",
"dev": true,
"license": "MIT",
"engines": {
@@ -2038,8 +1864,6 @@
},
"node_modules/@typescript-eslint/type-utils": {
"version": "8.37.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.37.0.tgz",
- "integrity": "sha512-SPkXWIkVZxhgwSwVq9rqj/4VFo7MnWwVaRNznfQDc/xPYHjXnPfLWn+4L6FF1cAz6e7dsqBeMawgl7QjUMj4Ow==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -2063,8 +1887,6 @@
},
"node_modules/@typescript-eslint/types": {
"version": "8.37.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.37.0.tgz",
- "integrity": "sha512-ax0nv7PUF9NOVPs+lmQ7yIE7IQmAf8LGcXbMvHX5Gm+YJUYNAl340XkGnrimxZ0elXyoQJuN5sbg6C4evKA4SQ==",
"dev": true,
"license": "MIT",
"engines": {
@@ -2077,8 +1899,6 @@
},
"node_modules/@typescript-eslint/typescript-estree": {
"version": "8.37.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.37.0.tgz",
- "integrity": "sha512-zuWDMDuzMRbQOM+bHyU4/slw27bAUEcKSKKs3hcv2aNnc/tvE/h7w60dwVw8vnal2Pub6RT1T7BI8tFZ1fE+yg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -2106,8 +1926,6 @@
},
"node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": {
"version": "2.0.2",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
- "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -2116,8 +1934,6 @@
},
"node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": {
"version": "9.0.5",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
- "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
"dev": true,
"license": "ISC",
"dependencies": {
@@ -2132,8 +1948,6 @@
},
"node_modules/@typescript-eslint/utils": {
"version": "8.37.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.37.0.tgz",
- "integrity": "sha512-TSFvkIW6gGjN2p6zbXo20FzCABbyUAuq6tBvNRGsKdsSQ6a7rnV6ADfZ7f4iI3lIiXc4F4WWvtUfDw9CJ9pO5A==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -2156,8 +1970,6 @@
},
"node_modules/@typescript-eslint/visitor-keys": {
"version": "8.37.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.37.0.tgz",
- "integrity": "sha512-YzfhzcTnZVPiLfP/oeKtDp2evwvHLMe0LOy7oe+hb9KKIumLNohYS9Hgp1ifwpu42YWxhZE8yieggz6JpqO/1w==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -2174,8 +1986,6 @@
},
"node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": {
"version": "4.2.1",
- "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
- "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
"dev": true,
"license": "Apache-2.0",
"engines": {
@@ -2512,8 +2322,6 @@
},
"node_modules/array-union": {
"version": "2.1.0",
- "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
- "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
"dev": true,
"license": "MIT",
"engines": {
@@ -3023,6 +2831,15 @@
"dev": true,
"license": "ISC"
},
+ "node_modules/browser-tabs-lock": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/browser-tabs-lock/-/browser-tabs-lock-1.3.0.tgz",
+ "integrity": "sha512-g6nHaobTiT0eMZ7jh16YpD2kcjAp+PInbiVq3M1x6KKaEIVhT4v9oURNIpZLOZ3LQbQ3XYfNhMAb/9hzNLIWrw==",
+ "hasInstallScript": true,
+ "dependencies": {
+ "lodash": ">=4.17.21"
+ }
+ },
"node_modules/browserslist": {
"version": "4.24.4",
"dev": true,
@@ -4339,26 +4156,50 @@
}
},
"node_modules/del": {
- "version": "6.1.1",
- "resolved": "https://registry.npmjs.org/del/-/del-6.1.1.tgz",
- "integrity": "sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg==",
+ "version": "5.1.0",
"dev": true,
"license": "MIT",
"dependencies": {
- "globby": "^11.0.1",
- "graceful-fs": "^4.2.4",
+ "globby": "^10.0.1",
+ "graceful-fs": "^4.2.2",
"is-glob": "^4.0.1",
"is-path-cwd": "^2.2.0",
- "is-path-inside": "^3.0.2",
- "p-map": "^4.0.0",
- "rimraf": "^3.0.2",
+ "is-path-inside": "^3.0.1",
+ "p-map": "^3.0.0",
+ "rimraf": "^3.0.0",
"slash": "^3.0.0"
},
"engines": {
- "node": ">=10"
+ "node": ">=8"
+ }
+ },
+ "node_modules/del/node_modules/globby": {
+ "version": "10.0.2",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/glob": "^7.1.1",
+ "array-union": "^2.1.0",
+ "dir-glob": "^3.0.1",
+ "fast-glob": "^3.0.3",
+ "glob": "^7.1.3",
+ "ignore": "^5.1.1",
+ "merge2": "^1.2.3",
+ "slash": "^3.0.0"
},
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/del/node_modules/p-map": {
+ "version": "3.0.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "aggregate-error": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
}
},
"node_modules/delayed-stream": {
@@ -4425,8 +4266,6 @@
},
"node_modules/dir-glob": {
"version": "3.0.1",
- "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
- "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -4477,6 +4316,14 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/dpop": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/dpop/-/dpop-2.1.1.tgz",
+ "integrity": "sha512-J0Of2JTiM4h5si0tlbPQ/lkqfZ5wAEVkKYBhkwyyANnPJfWH4VsR5uIkZ+T+OSPIwDYUg1fbd5Mmodd25HjY1w==",
+ "funding": {
+ "url": "https://github.com/sponsors/panva"
+ }
+ },
"node_modules/dunder-proto": {
"version": "1.0.1",
"dev": true,
@@ -4708,6 +4555,11 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/es-cookie": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/es-cookie/-/es-cookie-1.3.2.tgz",
+ "integrity": "sha512-UTlYYhXGLOy05P/vKVT2Ui7WtC7NiRzGtJyAKKn32g5Gvcjn7KAClLPWlipCtxIus934dFg9o9jXiBL0nP+t9Q=="
+ },
"node_modules/es-define-property": {
"version": "1.0.1",
"dev": true,
@@ -5517,16 +5369,12 @@
}
},
"node_modules/form-data": {
- "version": "4.0.4",
- "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz",
- "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==",
+ "version": "4.0.1",
"dev": true,
"license": "MIT",
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
- "es-set-tostringtag": "^2.1.0",
- "hasown": "^2.0.2",
"mime-types": "^2.1.12"
},
"engines": {
@@ -5848,27 +5696,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/globby": {
- "version": "11.1.0",
- "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
- "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "array-union": "^2.1.0",
- "dir-glob": "^3.0.1",
- "fast-glob": "^3.2.9",
- "ignore": "^5.2.0",
- "merge2": "^1.4.1",
- "slash": "^3.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/gopd": {
"version": "1.2.0",
"dev": true,
@@ -6596,8 +6423,6 @@
},
"node_modules/is-path-cwd": {
"version": "2.2.0",
- "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz",
- "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==",
"dev": true,
"license": "MIT",
"engines": {
@@ -8123,8 +7948,6 @@
},
"node_modules/koa": {
"version": "2.16.1",
- "resolved": "https://registry.npmjs.org/koa/-/koa-2.16.1.tgz",
- "integrity": "sha512-umfX9d3iuSxTQP4pnzLOz0HKnPg0FaUUIKcye2lOiz3KPu1Y3M3xlz76dISdFPQs37P9eJz1wUpcTS6KDPn9fA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -8432,8 +8255,6 @@
},
"node_modules/linkify-it": {
"version": "5.0.0",
- "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz",
- "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -8524,7 +8345,6 @@
},
"node_modules/lodash": {
"version": "4.17.21",
- "dev": true,
"license": "MIT"
},
"node_modules/lodash.defaults": {
@@ -8717,8 +8537,6 @@
},
"node_modules/markdown-it": {
"version": "14.1.0",
- "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz",
- "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -8743,8 +8561,6 @@
},
"node_modules/mdurl": {
"version": "2.0.0",
- "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz",
- "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==",
"dev": true,
"license": "MIT"
},
@@ -9211,8 +9027,6 @@
},
"node_modules/oidc-provider": {
"version": "8.8.1",
- "resolved": "https://registry.npmjs.org/oidc-provider/-/oidc-provider-8.8.1.tgz",
- "integrity": "sha512-qVChpayTwojUREJxLkFofUSK8kiSRIdzPrVSsoGibqRHl/YO60ege94OZS8vh7zaK+zxcG/Gu8UMaYB5ulohCQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -9522,8 +9336,6 @@
},
"node_modules/path-type": {
"version": "4.0.0",
- "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
- "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
"dev": true,
"license": "MIT",
"engines": {
@@ -9902,8 +9714,6 @@
},
"node_modules/punycode.js": {
"version": "2.3.1",
- "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz",
- "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==",
"dev": true,
"license": "MIT",
"engines": {
@@ -10034,8 +9844,6 @@
},
"node_modules/react": {
"version": "19.1.0",
- "resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz",
- "integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==",
"dev": true,
"license": "MIT",
"engines": {
@@ -10044,8 +9852,6 @@
},
"node_modules/react-dom": {
"version": "19.1.0",
- "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz",
- "integrity": "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -10419,13 +10225,11 @@
}
},
"node_modules/rollup-plugin-delete": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/rollup-plugin-delete/-/rollup-plugin-delete-2.2.0.tgz",
- "integrity": "sha512-REKtDKWvjZlbrWpPvM9X/fadCs3E9I9ge27AK8G0e4bXwSLeABAAwtjiI1u3ihqZxk6mJeB2IVeSbH4DtOcw7A==",
+ "version": "2.1.0",
"dev": true,
"license": "MIT",
"dependencies": {
- "del": "^6.1.1"
+ "del": "^5.1.0"
},
"engines": {
"node": ">=10"
@@ -10670,8 +10474,6 @@
},
"node_modules/scheduler": {
"version": "0.26.0",
- "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz",
- "integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==",
"dev": true,
"license": "MIT"
},
@@ -10694,8 +10496,6 @@
},
"node_modules/semver": {
"version": "7.7.2",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
- "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
"dev": true,
"license": "ISC",
"bin": {
@@ -11511,9 +11311,7 @@
"license": "MIT"
},
"node_modules/tmp": {
- "version": "0.2.4",
- "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.4.tgz",
- "integrity": "sha512-UdiSoX6ypifLmrfQ/XfiawN6hkjSBpCjhKxxZcWlUUmoXLaCKQU0bx4HF/tdDK2uzRuchf1txGvrWBzYREssoQ==",
+ "version": "0.2.3",
"dev": true,
"license": "MIT",
"engines": {
@@ -11581,8 +11379,6 @@
},
"node_modules/ts-api-utils": {
"version": "2.1.0",
- "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz",
- "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==",
"dev": true,
"license": "MIT",
"engines": {
@@ -11594,8 +11390,6 @@
},
"node_modules/ts-jest": {
"version": "29.4.0",
- "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.0.tgz",
- "integrity": "sha512-d423TJMnJGu80/eSgfQ5w/R+0zFJvdtTxwtF9KzFFunOpSeD+79lHJQIiAhluJoyGRbvj9NZJsl9WjCUo0ND7Q==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -11647,8 +11441,6 @@
},
"node_modules/ts-jest/node_modules/type-fest": {
"version": "4.41.0",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz",
- "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==",
"dev": true,
"license": "(MIT OR CC0-1.0)",
"engines": {
@@ -11817,8 +11609,6 @@
},
"node_modules/typedoc": {
"version": "0.28.7",
- "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.28.7.tgz",
- "integrity": "sha512-lpz0Oxl6aidFkmS90VQDQjk/Qf2iw0IUvFqirdONBdj7jPSN9mGXhy66BcGNDxx5ZMyKKiBVAREvPEzT6Uxipw==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
@@ -11863,8 +11653,6 @@
},
"node_modules/typescript": {
"version": "5.8.3",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
- "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
"dev": true,
"license": "Apache-2.0",
"bin": {
@@ -11877,8 +11665,6 @@
},
"node_modules/uc.micro": {
"version": "2.1.0",
- "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz",
- "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==",
"dev": true,
"license": "MIT"
},
@@ -12561,8 +12347,6 @@
},
"node_modules/yaml": {
"version": "2.8.0",
- "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.0.tgz",
- "integrity": "sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ==",
"dev": true,
"license": "ISC",
"bin": {
From b612cb447d81b0b44efd23031b67e76fdfd26d0c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mart=C3=ADn=20Melado?=
<217925+martinml@users.noreply.github.com>
Date: Mon, 15 Sep 2025 09:51:26 +0200
Subject: [PATCH 9/9] Force 2.4.1 since 2.4.0 had wrong deps
---
package-lock.json | 2 +-
package.json | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index f3acbf50..1ed60ce7 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -9,7 +9,7 @@
"version": "2.4.0",
"license": "MIT",
"dependencies": {
- "@auth0/auth0-spa-js": "^2.4.0"
+ "@auth0/auth0-spa-js": "^2.4.1"
},
"devDependencies": {
"@rollup/plugin-node-resolve": "^15.0.1",
diff --git a/package.json b/package.json
index e9e15e41..1f0b471a 100644
--- a/package.json
+++ b/package.json
@@ -95,6 +95,6 @@
"react-dom": "^16.11.0 || ^17 || ^18 || ^19"
},
"dependencies": {
- "@auth0/auth0-spa-js": "^2.4.0"
+ "@auth0/auth0-spa-js": "^2.4.1"
}
}