Skip to content

Commit

Permalink
feat: add withAuthenticationRequired
Browse files Browse the repository at this point in the history
  • Loading branch information
pamapa committed Dec 15, 2023
1 parent 72d4585 commit 43dd058
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 0 deletions.
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,21 @@ export const getPosts = createAsyncThunk(
)
```
### Protect a route
Secure a route component by using the withAuthenticationRequired higher-order component. If a user attempts to access this route without authentication, they will be redirected to the login page.
```jsx
import React from 'react';
import { withAuthenticationRequired } from "react-oidc-context";

const PrivateRoute = () => (<div>Private</div>);

export default withAuthenticationRequired(PrivateRoute, {
onRedirecting: () => (<div>Redirecting to the login page...</div>)
});
```
### Adding event listeners
The underlying [`UserManagerEvents`](https://authts.github.io/oidc-client-ts/classes/UserManagerEvents.html) instance can be imperatively managed with the `useAuth` hook.
Expand Down
7 changes: 7 additions & 0 deletions docs/react-oidc-context.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,13 @@ export const useAuth: () => AuthContextProps;
// @public
export function withAuth<P>(Component: React_2.ComponentType<P>): React_2.ComponentType<Omit<P, keyof AuthContextProps>>;

// @public (undocumented)
export interface WithAuthenticationRequiredOptions {
onBeforeSignin?: () => Promise<void> | void;
onRedirecting?: () => JSX.Element;
signinRedirectArgs?: SigninRedirectArgs;
}

// (No @packageDocumentation comment for this package)

```
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ export type { AuthState } from "./AuthState";
export * from "./useAuth";
export { hasAuthParams } from "./utils";
export * from "./withAuth";
export * from "./withAuthenticationRequired";
66 changes: 66 additions & 0 deletions src/withAuthenticationRequired.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import React from "react";

import { useAuth } from "./useAuth";
import type { SigninRedirectArgs } from "oidc-client-ts";

/**
* @public
*/
export interface WithAuthenticationRequiredOptions {
/**
* Show a message when redirected to the login page.
*/
onRedirecting?: () => JSX.Element;

/**
* Allows executing logic before the user is redirected to the login page.
*/
onBeforeSignin?: () => Promise<void> | void;

/**
* Pass additional signin redirect options.
*/
signinRedirectArgs?: SigninRedirectArgs;
}

/**
* A public higher-order component to protect accessing not public content. 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; after logging in, they
* will return to the page from which they were redirected.
*
* @public
*/
const withAuthenticationRequired = <P extends object>(
Component: React.ComponentType<P>,
options: WithAuthenticationRequiredOptions = {},
): React.FC<P> => {
const { onRedirecting = (): JSX.Element => <></>, onBeforeSignin, signinRedirectArgs } = options;

const displayName = `withAuthenticationRequired(${Component.displayName || Component.name})`;
const C: React.FC<P> = (props) => {
const auth = useAuth();

Check warning on line 41 in src/withAuthenticationRequired.tsx

View check run for this annotation

Codecov / codecov/patch

src/withAuthenticationRequired.tsx#L40-L41

Added lines #L40 - L41 were not covered by tests

React.useEffect(() => {

Check warning on line 43 in src/withAuthenticationRequired.tsx

View check run for this annotation

Codecov / codecov/patch

src/withAuthenticationRequired.tsx#L43

Added line #L43 was not covered by tests
if (auth.isLoading || auth.isAuthenticated) {
return;

Check warning on line 45 in src/withAuthenticationRequired.tsx

View check run for this annotation

Codecov / codecov/patch

src/withAuthenticationRequired.tsx#L45

Added line #L45 was not covered by tests
}
void (async (): Promise<void> => {

Check warning on line 47 in src/withAuthenticationRequired.tsx

View check run for this annotation

Codecov / codecov/patch

src/withAuthenticationRequired.tsx#L47

Added line #L47 was not covered by tests
onBeforeSignin && await onBeforeSignin();
await auth.signinRedirect(signinRedirectArgs);

Check warning on line 49 in src/withAuthenticationRequired.tsx

View check run for this annotation

Codecov / codecov/patch

src/withAuthenticationRequired.tsx#L49

Added line #L49 was not covered by tests
})();
}, [
auth.isLoading,
auth.isAuthenticated,
onBeforeSignin,
signinRedirectArgs,
]);

return auth.isAuthenticated ? <Component {...props} /> : onRedirecting();
};

C.displayName = displayName;

Check warning on line 61 in src/withAuthenticationRequired.tsx

View check run for this annotation

Codecov / codecov/patch

src/withAuthenticationRequired.tsx#L61

Added line #L61 was not covered by tests

return C;

Check warning on line 63 in src/withAuthenticationRequired.tsx

View check run for this annotation

Codecov / codecov/patch

src/withAuthenticationRequired.tsx#L63

Added line #L63 was not covered by tests
};

export default withAuthenticationRequired;

0 comments on commit 43dd058

Please sign in to comment.