@entrustcorp/idaas-auth-js v0.1.40
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
- After logging in as an administrator, navigate to the applications page.
- Click the plus sign in the top left to create a new application.
- Scroll down and select
Generic SPA Application
. - On the
Setup
page, check theAuthorization Code
grant type. This SDK supports only the authorization code flow with PKCE. - 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. - 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.
- 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