> For AI agents: [llms.txt](https://docs.trustedauth.com/llms.txt) provides a Markdown index of this documentation.

# Protect a Single Page Application (SPA)

## Integrating the IDaaS Auth SDK in your SPA

Once you have [set up your OIDC configuration in IDaaS](/docs/applications-and-sso/oidc/configuring-idaas.md), you can easily add authentication to your Single Page Application with the IDaaS Authentication SDK:

- [JavaScript SDK](https://github.com/EntrustCorporation/idaas-auth-spa)
- [React SDK](https://github.com/EntrustCorporation/idaas-auth-react)

## Installation

**JavaScript**

**npm**

```bash
npm install @entrustcorp/idaas-auth-js
```

**Yarn**

```bash
yarn add @entrustcorp/idaas-auth-js
```

**pnpm**

```bash
pnpm add @entrustcorp/idaas-auth-js
```

**Bun**

```bash
bun add @entrustcorp/idaas-auth-js
```

**React**

**npm**

```bash
npm install @entrustcorp/idaas-auth-react
```

**Yarn**

```bash
yarn add @entrustcorp/idaas-auth-react
```

**pnpm**

```bash
pnpm add @entrustcorp/idaas-auth-react
```

**Bun**

```bash
bun add @entrustcorp/idaas-auth-react
```

## Getting Started

info

Before deploying to production, make sure you update your [Content Security Policy](#content-security-policy-csp) to allow API calls to your IDaaS tenant.

**JavaScript**

Create an `IdaasClient` before rendering or initializing your application. You should
only ever have one instance of the client.

```ts
import { IdaasClient } from "@entrustcorp/idaas-auth-js";

// Create a client.
const defaultIdaasClient = new IdaasClient({
  clientId: "<IDAAS_CLIENT_ID>",
  issuerUrl: "<IDAAS_ISSUER_URL>",
});

// or create a customized variant by setting the global values to be used.
const customIdaasClient = new IdaasClient({
  clientId: "<IDAAS_CLIENT_ID>",
  issuerUrl: "<IDAAS_ISSUER_URL>",
  globalAudience: "<GLOBAL_AUDIENCE>",
  globalScope: "<GLOBAL_SCOPE>",
  globalUseRefreshToken: true | false,
});
```

**React**

Wrap your application in the `IdaasProvider` component. You will need to pass it your
OIDC Application's `clientId` and `issuerUrl`.

```tsx
// Wrap your application.
root.render(
  <IdaasProvider clientId="<IDAAS_CLIENT_ID>" issuerUrl="<IDAAS_ISSUER_URL>">
    <App />
  </IdaasProvider>,
);

// or can override defaults using the props below.
root.render(
  <IdaasProvider
    clientId="<IDAAS_CLIENT_ID>"
    issuerUrl="<IDAAS_ISSUER_URL>"
    globalAudience="<GLOBAL_AUDIENCE>"
    globalScope="<GLOBAL_SCOPE>"
    globalUseRefreshToken={true | false}
  >
    <App />
  </IdaasProvider>,
);
```

## Logging In

The IDaaS Auth SDK supports two methods of authenticating your users:

- login with redirect - The browser will redirect the user to your IDaaS login page to authenticate. After authenticating, the user will be redirected back to your application.

- login with popup - The browser will open a popup window with the IDaaS login page for the user to authenticate. After authenticating, the popup window will be closed.

  tip
  When using popup, if the user closes the popup or clicks "Back", an error is thrown. You may use a try/catch to handle this.

**JavaScript**

Using the `IdaasClient` instance you created you can access the `login` method.

```html
<button id="login-with-redirect">Click to Login With Redirect</button>
```

```ts
// redirect to the IDaaS login page when the login button is clicked
document.getElementById("login-with-redirect").addEventListener("click", () => {
  idaasClient.login();
  // Or you can also configure the login with the following properties.
  idaasClient.login({
    audience: "YOUR_AUDIENCE",
    scope: "YOUR_SCOPES",
    redirectUri: "YOUR_REDIRECT_URI", // You will also need to configure the login redirectUri in your OIDC Application in IDaaS
    useRefreshToken: true | false,
    popup: true | false,
  });
});
```

note

You will need to invoke the `handleRedirect` method on the page that you redirect to after logging in.

```ts
// in your callback route (<MY_LOGIN_REDIRECT_URI>)
window.addEventListener("load", async () => {
  await idaasClient.handleRedirect();
  // if the user has successfully authenticated, you can access the user's claims from their ID token:
  const idToken = idaasClient.getIdTokenClaims();
  console.log(idToken);
});
```

You can specify the methods of authentication that are acceptable to be used to authenticate the user. Successful authentication via methods that do not fall under the specified authentication methods will be treated as a failed authentication attempt.

note

To use this value later, the received access token must not be opaque.

```ts
document
  .getElementById("login-with-popup")
  .addEventListener("click", async () => {
    // authenticate using an authentication method that falls under the `possession` or `inherence` authentication types.
    await idaasClient.login({
      popup: true,
      acrValues: ["possession", "inherence"],
    });
    const idToken = idaasClient.getIdTokenClaims();
    console.log(idToken);
  });
```

**React**

Now within child components of the `IdaasProvider` you can use the `useIdaas` hook to pull out the login method.

```tsx
import { useIdaas } from "@entrustcorp/idaas-auth-react";

function LoginButton() {
  const { login } = useIdaas();

  return <button onClick={() => login()}>Login</button>;

  // You can also configure the login with the following properties.
  return (
    <button
      onClick={() =>
        login({
          audience: "YOUR_AUDIENCE",
          scope: "YOUR_SCOPES",
          redirectUri: "YOUR_REDIRECT_URI", // You will also need to configure the login redirectUri in your Generic SPA Application
          useRefreshToken: true | false,
          popup: true | false,
        })
      }
    >
      Login
    </button>
  );
}
```

You can specify the type(s) of authentication that are acceptable to be used to authenticate the user. Successful authentication via methods that do not fall under the specified authentication types(s) will be treated as a failed authentication attempt.

note

If you need to know the ACR value used to retrieve an access token the received access token must not be opaque.
An opaque token is returned if an audience is not specified.

```tsx
const { getIdTokenClaims } = useIdaas();

const handleOnClick = () => {
  await login({ popup: true, acrValues: ["possession", "inherence"] });
  const idToken = getIdTokenClaims();
  console.log(idToken);
};
```

## Logging Out

End the user session by using the `logout` method. This will log the user out of
IDaaS as well.

**JavaScript**

```html
<button id="logout">Logout</button>
```

```ts
document.getElementById("logout").addEventListener("click", () => {
  idaasClient.logout();
});

// You can also configure the logout.
document.getElementById("logout").addEventListener("click", () => {
  // You will also need to configure redirectUri in your Generic SPA Application.
  idaasClient.logout({ redirectUri: "<MY_LOGOUT_REDIRECT_URI>" });
});
```

**React**

```tsx
function LogoutPage() {
  const { logout } = useIdaas();

  return <button onClick={() => logout()}>Logout</button>;

  // End the user session when the logout button is clicked.
  return (
    // You will also need to configure redirectUri in your Generic SPA Application.
    <button onClick={() => logout({ redirectUri: "YOUR_REDIRECT_URI" })}>
      Logout
    </button>
  );
}
```

## Authentication Status

Authentication status is determined by the presence of a non-expired ID token.If an ID token is stored and not expired, the user is authenticated.

**JavaScript**

```html
<button id="check-authentication">Click to Check Authentication Status</button>
```

```ts
document
  .getElementById("check-authentication")
  .addEventListener("click", () => {
    const isAuthenticated = idaasClient.isAuthenticated();

    if (isAuthenticated) {
      console.log("User is authenticated");
    } else {
      console.log("User is not authenticated");
    }
  });
```

**React**

```tsx
import { useIdaas } from "@entrustcorp/idaas-auth-react";
...
const { isAuthenticated } = useIdaas();

const handleOnClick = async () => {
  if (isAuthenticated) {
    console.log("User is authenticated");
  } else {
    console.log("User is not authenticated");
  }
};
...
<button onClick={handleOnClick}>Click to Check Authentication Status</button>;
```

## Protecting components

With the React SDK, you have access to the `RequireAuth` component. Children wrapped in `RequireAuth` will only render if the user is logged in. You can provide an `onUnauthenticated` method to determin what to do with with an unauthenticated user who tries to access the protected children. The suggested use is to use your router to redirect to the login page.

```tsx
import { RequireAuth } from "@entrustcorp/idaas-auth-react";
...

function Profile() {
  return (
    <RequireAuth onUnauthenticated={()=>redirect('/login')}>
      ...
    </RequireAuth>)
};
```

## Getting Information About the User

When a user is logged in, you have access to the the claims that were returned
in their Access and ID tokens.

**JavaScript**

You can get information about the logged in user sending a request to the `userInfo` endpoint.

```html
<button id="get-information">Click to get Information</button>
```

```ts
document
  .getElementById("get-information")
  .addEventListener("click", async () => {
    // assumes the user is logged in and an access token is stored
    const userInfo = await idaasClient.getUserInfo();
    console.log("User Info", userInfo);
  });
```

#### Fetching the Stored ID Token

```html
<button id="get-id-token">Click to get ID token</button>
```

```ts
document.getElementById("get-id-token").addEventListener("click", () => {
  // assumes the user is authenticated
  const idToken = idaasClient.getIdTokenClaims();
  console.log("ID Token", idToken);
});
```

**React**

You can get information about the logged in user sending a request to the `userInfo` endpoint

```tsx
import { useIdaas } from "@entrustcorp/idaas-auth-react";
  ...
  const { getUserInfo } = useIdaas();
  const userInfo = await getUserInfo();
  ...
    <div>Welcome {userInfo?.given_name}</div>
```

#### Fetching the Stored ID Token

tip

You can configure IDaaS to include desired claims in the ID Token

```tsx
import { useIdaas } from "@entrustcorp/idaas-auth-react";
  ...
  const { user } = useIdaas();
  ...
    <div>Welcome {user.given_name}</div>
```

## Content Security Policy (CSP)

The IDaaS Auth SDK will send API requests to your IDaaS tenant. You will need to ensure the Content Security Policy of your web application is updated to include your IDaaS tenant hostname as an allowed connection source. For more information regarding CSP, see the MDN [Content Security Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) documentation.

The following must be set in your Content Security Policy for the SDK to work. Replace `entrust.us.trustedauth.com` with your IDaaS tenant hostname.

```text
connect-src 'entrust.us.trustedauth.com'
```
