-
Notifications
You must be signed in to change notification settings - Fork 266
/
Copy pathwith-authentication-required.tsx
123 lines (115 loc) · 3.26 KB
/
with-authentication-required.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
import React, { ComponentType, useEffect, FC } from 'react';
import useAuth0 from './use-auth0';
import Auth0Context, {
Auth0ContextInterface,
RedirectLoginOptions,
} from './auth0-context';
/**
* @ignore
*/
const defaultOnRedirecting = (): JSX.Element => <></>;
/**
* @ignore
*/
const defaultReturnTo = (): string =>
`${window.location.pathname}${window.location.search}`;
/**
* Options for the withAuthenticationRequired Higher Order Component
*/
export interface WithAuthenticationRequiredOptions {
/**
* ```js
* withAuthenticationRequired(Profile, {
* returnTo: '/profile'
* })
* ```
*
* or
*
* ```js
* withAuthenticationRequired(Profile, {
* returnTo: () => window.location.hash.substr(1)
* })
* ```
*
* Add a path for the `onRedirectCallback` handler to return the user to after login.
*/
returnTo?: string | (() => string);
/**
* ```js
* withAuthenticationRequired(Profile, {
* onRedirecting: () => <div>Redirecting you to the login...</div>
* })
* ```
*
* Render a message to show that the user is being redirected to the login.
*/
onRedirecting?: () => JSX.Element;
/**
* ```js
* withAuthenticationRequired(Profile, {
* loginOptions: {
* appState: {
* customProp: 'foo'
* }
* }
* })
* ```
*
* Pass additional login options, like extra `appState` to the login page.
* This will be merged with the `returnTo` option used by the `onRedirectCallback` handler.
*/
loginOptions?: RedirectLoginOptions;
/**
* The context to be used when calling useAuth0, this should only be provided if you are using multiple Auth0Providers
* within your application and you wish to tie a specific component to a Auth0Provider other than the Auth0Provider
* associated with the default Auth0Context.
*/
context?: React.Context<Auth0ContextInterface>;
}
/**
* ```js
* const MyProtectedComponent = withAuthenticationRequired(MyComponent);
* ```
*
* When you wrap your components in this Higher Order Component and an anonymous user visits your component
* they will be redirected to the login page and returned to the page they we're redirected from after login.
*/
const withAuthenticationRequired = <P extends object>(
Component: ComponentType<P>,
options: WithAuthenticationRequiredOptions = {}
): FC<P> => {
return function WithAuthenticationRequired(props: P): JSX.Element {
const {
returnTo = defaultReturnTo,
onRedirecting = defaultOnRedirecting,
loginOptions,
context = Auth0Context,
} = options;
const { isAuthenticated, isLoading, loginWithRedirect } =
useAuth0(context);
useEffect(() => {
if (isLoading || isAuthenticated) {
return;
}
const opts = {
...loginOptions,
appState: {
...(loginOptions && loginOptions.appState),
returnTo: typeof returnTo === 'function' ? returnTo() : returnTo,
},
};
(async (): Promise<void> => {
await loginWithRedirect(opts);
})();
}, [
isLoading,
isAuthenticated,
loginWithRedirect,
loginOptions,
returnTo,
]);
return isAuthenticated ? <Component {...props} /> : onRedirecting();
};
};
export default withAuthenticationRequired;