Building AWS Cognito Authentication Context In React.js

Authentication is a crucial aspect of modern web applications, ensuring secure access to resources and protecting user data. In this blog post, we'll explore how to integrate Amazon Cognito, a fully managed authentication service by AWS, into a React.js application to create a robust security context.
Prerequisites
Before diving into the implementation, make sure you have the following prerequisites:
- AWS account with Cognito User Pool and App Client set up.
- A React.js application with dependencies such as
amazon-cognito-identity-js
andaxios
.
Setting up AWS Cognito
Amazon Cognito simplifies the authentication process by handling user registration, authentication, and account recovery. To get started, create a new User Pool and App Client in the AWS Management Console.
Retrieve the UserPoolId
and ClientId
from the created User Pool, as these will be used in the React.js application.
Integrating Cognito in React.js
The provided React.js code encapsulates the Cognito integration in a custom AuthProvider
. Let's break down the key components and functionalities:
import PropTypes from 'prop-types';
import { createContext, useCallback, useEffect, useReducer } from 'react';
import { CognitoUser, CognitoUserPool, AuthenticationDetails } from 'amazon-cognito-identity-js';
import axios from '../utils/axios';
import { PATH_AUTH } from '../routes/paths';
import { cognitoConfig } from '../config';
// ... (imports and configurations)
Imports and Configurations
PropTypes
: A library for defining the types of props expected by React components.createContext, useCallback, useEffect, useReducer
: Hooks and functions provided by React for managing state and side effects.CognitoUser, CognitoUserPool, AuthenticationDetails
: Classes from theamazon-cognito-identity-js
library for working with AWS Cognito.axios
: A popular library for making HTTP requests.PATH_AUTH
: Import of path constants for routing.cognitoConfig
: Configuration object containing AWS Cognito User Pool details.
export const UserPool = new CognitoUserPool({
UserPoolId: cognitoConfig.userPoolId,
ClientId: cognitoConfig.clientId
});
const initialState = {
isAuthenticated: false,
isInitialized: false,
user: null
};
User Pool Initialization and Initial State
UserPool
: Instantiation of a newCognitoUserPool
using the configuration fromcognitoConfig
.initialState
: The initial state for the authentication context, indicating that the user is not authenticated, the initialization is not complete, and there is no user data.
const handlers = {
AUTHENTICATE: (state, action) => {
const { isAuthenticated, user } = action.payload;
return {
...state,
isAuthenticated,
isInitialized: true,
user
};
},
LOGOUT: (state) => ({
...state,
isAuthenticated: false,
user: null
})
};
Reducer and Handlers
handlers
: An object containing functions that handle different actions dispatched to the reducer. In this case, it handles authentication (AUTHENTICATE
) and logout (LOGOUT
) actions.
const reducer = (state, action) => (handlers[action.type] ? handlers[action.type](state, action) : state);
Reducer Function
reducer
: A function that takes the current state and an action, then returns the new state based on the action type. If the action type is not recognized, it returns the current state unchanged.
const AuthContext = createContext({
...initialState,
method: 'cognito',
login: () => Promise.resolve(),
register: () => Promise.resolve(),
logout: () => Promise.resolve()
});
AuthContext
AuthContext
: A React context that provides the authentication state and methods to its consumers. It has an initial value containing theinitialState
, a method identifier ('cognito'), and placeholder functions forlogin
,register
, andlogout
.
AuthProvider.propTypes = {
children: PropTypes.node
};
function AuthProvider({ children }) {
const [state, dispatch] = useReducer(reducer, initialState);
// ... (other functions and hooks)
}
AuthProvider Component
AuthProvider
: A component that serves as the provider for the authentication context. It uses theuseReducer
hook to manage the authentication state.
// ... (other functions and hooks)
const getSession = useCallback(
() =>
new Promise((resolve, reject) => {
const user = UserPool.getCurrentUser();
// ... (session handling logic)
}),
[getUserAttributes]
);
const initial = useCallback(async () => {
try {
await getSession();
} catch {
dispatch({
type: 'AUTHENTICATE',
payload: {
isAuthenticated: false,
user: null
}
});
}
}, [getSession]);
getSession and initial Functions
getSession
: A function that returns a promise to retrieve the current session. It sets up the necessary headers for axios and dispatches anAUTHENTICATE
action if successful.initial
: A function that initializes the authentication state, callinggetSession
and handling errors.
useEffect(() => {
initial();
}, [initial]);
useEffect Hook
useEffect
: A hook that runs theinitial
function when the component mounts. It ensures that the authentication state is properly initialized.
curl -fsSL https://bun.sh/install | bash # for macOS, Linux, and WSL
login Function
login
: A function that takes an email and password, authenticates the user using Cognito, and resolves with the authentication data. It also handles cases where a new password is required.
const logout = () => {
const user = UserPool.getCurrentUser();
if (user) {
user.signOut();
dispatch({ type: 'LOGOUT' });
}
};
logout Function
logout
: A function that signs out the current user and dispatches aLOGOUT
action.
const register = (email, password, firstName, lastName) =>
new Promise((resolve, reject) =>
UserPool.signUp(
email,
password,
[
{ Name: 'email', Value: email },
{ Name: 'name', Value: `${firstName} ${lastName}` }
],
null,
async (err) => {
if (err) {
reject(err);
return;
}
resolve();
window.location.href = PATH_AUTH.login;
}
)
);
register Function
register
: A function that registers a new user using Cognito. It resolves when registration is successful and redirects to the login page.
const resetPassword = () => {};
// ... (other functions and hooks)
return (
<AuthContext.Provider
value={{
...state,
method: 'cognito',
user: {
displayName: state?.user?.name || 'Minimals',
role: 'admin',
...state.user
},
login,
register,
logout,
resetPassword
}}
>
{children}
</AuthContext.Provider>
);
AuthContext.Provider
- The
AuthContext.Provider
component wraps the application, providing the authentication context to its children. - It exposes the authentication state
Step 1: Set Up a New React App
If you haven't already, create a new React app using Create React App or any other preferred method:
npx create-react-app my-react-app
cd my-react-app
Step 2: Install Dependencies
Install the necessary dependencies used in the provided code:
npm install amazon-cognito-identity-js axios
Step 3: Create Configuration and Utility Files
Create configuration files for AWS Cognito and utility files as needed. The provided code assumes the existence of cognitoConfig
, axios
, and route-related files.
Step 4: Create a AuthProvider.js
file
Copy the provided AuthProvider
code into a new file, such as AuthProvider.js
, and place it in a relevant location in your project.
Step 5: Integrate AuthProvider
in index.js
or App.js
In your index.js
or App.js
, import and wrap your main component with the AuthProvider
. Make sure to import any necessary styles or additional setup your application might require.
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import { AuthProvider } from './path/to/AuthProvider';
ReactDOM.render(
<React.StrictMode>
<AuthProvider>
<App />
</AuthProvider>
</React.StrictMode>,
document.getElementById('root')
);
Step 6: Use Authentication Context in Components
Now, you can use the authentication context in your components. Import the AuthContext
and use the useContext
hook to access the authentication state and methods.
import React, { useContext } from 'react';
import { AuthContext } from './path/to/AuthProvider';
function MyComponent() {
const { isAuthenticated, user, login, logout, register } = useContext(AuthContext);
// Your component logic based on authentication state and user information
return (
<div>
{isAuthenticated ? (
<p>Hello, {user.displayName}!</p>
) : (
<button onClick={() => login('example@email.com', 'password')}>Login</button>
)}
</div>
);
}
Step 7: Run Your React App
Start your React app to see the changes:
npm start


GitHub URL : https://github.com/kaviyarasumaran/Firebase-authContext/blob/main/AwsAuthContext.js
Conclusion
By integrating Amazon Cognito into your React.js application, you enhance security and provide a seamless authentication experience for users. The AuthProvider
simplifies the management of authentication state and actions, allowing developers to focus on building feature-rich applications while ensuring robust security.
Feel free to adapt and expand upon this code to meet the specific requirements of your application. Happy coding!