Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding Next.js Guides #4925

Merged
merged 5 commits into from
Dec 10, 2024
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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.
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.
19 changes: 19 additions & 0 deletions en/asgardeo/docs/complete-guides/fesecurity/csrf.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
template: templates/complete-guide.html
heading: Cross-Site Request Forgery (CSRF)
read_time: 2 mins
---

Cross-Site Request Forgery (CSRF) is an attack where an attacker tricks a user into performing unwanted actions on a web application where they are authenticated. This can lead to unauthorized actions being executed on behalf of the user, such as changing account details or making transactions.


![CSRF Attack Flow]({{base_path}}/complete-guides/fesecurity/assets/img/image12.png){: width="800" style="display: block; margin: 0;"}


CSRF exploits the trust that a web application has in the user's browser. If an application relies solely on cookies for authentication, an attacker can craft a request to the application from a different site, using the authenticated user's credentials to perform malicious actions.


To mitigate CSRF attacks:

1. Include a unique, unpredictable token in each request, also referred to as CSRF token. The server should validate this token to ensure the request is legitimate.
2. Set cookies with the SameSite attribute to Strict or Lax to prevent them from being sent in cross-site requests.
89 changes: 89 additions & 0 deletions en/asgardeo/docs/complete-guides/fesecurity/insecure-tokens.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
---
template: templates/complete-guide.html
heading: Insecure token handling
read_time: 2 min
---

When handling tokens such as the ID tokens and access tokens that we looked at in the previous section, there’s a risk of manipulation, such as replaying or tampering with a JWT token to elevate privileges or exploiting JWT invalidation. Due to this reason, it’s important to validate the ID token before using any information from it or storing it in the browser. Let’s look at how you can validate the ID token here because we use the ID token to establish the logged-in user context at the application level.

The ID token is a JWT (JSON Web Token) consisting of a header, payload, and signature, each encoded in Base64 and separated by dots. Here's an example of a decoded JWT token:




```json

{
"x5t": "C2wu7Amo4wsyJgLt5Td1l7dpztc",
"kid": "OTMyNmUwMjAxNWE0ODFiZTI5NzIxYTJhOTgxYTI4NjA4ZmUzNWUyZDhlNWI4MzQ3ZWU5OTUxYTU3YTczNjcxMA_RS256",
"alg": "RS256"
}
{
...
"iss": "https://api.asgardeo.io/t/mifrazmurthaja/oauth2/token",
"sid": "eefd4513-e01c-44a3-ae8b-e59cc11c64e1",
"aud": "sq4ktPY4lnEDBj8u5kImfHi4nSca",
"nbf": 1724261085,
"azp": "sq4ktPY4lnEDBj8u5kImfHi4nSca",
"exp": 1724264685,
"iat": 1724261085,
...
}
{
<SIGNATURE>
}

```

The header typically contains certificate information and the signature algorithm, while the payload includes user attributes and other crucial data. To validate an ID token,

1. **Validate the signature of the ID token.**
2. **Verify key attributes such as issuer (iss), audience (aud), issued-at time (iat), and expiration time (exp).**

Refer to the Validate ID Tokens [documentation](https://wso2.com/asgardeo/docs/guides/authentication/oidc/validate-id-tokens){:target="_blank"} for more details on these attributes and the validation process.

Again you don’t need to attend the token validation by yourself, following the security best practices, the Asgardeo SDK enables ID token validation by default, using the JWKS (JSON Web Key Set) endpoint of Asgardeo to validate the signature. The SDK constructs the JWKS and other necessary endpoints based on the baseUrl, so providing the baseUrl is typically sufficient. To give you an idea about what happens behind the scenes, the Asgardeo React SDK retrieves the public key of your Asgardeo organization through the JWKS endpoint and uses it to verify whether the token has been signed by the private key of your Asgardeo organization. If required, you can modify the JWKS endpoint and other parameters.

```javascript title="src/main.jsx" hl_lines="9-11"

import { AuthProvider } from "@asgardeo/auth-react";

const authConfig = {
clientID: "YOUR_CLIENT_ID",
signInRedirectURL: "http://localhost:3000",
signOutRedirectURL: "http://localhost:3000",
baseUrl: "https://api.asgardeo.io/t/{org_name}",
scope: [ "openid","profile"],
endpoints: {jwksUri: "https://api.asgardeo.io/t/{org_name}/oauth2/token"}
validateIDToken: true,
clockTolerance: 60,
...
};


```

The Asgardeo React SDK also validates other attributes such as the issuer and expiration period, with a default clock tolerance of 60 seconds.

Once you have validated the ID token and the access token received from the IdP, it's crucial to store them securely in the browser making sure the token can not be stolen from the storage to maintain the user state.

There are several storage mechanisms available in the browser, such as Session Storage, Local Storage, Web Workers, and Browser Memory. By default, the Asgardeo SDK stores session information, including the access token, in Session Storage. However, this can be configured as per your requirements. Here is an example using Asgardeo React SDK.

```javascript title="src/main.jsx" hl_lines="9"
import { AuthProvider } from "@asgardeo/auth-react";

const authConfig = {
clientID: "YOUR_CLIENT_ID",
signInRedirectURL: "http://localhost:3000",
signOutRedirectURL: "http://localhost:3000",
baseUrl: "https://api.asgardeo.io/t/{org_name}",
scope: [ "openid","profile"],
storage: "sessionStorage"
...
};



```

The available storage options of Asgardeo React SDK includes localStorage, sessionStorage, webWorker, and browserMemory. WebWorker is the recommended storage option as it operates in a separate thread, providing better security by isolating the stored data from the main browser thread. This isolation makes it less vulnerable to cross-site scripting (XSS) attacks. However, the downside is that WebWorker storage is cleared when the page is reloaded, meaning the data doesn't persist across page reloads or browser sessions. As a result, the SDK will initiate a new authentication request to the IDP every time the page reloads. You may analyze the pros and cons of each storage type to determine the most suitable option for storing session information, including the access token. Striking a balance between user experience and security based on your application's needs is essential.
58 changes: 58 additions & 0 deletions en/asgardeo/docs/complete-guides/fesecurity/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
---
template: templates/complete-guide.html
heading: Introduction
read_time: 2 mins
---

## Securing Frontend Applications
Are you a front-end developer working with React, Angular, Vue or other JavaScript frameworks? If so, you know that implementing user login functionality is essential—not only to meet business requirements but also to ensure the security and compliance of your application. However, frontend applications face unique security challenges that require careful attention to safeguard user data and maintain trust. In this guide, we will explore key security concerns specific to front-end applications—particularly those built with React—and discuss practical strategies and best practices to address these risks effectively.




## Learning objectives

In this guide, you will:

* In-app vs IdP-based login
* Public clients
* Unverified tokens
* Insecure tokens
* Weak access control
* Unauthorized privilege gain
* Unauthorized account access
* Weak Multi-factor authentication
* Partial user logouts
* Product misconfiguration
* Outdated SDKs
* Cross-Site Scripting (XSS)
* Cross-Site Request Forgery (CSRF)



!!! tip "Tip"

If you're a **React developer**, check out these guides to learn how to easily add user login functionality to your React applications.

- [{{product_name}} React Quickstart Guide]({{base_path}}/quick-starts/react/)

- [{{product_name}} React Complete Guide]({{base_path}}/complete-guides/react/introduction/)

!!! tip "Tip"

If you're a **Angular developer**, check out these guides to learn how to easily add user login functionality to your React applications.

- [{{product_name}} React Quickstart Guide]({{base_path}}/quick-starts/angular/)

- [{{product_name}} React Complete Guide]({{base_path}}/complete-guides/angular/introduction/)











29 changes: 29 additions & 0 deletions en/asgardeo/docs/complete-guides/fesecurity/login-options.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
template: templates/complete-guide.html
heading: In-app vs IdP-based login
read_time: 30 secs
---

## In-app vs IdP-based login

Before we move further, let’s briefly look at two main options available for you to implement user login in your frontend app:

1. **Build In-app login:** This approach involves creating your own login mechanism, typically requiring you to store usernames and passwords in a database. While this may seem simple at first, adding features like multi-factor authentication (MFA), conditional logic, and account recovery can significantly increase complexity. Over time, you might find yourself building an entire Identity Provider (IdP), which can divert your focus from the core business requirements of your app.

![In-app login]({{base_path}}/complete-guides/fesecurity/assets/img/image1.png){: width="550" style="display: block; margin: 0;"}

2. **Integrate with an Identity Provider (IdP):** This option involves integrating your frontend app with an IdP, which can be deployed on your infrastructure or accessed as a cloud service. By using open standards like SAML 2.0 and OpenID Connect (OIDC), you can delegate authentication and authorization responsibilities to the IDP, thereby improving the scalability and flexibility of your authentication flow.

![In-app login]({{base_path}}/complete-guides/fesecurity/assets/img/image2.png){: width="800" style="display: block; margin: 0;"}

In this guide, we assume you have integrated your frontend app with an IdP using the OIDC protocol for user login. You can use a cloud IdP such as Asgardeo as the IdP or any OIDC-supported IdP such as WSO2 Identity Server. Integrating your frontend app with an IdP typically involves two main steps:

1. Add the OIDC SDK as a dependency to your app to simplify handling OIDC request-response flows and tokens. While you could implement OIDC flows on your own, using the SDK saves time and ensures you’re following the best practices. Although the security implications and solutions are common across all frontend technologies, this guide presents examples from [Asgardeo React SDK](https://wso2.com/identity-and-access-management/react/){:target="_blank"}.

2. Register your app with an Identity Provider (IdP) as a Relying Party (RP) and obtain the necessary credentials to integrate your app with the IdP. In Asgardeo you can achieve this by creating an application in the console.


For this guide, we'll use a sample application, [asgardeo-react-b2c-sample-app](https://github.com/wso2/asgardeo-react-b2c-sample-app?tab=readme-ov-file){:target="_blank"}. With Asgardeo successfully integrated, you should now have working login functionality within your application.

Now, let's discuss the security concerns present in the application and explore how to effectively mitigate them.

25 changes: 25 additions & 0 deletions en/asgardeo/docs/complete-guides/fesecurity/misconfiguration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
---
template: templates/complete-guide.html
heading: Product misconfiguration
read_time: 2 mins
---

During the development phase, applications often include debug logs in the browser console, use hardcoded values, or retain test configurations. These practices, while useful for debugging, can expose sensitive information or introduce security vulnerabilities if left in the production environment.


The SDKs are designed to be production-ready out of the box, requiring no additional changes. However, it's essential to review your application's design and code to ensure it's production-ready. This includes removing any debug logs from the browser console, eliminating hardcoded values, securing configurations, and conducting a thorough security audit to mitigate potential risks

Ensuring the ongoing security and efficiency of your application requires regular maintenance of the SDK and its components. Using outdated or vulnerable components can expose your application to security risks and hinder performance.


- **Vulnerable and Outdated Components:** Regularly check for SDK updates and other dependencies. Keeping components up to date minimizes security vulnerabilities. Tools like dependency checkers can help automate this process, ensuring that you’re always using the latest, most secure versions.

- **Minimization:** Remove any unused dependencies and code to reduce the attack surface of your application. This practice not only improves security but also enhances performance.

- **Continuous Review:** Incorporate a continuous review process into your CI/CD pipeline. This includes security testing, code quality checks, and dependency scanning to catch potential issues early and ensure that your application remains secure and efficient over time.

- **dditional Best Practices:** Beyond maintaining the SDK, ensure your application follows industry best practices. This includes implementing secure coding practices, using strong encryption methods, regularly conducting security audits, and ensuring that your CI/CD pipeline is secure and resilient against threats.

By continuously maintaining the SDK and adhering to these best practices, you can ensure that your application remains secure, performant, and ready for production.


29 changes: 29 additions & 0 deletions en/asgardeo/docs/complete-guides/fesecurity/next-steps.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
template: templates/complete-guide.html
heading: Next Steps
read_time: 1 min
---

Now that your React application is secured with authentication features integrated, It is time to explore the additional features {{product_name}} offers to make the login flow more diverse and secure.

- [Multi factor authentication]({{base_path}}/guides/authentication/mfa/){:target="_blank"}
- [Passwordless authentication]({{base_path}}/guides/authentication/passwordless-login/){:target="_blank"}
- [Self registration]({{base_path}}/guides/user-accounts/configure-self-registration/){:target="_blank"}
- [Login UI customization]({{base_path}}/guides/branding/){:target="_blank"}


!!! tip "Tip"

If you're a **React developer**, check out these guides to learn how to easily add user login functionality to your React applications.

- [{{product_name}} React Quickstart Guide]({{base_path}}/quick-starts/react/)

- [{{product_name}} React Complete Guide]({{base_path}}/complete-guides/react/introduction/)

!!! tip "Tip"

If you're a **Angular developer**, check out these guides to learn how to easily add user login functionality to your React applications.

- [{{product_name}} React Quickstart Guide]({{base_path}}/quick-starts/angular/)

- [{{product_name}} React Complete Guide]({{base_path}}/complete-guides/angular/introduction/)
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
template: templates/complete-guide.html
heading: Partial user logouts
read_time: 2 min
---

When a user logs out from a frontend application, it’s important to revoke the access token as soon as possible in addition to clearing the current user context at the frontend. The reason is that if the access token remains valid after logout, it could potentially be misused if intercepted, leading to unauthorized access. Additionally, the session identifier should not be reused after logout to prevent session hijacking, especially on shared devices.


{{product_name}} offers various types of [Token Binding]({{base_path}}/docs/references/app-settings/oidc-settings-for-app/#token-binding-type){:target="_blank"}, each designed to serve a specific purpose. For example, the "SSO-session" token binding ensures that tokens are linked to a particular session, preventing them from being misused in other contexts. For a more detailed explanation, you can refer to the OIDC Token Configurations.

When you create a Single-Page Application in {{product_name}}, the token binding type is set to SSO-session by default. This means that the access token is automatically revoked when the user logs out. You can verify and adjust this setting through the application configurations in the {{product_name}} Console.

Additionally, {{product_name}} doesn’t reuse session identifiers; instead, it generates a new session identifier for each new session, enhancing security.
77 changes: 77 additions & 0 deletions en/asgardeo/docs/complete-guides/fesecurity/public-clients.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
---
template: templates/complete-guide.html
heading: public Clients
read_time: 2 min
---

## OAuth2/OIDC Public Clients

OIDC is an authentication protocol that builds on OAuth 2.0, standardizing the process of authenticating and authorizing users when they sign in to access digital services. OIDC supports several grant types, each designed for different application scenarios. For example, the authorization code grant type is intended for confidential clients to authenticate end users, while the client credentials grant type is meant for machine-to-machine authentication. Each grant type ultimately provides an access token, but the method of obtaining the token varies depending on the grant type. You can refer to the OAuth2 grant types [documentation](https://wso2.com/asgardeo/docs/references/grant-types/){:target="_blank"} to understand how each grant type works. According to current OAuth2 best practices, the Authorization Code grant type is the most recommended for browser-based front-end applications, such as React, Angular and Vue applications. As a frontend developer, it's crucial to ensure you're using the correct grant type, which, in this case, is the Authorization Code flow. Let’s explore the Authorization Code grant type with the help of the following diagram to better understand its flow.

![Code grant type]({{base_path}}/complete-guides/fesecurity/assets/img/image3.png){: width="800" style="display: block; margin: 0;"}


As depicted in the diagram above, once the user is authenticated, an authorization code is issued to the application. The application must then make a token request to the authorization server (IdP), supplying the authorization code. The IdP will issue an access token together with an ID token to the application upon verifying the request. This token request requires the client application to be verified using an application identifier and a secret. However, since frontend apps run entirely on the frontend typically within the user’s browser, they are classified as public clients. This means that their source code is accessible to anyone who interacts with the application. Storing secrets or credentials in this context is insecure because it exposes the client secret in the request headers, making the login process vulnerable to misuse. Therefore, traditional client authentication methods are not suitable for SPAs.

Without client authentication, this flow makes public clients vulnerable to authorization code interception attacks. In such attacks, an attacker intercepts the authorization code returned from the authorization endpoint through a communication path not protected by Transport Layer Security (TLS), such as inter-app communication within the client's operating system. Once the attacker obtains the authorization code, they can use it to acquire the access token. For more details on how this attack can be executed, you can refer to the [PKCE specification](https://www.rfc-editor.org/rfc/rfc7636#section-1){:target="_blank"}.


The Proof Key for Code Exchange (PKCE) extension to the OAuth 2.0 Authorization Code flow was introduced to address the security concerns of OIDC public clients. PKCE enhances the security of public clients by mitigating the risk of authorization code interception.

![PKCE]({{base_path}}/complete-guides/fesecurity/assets/img/image4.png){: width="800" style="display: block; margin: 0;"}

When a user logging into an application, the client (the application) generates a cryptographically random key called the “code verifier”. This is a long string of random characters, usually base64 encoded. The client then transforms the code verifier into a derived value called the “code challenge”. Typically, this transformation is done using a hashing algorithm like SHA-256, and the result is base64-url encoded. This makes the code challenge smaller and harder to reverse engineer, but the transformation itself is optional (the challenge can also be the plain code verifier).

The client initiates the OAuth 2.0 flow by sending an authorization request to the Authorization Server (IdP). This request includes the code challenge and the code challenge method (either plain or S256, indicating the hashing algorithm used) as indicated in the image below.

![PKCE code chalange]({{base_path}}/complete-guides/fesecurity/assets/img/image5.png){: width="800" style="display: block; margin: 0;"}


After successful authentication, the IdP generates an authorization code and sends it back to the client. The client now makes a request to the token endpoint to exchange the authorization code for an access token. This request includes the authorization code and the code verifier (the original random string) as indicated in the image below.

![PKCE code verifier]({{base_path}}/complete-guides/fesecurity/assets/img/image6.png){: width="800" style="display: block; margin: 0;"}

The IdP takes the code verifier sent in the token request and applies the same transformation (if any) that was applied earlier. It compares the result with the code challenge that was sent earlier with the authorization request. If the two match, it verifies that the same client who initiated the flow is completing it and issues an access token.

This process ensures that if an attacker were to intercept the authorization code during the authorization phase, they wouldn't be able to exchange it for tokens. This is because they wouldn't possess the code verifier, a secret known only to the legitimate client. Since the code verifier is generated dynamically and is used only once, even if an attacker somehow obtains it, it would be useless for future requests.

PKCE is an important security improvement for frontend applications but at the same time it sounds like an extra burden for you to generate and process all these code challenges and code verifiers by yourself. The good news here is, following the security best practices such as secure by design, secure by default, most of the the frontend authentication SDKs automatically enable PKCE extension for you. For instance, Asgardeo React SDK enables PKCE extension for your apps by default. Here is how you can enable it manually by setting the enable PKCE option to true in the Asgardeo SDK configuration:


```javascript title="src/main.jsx" hl_lines="9"

import { AuthProvider } from "@asgardeo/auth-react";

const authConfig = {
clientID: "YOUR_CLIENT_ID",
signInRedirectURL: "http://localhost:3000",
signOutRedirectURL: "http://localhost:3000",
baseUrl: "https://api.asgardeo.io/t/{org_name}",
scope: [ "openid","profile"],
enablePKCE: true,
...
};

```

After successful login, you'll receive an access token and an ID token in response to the token request.

- The ID token is a JWT containing user information such as user attributes, roles, and groups, which the application uses to identify and interact with the authenticated user. You can configure the information to be included in the ID token via the user attributes section in Asgardeo's application configuration.

- The access token is used to access protected APIs in the same IdP, such as SCIM APIs in Asgardeo, for retrieving and updating user profiles or a business API protected by Asgardeo.

A sample response is provided below for your reference.

A sample response is provided below for your reference.

```json
{
"access_token": "f39b1125-1cfa-372c-9a6c-4077fa32e321",
"scope": "internal_login openid",
"id_token": "eyJ4OiJ...IlJU2In0.eyJpcOiIyY...bC5jbfQ.jymfdT5L...Fqs390MNg",
"token_type": "Bearer",
"expires_in": 3600
}


```
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
---
template: templates/complete-guide.html
heading: Unauthorized access
read_time: 2 min
---

It's also important to ensure that components intended for authenticated users are not accessible without logging in. Allowing unauthorized access to such components poses a security risk. Additionally, components designed for higher-privilege users should not be accessible to regular users.


Similar to the role-based access control example provided earlier, you can define access rules for components, specifying whether they can be accessed by unauthenticated users and the roles required for access. The following sample code demonstrates how to define roles for components and redirect unauthenticated or unauthorized users who attempt to access restricted components.

```javascript title="src/main.jsx" hl_lines="15"

const {state, getDecodedIDToken } = useAuthContext();
const [decodedIdToken, setDecodedIdToken] = useState();

useEffect(() => {
if (state.isAuthenticated) {
const fetchUserInfo = async () => {
const info = await getDecodedIDToken();
setDecodedIdToken(info);
};
fetchUserInfo();
}
}, [state.isAuthenticated, getDecodedIDToken]);

const roleBasedComponent = (Component, requiredRole) => {
if (!state.isAuthenticated) {
return <Navigate to="/HomePage" />;
}
if (decodedIdToken && decodedIdToken?.roles.includes(requiredRole)) {
return <Component />;
}
return <Navigate to="/AuthPage" />;
};

return (
<div className="App">
<main>
<Routes>
<Route path="/" element={<HomePage />} />
<Route path="/HomePage" element={<HomePage />} />
<Route path="/AuthPage" element={<AuthPage />} />
<Route path="/HouseOwner/:username" element={roleBasedComponent(HouseOwnerHouseList,"HouseOwner")} />
<Route path="/house-owner/:houseId" element={ roleBasedComponent(HouseOwnerHouseRequest,"HouseOwner")} />
<Route path="/Renter" element={roleBasedComponent(Renter,"Renter")} />
<Route path="/Admin" element={roleBasedComponent(Admin,"Admin")}/>
</Routes>
</main>
</div>
);

```
There can be scenarios where someone else’s user account can be accessed simply by providing its unique identifier. For example, if the user1 can view their user account using, **`http://localhost:3000/user1`** and if the same user can view or modify user2’s account using **`http://localhost:3000/user2`**, it exposes a security concern violating confidentiality and integrity.

![Unauthorized User Account Modifications
]({{base_path}}/complete-guides/fesecurity/assets/img/image9.png){: width="800" style="display: block; margin: 0;"}


To prevent unauthorized access, every API request from the application should include the access token in the authorization header. The API server can then validate the access token and grant access based on the token's owner. You can use the httpRequest method in the Asgardeo SDK to make API calls, which automatically includes the access token in the authorization header. Below is a sample code segment that makes an API call to the SCIM2/Me endpoint in Asgardeo to retrieve user details. Asgardeo validates the access token and returns the details of the token's owner if the token is valid. You can also explore additional parameters available in httpRequest.

```javascript title="src/main.jsx"
export async function getUserDetails () {
const requestConfig = {
headers: {
"Accept": "application/json",
"Content-Type": "application/scim+json"
},
method: "GET",
url: "https://api.asgardeo.io/t/mifrazmurthaja/scim2/Me"
};
return auth.httpRequest(requestConfig)
.then((response) => {
return response.data;
})
.catch((error) => {
throw new Error('Failed to fetch user profile.');
});
};
```
78 changes: 78 additions & 0 deletions en/asgardeo/docs/complete-guides/fesecurity/weak-access-control.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
---
template: templates/complete-guide.html
heading: Weak access control
read_time: 4 min
---

A typical frontend app consists of several components. Given that the user is already logged in, the app should provide access to these components based on the user's role, such as Administrator, Employee, or Customer. The user interface elements and components should only be visible to, and accessible to, users with the appropriate roles or capabilities. If an unauthorized user can access restricted components, this poses a serious security risk, potentially leading to sensitive information leakage and other critical issues.


![role and components]({{base_path}}/complete-guides/fesecurity/assets/img/image7.png){: width="800" style="display: block; margin: 0;"}

Additionally, bypassing access control by modifying the URL, internal application state, HTML page, or API requests can severely compromise the application's data confidentiality and integrity. For example, if a customer component is displayed at http://localhost:3000/customer, and an authenticated user can view admin components at http://localhost:3000/admin without being validated as an administrator, it represents a significant security flaw.

To implement secure access in your application, you need to implement an access control mechanism. Role-Based Access Control (RBAC) is one of the widely used access control mechanisms, another suitable option would be to use Attribute-Based Access Control (ABAC). RBAC grants access based on user roles, while ABAC provides more granular control by defining access based on user attributes.


![Obtaining the Roles from the IDP]({{base_path}}/complete-guides/fesecurity/assets/img/image8.png){: width="800" style="display: block; margin: 0;"}

The Role Based Access Control which the access to the application based on the user roles or any other suitable access control such as attribute-based access control which defines the access to the application based on the user attributes - granular level access control must be defined in the application. Let’s again take an example of Asgardeo React SDK.

1. Return Roles from the IdP: The IdP should return user roles in the ID token. In Asgardeo, include ‘roles’ as a requested attribute via the user attributes section in the application configuration and define a scope called roles and add the roles attribute.

2. Request Roles Using Asgardeo SDK: In your React app, configure the Asgardeo SDK to request the “roles” scope. This ensures the ID token returned by Asgardeo includes the user's roles.


```javascript title="src/main.jsx" hl_lines="8"

import { AuthProvider } from "@asgardeo/auth-react";

const authConfig = {
clientID: "YOUR_CLIENT_ID",
signInRedirectURL: "http://localhost:3000",
signOutRedirectURL: "http://localhost:3000",
baseUrl: "https://api.asgardeo.io/t/{org_name}",
scope: [ "openid","profile", "roles"],
...
};

```

3. Utilize the Returned Roles: Use the roles obtained from the ID token to define access controls for components in your application. Ensure that only users with the appropriate roles can access specific routes or components. Below are sample code segments that demonstrate how to retrieve the roles from the ID token and define UI elements based on those roles.

```javascript title="src/main.jsx" hl_lines="9-11 26-27"

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

---
const { state, getDecodedIDToken } = useAuthContext();
const [ isResourcesAllowed, setIsResourcesAllowed ] = useState();

---
useEffect(() => {
getDecodedIDToken().then((decodedIdToken) => {
if (decodedIdToken?.application_roles === "React-App-Manager") {
setIsResourcesAllowed(true);
}
}).catch((error) => {

})
}, [getDecodedIDToken, state]);

---
<div className='center-panel' id='center-panel'>
<a href='#/' className='nav active' id ='home' onClick={routeHomeChange}>Home</a>
{
state.isAuthenticated
&& <a href='#/' className='nav' id='resource' onClick={routeResourcesChange}>API Call</a>
}
{
isResourcesAllowed
&& state.isAuthenticated
&& <a href='#/' className='nav' id='setting' onClick={routeSettingsChange}>Settings</a>
}
</div>


```
18 changes: 18 additions & 0 deletions en/asgardeo/docs/complete-guides/fesecurity/weak-mfa.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
template: templates/complete-guide.html
heading: Weak Multi-factor authentication
read_time: 4 min
---

Multi-factor authentication (MFA) is essential in any application to enhance security by requiring multiple forms of verification from the user, reducing the risk of unauthorized access.


If you're using OIDC with PKCE and the Asgardeo SDK for login, you can easily add the necessary [multi-factor authentication]({{ base_path }}/guides/authentication/mfa/){:target="_blank"} steps within the application configuration in {{product_name}}. You can also implement [conditional authentication]({{ base_path }}/docs/guides/authentication/conditional-auth/){:target="_blank"} logic to tailor the login process based on risk factors, without requiring any changes to the SDK—simply configure it in the {{product_name}} console.

![Sample Authentication Step Configurations in Asgardeo]({{base_path}}/complete-guides/fesecurity/assets/img/image10.png){: width="800" style="display: block; margin: 0;"}



Additionally, {{product_name}} offers [App-Native authentication]({{ base_path }}/guides/authentication/app-native-authentication/){:target="_blank"}, allowing you to create your own user interfaces while handling authentication via REST APIs. In this case, you must follow the [API specifications]({{ base_path }}/docs/references/app-native-authentication/){:target="_blank"} and incorporate all required MFA steps to complete the authentication process. If the authentication flow involves a federated IdP, you'll also need to manage IdP redirection accordingly.


66 changes: 66 additions & 0 deletions en/asgardeo/docs/complete-guides/fesecurity/xss.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
---
template: templates/complete-guide.html
heading: Cross-Site Scripting (XSS)
read_time: 2 mins
---

Cross-Site Scripting (XSS) is a vulnerability that allows attackers to inject malicious scripts into web applications. In frontend applications, XSS can occur when untrusted user input is rendered as HTML or JavaScript. XSS can compromise user data, hijack sessions, or perform unauthorized actions.

![XSS Attack Flow]({{base_path}}/complete-guides/fesecurity/assets/img/image11.png){: width="800" style="display: block; margin: 0;"}


In React, the React DOM escapes any values embedded in JSX before rendering them. This means that any content inserted into JSX is automatically converted to a string, mitigating XSS risks. By default, React protects against XSS when embedding user input in JSX.
However, When using dangerouslySetInnerHTML to render HTML, the content is directly inserted into the DOM, which can expose XSS vulnerabilities if the HTML is not sanitized. This should be used with extreme caution, especially when dealing with untrusted data.

The example below demonstrates the use of the dangerouslySetInnerHTML function to render HTML from user input, which can lead to XSS vulnerabilities if the input contains malicious scripts.

```javascript
{% raw %}
function Comment({ userInput }) {
return <div dangerouslySetInnerHTML={{ __html: userInput }} />;
}


// Example usage
<Comment userInput="<script>alert('XSS Attack!')</script>" />;
{% endraw %}

```


This is how you can make sure your app is safe from XSS attacks.

1. When possible, avoid using dangerouslySetInnerHTML altogether and render user input safely within JSX.

```javascript
function Comment({ userInput }) {
return <div>{userInput}</div>;
}

// Example usage
<Comment userInput="This is a safe comment" />;

```


2. If you must use dangerouslySetInnerHTML, ensure that the HTML is sanitized to prevent XSS attacks.


```javascript
import DOMPurify from 'dompurify';

{% raw %}
function Comment({ userInput }) {
return <div dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(userInput) }} />;
}
{% endraw %}


```







15 changes: 15 additions & 0 deletions en/asgardeo/mkdocs.yml
Original file line number Diff line number Diff line change
@@ -502,6 +502,8 @@ nav:
- Quick Starts:
- React Quickstart: quick-starts/react.md
- Angular Quickstart: quick-starts/angular.md
- Next.js Quickstart: quick-starts/nextjs.md
- Spring Boot Quickstart: quick-starts/springboot.md
- React Guide:
- Introduction: complete-guides/react/introduction.md
- Prerequisite: complete-guides/react/prerequisite.md
@@ -549,6 +551,19 @@ nav:
- Accessing protected API : complete-guides/nextjs/accessing-protected-api.md
- Manage tokens in Next.js : complete-guides/nextjs/manage-tokens-in-apps.md
- Next Steps: complete-guides/nextjs/next-steps.md
- Frontend Security Guide:
- Introduction: complete-guides/fesecurity/introduction.md
- In-app vs IdP-based login: complete-guides/fesecurity/login-options.md
- Public clients: complete-guides/fesecurity/public-clients.md
- Insecure token handling : complete-guides/fesecurity/insecure-tokens.md
- Weak access control: complete-guides/fesecurity/weak-access-control.md
- Unauthorized access: complete-guides/fesecurity/unauthorized-privilege-gain.md
- Weak MFA : complete-guides/fesecurity/weak-mfa.md
- Partial user logouts: complete-guides/fesecurity/partial-user-logouts.md
- Product misconfiguration: complete-guides/fesecurity/misconfiguration.md
- Cross-Site Scripting (XSS): complete-guides/fesecurity/xss.md
- Cross-Site Request Forgery (CSRF): complete-guides/fesecurity/csrf.md
- Next Steps: complete-guides/fesecurity/next-steps.md
not_in_nav: |
/page-not-found.md
/get-started/explore-asgardeo.md