Introduction#

  • Create UserPool and Identity Pool using CDK
  • Authentication using AWS SDK
  • Authetication using axios

Stack#

Let create userpool with

  • domain for hosted ui
  • client with secrete key for server side auth
  • client without secret key for client side auth
const userPool = new aws_cognito.UserPool(this, 'UserPoolForWebEntest', {
userPoolName: 'UserPoolForWebEntest',
selfSignUpEnabled: true,
signInAliases: {
email: true
},
autoVerify: {
email: true
},
removalPolicy: RemovalPolicy.DESTROY
})

Then create an identity pool

const clientWithoutSecret = new aws_cognito.UserPoolClient(
this,
'ClientWithoutSecret',
{
userPool: userPool,
authFlows: {
userPassword: true,
adminUserPassword: true,
custom: true,
userSrp: true
},
userPoolClientName: 'ClientWithoutSecret'
}
)
const clientWithSecret = new aws_cognito.UserPoolClient(
this,
'ClientWithSecret',
{
userPool: userPool,
authFlows: {
userPassword: true,
adminUserPassword: true,
custom: true,
userSrp: true
},
userPoolClientName: 'ClientWithSecret',
generateSecret: true,
oAuth: {
flows: {
authorizationCodeGrant: true
},
callbackUrls: props.callbackUrls,
logoutUrls: props.logoutUrls,
scopes: [
aws_cognito.OAuthScope.EMAIL,
aws_cognito.OAuthScope.OPENID,
aws_cognito.OAuthScope.PHONE
]
}
}
)

Add a domain for hosted ui

const domain = userPool.addDomain('domain', {
cognitoDomain: {
domainPrefix: 'domain-prefix'
}
})
domain.signInUrl(clientWithSecret, {
redirectUri: ''
})

Finally let add an identity pool

const cognitoIdentityPool = new aws_cognito.CfnIdentityPool(
this,
"IdentityPoolForWebEntest",
{
allowUnauthenticatedIdentities: true,
identityPoolName: "IdentityPoolForWebEntest",
cognitoIdentityProviders: [
{
clientId: clientWithSecret.userPoolClientId,
providerName: userPool.userPoolProviderName,
},
{
clientId: clientWithoutSecret.userPoolClientId,
providerName: userPool.userPoolProviderName,
},
],
// supportedLoginProviders: [],
}
);
this.userPool = userPool.userPoolArn;
this.identityPool = cognitoIdentityPool;
}

To grant auth and unauth role for the identity pool

export class CognitoAuthRole extends Stack {
constructor(scope: Construct, id: string, props: CognitoAuthProps) {
super(scope, id, props)
const role = new aws_iam.Role(this, 'RoleForAuthenticatedUserWebEntest', {
assumedBy: new aws_iam.FederatedPrincipal(
'cognito-identity.amazonaws.com',
{
StringEquals: {
'cognito-identity.amazonaws.com:aud': props.cognitoIdentityPool.ref
},
'ForAnyValue:StringLike': {
'cognito-identity.amazonaws.com:amr': 'authenticated'
}
},
'sts:AssumeRoleWithWebIdentity'
),
roleName: 'RoleForAuthenticatedUserWebEntest'
})
// auth role access s3
role.addToPolicy(
new aws_iam.PolicyStatement({
effect: aws_iam.Effect.ALLOW,
actions: ['s3:PutObject', 's3:GetObject'],
resources: [
`arn:aws:s3:::${props.bucketName}`,
`arn:aws:s3:::${props.bucketName}/*`
]
})
)
// unauth role
const unauthRole = new aws_iam.Role(
this,
'RoleForUnAuthenticatedUserWebEntest',
{
assumedBy: new aws_iam.FederatedPrincipal(
'cognito-identity.amazonaws.com',
{
StringEquals: {
'cognito-identity.amazonaws.com:aud':
props.cognitoIdentityPool.ref
},
'ForAnyValue:StringLike': {
'cognito-identity.amazonaws.com:amr': 'unauthenticated'
}
},
'sts:AssumeRoleWithWebIdentity'
),
roleName: 'RoleForUnAuthenticatedUserWebEntest'
}
)
// unauth role access s3
unauthRole.addToPolicy(
new aws_iam.PolicyStatement({
effect: aws_iam.Effect.ALLOW,
actions: ['s3:PutObject', 's3:GetObject'],
resources: [
`arn:aws:s3:::${props.bucketName}`,
`arn:aws:s3:::${props.bucketName}/*`
]
})
)
// unauth role access polly
unauthRole.addToPolicy(
new aws_iam.PolicyStatement({
effect: aws_iam.Effect.ALLOW,
actions: ['polly:SynthesizeSpeech'],
resources: ['*']
})
)
const attach = new aws_cognito.CfnIdentityPoolRoleAttachment(
this,
'RoleAttachmentForWebEntest',
{
identityPoolId: props.cognitoIdentityPool.ref,
roles: {
authenticated: role.roleArn,
unauthenticated: unauthRole.roleArn
}
}
)
}
}

Finally add an s3 bucket

interface S3Props extends StackProps {
bucketName: string
}
export class S3Stack extends Stack {
public readonly bucket: aws_s3.Bucket
constructor(scope: Construct, id: string, props: S3Props) {
super(scope, id, props)
this.bucket = new aws_s3.Bucket(this, props.bucketName, {
bucketName: props.bucketName,
removalPolicy: RemovalPolicy.DESTROY,
autoDeleteObjects: true,
cors: [
{
allowedHeaders: ['*'],
allowedMethods: [
aws_s3.HttpMethods.GET,
aws_s3.HttpMethods.PUT,
aws_s3.HttpMethods.DELETE,
aws_s3.HttpMethods.POST
],
allowedOrigins: ['*'],
exposedHeaders: [
'x-amz-server-side-encryption',
'x-amz-request-id',
'x-amz-id-2',
'ETag'
],
maxAge: 3000
}
]
})
}
}

Here is full cdk stack

cdk-stack.ts
import { Construct } from 'constructs'
import {
aws_cognito,
aws_iam,
aws_s3,
RemovalPolicy,
Stack,
StackProps
} from 'aws-cdk-lib'
interface CognitoProps extends StackProps {
callbackUrls: string[]
logoutUrls: string[]
}
export class CognitoAuthorizer extends Stack {
public readonly userPool: string
public readonly identityPool: aws_cognito.CfnIdentityPool
constructor(scope: Construct, id: string, props: CognitoProps) {
super(scope, id, props)
const userPool = new aws_cognito.UserPool(this, 'UserPoolForWebEntest', {
userPoolName: 'UserPoolForWebEntest',
selfSignUpEnabled: true,
signInAliases: {
email: true
},
autoVerify: {
email: true
},
removalPolicy: RemovalPolicy.DESTROY
})
const clientWithoutSecret = new aws_cognito.UserPoolClient(
this,
'ClientWithoutSecret',
{
userPool: userPool,
authFlows: {
userPassword: true,
adminUserPassword: true,
custom: true,
userSrp: true
},
userPoolClientName: 'ClientWithoutSecret'
}
)
const clientWithSecret = new aws_cognito.UserPoolClient(
this,
'ClientWithSecret',
{
userPool: userPool,
authFlows: {
userPassword: true,
adminUserPassword: true,
custom: true,
userSrp: true
},
userPoolClientName: 'ClientWithSecret',
generateSecret: true,
oAuth: {
flows: {
authorizationCodeGrant: true
},
callbackUrls: props.callbackUrls,
logoutUrls: props.logoutUrls,
scopes: [
aws_cognito.OAuthScope.EMAIL,
aws_cognito.OAuthScope.OPENID,
aws_cognito.OAuthScope.PHONE
]
}
}
)
const domain = userPool.addDomain('domain', {
cognitoDomain: {
domainPrefix: 'domain-prefix'
}
})
domain.signInUrl(clientWithSecret, {
redirectUri: ''
})
const cognitoIdentityPool = new aws_cognito.CfnIdentityPool(
this,
'IdentityPoolForWebEntest',
{
allowUnauthenticatedIdentities: true,
identityPoolName: 'IdentityPoolForWebEntest',
cognitoIdentityProviders: [
{
clientId: clientWithSecret.userPoolClientId,
providerName: userPool.userPoolProviderName
},
{
clientId: clientWithoutSecret.userPoolClientId,
providerName: userPool.userPoolProviderName
}
]
// supportedLoginProviders: [],
}
)
this.userPool = userPool.userPoolArn
this.identityPool = cognitoIdentityPool
}
}
interface CognitoAuthProps extends StackProps {
cognitoIdentityPool: aws_cognito.CfnIdentityPool
bucketName: string
}
export class CognitoAuthRole extends Stack {
constructor(scope: Construct, id: string, props: CognitoAuthProps) {
super(scope, id, props)
const role = new aws_iam.Role(this, 'RoleForAuthenticatedUserWebEntest', {
assumedBy: new aws_iam.FederatedPrincipal(
'cognito-identity.amazonaws.com',
{
StringEquals: {
'cognito-identity.amazonaws.com:aud': props.cognitoIdentityPool.ref
},
'ForAnyValue:StringLike': {
'cognito-identity.amazonaws.com:amr': 'authenticated'
}
},
'sts:AssumeRoleWithWebIdentity'
),
roleName: 'RoleForAuthenticatedUserWebEntest'
})
// auth role access s3
role.addToPolicy(
new aws_iam.PolicyStatement({
effect: aws_iam.Effect.ALLOW,
actions: ['s3:PutObject', 's3:GetObject'],
resources: [
`arn:aws:s3:::${props.bucketName}`,
`arn:aws:s3:::${props.bucketName}/*`
]
})
)
// unauth role
const unauthRole = new aws_iam.Role(
this,
'RoleForUnAuthenticatedUserWebEntest',
{
assumedBy: new aws_iam.FederatedPrincipal(
'cognito-identity.amazonaws.com',
{
StringEquals: {
'cognito-identity.amazonaws.com:aud':
props.cognitoIdentityPool.ref
},
'ForAnyValue:StringLike': {
'cognito-identity.amazonaws.com:amr': 'unauthenticated'
}
},
'sts:AssumeRoleWithWebIdentity'
),
roleName: 'RoleForUnAuthenticatedUserWebEntest'
}
)
// unauth role access s3
unauthRole.addToPolicy(
new aws_iam.PolicyStatement({
effect: aws_iam.Effect.ALLOW,
actions: ['s3:PutObject', 's3:GetObject'],
resources: [
`arn:aws:s3:::${props.bucketName}`,
`arn:aws:s3:::${props.bucketName}/*`
]
})
)
// unauth role access polly
unauthRole.addToPolicy(
new aws_iam.PolicyStatement({
effect: aws_iam.Effect.ALLOW,
actions: ['polly:SynthesizeSpeech'],
resources: ['*']
})
)
const attach = new aws_cognito.CfnIdentityPoolRoleAttachment(
this,
'RoleAttachmentForWebEntest',
{
identityPoolId: props.cognitoIdentityPool.ref,
roles: {
authenticated: role.roleArn,
unauthenticated: unauthRole.roleArn
}
}
)
}
}
interface S3Props extends StackProps {
bucketName: string
}
export class S3Stack extends Stack {
public readonly bucket: aws_s3.Bucket
constructor(scope: Construct, id: string, props: S3Props) {
super(scope, id, props)
this.bucket = new aws_s3.Bucket(this, props.bucketName, {
bucketName: props.bucketName,
removalPolicy: RemovalPolicy.DESTROY,
autoDeleteObjects: true,
cors: [
{
allowedHeaders: ['*'],
allowedMethods: [
aws_s3.HttpMethods.GET,
aws_s3.HttpMethods.PUT,
aws_s3.HttpMethods.DELETE,
aws_s3.HttpMethods.POST
],
allowedOrigins: ['*'],
exposedHeaders: [
'x-amz-server-side-encryption',
'x-amz-request-id',
'x-amz-id-2',
'ETag'
],
maxAge: 3000
}
]
})
}
}

Cognito SDK#

Let create a new TypeScript project

npm init

Then install dependencies

{
"name": "app",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"devDependencies": {
"@types/node": "^20.11.19",
"tslint": "^6.1.3",
"typescript": "^5.3.3"
},
"dependencies": {
"@aws-sdk/client-cognito-identity-provider": "^3.427.0",
"@aws-sdk/client-dynamodb": "^3.438.0",
"@aws-sdk/client-s3": "^3.427.0",
"@aws-sdk/credential-providers": "^3.427.0",
"@aws-sdk/s3-presigned-post": "^3.429.0",
"aws-cloudfront-sign": "^3.0.2",
"aws-jwt-verify": "^4.0.0",
"aws-lambda": "^1.0.7",
"axios": "^1.6.7",
"package.json": "^2.0.1"
}
}

Then we can create a Cognito client

import { config } from './config'
import {
CognitoIdentityProviderClient,
SignUpCommand,
ConfirmSignUpCommand,
InitiateAuthCommand
} from '@aws-sdk/client-cognito-identity-provider'
import { CognitoJwtVerifier } from 'aws-jwt-verify'
const cognitoClient = new CognitoIdentityProviderClient({
region: config.REGION
})

Perform some actions such as sign up, confirm sign up and sin in

const signUp = async (username: string, password: string) => {
try {
const response = await cognitoClient.send(
new SignUpCommand({
ClientId: config.CLIENT_ID,
Username: username,
Password: password
})
)
console.log(response)
} catch (error) {
console.log(error)
}
}
const confirmSignUp = async (username: string, code: string) => {
try {
const response = await cognitoClient.send(
new ConfirmSignUpCommand({
ClientId: config.CLIENT_ID,
Username: username,
ConfirmationCode: code
})
)
} catch (error) {
console.log(error)
}
}
export const signIn = async (username: string, password: string) => {
try {
const response = await cognitoClient.send(
new InitiateAuthCommand({
AuthFlow: 'USER_PASSWORD_AUTH',
AuthParameters: {
USERNAME: username,
PASSWORD: password
},
ClientId: config.CLIENT_ID
})
)
console.log('cognito auth: ', response)
return response
} catch (error) {
console.log(error)
return null
}
}
const decodeToken = async ({ token }: { token: string }) => {
// const token = "";
// const response = (await decode({
// token: token,
// secret: "b10cda68fe67233283a06a30a76eb161",
// })) as any;
// console.log(response.id_token);
// const idToken = response.id_token;
const tokenUse = 'access'
const verifier = CognitoJwtVerifier.create({
userPoolId: config.USER_POOL_ID,
tokenUse: tokenUse,
clientId: config.CLIENT_ID
})
try {
const payload = await verifier.verify(token, {
tokenUse: tokenUse,
clientId: config.CLIENT_ID
})
console.log('Token is valid. Payload:', payload)
} catch {
console.log('Token not valid!')
}
}
// signUp("hai@entest.io", "mypassword");
// confirmSignUp("hai@entest.io", "113656");
// signIn("hai@entest.io", "mypassword");

Heres is full script

cognito-sdk.ts
// getting started with cognito userpool
// without using sdk
// 20/02/2024
import { config } from './config'
import {
CognitoIdentityProviderClient,
SignUpCommand,
ConfirmSignUpCommand,
InitiateAuthCommand
} from '@aws-sdk/client-cognito-identity-provider'
import { CognitoJwtVerifier } from 'aws-jwt-verify'
const cognitoClient = new CognitoIdentityProviderClient({
region: config.REGION
})
const signUp = async (username: string, password: string) => {
try {
const response = await cognitoClient.send(
new SignUpCommand({
ClientId: config.CLIENT_ID,
Username: username,
Password: password
})
)
console.log(response)
} catch (error) {
console.log(error)
}
}
const confirmSignUp = async (username: string, code: string) => {
try {
const response = await cognitoClient.send(
new ConfirmSignUpCommand({
ClientId: config.CLIENT_ID,
Username: username,
ConfirmationCode: code
})
)
} catch (error) {
console.log(error)
}
}
export const signIn = async (username: string, password: string) => {
try {
const response = await cognitoClient.send(
new InitiateAuthCommand({
AuthFlow: 'USER_PASSWORD_AUTH',
AuthParameters: {
USERNAME: username,
PASSWORD: password
},
ClientId: config.CLIENT_ID
})
)
console.log('cognito auth: ', response)
return response
} catch (error) {
console.log(error)
return null
}
}
const decodeToken = async ({ token }: { token: string }) => {
// const token = "";
// const response = (await decode({
// token: token,
// secret: "b10cda68fe67233283a06a30a76eb161",
// })) as any;
// console.log(response.id_token);
// const idToken = response.id_token;
const tokenUse = 'access'
const verifier = CognitoJwtVerifier.create({
userPoolId: config.USER_POOL_ID,
tokenUse: tokenUse,
clientId: config.CLIENT_ID
})
try {
const payload = await verifier.verify(token, {
tokenUse: tokenUse,
clientId: config.CLIENT_ID
})
console.log('Token is valid. Payload:', payload)
} catch {
console.log('Token not valid!')
}
}
// signUp("hai@entest.io", "mypassword");
// confirmSignUp("hai@entest.io", "113656");
// signIn("hai@entest.io", "mypassword");

Cognito Axios#

  • Cognito without using SDK
  • Simple frontend

First, let use axios to send request to Cognito to perform sign up an new account

import { config } from './config'
import axios from 'axios'
import { CognitoJwtVerifier } from 'aws-jwt-verify'
const signUp = async ({
username,
password
}: {
username: string
password: string
}) => {
axios
.post(
config.ENDPOINT,
{
ClientId: config.CLIENT_ID,
Username: username,
Password: password
},
{
headers: {
'Content-Type': 'application/x-amz-json-1.1',
Accept: '*/*',
'X-Amz-Target': 'AWSCognitoIdentityProviderService.SignUp'
}
}
)
.then(response => {
console.log(response)
})
.catch(error => {
console.log(error)
})
}

For confirm signup with code received form email

const confirmSignUp = async ({
confirmCode,
username
}: {
confirmCode: string
username: string
}) => {
axios
.post(
config.ENDPOINT,
{
ClientId: config.CLIENT_ID,
ConfirmationCode: confirmCode,
Username: username
},
{
headers: {
'Content-Type': 'application/x-amz-json-1.1',
Accept: '*/*',
'X-Amz-Target': 'AWSCognitoIdentityProviderService.ConfirmSignUp'
}
}
)
.then(response => {
console.log(response)
})
.catch(error => {
console.log(error)
})
}

Finally, sign in an user with username and password

const signIn = async ({
username,
password
}: {
username: string
password: string
}) => {
axios
.post(
config.ENDPOINT,
{
AuthFlow: 'USER_PASSWORD_AUTH',
ClientId: config.CLIENT_ID,
AuthParameters: {
USERNAME: username,
PASSWORD: password
}
},
{
headers: {
'Content-Type': 'application/x-amz-json-1.1',
Accept: '*/*',
'X-Amz-Target': 'AWSCognitoIdentityProviderService.InitiateAuth'
}
}
)
.then(response => {
console.log(response)
})
.catch(error => {
console.log(error)
})
}

Validate and decode token

const validateToken = async ({ token }: { token: string }) => {
const tokenUse = 'access'
const verifier = CognitoJwtVerifier.create({
userPoolId: config.USER_POOL_ID,
tokenUse: tokenUse,
clientId: config.CLIENT_ID
})
try {
const payload = await verifier.verify(token, {
tokenUse: tokenUse,
clientId: config.CLIENT_ID
})
console.log('Token is valid. Payload:', payload)
} catch {
console.log('Token not valid!')
}
}
signUp({ username: 'myemail@gmail.com', password: 'mypassword' })
confirmSignUp({ confirmCode: '711595', username: 'myemail@gmail.com' })
signIn({ username: 'myemail@gmail.com', password: 'mypassword' })

Here is full script

cognito-axios.ts
// getting started with cognito userpool
// without using sdk
// 20/02/2024
import { config } from './config'
import axios from 'axios'
import { CognitoJwtVerifier } from 'aws-jwt-verify'
const signUp = async ({
username,
password
}: {
username: string
password: string
}) => {
axios
.post(
config.ENDPOINT,
{
ClientId: config.CLIENT_ID,
Username: username,
Password: password
},
{
headers: {
'Content-Type': 'application/x-amz-json-1.1',
Accept: '*/*',
'X-Amz-Target': 'AWSCognitoIdentityProviderService.SignUp'
}
}
)
.then(response => {
console.log(response)
})
.catch(error => {
console.log(error)
})
}
const confirmSignUp = async ({
confirmCode,
username
}: {
confirmCode: string
username: string
}) => {
axios
.post(
config.ENDPOINT,
{
ClientId: config.CLIENT_ID,
ConfirmationCode: confirmCode,
Username: username
},
{
headers: {
'Content-Type': 'application/x-amz-json-1.1',
Accept: '*/*',
'X-Amz-Target': 'AWSCognitoIdentityProviderService.ConfirmSignUp'
}
}
)
.then(response => {
console.log(response)
})
.catch(error => {
console.log(error)
})
}
const signIn = async ({
username,
password
}: {
username: string
password: string
}) => {
axios
.post(
config.ENDPOINT,
{
AuthFlow: 'USER_PASSWORD_AUTH',
ClientId: config.CLIENT_ID,
AuthParameters: {
USERNAME: username,
PASSWORD: password
}
},
{
headers: {
'Content-Type': 'application/x-amz-json-1.1',
Accept: '*/*',
'X-Amz-Target': 'AWSCognitoIdentityProviderService.InitiateAuth'
}
}
)
.then(response => {
console.log(response)
})
.catch(error => {
console.log(error)
})
}
const validateToken = async ({ token }: { token: string }) => {
const tokenUse = 'access'
const verifier = CognitoJwtVerifier.create({
userPoolId: config.USER_POOL_ID,
tokenUse: tokenUse,
clientId: config.CLIENT_ID
})
try {
const payload = await verifier.verify(token, {
tokenUse: tokenUse,
clientId: config.CLIENT_ID
})
console.log('Token is valid. Payload:', payload)
} catch {
console.log('Token not valid!')
}
}
signUp({ username: 'myemail@gmail.com', password: 'mypassword' })
confirmSignUp({ confirmCode: '711595', username: 'myemail@gmail.com' })
signIn({ username: 'myemail@gmail.com', password: 'mypassword' })

FrontEnd#

Let create a simple frontend for client side auth

  • index.html with login form
  • profile.html for authenticated page

Here is index.html

index.html
<html>
<head>
<title>simple cognito</title>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<style>
:root {
box-sizing: border-box;
}
*,
::before,
::after {
box-sizing: inherit;
}
body {
background-color: antiquewhite;
}
.container {
max-width: 800px;
margin-left: auto;
margin-right: auto;
justify-content: center;
align-items: center;
display: flex;
flex-direction: column;
min-height: 100%;
}
.form {
display: grid;
row-gap: 10px;
grid-template-columns: repeat(1, minmax(0, 1fr));
gap: 15px;
background-color: gainsboro;
padding: 20px 20px;
min-width: 350px;
}
.button-submit {
padding: 10px 15px;
border-radius: 5px;
background-color: greenyellow;
border: none;
cursor: pointer;
}
.button-submit:hover {
background-color: aqua;
}
.input-username {
padding: 5px 10px;
width: 100%;
}
</style>
</head>
<body>
<div class="container">
<form class="form" id="form">
<div>
<label for="username">username</label>
<input
type="text"
id="username"
name="username"
class="input-username"
placeholder="htranminhhai20@gmail.com"
/>
</div>
<div>
<label for="password">password</label>
<input
type="password"
id="password"
name="password"
class="input-username"
placeholder="PasswordPlacehoder"
/>
</div>
<button class="button-submit" id="submit">Sign In</button>
</form>
</div>
</body>
<script>
const config = {
REGION: 'us-east-1',
BUCKET: 'bucket-name',
// client auth
USER_POOL_ID: 'USER_POOL_ID',
COGNITO_POOL_ID: 'cognito-idp.us-east-1.amazonaws.com/USER_POOL_ID',
IDENTITY_POOL_ID: 'us-east-1:IDENTITY_POOL_ID',
CLIENT_ID: 'CLIENT_ID',
//
ENDPOINT: 'https://cognito-idp.us-east-1.amazonaws.com'
}
const signIn = async (username, password) => {
axios
.post(
config.ENDPOINT,
{
AuthFlow: 'USER_PASSWORD_AUTH',
ClientId: config.CLIENT_ID,
AuthParameters: {
USERNAME: username,
PASSWORD: password
}
},
{
headers: {
'Content-Type': 'application/x-amz-json-1.1',
Accept: '*/*',
'X-Amz-Target': 'AWSCognitoIdentityProviderService.InitiateAuth'
}
}
)
.then(response => {
console.log(response)
// store access token in local storage
localStorage.setItem(
'AccessToken',
response.data.AuthenticationResult.AccessToken
)
// store id token in local storage
localStorage.setItem(
'IdToken',
response.data.AuthenticationResult.IdToken
)
// open profile page
window.location.href = 'profile.html'
})
.catch(error => {
console.log(error)
})
}
document.getElementById('submit').addEventListener('click', async event => {
event.preventDefault()
const username = document.getElementById('username').value
const password = document.getElementById('password').value
signIn(username, password)
})
</script>
</html>

And here is profile.html

profile.html
<!DOCTYPE html>
<html>
<head>
<title>profile page</title>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<style>
.main {
max-width: 1000px;
margin: auto;
background-color: gainsboro;
height: 100vh;
}
.token {
width: 90%;
height: 200px;
margin: auto;
padding: 10px;
overflow: auto;
background-color: beige;
word-wrap: break-word;
}
.button-decode {
background-color: orange;
padding: 10px 20px;
cursor: pointer;
}
.decoded-token {
background-color: beige;
}
</style>
</head>
<body>
<div class="main">
<div>
<h3>Access Token</h3>
<textarea id="AccessToken" class="token"></textarea>
<h3>Id Token</h3>
<textarea id="IdToken" class="token"></textarea>
<button class="button-decode" id="decode-access-token">
Decode Token
</button>
<h3>Decoded Id Token</h3>
<pre id="DecodedIdToken" class="decoded-token"></pre>
</div>
</div>
<script>
// get access token from local storage
document.getElementById('AccessToken').innerHTML =
localStorage.getItem('AccessToken')
// get id token from local storage
document.getElementById('IdToken').innerHTML =
localStorage.getItem('IdToken')
// cognito configuration
const config = {
REGION: 'us-east-1',
BUCKET: 'bucket-name',
// client auth
USER_POOL_ID: 'USER_POOL_ID',
COGNITO_POOL_ID: 'cognito-idp.us-east-1.amazonaws.com/USER_POOL_ID',
IDENTITY_POOL_ID: 'us-east-1:IDENTITY_POOL_ID',
CLIENT_ID: 'CLIENT_ID',
//
ENDPOINT: 'https://cognito-idp.us-east-1.amazonaws.com'
}
// only decode not validate
const decodeToken = () => {
var token = localStorage.getItem('IdToken')
var base64Url = token.split('.')[1]
var base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/')
var jsonPayload = decodeURIComponent(
window
.atob(base64)
.split('')
.map(function (c) {
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)
})
.join('')
)
let obj = JSON.parse(jsonPayload)
let dec = document.getElementById('DecodedIdToken')
dec.innerHTML = JSON.stringify(obj, undefined, 2).toString()
console.log(JSON.stringify(obj, undefined, 2))
return JSON.parse(jsonPayload)
}
document
.getElementById('decode-access-token')
.addEventListener('click', decodeToken)
</script>
</body>
</html>