{
  "doc": {
    "id": "app/guides/authentication-testing/amazon-cognito-authentication",
    "title": "Amazon Cognito Authentication: Cypress Guide",
    "description": "Implement Amazon Cognito authentication in Cypress. Securely manage authentication processes for Cypress end-to-end testing scenarios",
    "section": "app",
    "source_path": "/llm/markdown/app/guides/authentication-testing/amazon-cognito-authentication.md",
    "version": "3cf5b86b3403f604bdf7f3e35025c3bc3865e02c",
    "updated_at": "2026-05-07T17:44:31.931Z",
    "headings": [
      {
        "id": "app/guides/authentication-testing/amazon-cognito-authentication#amazon-cognito-authentication",
        "text": "Amazon Cognito Authentication",
        "level": 1
      },
      {
        "id": "app/guides/authentication-testing/amazon-cognito-authentication#what-youll-learn",
        "text": "What you'll learn",
        "level": 5
      },
      {
        "id": "app/guides/authentication-testing/amazon-cognito-authentication#amazon-cognito-setup",
        "text": "Amazon Cognito Setup",
        "level": 2
      },
      {
        "id": "app/guides/authentication-testing/amazon-cognito-authentication#setting-amazon-cognito-app-credentials-in-cypress",
        "text": "Setting Amazon Cognito app credentials in Cypress",
        "level": 2
      },
      {
        "id": "app/guides/authentication-testing/amazon-cognito-authentication#custom-command-for-amazon-cognito-authentication",
        "text": "Custom Command for Amazon Cognito Authentication",
        "level": 2
      },
      {
        "id": "app/guides/authentication-testing/amazon-cognito-authentication#login-with-cy-origin",
        "text": "Login with cy.origin()",
        "level": 3
      },
      {
        "id": "app/guides/authentication-testing/amazon-cognito-authentication#programmatic-login",
        "text": "Programmatic Login",
        "level": 3
      },
      {
        "id": "app/guides/authentication-testing/amazon-cognito-authentication#adapting-an-amazon-cognito-app-for-testing",
        "text": "Adapting an Amazon Cognito App for Testing",
        "level": 3
      },
      {
        "id": "app/guides/authentication-testing/amazon-cognito-authentication#adapting-the-back-end",
        "text": "Adapting the back end",
        "level": 4
      },
      {
        "id": "app/guides/authentication-testing/amazon-cognito-authentication#adapting-the-front-end",
        "text": "Adapting the front end",
        "level": 4
      }
    ]
  },
  "content": {
    "type": "root",
    "children": [
      {
        "type": "heading",
        "depth": 1,
        "children": [
          {
            "type": "text",
            "value": "Amazon Cognito Authentication"
          }
        ]
      },
      {
        "type": "heading",
        "depth": 5,
        "children": [
          {
            "type": "text",
            "value": "What you'll learn"
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "How to implement Amazon Cognito authentication in Cypress"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "How to securely manage authentication processes for Cypress end-to-end testing scenarios"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Amazon "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://aws.amazon.com/cognito",
            "children": [
              {
                "type": "text",
                "value": "Cognito"
              }
            ]
          },
          {
            "type": "text",
            "value": " is an authentication provider apart of "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://aws.amazon.com",
            "children": [
              {
                "type": "text",
                "value": "Amazon Web Services (AWS)"
              }
            ]
          },
          {
            "type": "text",
            "value": "."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "The documentation for "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://aws.amazon.com/cognito",
            "children": [
              {
                "type": "text",
                "value": "Amazon Cognito"
              }
            ]
          },
          {
            "type": "text",
            "value": " recommends using the "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://aws-amplify.github.io/amplify-js/api/classes/authclass.html",
            "children": [
              {
                "type": "text",
                "value": "AWS Amplify Framework Authentication Library"
              }
            ]
          },
          {
            "type": "text",
            "value": " from the "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://aws.amazon.com/amplify/framework/",
            "children": [
              {
                "type": "text",
                "value": "AWS Amplify Framework"
              }
            ]
          },
          {
            "type": "text",
            "value": " to interact with a deployed "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://aws.amazon.com/cognito",
            "children": [
              {
                "type": "text",
                "value": "Amazon Cognito"
              }
            ]
          },
          {
            "type": "text",
            "value": " instance. Using the "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://aws-amplify.github.io/amplify-js/api/classes/authclass.html",
            "children": [
              {
                "type": "text",
                "value": "AWS Amplify Framework Authentication Library"
              }
            ]
          },
          {
            "type": "text",
            "value": ", we are able to programmatically drive the creation and authentication of users against a fully deployed back end."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "This guide illustrates the limited code from the "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://aws.amazon.com/amplify/framework/",
            "children": [
              {
                "type": "text",
                "value": "AWS Amplify Framework"
              }
            ]
          },
          {
            "type": "text",
            "value": " needed to programmatically log an existing a user into an application."
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "Amplify v5.x.x"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "Amplify v6.x.x"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "// Add 'aws-amplify' library into your applicationimport Amplify, { Auth } from 'aws-amplify'// Configure Auth category with your Amazon Cognito credentialsAmplify.configure({  Auth: {    identityPoolId: 'XX-XXXX-X:XXXXXXXX-XXXX', // Amazon Cognito Identity Pool ID    region: 'XX-XXXX-X', // Amazon Cognito Region  },})// Call Auth.signIn with user credentialsAuth.signIn(username, password)  .then((user) => console.log(user))  .catch((err) => console.log(err))"
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "import { Amplify } from \"aws-amplify\";import { fetchAuthSession, signIn } from \"aws-amplify/auth\";Amplify.configure({  Auth: {    Cognito: {      userPoolId: \"XX-XXXX-X_XXXXXXXXX\",      userPoolClientId: \"XXXXXXXXXXXXXXXXXXXXXXXXX\",      // OR:      identityPoolId: 'XX-XXXX-X:XXXXXXXX-XXXX', // Amazon Cognito Identity Pool ID    },  },});signIn({ username, password, { authFlowType: \"USER_PASSWORD_AUTH\" } })  // eslint-disable-next-line @typescript-eslint/no-unused-vars  .then((_signInOutput) => fetchAuthSession())  .then((authSession) => console.log(authSession))  .catch((err) => console.log(err));"
      },
      {
        "type": "heading",
        "depth": 2,
        "children": [
          {
            "type": "text",
            "value": "Amazon Cognito Setup"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "If not already setup, you will need to "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://docs.amplify.aws/start/getting-started/installation/q/integration/react#sign-up-for-an-aws-account",
            "children": [
              {
                "type": "text",
                "value": "create an account"
              }
            ]
          },
          {
            "type": "text",
            "value": " with "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://aws.amazon.com",
            "children": [
              {
                "type": "text",
                "value": "Amazon Web Services (AWS)"
              }
            ]
          },
          {
            "type": "text",
            "value": "."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "An "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://aws.amazon.com/cognito",
            "children": [
              {
                "type": "text",
                "value": "Amazon Cognito"
              }
            ]
          },
          {
            "type": "text",
            "value": " integration is available in the"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "link",
            "title": null,
            "url": "https://github.com/cypress-io/cypress-realworld-app",
            "children": [
              {
                "type": "text",
                "value": "Real World App (RWA)"
              }
            ]
          },
          {
            "type": "text",
            "value": ". Clone the Cypress Real World App and install the "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://docs.amplify.aws/cli",
            "children": [
              {
                "type": "text",
                "value": "AWS Amazon Amplify CLI"
              }
            ]
          },
          {
            "type": "text",
            "value": " as follows:"
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "npm install @aws-amplify/cli --global"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "The"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "link",
            "title": null,
            "url": "https://github.com/cypress-io/cypress-realworld-app",
            "children": [
              {
                "type": "text",
                "value": "Real World App (RWA)"
              }
            ]
          },
          {
            "type": "text",
            "value": " is configured with an optional "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://aws.amazon.com/cognito",
            "children": [
              {
                "type": "text",
                "value": "Amazon Cognito"
              }
            ]
          },
          {
            "type": "text",
            "value": " instance via the "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://aws-amplify.github.io/amplify-js/api/classes/authclass.html",
            "children": [
              {
                "type": "text",
                "value": "AWS Amplify Framework Authentication Library"
              }
            ]
          },
          {
            "type": "text",
            "value": ". The "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://docs.amplify.aws/cli",
            "children": [
              {
                "type": "text",
                "value": "AWS Amazon Amplify CLI"
              }
            ]
          },
          {
            "type": "text",
            "value": " is used to provision the "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://aws.amazon.com",
            "children": [
              {
                "type": "text",
                "value": "Amazon Web Services (AWS)"
              }
            ]
          },
          {
            "type": "text",
            "value": " infrastructure needed to configure your environment and cloud resources."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "First, run the "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://docs.amplify.aws/cli/start/workflows#initialize-new-project",
            "children": [
              {
                "type": "text",
                "value": "amplify init"
              }
            ]
          },
          {
            "type": "text",
            "value": " command to initialize the Real World App. This will provision the project with your "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://aws.amazon.com",
            "children": [
              {
                "type": "text",
                "value": "AWS"
              }
            ]
          },
          {
            "type": "text",
            "value": " credentials."
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "amplify init"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Next, run the "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://docs.amplify.aws/cli/start/workflows#amplify-push",
            "children": [
              {
                "type": "text",
                "value": "amplify push"
              }
            ]
          },
          {
            "type": "text",
            "value": " command to create the "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://aws.amazon.com/cognito",
            "children": [
              {
                "type": "text",
                "value": "Amazon Cognito"
              }
            ]
          },
          {
            "type": "text",
            "value": " resources in the cloud:"
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "amplify push"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Note"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Use the `yarn dev:cognito` command when starting the Real World App."
          }
        ]
      },
      {
        "type": "heading",
        "depth": 2,
        "children": [
          {
            "type": "text",
            "value": "Setting Amazon Cognito app credentials in Cypress"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "First, we need to configure Cypress to use the "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://aws.amazon.com/cognito",
            "children": [
              {
                "type": "text",
                "value": "AWS Cognito"
              }
            ]
          },
          {
            "type": "text",
            "value": " environment variables set in the `.env` file. In addition, we are using the `aws-exports.js` supplied during the "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://docs.amplify.aws/cli",
            "children": [
              {
                "type": "text",
                "value": "AWS Amplify CLI"
              }
            ]
          },
          {
            "type": "text",
            "value": " build process."
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "cypress.config.js"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "cypress.config.ts"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "const { defineConfig } = require('cypress')// Populate process.env with values from .env filerequire('dotenv').config()// AWS exportsconst awsConfig = require('./aws-exports-es5.js')module.exports = defineConfig({  env: {    awsConfig: awsConfig.default,  },  setupNodeEvents(on, config) {    on('task', {      getCognitoCredentials() {        const username = process.env.AWS_COGNITO_USERNAME        const password = process.env.AWS_COGNITO_PASSWORD        if (!username || !password) {          throw new Error(            'AWS_COGNITO_USERNAME and AWS_COGNITO_PASSWORD must be set'          )        }        return { username, password }      },    })    return config  },})"
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "import { defineConfig } from 'cypress'// Populate process.env with values from .env filerequire('dotenv').config()// AWS exportsconst awsConfig = require('./aws-exports-es5.js')export default defineConfig({  env: {    awsConfig: awsConfig.default,  },  setupNodeEvents(on, config) {    on('task', {      getCognitoCredentials() {        const username = process.env.AWS_COGNITO_USERNAME        const password = process.env.AWS_COGNITO_PASSWORD        if (!username || !password) {          throw new Error(            'AWS_COGNITO_USERNAME and AWS_COGNITO_PASSWORD must be set'          )        }        return { username, password }      },    })    return config  },})"
      },
      {
        "type": "heading",
        "depth": 2,
        "children": [
          {
            "type": "text",
            "value": "Custom Command for Amazon Cognito Authentication"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "There are two ways you can authenticate to AWS Cognito:"
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "link",
                    "title": null,
                    "url": "/llm/markdown/app/guides/authentication-testing/amazon-cognito-authentication.md#Login-with-cyorigin",
                    "children": [
                      {
                        "type": "text",
                        "value": "Login with `cy.origin()`"
                      }
                    ]
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "link",
                    "title": null,
                    "url": "/llm/markdown/app/guides/authentication-testing/amazon-cognito-authentication.md#Programmatic-Login",
                    "children": [
                      {
                        "type": "text",
                        "value": "Programmatic Access"
                      }
                    ]
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "heading",
        "depth": 3,
        "children": [
          {
            "type": "text",
            "value": "Login with "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/api/commands/origin.md",
            "children": [
              {
                "type": "text",
                "value": "`cy.origin()`"
              }
            ]
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "We'll write a custom command called `loginByCognito` to perform a login to "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://aws.amazon.com/cognito",
            "children": [
              {
                "type": "text",
                "value": "Amazon Cognito"
              }
            ]
          },
          {
            "type": "text",
            "value": ". This command will use "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/api/commands/origin.md",
            "children": [
              {
                "type": "text",
                "value": "`cy.origin()`"
              }
            ]
          },
          {
            "type": "text",
            "value": " to"
          }
        ]
      },
      {
        "type": "list",
        "ordered": true,
        "start": 1,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "Navigate to the Cognito origin"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "Input user credentials"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "Sign in and redirect back to the "
                  },
                  {
                    "type": "link",
                    "title": null,
                    "url": "https://github.com/cypress-io/cypress-realworld-app",
                    "children": [
                      {
                        "type": "text",
                        "value": "Real World App (RWA)"
                      }
                    ]
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "Cache the results with "
                  },
                  {
                    "type": "link",
                    "title": null,
                    "url": "/llm/markdown/api/commands/session.md",
                    "children": [
                      {
                        "type": "text",
                        "value": "`cy.session()`"
                      }
                    ]
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "cypress/support/auth-provider-commands/cognito.ts"
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "// Amazon Cognitoconst loginToCognito = (username: string, password: string) => {  Cypress.log({    displayName: 'COGNITO LOGIN',    message: [`🔐 Authenticating | ${username}`],    autoEnd: false,  })  cy.visit('/')  cy.origin(    Cypress.expose('cognito_domain'),    {      args: {        username,        password,      },    },    ({ username, password }) => {      cy.contains('Sign in with your email and password')      // Cognito log in page has some elements of the same id but are off screen.      // We only want the visible elements to log in      cy.get('input[name=\"username\"]:visible').type(username)      cy.get('input[name=\"password\"]:visible').type(password, {        // use log: false to prevent your password from showing in the Command Log        log: false,      })      cy.get('input[name=\"signInSubmitButton\"]:visible').click()    }  )  // give a few seconds for redirect to settle  cy.wait(2000)  // verify we have made it passed the login screen  cy.contains('Get Started').should('be.visible')}// right now our custom command is light. More on this later!Cypress.Commands.add('loginByCognito', (username, password) => {  return loginToCognito(username, password)})"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Now, we can use our `loginByCognito` command in the test. Below is our test to login as a user via "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://aws.amazon.com/cognito",
            "children": [
              {
                "type": "text",
                "value": "Amazon Cognito"
              }
            ]
          },
          {
            "type": "text",
            "value": ", complete the onboarding process and logout."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "The "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://github.com/cypress-io/cypress-realworld-app/blob/develop/cypress/tests/ui-auth-providers/cognito.spec.ts",
            "children": [
              {
                "type": "text",
                "value": "runnable version of this test"
              }
            ]
          },
          {
            "type": "text",
            "value": " is in the"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "link",
            "title": null,
            "url": "https://github.com/cypress-io/cypress-realworld-app",
            "children": [
              {
                "type": "text",
                "value": "Real World App (RWA)"
              }
            ]
          },
          {
            "type": "text",
            "value": "."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "auth.spec.js"
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "describe('Cognito, cy.origin() login', function () {  beforeEach(function () {    // Seed database with test data    cy.task('db:seed')    // login via Amazon Cognito via cy.origin()    cy.env(['AWS_COGNITO_USERNAME', 'AWS_COGNITO_PASSWORD']).then(      ({ username, password }) => {        cy.loginByCognito(username, password)      }    )  })  it('shows onboarding', function () {    cy.contains('Get Started').should('be.visible')  })})"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Now, we can refactor our login command to take advantage of "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/api/commands/session.md",
            "children": [
              {
                "type": "text",
                "value": "`cy.session()`"
              }
            ]
          },
          {
            "type": "text",
            "value": " to store our logged in user so we don't have to reauthenticate with every test."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "cypress/support/auth-provider-commands/cognito.ts"
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "// Amazon CognitoCypress.Commands.add(  'loginByCognito, cy.origin() login',  (username, password) => {    cy.session(      `cognito-${username}`,      () => {        return loginToCognito(username, password)      },      {        validate() {          cy.visit('/')          // revalidate our session to make sure we are logged in          cy.contains('Get Started').should('be.visible')        },      }    )  })"
      },
      {
        "type": "heading",
        "depth": 3,
        "children": [
          {
            "type": "text",
            "value": "Programmatic Login"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Next, we'll write a command to perform a programmatic login into "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://aws.amazon.com/cognito",
            "children": [
              {
                "type": "text",
                "value": "Amazon Cognito"
              }
            ]
          },
          {
            "type": "text",
            "value": " and set items in `localStorage` with the authenticated users details, which we will use in our application code to verify we are authenticated under test."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "In this `loginByCognitoApi` command, we call `Auth.signIn`, then use that response to set the items inside of localStorage for the UI to know that our user is logged into the application."
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "Amplify v5.x.x"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "Amplify v6.x.x"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "cypress/support/auth-provider-commands/cognito.ts"
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "import Amplify, { Auth } from 'aws-amplify'Amplify.configure(Cypress.expose('awsConfig'))// Amazon CognitoCypress.Commands.add('loginByCognitoApi', (username, password) => {  const log = Cypress.log({    displayName: 'COGNITO LOGIN',    message: [`🔐 Authenticating | ${username}`],    // @ts-ignore    autoEnd: false,  })  log.snapshot('before')  const signIn = Auth.signIn({ username, password })  cy.wrap(signIn, { log: false }).then((cognitoResponse) => {    const keyPrefixWithUsername = `${cognitoResponse.keyPrefix}.${cognitoResponse.username}`    window.localStorage.setItem(      `${keyPrefixWithUsername}.idToken`,      cognitoResponse.signInUserSession.idToken.jwtToken    )    window.localStorage.setItem(      `${keyPrefixWithUsername}.accessToken`,      cognitoResponse.signInUserSession.accessToken.jwtToken    )    window.localStorage.setItem(      `${keyPrefixWithUsername}.refreshToken`,      cognitoResponse.signInUserSession.refreshToken.token    )    window.localStorage.setItem(      `${keyPrefixWithUsername}.clockDrift`,      cognitoResponse.signInUserSession.clockDrift    )    window.localStorage.setItem(      `${cognitoResponse.keyPrefix}.LastAuthUser`,      cognitoResponse.username    )    window.localStorage.setItem('amplify-authenticator-authState', 'signedIn')    log.snapshot('after')    log.end()  })  cy.visit('/')})"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "cypress/support/auth-provider-commands/cognito.ts"
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "import { Amplify } from 'aws-amplify'import { fetchAuthSession, signIn } from 'aws-amplify/auth'Amplify.configure(Cypress.expose('awsConfig'))const fetchJwts = async (username: string, password: string) => {  const options = { authFlowType: 'USER_PASSWORD_AUTH' as const }  await signIn({ username, password, options })  const authSession = await fetchAuthSession()  const tokens = authSession.tokens!  const accessToken = tokens.accessToken  const accessTokenPayload = accessToken.payload  return {    idToken: tokens.idToken!.toString(),    accessToken: accessToken.toString(),    clientId: accessTokenPayload.client_id as string,    accessTokenSub: accessTokenPayload.sub!,  }}type JwtResponse = Awaited<ReturnType<typeof fetchJwts>>// Amazon CognitoCypress.Commands.add(  // eslint-disable-next-line @typescript-eslint/ban-ts-comment  // @ts-ignore  'loginByCognitoApi',  (username: string, password: string) => {    const log = Cypress.log({      displayName: 'COGNITO LOGIN',      message: [`🔐 Authenticating | ${username}`],      autoEnd: false,    })    log.snapshot('before')    cy.wrap(fetchJwts(username, password), { log: false }).then(      (unknownJwts) => {        const { idToken, accessToken, clientId, accessTokenSub } =          unknownJwts as JwtResponse        const keyPrefix = `CognitoIdentityServiceProvider.${clientId}`        const keyPrefixWithUsername = `${keyPrefix}.${accessTokenSub}`        const ls = window.localStorage        ls.setItem(`${keyPrefixWithUsername}.idToken`, idToken)        ls.setItem(`${keyPrefixWithUsername}.accessToken`, accessToken)        ls.setItem(`${keyPrefix}.LastAuthUser`, accessTokenSub)        log.snapshot('after')        log.end()      }    )  })"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Finally, we can use our `loginByCognitoApi` command in at test. Below is our test to login as a user via "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://aws.amazon.com/cognito",
            "children": [
              {
                "type": "text",
                "value": "Amazon Cognito"
              }
            ]
          },
          {
            "type": "text",
            "value": ", complete the onboarding process and logout."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "The "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://github.com/cypress-io/cypress-realworld-app/blob/develop/cypress/tests/ui-auth-providers/cognito.spec.ts",
            "children": [
              {
                "type": "text",
                "value": "runnable version of this test"
              }
            ]
          },
          {
            "type": "text",
            "value": " is in the "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://github.com/cypress-io/cypress-realworld-app",
            "children": [
              {
                "type": "text",
                "value": "Real World App (RWA)"
              }
            ]
          },
          {
            "type": "text",
            "value": "."
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "describe('Cognito, programmatic login', function () {  beforeEach(function () {    // Seed database with test data    cy.task('db:seed')    // Programmatically login via Amazon Cognito API    cy.env(['AWS_COGNITO_USERNAME', 'AWS_COGNITO_PASSWORD']).then(      ({ username, password }) => {        cy.loginByCognitoApi(username, password)      }    )  })  it('shows onboarding', function () {    cy.contains('Get Started').should('be.visible')  })})"
      },
      {
        "type": "heading",
        "depth": 3,
        "children": [
          {
            "type": "text",
            "value": "Adapting an Amazon Cognito App for Testing"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "AWS Backend Services Need No Adaptation"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Often times, AWS Cognito is used when other AWS services provide the backend, such as AWS AppSync for GraphQL APIs or AWS API Gateway for REST APIs. These backend services can be configured to verify cognito JWTs without additional code. However, if you are hosting a webserver backend, like the "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://github.com/cypress-io/cypress-realworld-app",
            "children": [
              {
                "type": "text",
                "value": "cypress real-world app"
              }
            ]
          },
          {
            "type": "text",
            "value": " does with the Express npm library, it must be adapted, as the real-world app is, to verify the Cognito JWTs to authorize the frontend's requests."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "The"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "link",
            "title": null,
            "url": "https://github.com/cypress-io/cypress-realworld-app",
            "children": [
              {
                "type": "text",
                "value": "Real World App (RWA)"
              }
            ]
          },
          {
            "type": "text",
            "value": " is used and provides configuration and runnable code for both the React SPA and the Express back end."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "The front end uses the "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://aws-amplify.github.io/amplify-js/api/classes/authclass.html",
            "children": [
              {
                "type": "text",
                "value": "AWS Amplify Framework Authentication Library"
              }
            ]
          },
          {
            "type": "text",
            "value": ". The back end uses the "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://github.com/auth0/express-jwt",
            "children": [
              {
                "type": "text",
                "value": "express-jwt"
              }
            ]
          },
          {
            "type": "text",
            "value": " to validate JWTs from "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://aws.amazon.com/cognito",
            "children": [
              {
                "type": "text",
                "value": "Amazon Cognito"
              }
            ]
          },
          {
            "type": "text",
            "value": "."
          }
        ]
      },
      {
        "type": "heading",
        "depth": 4,
        "children": [
          {
            "type": "text",
            "value": "Adapting the back end"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "In order to validate API requests from the frontend, we install "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://github.com/auth0/express-jwt",
            "children": [
              {
                "type": "text",
                "value": "express-jwt"
              }
            ]
          },
          {
            "type": "text",
            "value": " and "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://github.com/auth0/node-jwks-rsa",
            "children": [
              {
                "type": "text",
                "value": "jwks-rsa"
              }
            ]
          },
          {
            "type": "text",
            "value": " and configure validation for JWT's from "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://aws.amazon.com/cognito",
            "children": [
              {
                "type": "text",
                "value": "Amazon Cognito"
              }
            ]
          },
          {
            "type": "text",
            "value": "."
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "Amplify v5.x.x"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "Amplify v6.x.x"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "backend/helpers.ts"
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "// ... initial importsimport jwt from 'express-jwt'import jwksRsa from 'jwks-rsa'// ...const awsCognitoJwtConfig = {  secret: jwksRsa.expressJwtSecret({    jwksUri: `https://cognito-idp.${awsConfig.aws_cognito_region}.amazonaws.com/${awsConfig.aws_user_pools_id}/.well-known/jwks.json`,  }),  issuer: `https://cognito-idp.${awsConfig.aws_cognito_region}.amazonaws.com/${awsConfig.aws_user_pools_id}`,  algorithms: ['RS256'],}export const checkCognitoJwt = jwt(awsCognitoJwtConfig).unless({  path: ['/testData/*'],})"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "backend/helpers.ts"
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "// ... initial importsimport jwt from 'express-jwt'import jwksRsa from 'jwks-rsa'// ...const userPoolId = awsConfig.Auth.Cognito.userPoolIdconst region = userPoolId.split('_')[0]const awsCognitoJwtConfig = {  secret: jwksRsa.expressJwtSecret({    jwksUri: `https://cognito-idp.${region}.amazonaws.com/${userPoolId}/.well-known/jwks.json`,  }),  issuer: `https://cognito-idp.${region}.amazonaws.com/${userPoolId}`,  algorithms: ['RS256'],}export const checkCognitoJwt = jwt(awsCognitoJwtConfig).unless({  path: ['/testData/*'],})"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Once this helper is defined, we can use globally to apply to all routes:"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "backend/app.ts"
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "// initial imports ...import { checkCognitoJwt } from './helpers'// ...if (process.env.REACT_APP_AWS_COGNITO) {  app.use(checkCognitoJwt)}// routes ..."
      },
      {
        "type": "heading",
        "depth": 4,
        "children": [
          {
            "type": "text",
            "value": "Adapting the front end"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "We need to update our front end React app to allow for authentication with "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://aws.amazon.com/cognito",
            "children": [
              {
                "type": "text",
                "value": "Amazon Cognito"
              }
            ]
          },
          {
            "type": "text",
            "value": " using the "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://aws-amplify.github.io/amplify-js/api/classes/authclass.html",
            "children": [
              {
                "type": "text",
                "value": "AWS Amplify Framework Authentication Library"
              }
            ]
          },
          {
            "type": "text",
            "value": "."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "First, we create a `AppCognito.tsx` container, based off of the `App.tsx` component."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "A `useEffect` hook is added to get the access token for the authenticated user and send a `COGNITO` event with the token to work with the existing authentication layer (`authMachine.ts`). If no access token is yet available, we redirect the browser to the "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://aws.amazon.com/cognito",
            "children": [
              {
                "type": "text",
                "value": "Amazon Cognito"
              }
            ]
          },
          {
            "type": "text",
            "value": " User Pool Hosted UI to provide the login form."
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "Amplify v6.x.x"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "src/containers/AppCognito.tsx"
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "// amplify v6// initial imports ...import { Amplify, ResourcesConfig } from \"aws-amplify\";import { fetchAuthSession, signInWithRedirect, signOut } from \"aws-amplify/auth\";import awsConfig from \"../aws-exports\";Amplify.configure(awsConfig as ResourcesConfig);// ...const AppCognito: React.FC = () => {  // ...  useEffect(() => {    if (!isLoggedIn) {      fetchAuthSession().then((authSession) => {        if (authSession && authSession.tokens && authSession.tokens.accessToken) {          const { tokens, userSub } = authSession;          authService.send(\"COGNITO\", {            accessTokenJwtString: tokens!.accessToken.toString(),            userSub: userSub!,            email: tokens!.idToken!.payload.email,          });        } else {          void signInWithRedirect();        }      });    }  }, [isLoggedIn]);  // ...  if (!isLoggedIn) {    return null; // redirection will occur soon anyway  }};export default AppCognito;"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Try it out"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "The complete "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://github.com/cypress-io/cypress-realworld-app/blob/develop/src/containers/AppCognito.tsx",
            "children": [
              {
                "type": "text",
                "value": "AppCognito.tsx component"
              }
            ]
          },
          {
            "type": "text",
            "value": " is in the "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://github.com/cypress-io/cypress-realworld-app",
            "children": [
              {
                "type": "text",
                "value": "Real World App (RWA)"
              }
            ]
          },
          {
            "type": "text",
            "value": "."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Next, we update our entry point (`index.tsx`) to use our `AppCognito.tsx` component."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "src/index.tsx"
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "// ... initial importsimport AppCognito from './containers/AppCognito'// ...if (process.env.REACT_APP_AWS_COGNITO) {  ReactDOM.render(    <Router history={history}>      <ThemeProvider theme={theme}>        <AppCognito />      </ThemeProvider>    </Router>,    document.getElementById('root')  )}"
      }
    ]
  },
  "token_estimate": 2443
}