Skip to content

Commit

Permalink
Merge pull request #4845 from sagara-gunathunga/master
Browse files Browse the repository at this point in the history
Adding Asgardeo React complete guide
  • Loading branch information
jeradrutnam authored Nov 11, 2024
2 parents 1362e3b + b0285dc commit 03320ce
Show file tree
Hide file tree
Showing 21 changed files with 837 additions and 108 deletions.
146 changes: 146 additions & 0 deletions en/asgardeo/docs/complete-guides/react/accessing-protected-api.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
---
template: templates/complete-guide.html
heading: Accessing protected API from your React app
read_time: 2 min
---

In this section, we will focus on how to call a secure API from your React app using the other token—the access token.

For simplicity, let's assume that the APIs we’re calling are secured by the same Identity Provider (IdP) and use the same issuer— in this case, the same {{product_name}} organization. This is typical when React apps are interacting with internal APIs within the same organization.

!!! tip "Tip"

If your app needs to call APIs secured by a different IdP, you’ll need to exchange your current access token for a new one issued by the IdP securing those APIs. This can be done using the OAuth2 token exchange grant type or other supported grant types. We will cover these scenarios in a separate guide.

## Using SDK Built-in HTTP client

You can use the `httpRequest` API provided by the Asgardeo SDK to make HTTP requests to these endpoints. This function is used to send http requests to {{product_name}} or desired backend. The developer doesn’t need to manually attach the access token since this function does it automatically.

The following is a simple example of how you might use the Asgardeo SDK’s `httpRequest` to call a protected API endpoint, such as `/scim2/me` (to get the user profile details after signing in). In this case, the SCIM 2 endpoint is secured by the same {{product_name}} organization. {{product_name}} provides a SCIM 2 API for managing users within your organization. While user management with SCIM 2 is a topic for a different guide, we will use the API as part of our current guide.

!!! note "Note"

The storage type must be set to `webWorker` for the token to be automatically attached. If it’s set to `sessionStorage` or `localStorage`, you may implement your own function for attaching the access token to the network request.

```javascript

const App = () => {


const { httpRequest } = useAuthContext();


const requestConfig = {
headers: {
"Accept": "application/json",
"Content-Type": "application/scim+json"
},
method: "GET",
url: "https://api.asgardeo.io/t/<org_name>/scim2/me"
};


useEffect(() => {
// Make a GET request to a protected endpoint
httpRequest(requestConfig)
.then((response) => {
// Handle successful response
console.log('Response:', response.data);
})
.catch((error) => {
// Handle error
console.error('Error:', error);
});
}, [])
}

```

Note that you don’t need to manually specify the Authorization header under headers in `requestConfig`, as `httpRequest` function intercepts the request and attaches the access token to the network request as the Authorization header.

In the above example, the final request config sent by the `httpRequest` function would be as follows

```javascript
const requestConfig = {
headers: {
"Accept": "application/json",
"Content-Type": "application/scim+json",
"Authorization": "Bearer <access_token_retrieved_from_web_worker>"
},
method: "GET",
url: "https://api.asgardeo.io/t/<org_name>/scim2/me"
};


```

In case you want to send multiple API requests in parallel, you can use the `httpRequestAll` function to simultaneously trigger parallel network requests and receive responses after all network requests are completed.

The following code snippet shows a javascript function which accepts a list of application IDs and sends multiple network requests for each app ID in parallel. The responses will contain results for each id, as an array of responses.

```javascript
import { AsgardeoSPAClient } from "@asgardeo/auth-react";


const httpClientAll = AsgardeoSPAClient.getInstance()
.httpRequestAll.bind(AsgardeoSPAClient.getInstance());


export const getApplicationsByIds = async (ids) => {


const requests = [];


for (const id of ids) {
requests.push({
headers: {
"Accept": "application/json",
"Content-Type": "application/json"
},
method: "GET",
url: "https://localhost:9443/applications/" + id
});
}


try {
const responses = await httpClientAll(requests);


return Promise.resolve(responses);
} catch (error) {
console.error(error);
}
};

```

## Using a custom HTTP client

In case you are not using the webWorker as the storage type, the `getAccessToken` function can be used to fetch the access token and manually attach it to the network request. The following is an example where the access token is fetched and manually attached to the authorization header of a Fetch request.

```javascript
import { useAuthContext } from "@asgardeo/auth-react";


const App = () => {
const { getAccessToken } = useAuthContext();


useEffect(() => {
getAccessToken().then(async (accessToken) => {
const response = await fetch("https://api.asgardeo.io/t/<org_name>/scim2/me", {
"Authorization": "Bearer " + accessToken
})
console.log(response)
}).catch((error) => {
console.log(error);
});
}, []);

.
.
.
}
```
78 changes: 78 additions & 0 deletions en/asgardeo/docs/complete-guides/react/add-login-and-logout.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
---
template: templates/complete-guide.html
heading: Add login and logout to your app
read_time: 2 min
---

Next, let’s implement login and logout for our React app. React hooks are a special type of functions that let you access state and other React features in React functional components. Asgardeo provides one such hook, `useAuthContext()`, to conveniently access user authentication data such as the logged in user’s information, etc and utility functions, such as a function to validate user’s authentication status, and retrieve access tokens.

`useAuthContext` hook also provides us access with two key functions to perform sign in and sign out in your React application, `signIn` and `signOut` respectively. You can directly invoke the respective functions in our React application to trigger sign-in and sign-out requests as follows.

Update the `App.jsx` with the following code.

```javascript
import { useAuthContext } from "@asgardeo/auth-react";
import './App.css';

const App = () => {
const { state, signIn, signOut } = useAuthContext();

return (
<>
{
state.isAuthenticated
? <button onClick={() => signOut()}>Logout</button>
: <button onClick={() => signIn()}>Login</button>
}
</>
)
};

export default App;
```

Let’s look into the underlying details of what’s happening here.

The `authConfig` object holds the configuration necessary for connecting the app to {{product_name}}. It includes properties like `signInRedirectURL` and `signOutRedirectURL`, which determine where users are redirected after signing in or out. The `clientID` identifies the application, and `baseUrl` specifies the Asgardeo API endpoint specific to your organization. The scope array lists the OAuth 2.0 permissions the app requires, such as `openid` and `profile`. The scops are used to indicate what user attributes are expected by our React app.

The App component leverages the `useAuthContext` hook to access the authentication state (`state`) and actions (`signIn` and `signOut`). Inside the `AuthProvider`, the app conditionally renders a login or logout button based on whether the user is authenticated. If `state.isAuthenticated` is true, a "Logout" button is shown that triggers the `signOut` function. Otherwise, a "Login" button appears, which initiates the signIn process.

Save the changes and re-run the application in development mode if it is not running already.

```bash
npm run dev
```

Once the application is started, you will see the homepage of the application with the changes we made.

![Login screen]({{base_path}}/complete-guides/react/assets/img/image14.png){: width="800" style="display: block; margin: 0;"}

Initiate Sign In
Clicking on the login button will initiate an OIDC request. You will be able to observe the authorize request in the browser devtools as follows. To see this, right click on the application and click inspect and switch to the network tab. In the filter input, type “authorize”, and click on the sign in button.

![OIDC request]({{base_path}}/complete-guides/react/assets/img/image15.png){: width="800" style="display: block; margin: 0;"}

!!! tip "Tip"

The OpenID Connect specification offers several functions, known as grant types, to obtain an access token in exchange for user credentials. This example uses the authorization code grant type. In this process, the app first requests a unique code from the authentication server, which can later be used to obtain an access token. For more details on the authorization code grant type, please refer to the [Asgardeo documentation.](https://wso2.com/asgardeo/docs/guides/authentication/oidc/implement-auth-code-with-pkce/){:target="_blank"}

Asgardeo will receive this authorization request and respond by redirecting the user to a login page to enter their credentials.

![OIDC request]({{base_path}}/complete-guides/react/assets/img/image16.png){: width="800" style="display: block; margin: 0;"}

At this stage, **you need to create a [test user in Asgardeo](https://wso2.com/asgardeo/docs/guides/users/manage-users/#onboard-users){:target="_blank"} to try out the application.** Once you create a test user, you can enter the username and password of the test user to the login screen.

If the login is successful, you should be able to see the application as shown below.

![Login flow]({{base_path}}/complete-guides/react/assets/img/image17.png){: width="800" style="display: block; margin: 0;"}

!!! tip "Tip"

**PKCE (Proof Key for Code Exchange)** is an addition to the OAuth2 specification to make the authorization code more immune to replay attacks. It is enabled by default for public clients such as our single page React application.

If you want to disable PKCE for some reason, you can do so via following the steps below. **However, disabling PKCE for public clients such as our single page React app is highly discouraged.**
- Log in to the {{product_name}} console and select the application you created.
- Switch to the Protocol tab.
- Uncheck the Mandatory checkbox under PKCE section.

In this section, we have added login and logout features to our React app. In the next step, we will look into how to access the user attributes of the logged in user.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
39 changes: 39 additions & 0 deletions en/asgardeo/docs/complete-guides/react/create-a-react-app.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
---
template: templates/complete-guide.html
heading: Create a React app
read_time: 2 min
---

For this guide, you will be creating a simple React app using [Vite](https://vitejs.dev/){:target="_blank"}, a modern, fast and lightweight tool that helps you quickly set up and develop modern JavaScript apps.

Open a terminal, change directory to where you want to initialize the project, and run the following command to create your first React sample app.


```bash
npm create vite@latest asgardeo-react -- --template react
```

Running this command will create a folder with a ready-to-run boilerplate React project, with a development server to run the project and instantly reload changes to the project in your browser without manual refresh.

Once the application is created, install the dependencies using the following command.

```bash
cd asgardeo-react
npm install
```

Then run the sample in the development mode. This allows you to see real-time updates and debug the app as you make changes.

```bash
npm run dev
```

Confirm that the dev server is up and running by verifying the following output in the terminal.

![Dev server is runnig]({{base_path}}/complete-guides/react/assets/img/image13.png){: width="600" style="display: block; margin: 0;"}

Navigate to [http://localhost:5173](http://localhost:5173){:target="_blank"} and you should see the sample app working in the browser.

![Navigate to localhost]({{base_path}}/complete-guides/react/assets/img/image6.png){: width="600" style="display: block; margin: 0;"}

At this point, you have a simple yet fully functional React app. In the next step, let’s try to integrate an OIDC SDK with the app.

This file was deleted.

Loading

0 comments on commit 03320ce

Please sign in to comment.