Skip to main content

Cognito Authentication

By making a few changes to AWS products and incorporating a little front-end code, a website using AWS Cognito as its identity platform can implement OwnID to simplify and streamline the login experience for its users. Integrating OwnID with a website that leverages Cognito involves three basic steps:

  • Use the OwnID Console to create an OwnID application
  • Use the AWS Console to configure IAM, Lambda, and Cognito
  • Use the OwnID Web SDK to add the OwnID widget to client-side pages

Step 1: Create OwnID Application#

An OwnID application connects your website's identify platform with the OwnID widget in the front end. First, you integrate with Cognito when creating the application. Upon creation, this OwnID application is assigned a unique appId that is added to the website's front end, so both Cognito and the front end are bound to the application. To create an OwnID application:

  1. Open the OwnID Console and create an account or log in to an existing account.
  2. Select Create Application.
  3. Define the details of the OwnID application, and select Next.
  4. If you are ready to configure Cognito and modify your front end, select the Cognito Authentication card and proceed to Step 2: Configure AWS Products. If you would like to complete these steps later, select Skip for Now.

Step 2: Configure AWS Products#

The OwnID-Cognito integration includes using the AWS Console to configure IAM, Lambda, and Cognito. If you created an OwnID application without starting the Cognito integration, open the application in the OwnID Console and select the Integration tab before taking the following steps.

Create and Configure IAM Credentials#

OwnID needs credentials to access AWS so it can integrate itself with Cognito. Once AWS IAM generates these credentials, you can provide them to OwnID through the OwnID Console.

  1. In the AWS IAM Console, create an IAM User with Access Key-Programmatic Access credentials.
  2. Once the IAM User is created, copy the Access Key ID and Secret Access Key of the new User, then paste them into the corresponding fields of the OwnID application that you are configuring in the OwnID Console.
  3. In the IAM Console, create a new Policy. During the creation process, paste the following code into the JSON tab:
"Version": "2012-10-17",
"Statement": [
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"Resource": "*"
  1. In the IAM Console, open the User created for OwnID and attach the new Policy.

Configure Cognito#

OwnID uses the existing User Pool for your website to integrate with Cognito. This integration consists of using the OwnID Console to add the Pool ID of the User Pool to the OwnID application, creating an App Client, creating a custom Pool Attribute, and configuring three Cognito authentication triggers to use OwnID Lambda functions.

  1. Use the Cognito Console to find the Pool ID of your User Pool, then copy and paste the ID into the OwnID Console.
  2. Use the Cognito Console to add a new App Client to the User Pool. The new App Client's Auth Flows Configuration section must enable lambda trigger-based custom authentication (ALLOW_CUSTOM_AUTH).
  3. Copy the Client ID and Client Secret of the new App Client and paste them into the OwnID Console.
  4. In the Cognito Console, carefully add a Custom Pool Attribute with the following properties. This attribute cannot be modified or deleted after creation.
    • Type: String
    • Name: OwnIDConnections
    • Min Length: 1
    • Max length: 2048
    • Mutable: Enabled
  5. Use the OwnID Console to select Next.

Create Lambda Functions#

As part of the OwnID-Cognito integration, authentication triggers in Cognito invoke AWS Lambda functions written specifically for OwnID. Before configuring Cognito, you need to create these Lambda functions, one for each trigger.

For each Lambda function, Author from Scratch and select Runtime > Node.js 14.x.

  1. In the Lambda Console, create a Node.js function called ownid-DefineAuthChallenge. During creation, paste the following code in Index.js:
const USER_NOT_FOUND_EXCEPTION_STRING = 'User does not exist';
const INVALID_CREDITIALS = 'Invalid credentials';
exports.handler = (event, context, callback) => {
const verifyChallenge = challengeName => {
const session = event.request.session?.slice(-1)[0];
return session &&
session.length &&
session.challengeName === challengeName &&
session.challengeResult === true
const updateEvent = (challengeName ,issueTokens = false,failAuthentication = false) => {
event.response.issueTokens = issueTokens;
event.response.failAuthentication = failAuthentication;
if(challengeName) {
event.response.challengeName = challengeName;
// If user is not registered
if (event.request.userNotFound) {
if (verifyChallenge(CUSTOM_CHALLENGE_NAME)) {
// The user provided the right answer; succeed auth
}else if (verifyChallenge(PASSWORD_VERIFIER_CHALLENGE_NAME)){
}else if (event.request.session &&
event.request.session.length &&
event.request.session.slice(-1)[0].challengeName === SRP_CHALLENGE_NAME){
}else if(event.request.session.length >= 5 &&
event.request.session.slice(-1)[0].challengeResult === false){
throw new Error(INVALID_CREDITIALS);
// Return to Amazon Cognito
callback(null, event);
  1. In the Lambda console, create a Node.js function called ownid-CreateAuthChallenge. During creation, paste the following code in Index.js:
const crypto = require("crypto");
exports.handler = async (event) => {
const publicKeyCred = event.request.userAttributes["custom:fido2CredentialId"];
const challenge = crypto.randomBytes(64).toString('hex');
event.response.publicChallengeParameters = {
credId: publicKeyCred, //credetnial id
challenge: challenge
event.response.privateChallengeParameters = { challenge : challenge};
return event;
  1. In the Lambda console, create a Node.js function called ownid-VerifyAuthChallenge. During creation, paste the following code in Index.js:
exports.handler = async (event) => {
event.response.answerCorrect = true;
return event;
  1. Use the Cognito Console to configure three of the User Pool's Triggers (Define Auth Challenge, Create Auth Challenge, and Verify Auth Challenge Response) to invoke the corresponding OwnID Lambda functions. For example, open the Triggers and use the Define Auth Challenge drop-down to select ownid-DefineAuthChallenge.

  2. Use the OwnID Console to select Next.

Step 3: Add OwnID to Your Frontend#

The OwnID SDK includes straightforward functions that are called from your front-end code to add OwnID to your login and registration flows. This SDK is appropriate for websites that use raw JavaScript rather than a front-end framework. Each flow has its own variation of an OwnID widget that makes passwordless authentication possible. The ownid function creates the appropriate variation of the widget based on its first argument: login creates a widget for a login page while register creates a widget for a registration page.

Including the OwnID SDK#

Every HTML page that uses the OwnID widget must load the OwnID SDK. In addition, these registration and login pages must initialize this OwnID SDK with the appId of an OwnID application, which can be obtained by opening the application in the OwnID Console. Once you have the appId, place the following code in the head of the registration or login page to include and initialize the SDK.

(function (w, d, s, u, o, e, p, a) {w[o] = w[o] || function () {
a=arguments,(w[o].q = w[o].q || []).push(a);'function'==typeof a[1]&&a[1]()},
e = d.createElement(s), p = d.getElementsByTagName(s)[0];e.src = u;e.async = 1;p.parentNode.insertBefore(e, p)
})(window, document, 'script', '', 'ownid');
// Initialize with appId of your OwnID application
ownid('init', {appId: 'uw8nb56ipzsklu'});

Tip: You can customize the appearance of the OwnID widget using advanced initialization parameters. For details, see Customizing the UI.

Registration Page#

Once the registration page loads and initializes the OwnID SDK, it can use the following code to render the OwnID widget, which results in the Skip Password option appearing on the page. The getElementById method returns the elements defined in your existing registration form.

ownid('register', {
passwordField: document.getElementById("password"),
submitButton: document.getElementById("submitButton")

Now, modify the function that is executed when the registration form is submitted (for example, onSubmit) so it calls the ownid function. This ownid function handles errors and adds the user to Cognito, including storing the OwnID authentication payload into the custom pool attribute that you created in Cognito.

function onSubmit(email, password) {
ownid("getOwnIDData", "register").then((ownIdResponse) => {
//The error message is available as ownIdResponse.message
if ( {
ownIdData =;
const attributeList = [
new CognitoUserAttribute({
Name: 'email',
Value: email,
// Add OwnID info to attributes list if OwnID was used to register
if(ownIdData &&{
attributeList.push(new CognitoUserAttribute({
Name: 'preferred_username',
attributeList.push(new CognitoUserAttribute({
Name: 'custom:OwnIDConnections',
Value: JSON.stringify([ownIdData]),
// Register the user
userPool.signUp(email, password, attributeList, [], function (err, res) {
if (err) {
} else {
}).catch((err) => {
throw err

Login Page#

Once the login page loads and initializes the OwnID SDK, it can use the following code to render the OwnID widget, which results in the Skip Password option appearing on the page. The getElementById method returns the elements defined in your existing login form. A dataObj authentication object is returned by the SDK when the user successfully logs in with OwnID. Extracting the access token, ID token, and refresh token properties of this object allows you to set the session in Cognito.

ownid('login', {
loginIdField: document.getElementById('email'),
passwordField: document.getElementById("password"),
submitButton: document.getElementById('submit'),
onLogin: function(dataObj){
//Extract auth data needed to set the session in Cognito
var accessToken = dataObj.accessToken;
var idToken = dataObj.idToken;
var refreshToken = dataObj.refreshToken;
// Call your method to set the session
//Insert code that is executed after user logs in e.g., redirect the user to an authorized page

Customizing the UI#

The default code added to initialize the OwnID SDK has a single parameter: appId. In addition to this required parameter, there are optional parameters that can be added to the initialization code to modify the look of the Skip Password option. Each parameter is added to the ownid function of the initialization code as a key/value pair of the JSON object. For example, once you have copied the initialization code to your page, you could edit the ownid function to add the optional textColor parameter:

appId: 'uw8nb56ipzsklu',
textColor: '#0000FF'

The following is a complete list of initialization parameters.

Required Parameter

  • appId - The unique appId of the OwnID application for your website. To obtain the appId, go to the OwnID Console and open the application.

User Interface Parameters

  • variant - Determines whether the Skip Password feature appears as a button or inline text. Data type is String. Possible values are button(default) and inline. An inline widget displays "Skip Password" in the password field itself, while the button variation displays a Skip Password button to the right of the password field.
  • textColor - Defines the color of the Skip Password text. Data type is a String formatted as a hex color e.g., #0000FF.
  • borderColor - Defines the color of the border of the Skip Password widget. Data type is a String formated as a hex color e.g., #0000FF
  • addOrStatement - If you are using the default Skip Password button in your UI (as opposed to the inline variant), you have the option of displaying the word "or" in between the password field and the Skip Password button. Data type is Boolean. Default is true.