Skip to content

Commit

Permalink
Merge pull request #214 from pavinduLakshan/byor
Browse files Browse the repository at this point in the history
Remove secureroute component and react-router dependency
  • Loading branch information
brionmario authored Jun 28, 2024
2 parents 91e78ad + 0f0f78f commit 177e88c
Show file tree
Hide file tree
Showing 7 changed files with 90 additions and 179 deletions.
146 changes: 85 additions & 61 deletions API.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@

- [AuthProvider](#authprovider)
- [Securing routes with Asgardeo](#securing-routes-with-asgardeo)
- [SecureRoute](#1-secureroute)
- [SecureApp](#2-secureapp)
- [AuthenticatedComponent](#3-authenticatedcomponent)
- [SecureApp](#1-secureapp)
- [AuthenticatedComponent](#2-authenticatedcomponent)
- [Bring Your Own Router](#3-bring-your-own-router)
- [useAuthContext React Hook](#useauthcontext-react-hook)
- [`state` Object](#state-object)
- [Consuming the `isLoading` State of the Auth Flow](#consuming-the-isloading-state-of-the-auth-flow)
- [List of supported APIs](#list-of-supported-apis)
- [signIn](#signin)
- [isAuthenticated](#isauthenticated)
- [autoSignIn](#autoSignIn)
- [autoSignIn](#autosignin)
- [getBasicUserInfo](#getbasicuserinfo)
- [signOut](#signout)
- [getIDToken](#getidtoken)
Expand Down Expand Up @@ -67,7 +67,8 @@ The `AuthProvider` also automatically requests for the access token should the U

If the response mode is set to [`form_post`](#using-the-form_post-response-mode), then you will have your own ways of retrieving the authorization code and session state from your backend. In that case, you can use the `getAuthParams()` prop method to pass an async callback function that would return the `authorizationCode` and `sessionState` in a Promise. This way, the `AuthProvider` will use the authorization code returned by this method to automatically request for an access token.

#### Example
Example:

```TypeScript
export const MyApp = (): ReactElement => {
return (
Expand All @@ -78,7 +79,8 @@ export const MyApp = (): ReactElement => {
}
```

#### Example with an external Auth SPA plugin
Example with an external Auth SPA plugin:

```TypeScript
import { TokenExchangePlugin } from "@asgardeo/token-exchange-plugin";

Expand All @@ -92,62 +94,13 @@ export const MyApp = (): ReactElement => {
```
---
## Securing routes with Asgardeo
There are 3 approaches you can use to secure routes in your React application with Asgardeo. To learn more about the implementation, you can refer to [this article.](https://stackoverflow.com/collectives/wso2/articles/74041550/authenticate-react-applications-with-asgardeo-part-2-securing-routes)

### 1. SecureRoute
The SDK also provides a component called `SecureRoute` that wraps the `Route` component provided by `react-router-dom`. This allows you to secure your routes using the SDK. Only authenticated users will be taken to the route.

Use this if you want a route to be an authenticated route. So, this route will be rendered only if a user is authenticated. Otherwise, the `callback` function will be fired.

```TypeScript
<SecureRoute
path="/secure-page"
component={ <SecureComponent /> }
callback={ signInFunction }
/>
```
This component takes three props. The `path`, `component` and `callback`.

1. **path**: `string`
The path pattern to match against the URL to determine if this route matches a URL, link href, or form action. This prop just relay the prop values directly to the `<Route />` component of the `react-router-dom`.
2. **component**: `React.ReactNode | null`
The element to render when the route matches the URL. This prop just relay the prop values directly to the `<Route />` component of the `react-router-dom`.
3. **callback**: `() => void`
This takes a callback function that is fired when an unauthenticated user access the route. Developers can use this callback function to either to redirect the user to the login page of the app or to call the [`signIn`](#signIn) method.



#### Example
```typescript
import { SecureRoute, useAuthContext } from "@asgardeo/auth-react";
import { BrowserRouter, Route, Switch } from "react-router-dom";
There are 3 approaches you can use to secure routes in your React application with Asgardeo.

const Routes = () => {
const { signIn } = useAuthContext();
### 1. SecureApp

return (
<Router>
<Switch>
<Route exact path="/home" component={ HomePage } />
<SecureRoute
path="/secure-page"
component={ SecurePageComponent }
callback={ () => {
// Fires when the user is not authenticated.
// Will be directed to sign in.
signIn();
}}
/>
<Route component={NotFoundPage} />
</Switch>
</Router>
)
}
```
In the above example, an unauthenticated user can visit `/home` route. But they cannot visit the `/secure-page` route and they will be redirected to the Asgardeo sign-in page via [`signIn()`](#signin) function.

### 2. SecureApp
This is a component that can be used to secure a whole React app. This component wraps a React component and renders it only if the user is signed in. Otherwise, it renders the `fallback` prop. If the user is not signed in, this component automatically initiates the sign-in flow.

```TypeScript
<SecureApp
fallback={ <Loader /> }
Expand Down Expand Up @@ -186,15 +139,18 @@ const App = () => {
}
```

### 3. AuthenticatedComponent
### 2. AuthenticatedComponent

This component is used to wrap the components that need authentication. This offers more granular control of the elements that should or should not be rendered depending on whether the user is authenticated or not.

```TypeScript
<AuthenticatedComponent
fallback={ <FallbackComponent /> }
>
<SecureComponent />
</AuthenticatedComponent>
```

If the user is authenticated, the component renders the wrapped component. If the user is not authenticated, the component renders the `fallback` prop which accepts any **React element**.

#### Example
Expand Down Expand Up @@ -225,12 +181,79 @@ In this case, `<Header />` and `<Footer />` will render regardless of user's aut

If the user is **not** authenticated, the `<FallbackComponent/>` will be loaded. If you didn't include a `fallback`, it will render a `null` instead.

### 3. Implement Your Own Routing Logic

It's also possible to implement your own routing logic to secure the protected routes, based on the routing library you use.

#### React Router v6

Create a reusable component that redirects user to the sign in page based on the authentication status.

**ProtectedRoute.js**

```js
import { useAuthContext } from '@asgardeo/auth-react';

const ProtectedRoute = ({ children }) => {
const {
signIn,
state: { isAuthenticated }
} = useAuthContext();

if (!isAuthenticated) {
return (
<button
onClick={ () => signIn }
>
Sign In
</button>
)
}

return children;
};

export default ProtectedRoute;
```

Use the `ProtectedRoute` as follows, in your route definition.

```js
import { AuthProvider } from '@asgardeo/auth-react'
import { Routes, Route } from 'react-router-dom'
import ProtectedRoute from './components/ProtectedRoute'
import Home from './pages/Home'
import Dashboard from './pages/Dashboard'

const App = () => {
return (
<AuthProvider>
<Router>
<Routes>
<Route path="/" element={<Home />} />
<Route
path="/dashboard"
element={
<ProtectedRoute>
<Dashboard />
</ProtectedRoute>
}
/>
</Routes>
</Router>
</AuthProvider>
);
};

export default App;
```

---
## useAuthContext React Hook

This is a React hook that returns the session state that contains information such as the email address of the authenticated user and the methods that are required for implementing authentication.

#### Example
Example:

```TypeScript
const { signIn } = useAuthContext();
Expand All @@ -245,7 +268,8 @@ You can see all the APIs that can be accessed via `useAuthContext()` [in here](#

The state object will contain attributes such as whether a user is currently logged in, the username of the currently logged-in user etc. It is an object of type [`AuthStateInterface`](#authstateinterface).

#### Example
Example:

```json
{
"allowedScopes": "openid profile",
Expand Down
20 changes: 4 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ Asgardeo Auth React SDK allows React applications to use [OpenID Connect - OIDC
- [Authenticate users](#add-a-loginlogout-button)
- [Show Authenticated User's Information](#show-authenticated-users-information)
- [Retrieve Additional User Information](/API.md#getbasicuserinfo)
- [Secure Routes](/API.md#1-secureroute)
- [Secure Components](/API.md#3-authenticatedcomponent)
- [Send HTTP Requests to Asgardeo](/API.md#httprequest)

Expand All @@ -47,27 +46,18 @@ Follow this guide to integrate Asgardeo to your own React Application. To try ou

### 1. Installing the Package

Run the following command to install `@asgardeo/auth-react` & `react-router-dom` from the npm registry.

Use below command if you are using *React v16.8* or greater & *React Router v6*
Run the following command to install `@asgardeo/auth-react` from the npm registry.

```bash
npm install @asgardeo/auth-react react-router-dom --save
npm install @asgardeo/auth-react --save
```
Else if you are using *React v16.8* or greater & *React Router v5*, use below command

```bash
npm install @asgardeo/[email protected] [email protected] --save
```

> **Note**
> The `react-router-dom` package is a peer-dependency of the SDK and it is required to be installed for the SDK to work. We are working on making it optional.

### 2. Import [`AuthProvider`](/API.md#authprovider) and Provide [Configuration Parameters](/API.md#authreactconfig)

Asgardeo React SDK exposes the `AuthProvider` component, which helps you easily integrate Asgardeo to your application.

First, import the `AuthProvider` component from `@asgardeo/auth-react.` where you applications root component is defined.

> **Note**
> Typically the root component of a react app is defined in the index.* file.
Expand All @@ -76,7 +66,6 @@ import { AuthProvider } from "@asgardeo/auth-react";
```
Then, wrap your root component with the `AuthProvider`.


```TypeScript
import React from "react";
import { AuthProvider } from "@asgardeo/auth-react";
Expand All @@ -102,7 +91,6 @@ export const MyApp = (): ReactElement => {
Once the root component is wrapped with AuthProvider, [`useAuthContext()` hook](#useauthcontext-hook) can be used anywhere within the application to implement user authentication capabilities in the application.


## Using APIs

### Best practices when using APIs
Expand All @@ -118,7 +106,7 @@ Asgardeo Auth React SDK is built on top of [Asgardeo Auth SPA SDK](https://githu
<details><summary><strong>Click here for Tips:</strong> Do's When importing a component from Asgardeo React SDK</summary>
<p>

##### DO ✅
#### DO ✅
```TypeScript
import { AsgardeoSPAClient } from "@asgardeo/auth-react";
```
Expand Down
5 changes: 1 addition & 4 deletions lib/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@
"@babel/preset-typescript": "^7.18.6",
"@babel/runtime-corejs3": "^7.20.6",
"@types/node": "^18.11.17",
"@types/react-router-dom": "^5.3.3",
"@typescript-eslint/eslint-plugin": "^5.47.0",
"@typescript-eslint/parser": "^5.47.0",
"babel-loader": "^9.1.0",
Expand All @@ -62,7 +61,6 @@
"eslint-webpack-plugin": "^3.2.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.3.0",
"rimraf": "^3.0.2",
"typescript": "^4.9.4",
"webpack": "^5.75.0",
Expand All @@ -72,7 +70,6 @@
"peerDependencies": {
"@babel/runtime-corejs3": "^7.11.2",
"react": ">=16.8",
"react-dom": ">=16.8",
"react-router-dom": "^6.3.0"
"react-dom": ">=16.8"
}
}
5 changes: 0 additions & 5 deletions lib/src/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,11 +124,6 @@ export interface AuthContextInterface {
error: AsgardeoAuthException;
}

export interface SecureRouteInterface {
callback: () => void;
component: any;
}

/**
* The model of the object returned by the `getAuthParams` prop method of the `AuthProvider`.
*/
Expand Down
1 change: 0 additions & 1 deletion lib/src/public-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,5 @@

export * from "./authenticate";
export * from "./models";
export * from "./secure-route";
export * from "./authenticated-component";
export * from "./secure-app";
70 changes: 0 additions & 70 deletions lib/src/secure-route.tsx

This file was deleted.

Loading

0 comments on commit 177e88c

Please sign in to comment.