0.1.40 • Published 4 months ago

@entrustcorp/idaas-auth-js v0.1.40

Weekly downloads
-
License
Apache-2.0
Repository
github
Last release
4 months ago

IDaaS Auth JavaScript SPA SDK

The IDaaS Auth SDK simplifies integrating secure authentication into your JavaScript SPAs. Designed for flexibility and ease of use, it is fully configurable and customizable. Allowing developers to leverage the power of IDaaS through a simple API that handles their authentication needs.

Create a Free Trial Account

Entrust Identity as a Service (IDaaS) is a cloud-based identity and access management (IAM) solution with multi-factor authentication (MFA), credential-based passwordless access, and single sign-on (SSO).

Get started with a free trial account today.

Getting Started

Installation

npm i @entrustcorp/idaas-auth-spa

Configure Your IDaaS Application

  1. After logging in as an administrator, navigate to the applications page.
  2. Click the plus sign in the top left to create a new application.
  3. Scroll down and select Generic SPA Application.
  4. On the Setup page, check the Authorization Code grant type. This SDK supports only the authorization code flow with PKCE.
  5. If you intend to use refresh tokens, check the Refresh Token (OIDC) grant type. Failing to do so will cause errors if you attempt to use refresh tokens.
  6. Add all URIs that you may redirect to after a successful login or logout. Failing to do so will cause errors if you attempt to redirect to a different URI.
  7. Make any other changes necessary for your application, then submit your changes.

Make note of your application's Client ID and Issuer URL (typically https://{yourIdaasDomain}.region.trustedauth.com/api/oidc). These will be required to configure the SDK.

Configure the SDK

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

import { IdaasClient } from "./IdaasClient";

// you can create a client using our default global values
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,
});

Logging In With Redirect

You can then log in using the IdaasClient instance you created. Logging in with redirect will redirect the user to an IDaaS login page to enter their login information. It will then redirect them to redirectUrl if authentication is successful.

<button id="login-with-redirect">Click to Login With Redirect</button>
// redirect to the IDaaS login page
document.getElementById("login-with-redirect").addEventListener("click", () => {
  // ensure <MY_LOGIN_REDIRECT_URI> has been added to the list of valid login redirect URIs in your IDaaS application configuration
  idaasClient.login({ popup: false, redirectUri: "<MY_LOGIN_REDIRECT_URI>" });
});
// in your callback route (<MY_LOGIN_REDIRECT_URI>)
window.addEventListener("load", async () => {
  await idaasClient.handleRedirect();
  // you've now logged in with redirect, you can get the stored ID token claims like this:
  const idToken = idaasClient.getIdTokenClaims();
  console.log(idToken);
});

Logging Out

<button id="logout">Logout</button>
document.getElementById("logout").addEventListener("click", () => {
  idaasClient.logout();
});

You can redirect users back to your app after logging out. This URL must be present in the Logout Redirect URI(s) setting for the app in your IDaaS application configuration:

idaasClient.logout({ redirectUri: "<MY_LOGOUT_REDIRECT_URI>" });

More Examples

Logging In With Popup

To log in with popup, ensure the popup flag is true. Logging in with popup will open a login popup for the user to enter their login information. The access token received from this login will be returned upon successful authentication.

<button id="login-with-popup">Click to Login With Popup</button>
document.getElementById("login-with-popup").addEventListener("click", async () => {
  // open the IDaaS login popup
  await idaasClient.login({ popup: true });
  // you've now logged in with popup, you can get the stored ID token claims like this:
  const idToken = idaasClient.getIdTokenClaims();
  console.log(idToken);
});

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

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

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

Access Tokens

Accessing a Resource

Retrieve an access token to pass along in the Authorization header using getAccessToken:

<button id="access-resource">Click to Access Resource</button>
document.getElementById("access-resource").addEventListener("click", async () => {
  // "<SCOPE>" and "<AUDIENCE>" specify the scope and audience of the token to be fetched
  const token = idaasClient.getAccessToken({
    audience: "<AUDIENCE>",
    scope: "<SCOPE>",
  });
  const response = await fetch(`https://resource.com`, {
    method: "GET",
    headers: {
      Authorization: `Bearer ${token}`,
    },
  });
  const data = await response.json();
  console.log(data);
});

Requesting a New Access Token

Request an access token that is not already stored by supplying fallbackAuthorizationOptions to getAccessToken. Doing so will initiate an access token request from the authorization server.

<button id="access-resource">Click to Retrieve Access Token</button>
document.getElementById("access-resource").addEventListener("click", async () => {
  // a login with popup will be attempted to fetch a token with "<SCOPE>" and "<AUDIENCE>" if there is not a token with "<SCOPE>" and "<AUDIENCE>" already stored.
  const token = idaasClient.getAccessToken({
    audience: "<AUDIENCE>",
    scope: "<SCOPE>",
    fallbackAuthorizationOptions: {
      popup: true,
    },
  });

  const response = await fetch(`https://resource.com`, {
    method: "GET",
    headers: {
      Authorization: `Bearer ${token}`,
    },
  });
  const data = await response.json();
  console.log(data);
});

Verify Context Class of Authentication

You are able to specify the context class(es) of authentication that must be/have been used when authenticating the user to receive the token.

<button id="password_login">Authenticate Using Knowledge Authentication</button>
document.getElementById("access-resource").addEventListener("click", async () => {
  const token = idaasClient.getAccessToken({
    // Retrieve a token with <SCOPE> and <AUDIENCE> that was authenticated via a `knowledge` method of authentication
    audience: "<AUDIENCE>",
    scope: "<SCOPE>",
    acrValues: ["knowledge"],
    // If the token is not found, login via an authentication method that falls under the `knowledge` context class to receive this token
    fallbackAuthorizationOptions: {
      popup: true,
    },
  });

  const response = await fetch(`https://resource.com`, {
    method: "GET",
    headers: {
      Authorization: `Bearer ${token}`,
    },
  });
  const data = await response.json();
  console.log(data);
});

User Authentication

Authentication status is determined by the presence of an ID token. If an ID token is stored, the user is authenticated.

<button id="check-authentication">Click to Check Authentication Status</button>
document.getElementById("check-authentication").addEventListener("click", () => {
  const isAuthenticated = idaasClient.isAuthenticated();

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

Getting Information About the Logged-in User

<button id="get-information">Click to get Information</button>
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

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

In-app User Authentication

Rather than using the login method, you have the option to communicate with the IDaaS Authentication API via this SDK.

Authentication Using Password

You can quickly authenticate using password.

await idaasClient.authenticatePassword({
  options: {
    userId: "<USER_ID>",
  },
  password: "<USER_PASSWORD>",
});

Requesting an Authentication Challenge

It is necessary to request a challenge prior to submitting a challenge.

await idaasClient.requestChallenge({
  userId: "<USER_ID>",
});

Note: If the userId field is not provided, the authentication challenge received will be passkey authentication.

Additional Request Parameters

You may specify additional parameters to customize the way the user is authenticated, and to control the access token parameters.

// if OTP is available for the user, use OTP, else throw an error
await idaasClient.requestChallenge({
  userId: "<USER_ID>",
  preferredAuthenticationMethod: "OTP",
  strict: true,
});

// if OTP is available for the user, use OTP
await idaasClient.requestChallenge({
  userId: "<USER_ID>",
  preferredAuthenticationMethod: "OTP",
});

// additional parameters that affect the access token received
await idaasClient.requestChallenge({
  userId: "<USER_ID>",
  scope: "<SCOPE>",
  audience: "<AUDIENCE>",
  useRefreshToken: true | false,
  maxAge: number,
  transactionDetails: [
    {
      detail: "<DETAIL>",
      usage: ["RBA", "TVS"],
      value: "<VALUE>",
    },
  ],
});

// requires the user to complete a mutual challenge for the TOKENPUSH and FACE authenticators
await idaasClient.requestChallenge({
  userId: "<USER_ID>",
  mutualChallengeEnabled: true | false,
});

Submitting an Authentication Challenge

After requesting a challenge, some authentication methods require a user's input to be submitted. You will know if a submission is required by reading the pollForCompletion flag in the requestChallenge return value. If a submission is required, pollForCompletion will be false.

// The response field is used by all authenticators except KBA
await idaasClient.submitChallenge({
  response: "<USER_RESPONSE>",
});

// For KBA authentication, it is necessary to submit the user's answers in the same order that the questions were provided
await idaasClient.submitChallenge({
  kbaChallengeAnswers: ["USER", "KBA", "ANSWERS"],
});

Poll for User Authentication

For authentication methods where a user submission is not required or is external to your application, you may evaluate the user's authentication status by polling. You will know if polling is required by reading the pollForCompletion flag in the requestChallenge return value. If polling is required, pollForCompletion will be true.

await idaasClient.pollAuth();

Cancel User Authentication

You can cancel polling for user authentication.

await idaasClient.cancelAuth();

Examples

Default Login Flows

Password Authentication

In most cases, the user's response to the authentication challenge will be submitted from your application.

// get userId and password
const { authenticationCompleted } = await idaasClient.authenticatePassword({
  options: {
    userId: "<USER_ID>",
  },
  password: "<USER_PASSWORD>",
});

return authenticationCompleted; // true
// get userId
await idaasClient.requestChallenge({
  userId: "<USER_ID>",
});

// get user response
await idaasClient.submitChallenge({
  response: "<USER_RESPONSE>",
});

Token Push Authentication

In some cases, the user's response to the authentication challenge will not be submitted from your application. In these cases it is necessary to poll for completion as shown below.

Note: The pollForCompletion flag is used to indicate these cases.

// get userId
const {
  method, // TOKENPUSH
  pollForCompletion, // true
} = await idaasClient.requestChallenge({ userId: `<USER_ID>` });
// the `pollForCompletion` flag will be used to indicate when to poll
if (pollForCompletion) {
  const { authenticationCompleted } = await idaasClient.pollAuth();
  // polling will continue until authentication is completed/cancelled by the user or the challenge has timed out
}

Password and Second Factor Authentication

Two-Factor authentication can be implemented as shown below.

Example: password with OTP as a second factor

// get userId
const { method } = await idaasClient.requestChallenge({ userId: "<USER_ID>" }); // PASSWORD_AND_SECONDFACTOR
// get password
const { secondFactorMethod } = await idaasClient.submitChallenge({ response: "<USER_PASSWORD>" }); // OTP
// `secondFactorMethod` is the method that will be used as the second factor
// get user OTP
const { authenticationCompleted } = await idaasClient.submitChallenge({ response: `<USER_OTP>` }); // true

Additional Authentication Options

preferredAuthenticationMethod

You can specify a preferred authentication method when requesting an authentication challenge. If the preferred method is available, it will be used to authenticate the user.

// get userId
const { method, gridChallenge } = await idaasClient.requestChallenge({
  userId: "<USER_ID>",
  preferredAuthenticationMethod: "GRID",
}); // GRID if available
// gather the user's response to the `gridChallenge`
const { authenticationCompleted } = await idaasClient.submitChallenge({ response: "user_grid" }); // true

strict authentication method

You can force the authentication method to be the preferredAuthenticationMethod by setting the strict flag to true. If the preferred method is not available, an error will be thrown.

// get userId
const { method, kbaChallenge } = await idaasClient.requestChallenge({
  userId: "<USER_ID>",
  preferredAuthenticationMethod: "KBA",
  strict: true,
}); // KBA or error thrown
// gather the user's answers to the `kbaChallenge`
const { authenticationCompleted } = await idaasClient.submitChallenge({ kbaChallengeAnswers: [user_answers] }); // true
0.1.40

4 months ago

0.1.39

5 months ago