@versini/auth0-react-thin 2.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +185 -0
- package/dist/auth-state.d.ts +15 -0
- package/dist/auth-state.d.ts.map +1 -0
- package/dist/auth0-context.d.ts +423 -0
- package/dist/auth0-context.d.ts.map +1 -0
- package/dist/auth0-provider.d.ts +96 -0
- package/dist/auth0-provider.d.ts.map +1 -0
- package/dist/auth0-react.cjs.js +830 -0
- package/dist/auth0-react.cjs.js.map +1 -0
- package/dist/auth0-react.esm.js +723 -0
- package/dist/auth0-react.esm.js.map +1 -0
- package/dist/auth0-react.js +759 -0
- package/dist/auth0-react.js.map +1 -0
- package/dist/auth0-react.min.js +2 -0
- package/dist/auth0-react.min.js.map +1 -0
- package/dist/errors.d.ts +12 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/reducer.d.ts +19 -0
- package/dist/reducer.d.ts.map +1 -0
- package/dist/use-auth0.d.ts +29 -0
- package/dist/use-auth0.d.ts.map +1 -0
- package/dist/utils.d.ts +10 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/with-auth0.d.ts +29 -0
- package/dist/with-auth0.d.ts.map +1 -0
- package/dist/with-authentication-required.d.ts +77 -0
- package/dist/with-authentication-required.d.ts.map +1 -0
- package/package.json +43 -0
- package/src/auth-state.tsx +21 -0
- package/src/auth0-context.tsx +506 -0
- package/src/auth0-provider.tsx +488 -0
- package/src/errors.tsx +14 -0
- package/src/index.tsx +100 -0
- package/src/reducer.tsx +59 -0
- package/src/use-auth0.tsx +34 -0
- package/src/utils.tsx +74 -0
- package/src/with-auth0.tsx +44 -0
- package/src/with-authentication-required.tsx +141 -0
|
@@ -0,0 +1,488 @@
|
|
|
1
|
+
import React, {
|
|
2
|
+
useCallback,
|
|
3
|
+
useEffect,
|
|
4
|
+
useMemo,
|
|
5
|
+
useReducer,
|
|
6
|
+
useRef,
|
|
7
|
+
useState,
|
|
8
|
+
} from 'react';
|
|
9
|
+
import {
|
|
10
|
+
Auth0Client,
|
|
11
|
+
Auth0ClientOptions,
|
|
12
|
+
PopupLoginOptions,
|
|
13
|
+
PopupConfigOptions,
|
|
14
|
+
GetTokenWithPopupOptions,
|
|
15
|
+
RedirectLoginResult,
|
|
16
|
+
GetTokenSilentlyOptions,
|
|
17
|
+
User,
|
|
18
|
+
RedirectConnectAccountOptions,
|
|
19
|
+
ConnectAccountRedirectResult,
|
|
20
|
+
ResponseType,
|
|
21
|
+
CustomTokenExchangeOptions,
|
|
22
|
+
TokenEndpointResponse,
|
|
23
|
+
type PasskeyApiClient,
|
|
24
|
+
type PasskeySignupOptions,
|
|
25
|
+
type PasskeyLoginOptions
|
|
26
|
+
} from '@auth0/auth0-spa-js';
|
|
27
|
+
import Auth0Context, {
|
|
28
|
+
Auth0ContextInterface,
|
|
29
|
+
LogoutOptions,
|
|
30
|
+
RedirectLoginOptions,
|
|
31
|
+
} from './auth0-context';
|
|
32
|
+
import {
|
|
33
|
+
hasAuthParams,
|
|
34
|
+
loginError,
|
|
35
|
+
tokenError,
|
|
36
|
+
deprecateRedirectUri,
|
|
37
|
+
} from './utils';
|
|
38
|
+
import { reducer } from './reducer';
|
|
39
|
+
import { initialAuthState, type AuthState } from './auth-state';
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* The account that has been connected during the connect flow.
|
|
43
|
+
*/
|
|
44
|
+
export type ConnectedAccount = Omit<ConnectAccountRedirectResult, 'appState' | 'response_type'>;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* The state of the application before the user was redirected to the login page
|
|
48
|
+
* and any account that the user may have connected to.
|
|
49
|
+
*/
|
|
50
|
+
export type AppState = {
|
|
51
|
+
returnTo?: string;
|
|
52
|
+
connectedAccount?: ConnectedAccount;
|
|
53
|
+
response_type?: ResponseType;
|
|
54
|
+
[key: string]: any; // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
type Auth0ProviderBaseOptions<TUser extends User = User> = {
|
|
58
|
+
/**
|
|
59
|
+
* The child nodes your Provider has wrapped
|
|
60
|
+
*/
|
|
61
|
+
children?: React.ReactNode;
|
|
62
|
+
/**
|
|
63
|
+
* By default this removes the code and state parameters from the url when you are redirected from the authorize page.
|
|
64
|
+
* It uses `window.history` but you might want to overwrite this if you are using a custom router, like `react-router-dom`
|
|
65
|
+
* See the EXAMPLES.md for more info.
|
|
66
|
+
*/
|
|
67
|
+
onRedirectCallback?: (appState?: AppState, user?: TUser) => void;
|
|
68
|
+
/**
|
|
69
|
+
* By default, if the page url has code/state params, the SDK will treat them as Auth0's and attempt to exchange the
|
|
70
|
+
* code for a token. In some cases the code might be for something else (another OAuth SDK perhaps). In these
|
|
71
|
+
* instances you can instruct the client to ignore them eg
|
|
72
|
+
*
|
|
73
|
+
* ```jsx
|
|
74
|
+
* <Auth0Provider
|
|
75
|
+
* clientId={clientId}
|
|
76
|
+
* domain={domain}
|
|
77
|
+
* skipRedirectCallback={window.location.pathname === '/stripe-oauth-callback'}
|
|
78
|
+
* >
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
skipRedirectCallback?: boolean;
|
|
82
|
+
/**
|
|
83
|
+
* Context to be used when creating the Auth0Provider, defaults to the internally created context.
|
|
84
|
+
*
|
|
85
|
+
* This allows multiple Auth0Providers to be nested within the same application, the context value can then be
|
|
86
|
+
* passed to useAuth0, withAuth0, or withAuthenticationRequired to use that specific Auth0Provider to access
|
|
87
|
+
* auth state and methods specifically tied to the provider that the context belongs to.
|
|
88
|
+
*
|
|
89
|
+
* When using multiple Auth0Providers in a single application you should do the following to ensure sessions are not
|
|
90
|
+
* overwritten:
|
|
91
|
+
*
|
|
92
|
+
* * Configure a different redirect_uri for each Auth0Provider, and set skipRedirectCallback for each provider to ignore
|
|
93
|
+
* the others redirect_uri
|
|
94
|
+
* * If using localstorage for both Auth0Providers, ensure that the audience and scope are different for so that the key
|
|
95
|
+
* used to store data is different
|
|
96
|
+
*
|
|
97
|
+
* 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)
|
|
98
|
+
*/
|
|
99
|
+
context?: React.Context<Auth0ContextInterface<TUser>>;
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Options for `Auth0Provider` when configuring Auth0 via `domain` and `clientId`.
|
|
104
|
+
* Use this type when building wrapper components around `Auth0Provider`.
|
|
105
|
+
*/
|
|
106
|
+
export type Auth0ProviderWithConfigOptions<TUser extends User = User> =
|
|
107
|
+
Auth0ProviderBaseOptions<TUser> & Auth0ClientOptions & { client?: never };
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Options for `Auth0Provider` when supplying a pre-configured `Auth0Client` instance.
|
|
111
|
+
*/
|
|
112
|
+
export type Auth0ProviderWithClientOptions<TUser extends User = User> =
|
|
113
|
+
Auth0ProviderBaseOptions<TUser> & { client: Auth0Client };
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* The main configuration to instantiate the `Auth0Provider`.
|
|
117
|
+
*
|
|
118
|
+
* Either provide `domain` and `clientId` (`Auth0ProviderWithConfigOptions`)
|
|
119
|
+
* or a pre-configured `client` instance (`Auth0ProviderWithClientOptions`).
|
|
120
|
+
*/
|
|
121
|
+
export type Auth0ProviderOptions<TUser extends User = User> =
|
|
122
|
+
| Auth0ProviderWithConfigOptions<TUser>
|
|
123
|
+
| Auth0ProviderWithClientOptions<TUser>;
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Replaced by the package version at build time.
|
|
127
|
+
* @ignore
|
|
128
|
+
*/
|
|
129
|
+
declare const __VERSION__: string;
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* @ignore
|
|
133
|
+
*/
|
|
134
|
+
const toAuth0ClientOptions = (
|
|
135
|
+
opts: Auth0ClientOptions
|
|
136
|
+
): Auth0ClientOptions => {
|
|
137
|
+
deprecateRedirectUri(opts);
|
|
138
|
+
|
|
139
|
+
return {
|
|
140
|
+
...opts,
|
|
141
|
+
auth0Client: {
|
|
142
|
+
name: 'auth0-react',
|
|
143
|
+
version: __VERSION__,
|
|
144
|
+
},
|
|
145
|
+
};
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* @ignore
|
|
150
|
+
*/
|
|
151
|
+
const defaultOnRedirectCallback = (appState?: AppState): void => {
|
|
152
|
+
window.history.replaceState(
|
|
153
|
+
{},
|
|
154
|
+
document.title,
|
|
155
|
+
appState!.returnTo ?? window.location.pathname
|
|
156
|
+
);
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* ```jsx
|
|
161
|
+
* <Auth0Provider
|
|
162
|
+
* domain={domain}
|
|
163
|
+
* clientId={clientId}
|
|
164
|
+
* authorizationParams={{ redirect_uri: window.location.origin }}>
|
|
165
|
+
* <MyApp />
|
|
166
|
+
* </Auth0Provider>
|
|
167
|
+
* ```
|
|
168
|
+
*
|
|
169
|
+
* Provides the Auth0Context to its child components.
|
|
170
|
+
*/
|
|
171
|
+
const Auth0Provider = <TUser extends User = User>(opts: Auth0ProviderOptions<TUser>) => {
|
|
172
|
+
const {
|
|
173
|
+
children,
|
|
174
|
+
skipRedirectCallback,
|
|
175
|
+
onRedirectCallback = defaultOnRedirectCallback,
|
|
176
|
+
context = Auth0Context,
|
|
177
|
+
client: providedClient,
|
|
178
|
+
...clientOpts
|
|
179
|
+
} = opts as Auth0ProviderBaseOptions<TUser> & Auth0ClientOptions & { client?: Auth0Client };
|
|
180
|
+
if (providedClient && (clientOpts.domain || clientOpts.clientId)) {
|
|
181
|
+
console.warn(
|
|
182
|
+
'Auth0Provider: the `client` prop takes precedence over `domain`/`clientId` and other ' +
|
|
183
|
+
'configuration options. Remove `domain`, `clientId`, and any other Auth0Client configuration ' +
|
|
184
|
+
'props when using the `client` prop.'
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
const [client] = useState(
|
|
188
|
+
() => providedClient ?? new Auth0Client(toAuth0ClientOptions(clientOpts))
|
|
189
|
+
);
|
|
190
|
+
const [state, dispatch] = useReducer(reducer<TUser>, initialAuthState as AuthState<TUser>);
|
|
191
|
+
const didInitialise = useRef(false);
|
|
192
|
+
|
|
193
|
+
const handleError = useCallback((error: Error) => {
|
|
194
|
+
dispatch({ type: 'ERROR', error });
|
|
195
|
+
return error;
|
|
196
|
+
}, []);
|
|
197
|
+
|
|
198
|
+
useEffect(() => {
|
|
199
|
+
if (didInitialise.current) {
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
didInitialise.current = true;
|
|
203
|
+
(async (): Promise<void> => {
|
|
204
|
+
try {
|
|
205
|
+
let user: TUser | undefined;
|
|
206
|
+
if (hasAuthParams() && !skipRedirectCallback) {
|
|
207
|
+
const { appState = {}, response_type, ...result } = await client.handleRedirectCallback();
|
|
208
|
+
user = await client.getUser();
|
|
209
|
+
appState.response_type = response_type;
|
|
210
|
+
if (response_type === ResponseType.ConnectCode) {
|
|
211
|
+
appState.connectedAccount = result as ConnectedAccount;
|
|
212
|
+
}
|
|
213
|
+
onRedirectCallback(appState, user);
|
|
214
|
+
} else {
|
|
215
|
+
await client.checkSession();
|
|
216
|
+
user = await client.getUser();
|
|
217
|
+
}
|
|
218
|
+
dispatch({ type: 'INITIALISED', user });
|
|
219
|
+
} catch (error) {
|
|
220
|
+
handleError(loginError(error));
|
|
221
|
+
}
|
|
222
|
+
})();
|
|
223
|
+
}, [client, onRedirectCallback, skipRedirectCallback, handleError]);
|
|
224
|
+
|
|
225
|
+
const loginWithRedirect = useCallback(
|
|
226
|
+
(opts?: RedirectLoginOptions): Promise<void> => {
|
|
227
|
+
deprecateRedirectUri(opts);
|
|
228
|
+
|
|
229
|
+
return client.loginWithRedirect(opts);
|
|
230
|
+
},
|
|
231
|
+
[client]
|
|
232
|
+
);
|
|
233
|
+
|
|
234
|
+
const loginWithPopup = useCallback(
|
|
235
|
+
async (
|
|
236
|
+
options?: PopupLoginOptions,
|
|
237
|
+
config?: PopupConfigOptions
|
|
238
|
+
): Promise<void> => {
|
|
239
|
+
dispatch({ type: 'LOGIN_POPUP_STARTED' });
|
|
240
|
+
try {
|
|
241
|
+
await client.loginWithPopup(options, config);
|
|
242
|
+
} catch (error) {
|
|
243
|
+
handleError(loginError(error));
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
const user = await client.getUser();
|
|
247
|
+
dispatch({ type: 'LOGIN_POPUP_COMPLETE', user });
|
|
248
|
+
},
|
|
249
|
+
[client, handleError]
|
|
250
|
+
);
|
|
251
|
+
|
|
252
|
+
const logout = useCallback(
|
|
253
|
+
async (opts: LogoutOptions = {}): Promise<void> => {
|
|
254
|
+
await client.logout(opts);
|
|
255
|
+
if (opts.openUrl || opts.openUrl === false) {
|
|
256
|
+
dispatch({ type: 'LOGOUT' });
|
|
257
|
+
}
|
|
258
|
+
},
|
|
259
|
+
[client]
|
|
260
|
+
);
|
|
261
|
+
|
|
262
|
+
const getAccessTokenSilently = useCallback(
|
|
263
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
264
|
+
async (opts?: GetTokenSilentlyOptions): Promise<any> => {
|
|
265
|
+
let token;
|
|
266
|
+
try {
|
|
267
|
+
token = await client.getTokenSilently(opts);
|
|
268
|
+
} catch (error) {
|
|
269
|
+
throw tokenError(error);
|
|
270
|
+
} finally {
|
|
271
|
+
dispatch({
|
|
272
|
+
type: 'GET_ACCESS_TOKEN_COMPLETE',
|
|
273
|
+
user: await client.getUser(),
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
return token;
|
|
277
|
+
},
|
|
278
|
+
[client]
|
|
279
|
+
);
|
|
280
|
+
|
|
281
|
+
const getAccessTokenWithPopup = useCallback(
|
|
282
|
+
async (
|
|
283
|
+
opts?: GetTokenWithPopupOptions,
|
|
284
|
+
config?: PopupConfigOptions
|
|
285
|
+
): Promise<string | undefined> => {
|
|
286
|
+
let token;
|
|
287
|
+
try {
|
|
288
|
+
token = await client.getTokenWithPopup(opts, config);
|
|
289
|
+
} catch (error) {
|
|
290
|
+
throw tokenError(error);
|
|
291
|
+
} finally {
|
|
292
|
+
dispatch({
|
|
293
|
+
type: 'GET_ACCESS_TOKEN_COMPLETE',
|
|
294
|
+
user: await client.getUser(),
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
return token;
|
|
298
|
+
},
|
|
299
|
+
[client]
|
|
300
|
+
);
|
|
301
|
+
|
|
302
|
+
const connectAccountWithRedirect = useCallback(
|
|
303
|
+
(options: RedirectConnectAccountOptions) =>
|
|
304
|
+
client.connectAccountWithRedirect(options),
|
|
305
|
+
[client]
|
|
306
|
+
);
|
|
307
|
+
|
|
308
|
+
const getIdTokenClaims = useCallback(
|
|
309
|
+
() => client.getIdTokenClaims(),
|
|
310
|
+
[client]
|
|
311
|
+
);
|
|
312
|
+
|
|
313
|
+
const loginWithCustomTokenExchange = useCallback(
|
|
314
|
+
async (
|
|
315
|
+
options: CustomTokenExchangeOptions
|
|
316
|
+
): Promise<TokenEndpointResponse> => {
|
|
317
|
+
let tokenResponse;
|
|
318
|
+
try {
|
|
319
|
+
tokenResponse = await client.loginWithCustomTokenExchange(options);
|
|
320
|
+
} catch (error) {
|
|
321
|
+
throw tokenError(error);
|
|
322
|
+
} finally {
|
|
323
|
+
// We dispatch the standard GET_ACCESS_TOKEN_COMPLETE action here to maintain
|
|
324
|
+
// backward compatibility and consistency with the getAccessTokenSilently flow.
|
|
325
|
+
// This ensures the SDK's internal state lifecycle (loading/user updates) remains
|
|
326
|
+
// identical regardless of whether the token was retrieved via silent auth or CTE.
|
|
327
|
+
dispatch({
|
|
328
|
+
type: 'GET_ACCESS_TOKEN_COMPLETE',
|
|
329
|
+
user: await client.getUser(),
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
return tokenResponse;
|
|
333
|
+
},
|
|
334
|
+
[client]
|
|
335
|
+
);
|
|
336
|
+
|
|
337
|
+
const customTokenExchange = useCallback(
|
|
338
|
+
(options: CustomTokenExchangeOptions): Promise<TokenEndpointResponse> =>
|
|
339
|
+
client.customTokenExchange(options),
|
|
340
|
+
[client]
|
|
341
|
+
);
|
|
342
|
+
|
|
343
|
+
const exchangeToken = useCallback(
|
|
344
|
+
async (
|
|
345
|
+
options: CustomTokenExchangeOptions
|
|
346
|
+
): Promise<TokenEndpointResponse> => {
|
|
347
|
+
return loginWithCustomTokenExchange(options);
|
|
348
|
+
},
|
|
349
|
+
[loginWithCustomTokenExchange]
|
|
350
|
+
);
|
|
351
|
+
|
|
352
|
+
const handleRedirectCallback = useCallback(
|
|
353
|
+
async (
|
|
354
|
+
url?: string
|
|
355
|
+
): Promise<RedirectLoginResult | ConnectAccountRedirectResult> => {
|
|
356
|
+
try {
|
|
357
|
+
return await client.handleRedirectCallback(url);
|
|
358
|
+
} catch (error) {
|
|
359
|
+
throw tokenError(error);
|
|
360
|
+
} finally {
|
|
361
|
+
dispatch({
|
|
362
|
+
type: 'HANDLE_REDIRECT_COMPLETE',
|
|
363
|
+
user: await client.getUser(),
|
|
364
|
+
});
|
|
365
|
+
}
|
|
366
|
+
},
|
|
367
|
+
[client]
|
|
368
|
+
);
|
|
369
|
+
|
|
370
|
+
const getDpopNonce = useCallback<Auth0Client['getDpopNonce']>(
|
|
371
|
+
(id) => client.getDpopNonce(id),
|
|
372
|
+
[client]
|
|
373
|
+
);
|
|
374
|
+
|
|
375
|
+
const setDpopNonce = useCallback<Auth0Client['setDpopNonce']>(
|
|
376
|
+
(nonce, id) => client.setDpopNonce(nonce, id),
|
|
377
|
+
[client]
|
|
378
|
+
);
|
|
379
|
+
|
|
380
|
+
const generateDpopProof = useCallback<Auth0Client['generateDpopProof']>(
|
|
381
|
+
(params) => client.generateDpopProof(params),
|
|
382
|
+
[client]
|
|
383
|
+
);
|
|
384
|
+
|
|
385
|
+
const createFetcher = useCallback<Auth0Client['createFetcher']>(
|
|
386
|
+
(config) => client.createFetcher(config),
|
|
387
|
+
[client]
|
|
388
|
+
);
|
|
389
|
+
|
|
390
|
+
const getConfiguration = useCallback<Auth0Client['getConfiguration']>(
|
|
391
|
+
() => client.getConfiguration(),
|
|
392
|
+
[client]
|
|
393
|
+
);
|
|
394
|
+
|
|
395
|
+
const mfa = useMemo(() => client.mfa, [client]);
|
|
396
|
+
const myAccount = useMemo(() => client.myAccount, [client]);
|
|
397
|
+
|
|
398
|
+
const passkeySignup = useCallback(
|
|
399
|
+
async (options: PasskeySignupOptions): Promise<TokenEndpointResponse> => {
|
|
400
|
+
let tokenResponse;
|
|
401
|
+
try {
|
|
402
|
+
tokenResponse = await client.passkey.signup(options);
|
|
403
|
+
} catch (error) {
|
|
404
|
+
throw tokenError(error);
|
|
405
|
+
} finally {
|
|
406
|
+
dispatch({
|
|
407
|
+
type: 'GET_ACCESS_TOKEN_COMPLETE',
|
|
408
|
+
user: await client.getUser(),
|
|
409
|
+
});
|
|
410
|
+
}
|
|
411
|
+
return tokenResponse;
|
|
412
|
+
},
|
|
413
|
+
[client]
|
|
414
|
+
);
|
|
415
|
+
|
|
416
|
+
const passkeyLogin = useCallback(
|
|
417
|
+
async (options?: PasskeyLoginOptions): Promise<TokenEndpointResponse> => {
|
|
418
|
+
let tokenResponse;
|
|
419
|
+
try {
|
|
420
|
+
tokenResponse = await client.passkey.login(options);
|
|
421
|
+
} catch (error) {
|
|
422
|
+
throw tokenError(error);
|
|
423
|
+
} finally {
|
|
424
|
+
dispatch({
|
|
425
|
+
type: 'GET_ACCESS_TOKEN_COMPLETE',
|
|
426
|
+
user: await client.getUser(),
|
|
427
|
+
});
|
|
428
|
+
}
|
|
429
|
+
return tokenResponse;
|
|
430
|
+
},
|
|
431
|
+
[client]
|
|
432
|
+
);
|
|
433
|
+
|
|
434
|
+
const passkey = useMemo(
|
|
435
|
+
() => ({ signup: passkeySignup, login: passkeyLogin }) as unknown as PasskeyApiClient,
|
|
436
|
+
[passkeySignup, passkeyLogin]
|
|
437
|
+
);
|
|
438
|
+
|
|
439
|
+
const contextValue = useMemo<Auth0ContextInterface<TUser>>(() => {
|
|
440
|
+
return {
|
|
441
|
+
...state,
|
|
442
|
+
getAccessTokenSilently,
|
|
443
|
+
getAccessTokenWithPopup,
|
|
444
|
+
getIdTokenClaims,
|
|
445
|
+
loginWithCustomTokenExchange,
|
|
446
|
+
customTokenExchange,
|
|
447
|
+
exchangeToken,
|
|
448
|
+
loginWithRedirect,
|
|
449
|
+
loginWithPopup,
|
|
450
|
+
connectAccountWithRedirect,
|
|
451
|
+
logout,
|
|
452
|
+
handleRedirectCallback,
|
|
453
|
+
getDpopNonce,
|
|
454
|
+
setDpopNonce,
|
|
455
|
+
generateDpopProof,
|
|
456
|
+
createFetcher,
|
|
457
|
+
getConfiguration,
|
|
458
|
+
mfa,
|
|
459
|
+
passkey,
|
|
460
|
+
myAccount,
|
|
461
|
+
};
|
|
462
|
+
}, [
|
|
463
|
+
state,
|
|
464
|
+
getAccessTokenSilently,
|
|
465
|
+
getAccessTokenWithPopup,
|
|
466
|
+
getIdTokenClaims,
|
|
467
|
+
loginWithCustomTokenExchange,
|
|
468
|
+
customTokenExchange,
|
|
469
|
+
exchangeToken,
|
|
470
|
+
loginWithRedirect,
|
|
471
|
+
loginWithPopup,
|
|
472
|
+
connectAccountWithRedirect,
|
|
473
|
+
logout,
|
|
474
|
+
handleRedirectCallback,
|
|
475
|
+
getDpopNonce,
|
|
476
|
+
setDpopNonce,
|
|
477
|
+
generateDpopProof,
|
|
478
|
+
createFetcher,
|
|
479
|
+
getConfiguration,
|
|
480
|
+
mfa,
|
|
481
|
+
passkey,
|
|
482
|
+
myAccount,
|
|
483
|
+
]);
|
|
484
|
+
|
|
485
|
+
return <context.Provider value={contextValue}>{children}</context.Provider>;
|
|
486
|
+
};
|
|
487
|
+
|
|
488
|
+
export default Auth0Provider;
|
package/src/errors.tsx
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* An OAuth2 error will come from the authorization server and will have at least an `error` property which will
|
|
3
|
+
* be the error code. And possibly an `error_description` property
|
|
4
|
+
*
|
|
5
|
+
* See: https://openid.net/specs/openid-connect-core-1_0.html#rfc.section.3.1.2.6
|
|
6
|
+
*/
|
|
7
|
+
export class OAuthError extends Error {
|
|
8
|
+
constructor(public error: string, public error_description?: string) {
|
|
9
|
+
super(error_description ?? error);
|
|
10
|
+
|
|
11
|
+
// https://github.com/Microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work
|
|
12
|
+
Object.setPrototypeOf(this, OAuthError.prototype);
|
|
13
|
+
}
|
|
14
|
+
}
|
package/src/index.tsx
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
export {
|
|
2
|
+
default as Auth0Provider,
|
|
3
|
+
Auth0ProviderOptions,
|
|
4
|
+
Auth0ProviderWithConfigOptions,
|
|
5
|
+
Auth0ProviderWithClientOptions,
|
|
6
|
+
AppState,
|
|
7
|
+
ConnectedAccount
|
|
8
|
+
} from './auth0-provider';
|
|
9
|
+
export { default as useAuth0 } from './use-auth0';
|
|
10
|
+
export { default as withAuth0, WithAuth0Props } from './with-auth0';
|
|
11
|
+
export {
|
|
12
|
+
default as withAuthenticationRequired,
|
|
13
|
+
WithAuthenticationRequiredOptions,
|
|
14
|
+
} from './with-authentication-required';
|
|
15
|
+
export {
|
|
16
|
+
default as Auth0Context,
|
|
17
|
+
Auth0ContextInterface,
|
|
18
|
+
initialContext,
|
|
19
|
+
LogoutOptions,
|
|
20
|
+
RedirectLoginOptions,
|
|
21
|
+
} from './auth0-context';
|
|
22
|
+
export {
|
|
23
|
+
AuthorizationParams,
|
|
24
|
+
PopupLoginOptions,
|
|
25
|
+
PopupConfigOptions,
|
|
26
|
+
GetTokenWithPopupOptions,
|
|
27
|
+
LogoutUrlOptions,
|
|
28
|
+
CacheLocation,
|
|
29
|
+
GetTokenSilentlyOptions,
|
|
30
|
+
IdToken,
|
|
31
|
+
User,
|
|
32
|
+
ICache,
|
|
33
|
+
InMemoryCache,
|
|
34
|
+
LocalStorageCache,
|
|
35
|
+
Cacheable,
|
|
36
|
+
TimeoutError,
|
|
37
|
+
MfaRequiredError,
|
|
38
|
+
PopupCancelledError,
|
|
39
|
+
PopupTimeoutError,
|
|
40
|
+
PopupOpenError,
|
|
41
|
+
AuthenticationError,
|
|
42
|
+
MissingRefreshTokenError,
|
|
43
|
+
GenericError,
|
|
44
|
+
UseDpopNonceError,
|
|
45
|
+
RedirectConnectAccountOptions,
|
|
46
|
+
ConnectAccountRedirectResult,
|
|
47
|
+
ResponseType,
|
|
48
|
+
ConnectError,
|
|
49
|
+
CustomTokenExchangeOptions,
|
|
50
|
+
TokenEndpointResponse,
|
|
51
|
+
ActClaim,
|
|
52
|
+
ClientConfiguration,
|
|
53
|
+
// MFA Errors
|
|
54
|
+
MfaError,
|
|
55
|
+
MfaListAuthenticatorsError,
|
|
56
|
+
MfaEnrollmentError,
|
|
57
|
+
MfaChallengeError,
|
|
58
|
+
MfaVerifyError,
|
|
59
|
+
MfaEnrollmentFactorsError,
|
|
60
|
+
// Passkey Errors
|
|
61
|
+
PasskeyError,
|
|
62
|
+
PasskeyRegisterError,
|
|
63
|
+
PasskeyChallengeError,
|
|
64
|
+
PasskeyGetTokenError,
|
|
65
|
+
// MyAccount Errors
|
|
66
|
+
MyAccountApiError,
|
|
67
|
+
} from '@auth0/auth0-spa-js';
|
|
68
|
+
export type {
|
|
69
|
+
FetcherConfig,
|
|
70
|
+
InteractiveErrorHandler,
|
|
71
|
+
// MFA Types
|
|
72
|
+
MfaApiClient,
|
|
73
|
+
Authenticator,
|
|
74
|
+
MfaFactorType,
|
|
75
|
+
EnrollParams,
|
|
76
|
+
EnrollOtpParams,
|
|
77
|
+
EnrollSmsParams,
|
|
78
|
+
EnrollVoiceParams,
|
|
79
|
+
EnrollEmailParams,
|
|
80
|
+
EnrollPushParams,
|
|
81
|
+
EnrollmentResponse,
|
|
82
|
+
ChallengeAuthenticatorParams,
|
|
83
|
+
ChallengeResponse,
|
|
84
|
+
VerifyParams,
|
|
85
|
+
EnrollmentFactor,
|
|
86
|
+
// Passkey Types
|
|
87
|
+
PasskeyApiClient,
|
|
88
|
+
PasskeySignupOptions,
|
|
89
|
+
PasskeyLoginOptions,
|
|
90
|
+
// MyAccount Types
|
|
91
|
+
MyAccountApiClient,
|
|
92
|
+
AuthenticationMethod,
|
|
93
|
+
AuthenticationMethodType,
|
|
94
|
+
Factor,
|
|
95
|
+
UpdateAuthenticationMethodRequest,
|
|
96
|
+
EnrollmentChallengeOptions,
|
|
97
|
+
EnrollmentChallengeResponse,
|
|
98
|
+
EnrollmentVerifyOptions,
|
|
99
|
+
} from '@auth0/auth0-spa-js';
|
|
100
|
+
export { OAuthError } from './errors';
|
package/src/reducer.tsx
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { User } from '@auth0/auth0-spa-js';
|
|
2
|
+
import { AuthState } from './auth-state';
|
|
3
|
+
|
|
4
|
+
type Action =
|
|
5
|
+
| { type: 'LOGIN_POPUP_STARTED' }
|
|
6
|
+
| {
|
|
7
|
+
type:
|
|
8
|
+
| 'INITIALISED'
|
|
9
|
+
| 'LOGIN_POPUP_COMPLETE'
|
|
10
|
+
| 'GET_ACCESS_TOKEN_COMPLETE'
|
|
11
|
+
| 'HANDLE_REDIRECT_COMPLETE';
|
|
12
|
+
user: User | undefined;
|
|
13
|
+
}
|
|
14
|
+
| { type: 'LOGOUT' }
|
|
15
|
+
| { type: 'ERROR'; error: Error };
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Handles how that state changes in the `useAuth0` hook.
|
|
19
|
+
*/
|
|
20
|
+
export const reducer = <TUser extends User = User>(state: AuthState<TUser>, action: Action): AuthState<TUser> => {
|
|
21
|
+
switch (action.type) {
|
|
22
|
+
case 'LOGIN_POPUP_STARTED':
|
|
23
|
+
return {
|
|
24
|
+
...state,
|
|
25
|
+
isLoading: true,
|
|
26
|
+
};
|
|
27
|
+
case 'LOGIN_POPUP_COMPLETE':
|
|
28
|
+
case 'INITIALISED':
|
|
29
|
+
return {
|
|
30
|
+
...state,
|
|
31
|
+
isAuthenticated: !!action.user,
|
|
32
|
+
user: action.user as TUser | undefined,
|
|
33
|
+
isLoading: false,
|
|
34
|
+
error: undefined,
|
|
35
|
+
};
|
|
36
|
+
case 'HANDLE_REDIRECT_COMPLETE':
|
|
37
|
+
case 'GET_ACCESS_TOKEN_COMPLETE':
|
|
38
|
+
if (state.user === action.user) {
|
|
39
|
+
return state;
|
|
40
|
+
}
|
|
41
|
+
return {
|
|
42
|
+
...state,
|
|
43
|
+
isAuthenticated: !!action.user,
|
|
44
|
+
user: action.user as TUser | undefined,
|
|
45
|
+
};
|
|
46
|
+
case 'LOGOUT':
|
|
47
|
+
return {
|
|
48
|
+
...state,
|
|
49
|
+
isAuthenticated: false,
|
|
50
|
+
user: undefined,
|
|
51
|
+
};
|
|
52
|
+
case 'ERROR':
|
|
53
|
+
return {
|
|
54
|
+
...state,
|
|
55
|
+
isLoading: false,
|
|
56
|
+
error: action.error,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { useContext } from 'react';
|
|
2
|
+
import { User } from '@auth0/auth0-spa-js';
|
|
3
|
+
import Auth0Context, { Auth0ContextInterface } from './auth0-context';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* ```js
|
|
7
|
+
* const {
|
|
8
|
+
* // Auth state:
|
|
9
|
+
* error,
|
|
10
|
+
* isAuthenticated,
|
|
11
|
+
* isLoading,
|
|
12
|
+
* user,
|
|
13
|
+
* // Auth methods:
|
|
14
|
+
* getAccessTokenSilently,
|
|
15
|
+
* getAccessTokenWithPopup,
|
|
16
|
+
* getIdTokenClaims,
|
|
17
|
+
* loginWithCustomTokenExchange,
|
|
18
|
+
* exchangeToken, // deprecated - use loginWithCustomTokenExchange
|
|
19
|
+
* loginWithRedirect,
|
|
20
|
+
* loginWithPopup,
|
|
21
|
+
* logout,
|
|
22
|
+
* } = useAuth0<TUser>();
|
|
23
|
+
* ```
|
|
24
|
+
*
|
|
25
|
+
* Use the `useAuth0` hook in your components to access the auth state and methods.
|
|
26
|
+
*
|
|
27
|
+
* TUser is an optional type param to provide a type to the `user` field.
|
|
28
|
+
*/
|
|
29
|
+
const useAuth0 = <TUser extends User = User>(
|
|
30
|
+
context = Auth0Context
|
|
31
|
+
): Auth0ContextInterface<TUser> =>
|
|
32
|
+
useContext(context) as Auth0ContextInterface<TUser>;
|
|
33
|
+
|
|
34
|
+
export default useAuth0;
|