How to add Amazon Cognito Auth to a Web App (part 3)

Understanding the Next.JS code samples that creates the User Interface for an Amazon Cognito Authenticated Web App.

Table of Contents


In my last post, I explained how Terraform was being used to create the cloud infrastructure that enables Amazon Cognito to be implemented in the below demo 👇

In this post, I will explain how to integrate Amazon Cognito into the Front End of a Web App, so you can see it as visualised above.

Implementing Cognito Auth on the Front End

I have a Wrapper.js template that you can use to spin up an implementation of Cognito, here are some highlight files from that template:

In this example, I’ll show you a Next.js React App, that uses the Amazon Amplify library to authenticate the Front End with Amazon Cognito.

I recommend reading the first post in this series before continuing, so you understand the concept of what is being implemented!


Let’s start by showing how the variables that were exported from Terraform integrate into the Front End.

					import Amplify, { Auth } from 'aws-amplify';

export function setupAmplify() {
        Auth: {
            // REQUIRED only for Federated Authentication - Amazon Cognito Identity Pool ID
            identityPoolId: process.env.cognito_identity_pool_id,
            // REQUIRED - Amazon Cognito Region
            region: process.env.region,
            // OPTIONAL - Amazon Cognito User Pool ID
            userPoolId: process.env.cognito_user_pool_id,
            userPoolWebClientId: process.env.cognito_user_pool_client_id

You can see the following variables being set up in the AWS Amplify library:

  • identityPoolId: the ID for the identity pool that is used to authorise access to other AWS services
  • region: the region for the Amazon Cognito resource
  • userPoolId: the ID for the user pool where that allows users to create credentials that can be authenticated
  • userPoolWebClientId: the ID that is assigned from Cognito to our app, to allow it to access the User Pool


At the core of the application is _app.js, which executes logic each time a page is loaded.

					import { createGlobalStyle } from 'styled-components'
import Cognito from '../components/Cognito'
import {  Authenticator } from '@aws-amplify/ui-react';

const GlobalStyle = createGlobalStyle`
    html {
        overflow: hidden;
    *, *:before, *:after {
        box-sizing: inherit;
        margin: 0;
    :root {
        --amplify-primary-tint: #0A3369;
        --amplify-primary-contrast: var(--amplify-white);
        --amplify-font-family:'Helvetica Neue Light', 'Helvetica Neue', 'Helvetica', 'Arial', 'sans-serif';  
    amplify-authenticator {
        align-items: center;
        display: inline-block;
        height: auto;
        border: 0px solid;
        color: #0A3369;

export default function App({ Component, pageProps }) {
    return (
                <GlobalStyle />
                <Component {...pageProps} />

In this case, our app checks if a user is authenticated with Cognito (between lines 57 – 66) and renders content based on that users level of authorisation.


This component contains the core Amazon Cognito logic.

					import { Auth } from 'aws-amplify';
import { Authenticator, useAuthenticator } from '@aws-amplify/ui-react';
import '@aws-amplify/ui-react/styles.css';
import React, { useEffect } from 'react';
import cognitoStore from './../../stores/cognito';
import userStore from './../../stores/user';
import styled from 'styled-components';
import { setupAmplify } from './utils.js';
import { httpApiURL } from '../../utils';
import axios from 'axios';


const getUserData = (cognito) => axios({
    method: 'post',
    url: `${httpApiURL}/users/data`,
    data: {
      cognito: cognito
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${cognito.jwt}`
}).then((res) => {
    const data = JSON.parse(;
    return data;
}, (error) => {
    throw new Error(error);
const Cognito = (props) => {
    const { children } = props;
    const { cognito, setCognito, signInState, setSignInState } = cognitoStore();
    const { setUser } = userStore();
    const { user } = useAuthenticator((context) => [context.user]);

    useEffect(() => {
        const fetchData = async() => {
            // Update the document title using the browser API
            if(cognito != '' && cognito != undefined) {
                    setUser(await getUserData(cognito));
                } catch (e) {

            if(user != undefined && cognito == '' && user.signInUserSession) {
                const {accessToken, idToken} = user.signInUserSession;
                const role = accessToken.payload['cognito:groups'];
                const token = {
                    jwt: idToken.jwtToken,
                    role: (role) ? role[0] : '',
                    username: accessToken.payload.username 
        try {
        catch (e) {
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [user])
    useEffect(() => {
        const checkState = async() => {
            if(signInState == 'signOut') {
                await Auth.signOut();
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [signInState]);
    return (
            {cognito == '' ?
                        headerText="Enter your details below"
                        submitButtonText="Sign in"


const AmplifyWrapper = styled('div')`
    position: absolute;
    top: 50%;
    left: 50%;
    -ms-transform: translate(-50%, -50%);
    transform: translate(-50%, -50%);
const ContentWrapper = styled('div')`
    position: relative;
    z-index: 1;
    width: 100vw;
    height: 100vh;

export default Cognito;

Diving into the logic of how this Cognito component works:

  • Lines 37 – 66 shows the logic that attempts to make a request to authenticate with Cognito and get the JWT as a response.
  • Lines 81 – 96 renders a log in page if the user is not authenticated and renders the children content if the user is authenticated


The idea being, if a user is not authenticated, they enter their details into the log in form, this will trigger the an attempt to authenticate with Cognito and then to show content upon success.


Finally, we have a component that renders the web page (assuming that the user has passed Cognito Auth).

					import Head from 'next/head'
import React, { useEffect } from 'react'
import styled from 'styled-components'
import axios from 'axios'

import { httpApiURL } from './../utils'
import Header from '../components/Header'
import cognitoStore from '../stores/cognito' 

export default function Home() {
  const { cognito } = cognitoStore();
  useEffect(() => {
    const getData = async(cognito) => await axios({
      method: 'get',
      url: `${httpApiURL}/users/data`,
      data: {
        cognito: cognito
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${cognito.jwt}`
    }).then((res) => {
    }, (error) => {


    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  return (
        <title>Wrapper.js Authentication Example</title>
      <Header />

      <Img src='/wrapperjs.png' />
      <P>Authentication template</P>

const Img = styled('img')`
  display: block;
  height: 60vh;
  width: auto;
  position: relative;
  // min-width: 500px;

const P = styled('p')`
  text-align: center;
  font-weight: bold;

Talking through this example of how the content that could be shown on the Front End works:

  • Lines 13-33 shows data being loaded from the Back End based on an API request that uses JWT authentication.
  • Lines 35-46 show what the Front End should render if authentication has been successful.


I hope the above is helpful in showing you how to implement Amazon Cognito on the Front End using the Amplify library, to only show content to users that have gone through the Auth process!

In the next (and last) post in this series, I’ll talk through how to implement Amazon Cognito on the Back End to secure API data.

In the meantime, have fun 😀 

Share this post