Skip to content

Commit 67b5b75

Browse files
feat: add client prop and createAuth0Client factory
1 parent cb9539e commit 67b5b75

File tree

5 files changed

+94
-18
lines changed

5 files changed

+94
-18
lines changed

__tests__/auth-provider.test.tsx

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import '@testing-library/jest-dom';
77
import { act, render, renderHook, screen, waitFor } from '@testing-library/react';
88
import React, { StrictMode, useContext } from 'react';
99
import pkg from '../package.json';
10-
import { Auth0Provider, useAuth0 } from '../src';
10+
import { Auth0Provider, createAuth0Client, useAuth0 } from '../src';
1111
import Auth0Context, {
1212
Auth0ContextInterface,
1313
initialContext,
@@ -134,6 +134,27 @@ describe('Auth0Provider', () => {
134134
});
135135
});
136136

137+
it('should use provided client instance without creating a new one', async () => {
138+
const wrapper = createWrapper({ client: clientMock });
139+
renderHook(() => useContext(Auth0Context), { wrapper });
140+
await waitFor(() => {
141+
expect(Auth0Client).not.toHaveBeenCalled();
142+
expect(clientMock.checkSession).toHaveBeenCalled();
143+
});
144+
});
145+
146+
it('should inject auth0-react telemetry when using createAuth0Client', async () => {
147+
createAuth0Client({ clientId: 'foo', domain: 'bar' });
148+
expect(Auth0Client).toHaveBeenCalledWith(
149+
expect.objectContaining({
150+
auth0Client: {
151+
name: 'auth0-react',
152+
version: pkg.version,
153+
},
154+
})
155+
);
156+
});
157+
137158
it('should check session when logged out', async () => {
138159
const wrapper = createWrapper();
139160
const { result } = renderHook(

__tests__/helpers.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
import React, { PropsWithChildren } from 'react';
22
import Auth0Provider, { Auth0ProviderOptions } from '../src/auth0-provider';
33

4-
export const createWrapper = ({
5-
clientId = '__test_client_id__',
6-
domain = '__test_domain__',
7-
...opts
8-
}: Partial<Auth0ProviderOptions> = {}) => {
4+
export const createWrapper = (opts: Partial<Auth0ProviderOptions> = {}) => {
5+
const providerProps =
6+
'client' in opts && opts.client != null
7+
? (opts as Auth0ProviderOptions)
8+
: ({ clientId: '__test_client_id__', domain: '__test_domain__', ...opts } as Auth0ProviderOptions);
99
return function Wrapper({
1010
children,
1111
}: PropsWithChildren<Record<string, unknown>>): React.JSX.Element {
1212
return (
13-
<Auth0Provider domain={domain} clientId={clientId} {...opts}>
13+
<Auth0Provider {...providerProps}>
1414
{children}
1515
</Auth0Provider>
1616
);

examples/cra-react-router/src/index.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@ import React, { PropsWithChildren } from 'react';
33
import App from './App';
44
import { Auth0Provider, AppState, Auth0ContextInterface, User } from '@auth0/auth0-react';
55
import { BrowserRouter, useNavigate } from 'react-router-dom';
6-
import { Auth0ProviderOptions } from '../../../src/index.js';
6+
import { Auth0ProviderWithConfigOptions } from '../../../src/index.js';
77

88
const Auth0ProviderWithRedirectCallback = ({
99
children,
1010
context,
1111
...props
12-
}: PropsWithChildren<Omit<Auth0ProviderOptions, 'context'>> & {
12+
}: PropsWithChildren<Omit<Auth0ProviderWithConfigOptions, 'context'>> & {
1313
context?: React.Context<Auth0ContextInterface<User>>
1414
}) => {
1515
const navigate = useNavigate();

src/auth0-provider.tsx

Lines changed: 59 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,7 @@ export type AppState = {
5151
[key: string]: any; // eslint-disable-line @typescript-eslint/no-explicit-any
5252
};
5353

54-
/**
55-
* The main configuration to instantiate the `Auth0Provider`.
56-
*/
57-
export interface Auth0ProviderOptions<TUser extends User = User> extends Auth0ClientOptions {
54+
type Auth0ProviderBaseOptions<TUser extends User = User> = {
5855
/**
5956
* The child nodes your Provider has wrapped
6057
*/
@@ -97,7 +94,31 @@ export interface Auth0ProviderOptions<TUser extends User = User> extends Auth0Cl
9794
* For a sample on using multiple Auth0Providers review the [React Account Linking Sample](https://github.com/auth0-samples/auth0-link-accounts-sample/tree/react-variant)
9895
*/
9996
context?: React.Context<Auth0ContextInterface<TUser>>;
100-
}
97+
};
98+
99+
/**
100+
* Options for `Auth0Provider` when configuring Auth0 via `domain` and `clientId`.
101+
* Use this type when building wrapper components around `Auth0Provider`.
102+
*/
103+
export type Auth0ProviderWithConfigOptions<TUser extends User = User> =
104+
Auth0ProviderBaseOptions<TUser> & Auth0ClientOptions & { client?: never };
105+
106+
/**
107+
* Options for `Auth0Provider` when supplying a pre-configured `Auth0Client` instance.
108+
* Use `createAuth0Client` to create the client so telemetry is set correctly.
109+
*/
110+
export type Auth0ProviderWithClientOptions<TUser extends User = User> =
111+
Auth0ProviderBaseOptions<TUser> & Partial<Auth0ClientOptions> & { client: Auth0Client };
112+
113+
/**
114+
* The main configuration to instantiate the `Auth0Provider`.
115+
*
116+
* Either provide `domain` and `clientId` (`Auth0ProviderWithConfigOptions`)
117+
* or a pre-configured `client` instance (`Auth0ProviderWithClientOptions`).
118+
*/
119+
export type Auth0ProviderOptions<TUser extends User = User> =
120+
| Auth0ProviderWithConfigOptions<TUser>
121+
| Auth0ProviderWithClientOptions<TUser>;
101122

102123
/**
103124
* Replaced by the package version at build time.
@@ -109,7 +130,7 @@ declare const __VERSION__: string;
109130
* @ignore
110131
*/
111132
const toAuth0ClientOptions = (
112-
opts: Auth0ProviderOptions
133+
opts: Auth0ClientOptions
113134
): Auth0ClientOptions => {
114135
deprecateRedirectUri(opts);
115136

@@ -122,6 +143,35 @@ const toAuth0ClientOptions = (
122143
};
123144
};
124145

146+
/**
147+
* Creates a new `Auth0Client` with the `auth0-react` SDK telemetry header set.
148+
*
149+
* Use this when you need to share a single client instance with `Auth0Provider`
150+
* and also access Auth0 outside of React (e.g. in middleware or interceptors).
151+
*
152+
* @example
153+
* ```tsx
154+
* const client = createAuth0Client({ domain, clientId });
155+
*
156+
* // Use outside React (e.g. in TanStack middleware, axios interceptors, Redux middleware)
157+
* const token = await client.getTokenSilently();
158+
*
159+
* // Use inside React
160+
* function App() {
161+
* return <Auth0Provider client={client}><MyApp /></Auth0Provider>;
162+
* }
163+
* ```
164+
*/
165+
export const createAuth0Client = (options: Auth0ClientOptions): Auth0Client => {
166+
return new Auth0Client({
167+
...options,
168+
auth0Client: {
169+
name: 'auth0-react',
170+
version: __VERSION__,
171+
},
172+
});
173+
};
174+
125175
/**
126176
* @ignore
127177
*/
@@ -151,10 +201,11 @@ const Auth0Provider = <TUser extends User = User>(opts: Auth0ProviderOptions<TUs
151201
skipRedirectCallback,
152202
onRedirectCallback = defaultOnRedirectCallback,
153203
context = Auth0Context,
204+
client: providedClient,
154205
...clientOpts
155-
} = opts;
206+
} = opts as Auth0ProviderBaseOptions<TUser> & Auth0ClientOptions & { client?: Auth0Client };
156207
const [client] = useState(
157-
() => new Auth0Client(toAuth0ClientOptions(clientOpts))
208+
() => providedClient ?? new Auth0Client(toAuth0ClientOptions(clientOpts))
158209
);
159210
const [state, dispatch] = useReducer(reducer<TUser>, initialAuthState as AuthState<TUser>);
160211
const didInitialise = useRef(false);

src/index.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
export {
22
default as Auth0Provider,
33
Auth0ProviderOptions,
4+
Auth0ProviderWithConfigOptions,
5+
Auth0ProviderWithClientOptions,
46
AppState,
5-
ConnectedAccount
7+
ConnectedAccount,
8+
createAuth0Client,
69
} from './auth0-provider';
710
export { default as useAuth0 } from './use-auth0';
811
export { default as withAuth0, WithAuth0Props } from './with-auth0';
@@ -18,6 +21,7 @@ export {
1821
RedirectLoginOptions,
1922
} from './auth0-context';
2023
export {
24+
Auth0Client,
2125
AuthorizationParams,
2226
PopupLoginOptions,
2327
PopupConfigOptions,

0 commit comments

Comments
 (0)