-
Notifications
You must be signed in to change notification settings - Fork 314
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #4845 from sagara-gunathunga/master
Adding Asgardeo React complete guide
- Loading branch information
Showing
21 changed files
with
837 additions
and
108 deletions.
There are no files selected for viewing
146 changes: 146 additions & 0 deletions
146
en/asgardeo/docs/complete-guides/react/accessing-protected-api.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
78
en/asgardeo/docs/complete-guides/react/add-login-and-logout.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
39
en/asgardeo/docs/complete-guides/react/create-a-react-app.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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. |
42 changes: 0 additions & 42 deletions
42
en/asgardeo/docs/complete-guides/react/create-a-react-application.md
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.