Amazon Cognito
Initial Setup
This package provides integration with Amazon Cognito for authentication using FIDO2 standard. It simplifies the process of adding and signing in with a passkey in a Cognito User Pool with custom authentication.
The AWS setup is crucial for this integration to work and can be achieved by following this guide.
Required settings:
- Cognito User Pool ID
- Cognito Client ID
Add SDK to Existing Application
- NPM
npm install --save @loginid/cognito-web-sdk
Create an SDK Instance
- Javascript
import { LoginIDCognitoWebSDK } from "@/loginid/cognito-web-sdk";
const USER_POOL_ID = process.env.COGNITO_USER_POOL_ID;
const CLIENT_ID = process.env.COGNITO_USER_CLIENT_ID;
const LOGINID_BASE_URL = process.env.LOGINID_BASE_URL;
const config = new LoginIDCognitoWebSDK(
USER_POOL_ID,
CLIENT_ID,
LOGINID_BASE_URL
);
API Reference
LoginIDCognitoWebSDK
Class
Constructor
Creates a new instance of the LoginIDCognitoWebSDK class.
createPasskey
Create a passkey for the specified username using FIDO2 create operation.
createPasskey(username: string, authzToken: string, options?: CustomAuthenticationOptions): Promise<AuthResult>
Parameter | Type | Required | Details |
---|---|---|---|
username | str | yes | The username of the Cognito user. |
authzToken | str | yes | The authorization token can be Cognito ID token or access token associated with the user. |
options | CustomAuthenticationOptions | no | Additional options for custom authentication. |
options.metaData | object | no | Additional metadata for the custom authentication process during VerifyAuthChallenge Lambda phase. |
options.displayName | string | no | A human-palatable name for the user account, intended only for display on your passkeys and modals. |
- TypeScript
const { COGNITO_CLIENT_ID, COGNITO_USER_POOL_ID, LOGINID_BASE_URL } = config;
const Loginid = new LoginIDCognitoWebSDK(
COGNITO_USER_POOL_ID,
COGNITO_CLIENT_ID,
LOGINID_BASE_URL
);
const handlerSubmit = async (event: FormEvent<HTMLFormElement>) => {
event.preventDefault();
try {
// called after successful authenticated session with signup and autoSignIn or signin with password
const token = loginid.getSessionInfo().idToken;
if (token) {
await Loginid.createPasskey(username, token);
}
} catch (e: any) {
setError(e.message);
}
};
authenticateWithPasskey
Signs in with a passkey for the specified username using FIDO2 get operation.
authenticateWithPasskey(username: string, options?: CustomAuthenticationOptions): Promise<AuthResult>
Parameter | Type | Required | Details |
---|---|---|---|
username | str | yes | The username of the Cognito user. |
options | CustomAuthenticationOptions | no | Additional options for custom authentication. |
options.metaData | object | no | Additional metadata for the custom authentication process during VerifyAuthChallenge Lambda phase. |
- TypeScript
const { COGNITO_CLIENT_ID, COGNITO_USER_POOL_ID, LOGINID_BASE_URL } = config;
const Loginid = new LoginIDCognitoWebSDK(
COGNITO_USER_POOL_ID,
COGNITO_CLIENT_ID,
LOGINID_BASE_URL
);
const handlerSubmit = async (event: FormEvent<HTMLFormElement>) => {
event.preventDefault();
try {
const result = await Loginid.authenticateWithPasskey(username);
if (result.isAuthenticated) {
// handle success
} else {
// handle fallback options
}
} catch (e: any) {
setError(e.message);
}
};
authenticateWithPasskeyAutofill
Signs in with passkey autofill or conditional UI using LoginID SDK.
This method initiates a sign-in process with passkey autofill or conditional UI elements. It leverages WebAuthn to provide a secure, usernameless authentication.
authenticateWithPasskeyAutofill(options?: CustomAuthenticationOptions): Promise<AuthResult>
Parameter | Type | Required | Details |
---|---|---|---|
options | CustomAuthenticationOptions | no | Additional options for custom authentication. |
options.metaData | object | no | Additional metadata for the custom authentication process during VerifyAuthChallenge Lambda phase. |
options.abortController | AbortController | no | An AbortController to optionally abort the conditional UI authentication. |
- TypeScript
For this to work, make sure you have an input field within a form element that has the webauthn
value added to autocomplete
.
<form>
<input
id="email"
name="email"
type="email"
autocomplete="username webauthn"
/>
</form>
import { useEffect, useState } from "react";
const { COGNITO_CLIENT_ID, COGNITO_USER_POOL_ID, LOGINID_BASE_URL } = config;
const Loginid = new LoginIDCognitoWebSDK(
COGNITO_USER_POOL_ID,
COGNITO_CLIENT_ID,
LOGINID_BASE_URL
);
const passwordLessLogin = function () {
const [abortController] = useState(new AbortController());
// On page load or component load
useEffect(() => {
const conditionalUI = async () => {
try {
const options = { abortController: abortController };
await Loginid.authenticateithPasskeyAutofill(options);
} catch (e) {
setError(e.message);
}
};
conditionalUI();
return () => {
abortController.abort();
};
});
};
signUpWithPassword
Signs up a user and password using a cognito sdk signup method.
This method creates a new Cognito user with a password and email as username. LoginID provides this wrapper signup function on top of Cognito signup SDK to simplify the integration process.
signUpWithPassword(email: string, password: string, confirmPassword: string, autoSignIn: boolean): Promise<AuthResult>
Parameter | Type | Required | Details |
---|---|---|---|
str | yes | The email address of the user. | |
password | str | yes | The password of the user. |
confimPassword | str | yes | The confirm password of the user must match password field. |
autoSignIn | boolean | yes | Set whether auto sign-in after successful sign-up |
- TypeScript
const { COGNITO_CLIENT_ID, COGNITO_USER_POOL_ID, LOGINID_BASE_URL } = config;
const Loginid = new LoginIDCognitoWebSDK(
COGNITO_USER_POOL_ID,
COGNITO_CLIENT_ID,
LOGINID_BASE_URL
);
const registerUser = async (
email: string,
password: string,
confirmPassword: string
) => {
try {
const autoSignIn = true;
const result = await Loginid.signUpWithPassword(
email,
password,
confirmPassword,
autoSignIn
);
// will need to confirm user after signup if auto confirmation and autoSignIn is false
} catch (e: any) {
console.error("Error during sign up:", e.message);
}
};
signUpPasswordless
Signs up a user using a passwordless method.
This method creates a new Cognito user with a generated password and email as username. It simplifies the user registration process by eliminating the need for a password. This emulates a passwordless sign up experience. LoginID provides this wrapper signup function on top of Cognito signup SDK to simplify the integration process.
Cognito requires users to sign up with a password. The password is randomly generated and discarded, only to be used for signup.
signUpPasswordless(email: string, autoSignIn: boolean): Promise<AuthResult>
Parameter | Type | Required | Details |
---|---|---|---|
str | yes | The email address of the user. | |
autoSignIn | boolean | yes | Set whether auto sign-in after successful sign-up |
- TypeScript
const { COGNITO_CLIENT_ID, COGNITO_USER_POOL_ID, LOGINID_BASE_URL } = config;
const Loginid = new LoginIDCognitoWebSDK(
COGNITO_USER_POOL_ID,
COGNITO_CLIENT_ID,
LOGINID_BASE_URL
);
const registerUser = async (email: string) => {
try {
const result = await Loginid.signUpPasswordless(email);
// will need to confirm user after signup if auto confirmation and autoSignIn is false
} catch (e: any) {
console.error("Error during sign up:", e.message);
}
};
requestAndSendOtp
Request and Send the email OTP authentication process for a user.
This method initiates the email OTP authentication process for a given email address. It sets the current Cognito user and prepares them for completing the OTP verification. This method requires custom auth lambdas setup included in passkey and email otp example flow.
Requires:
- Verified email or domain with SES
requestAndSendOtp(email: string, method: string, options?: CustomAuthenticationOptions): Promise<null>
Parameter | Type | Required | Details |
---|---|---|---|
str | yes | The email address of the user. | |
method | str | yes | The delivery method default = "email" user. |
options | CustomAuthenticationOptions | no | Additional options for custom authentication. |
options.metaData | object | no | Additional metadata for the custom authentication process during VerifyAuthChallenge Lambda phase. |
validateOtp
Completes validate the email OTP authentication process for a user.
This method completes the email OTP authentication process by verifying the OTP provided by the user. It finalizes the custom authentication and returns the user session.
Requires:
- Verified email or domain with SES
validateOtp(otp: string, options?: CustomAuthenticationOptions): Promise<AuthResult>
Parameter | Type | Required | Details |
---|---|---|---|
otp | str | yes | The one-time password (OTP) received by the user via email. |
options | CustomAuthenticationOptions | no | Additional options for custom authentication. |
options.metaData | object | no | Additional metadata for the custom authentication process during VerifyAuthChallenge Lambda phase. |
- TypeScript
import { useState, useEffect } from "react";
const { COGNITO_CLIENT_ID, COGNITO_USER_POOL_ID, LOGINID_BASE_URL } = config;
const Loginid = new LoginIDCognitoWebSDK(
COGNITO_USER_POOL_ID,
COGNITO_CLIENT_ID,
LOGINID_BASE_URL
);
const EmailOTPLogin = function ({ username }) {
const [otp, setOtp] = useState("");
// On page load or component load
useEffect(() => {
const initalizeOTP = async () => {
try {
// Or invoke this on a click handler
await Loginid.requestAndSendOtp(username);
} catch (e) {
setError(e.message);
}
};
initializeOTP();
}, []);
const handlerSubmit = async (event: FormEvent<HTMLFormElement>) => {
event.preventDefault();
try {
const result = await Loginid.validateOtp(otp);
if (result.isAuthenticated) {
// success login
}
} catch (e: any) {
setError(e.message);
}
};
};
listPasskeys
Lists all passkeys for a given user.
Requires one of the following:
- User must be signed in.
- Cognito ID token.
listPasskeys(idToken?: string): Promise<PasskeyCollection>
Parameter | Type | Required | Details |
---|---|---|---|
idToken | str | No | The Cognito ID token of the user. |
- TypeScript
const { COGNITO_CLIENT_ID, COGNITO_USER_POOL_ID, LOGINID_BASE_URL } = config;
const Loginid = new LoginIDCognitoWebSDK(
COGNITO_USER_POOL_ID,
COGNITO_CLIENT_ID,
LOGINID_BASE_URL
);
const listUserPasskeys = async () => {
try {
const passkeys = await Loginid.listPasskeys();
console.log(passkeys);
} catch (e: any) {
console.error(e.message);
}
};
renamePasskey
Renames a specified passkey.
This method updates the name of a passkey identified by the passkeyId. It requires the new name for the passkey.
Requires one of the following:
- User must be signed in.
- Cognito ID token.
renamePasskey(passkeyId: string, name: string, idToken?: string): Promise<null>
Parameter | Type | Required | Details |
---|---|---|---|
passkeyId | str | yes | The unique identifier of the passkey. |
name | str | yes | The new name for the passkey. |
idToken | str | no | The Cognito ID token of the user. |
- TypeScript
const { COGNITO_CLIENT_ID, COGNITO_USER_POOL_ID, LOGINID_BASE_URL } = config;
const Loginid = new LoginIDCognitoWebSDK(
COGNITO_USER_POOL_ID,
COGNITO_CLIENT_ID,
LOGINID_BASE_URL
);
const renameUserPasskey = async () => {
const passkeyID = "34f4aa64-74e1-4f19-8ee0-939c4d32fe01";
try {
const token = await getCognitoIdToken(user);
await Loginid.renamePasskey(passkeyId, "My Passkey");
console.log("Passkey renamed successfully");
} catch (e: any) {
console.error(e.message);
}
};
deletePasskey
Deletes a specified passkey.
This method removes a passkey identified by the passkeyId from the user's account. It requires the unique identifier of the passkey.
Requires one of the following:
- User must be signed in.
- Cognito ID token.
deletePasskey(passkeyId: string, idToken?: string): Promise<null>
Parameter | Type | Required | Details |
---|---|---|---|
passkeyId | str | yes | The unique identifier of the passkey. |
idToken | str | no | The Cognito ID token of the user. |
- TypeScript
const { COGNITO_CLIENT_ID, COGNITO_USER_POOL_ID, LOGINID_BASE_URL } = config;
const Loginid = new LoginIDCognitoWebSDK(
COGNITO_USER_POOL_ID,
COGNITO_CLIENT_ID,
LOGINID_BASE_URL
);
const deleteUserPasskey = async () => {
const passkeyId = "34f4aa64-74e1-4f19-8ee0-939c4d32fe01";
try {
const token = await getCognitoIdToken(user);
await Loginid.deletePasskey(token, passkeyId);
console.log("Passkey deleted successfully");
} catch (e: any) {
console.error(e.message);
}
};
logout
Log out the current user.
This method logs out the currently authenticated user from the Cognito user pool.
logout(): void
This method does not take any arguments.
- TypeScript
const { COGNITO_CLIENT_ID, COGNITO_USER_POOL_ID, LOGINID_BASE_URL } = config;
const Loginid = new LoginIDCognitoWebSDK(
COGNITO_USER_POOL_ID,
COGNITO_CLIENT_ID,
LOGINID_BASE_URL
);
const logoutUser = () => {
Loginid.logout();
console.log("User signed out successfully");
};
getSessionInfo
Gets the current user authetnicated session info.
This method retrieves the SessionInfo
of the currently authenticated user from the Cognito user pool.
getSessionInfo(): SessionInfo
This method does not take any arguments.
- TypeScript
const { COGNITO_CLIENT_ID, COGNITO_USER_POOL_ID, LOGINID_BASE_URL } = config;
const Loginid = new LoginIDCognitoWebSDK(
COGNITO_USER_POOL_ID,
COGNITO_CLIENT_ID,
LOGINID_BASE_URL
);
const getCurrentUser = () => {
const info = Loginid.getSessionInfo();
if (info.username && info.accessToken) {
console.log("Current user:", info.username);
} else {
console.log("No user is currently authenticated");
}
};
getCurrentUsername
Gets the current username.
This method retrieves the username of the currently authenticated user from the Cognito user pool.
getCurrentUsername(): string | null
This method does not take any arguments.
- TypeScript
const { COGNITO_CLIENT_ID, COGNITO_USER_POOL_ID, LOGINID_BASE_URL } = config;
const Loginid = new LoginIDCognitoWebSDK(
COGNITO_USER_POOL_ID,
COGNITO_CLIENT_ID,
LOGINID_BASE_URL
);
const getCurrentUser = () => {
const username = Loginid.getCurrentUsername();
if (username) {
console.log("Current user:", username);
} else {
console.log("No user is currently authenticated");
}
};