Complete Guide to Build Authentication system with Amplify and Next.js
An efficient authentication system is essential to the security and usability of online applications in today’s networked digital environment. This post will show you how to utilize AWS Amplify and Next.js to easily develop a strong authentication system, giving you the power to design a frictionless registration and login process that improves both security and developer experience.
Are you sick of battling web app authentication? Would you like to integrate Amplify into your Next.js projects? You’re in the proper location! This thorough guide explains how to use AWS Amplify to implement an authentication mechanism into your Next.js applications. You can quickly create an authentication flow with the help of these step-by-step instructions!
Table of Contents:
- Setting up AWS Amplify CLI
- Build Amplify Authentication Service
- Creating a Next.js Project
- Implementing Amplify Default User Sign-In and Sign-Up
- Implementing Custom User Sign-In and Sign-Up
- Retrieving User Information
Make sure you have the following prerequisites in place before we start the implementation:
- Basic Understanding of React.js and Next.js
- An AWS account
- Nodejs and NPM in your local machine
Setting up AWS Amplify CLI
First, you need to have an AWS account. Now you need to install amplify CLI on your local machine, to do that runnpm install -g @aws-amplify/cli
Next, run amplify configure
This will automatically open up the AWS console to make sure you have an account and are signed in. After that, you can switch back to your code editor, press enter
, and select your region.
And you will be redirected to complete the user creation in the AWS console.
In the next step, you will see the permission level. Select attach policies directly, For our Amplify app, we will go with AdministratorAccess-Amplify
(set by default). Select Next to continue:
Finally, review the changes the confirm the IAM user Creation by clicking in Create User.
In the next page, you will see the IAM users and you can find recently created user in this page called auth-root
Now we need to generate Access Key and Secret Key in order to authenticate Amplify CLI.
Click on your IAM user and select Security Credential
tab and scroll down till you see Access Keys.
Now create a new Access Key and Select the use case Command Line Interface (CLI)
. It will generate an Access Key and Access Secret Key for your IAM user.
Now use these keys in your CLI to authenticate.
That’s it for the Amplify CLI configuration in your Terminal.
Now we can move on to the next step.
Build Amplify Authentication Service
Now, login to the AWS console and Search for Amplify service.
Now click on Get Started and start creating your new Amplify App.
Let's get started with building our App.
Now Give your app a name and confirm the deployment
After deployment is successful you will see the below screen now you need to launch Amplify studio
Launching Studio will bring you to the Amplify Studio page. Amplify studio has many other functions like Data, Functions, Storage etc but for now we will go into authentication.
Now Enable Authentication and It will redirect you to the Auth setup page.
Next, you need to configure your authentication system. In the first step, you can configure the Login mechanism and you can add as many mechanisms as you want like login with email, google, apple, facebook etc. In the Second part, you need to configure user signup attributes, these are the fields that the user is required to fill during signup. It provides many more config settings like password requirements and verification message settings. So, feel free to express the dashboard.
Here I have enabled email and Google login, For Google login you need to provide Client ID and Client Secret. And I have added two attributes Phone Number and Name for Signup.
Next, Deploy the authentication service.
After your Authentication service has been deployed to the AWS server. Now you can pull this service in your next.js app and use the service.
Creating and Configuring Next.js Project
Let’s create a next.js project by using the command npx create-next-app@v12
. After successfully creating a Next.js project let’s install the amplify dependencies.
npm install aws-amplify @aws-amplify/ui-react
@aws-amplify/ui-react
Is the UI component library provided by the AWS which makes building UI seamless for us.
Now, it’s time to pull the auth configuration we created in the previous app to our app. Using the below command, this command was given to us when the auth service was deployed successfully. Look at the most recent image above.
amplify pull - appId d3u3ibrthnx3za - envName staging
This code will pull all the auth configurations to your next.js app but before pulling it will ask some question
This will add amplify
directory in your project root and also a file called aws-exports.js
which contains the credentials for AWS auth app.
Now, let’s get started with the Coding part.
First, we need to add some configuration to your pages/_app.tsx
file. This will add amplify to your Project and we have also imported aws-amplify css
which will help us build beautiful UI easily.
import '../styles/globals.css'
import type { AppProps } from 'next/app'
import { Amplify } from 'aws-amplify'
import awsconfig from "../aws-exports"
import "@aws-amplify/ui-react/styles.css";
Amplify.configure({ ...awsconfig, ssr: true });
function MyApp({ Component, pageProps }: AppProps) {
return <Component {...pageProps} />
}
export default MyApp
Let’s create a page called auth/index.tsx
in pages directory and add the following code.
import React from "react";
import styled from "styled-components";
import { Authenticator } from "@aws-amplify/ui-react";
const Container = styled.div`
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
`;
const Authentication = () => {
return (
<Container>
<Authenticator>
{({ signOut, user }) => (
<main>
<h1>Hello, {user?.username}!</h1>
<button onClick={signOut}>Sign out</button>
</main>
)}
</Authenticator>
</Container>
);
};
export default Authentication;
We created an Authenticator
component for the homepage so that the user is required to create an account or log in to see the content. Run npm run dev
to start the developer server again and open http://localhost:3000:
Now, create an account using the attributes you provided in your auth service and try to sign in. You will be presented with the greeting indicating that you have successfully authenticated:
Tada, You have successfully implemented an Authentication service using Amplify and Next.js.
However, we will not stop here. If you have a pre-built login and signup page. You can implement login and signup in your own components. We will see how!
Implementing Custom User Sign-In and Sign-Up
For this, I have created custom-signup
, confirm-email, custom-login
pages in my project.
For Custom Signup Page:
import { Button, Input, Link } from "@aws-amplify/ui-react";
import { notification } from "antd";
import { Auth } from "aws-amplify";
import { useRouter } from "next/router";
import React, { useState } from "react";
import styled from "styled-components";
const Container = styled.div`
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100vh;
background-color: white;
color: black;
form {
width: 50%;
}
input {
margin-top: 20px;
margin-bottom: 20px;
}
`;
const Signup = () => {
const [email, setemail] = useState("");
const [password, setPassword] = useState("");
const [name, setname] = useState("");
const [phone, setPhone] = useState("");
const router = useRouter()
const handleSubmit = async (e: any) => {
e.preventDefault();
try {
await Auth.signUp({
username: email,
password: password,
attributes: {
email: email,
name: name,
phone_number: phone,
},
});
notification.success({
message: "User created successfully",
});
router.push(`/confirm-email?user=${email}`)
} catch (error) {
notification.error({
message: `Failed to create user ${error}`,
});
}
};
return (
<Container>
<div>AWS custom signup</div>
<form onSubmit={handleSubmit}>
<Input
name="Name"
placeholder="Enter Name"
required={true}
type="text"
onChange={(e) => setname(e.target.value)}
/>
<Input
name="Email"
placeholder="Enter Email"
required={true}
type="email"
onChange={(e) => setemail(e.target.value)}
/>
<Input
name="Password"
placeholder="Enter Password"
required={true}
type="password"
onChange={(e) => setPassword(e.target.value)}
/>
<Input
name="Phone"
placeholder="Enter Phone number"
required={true}
type="text"
onChange={(e) => setPhone(e.target.value)}
/>
<Button type="submit">Create Account</Button>
</form>
<Link href={"/custom-login"}>Go to Login page</Link>
</Container>
);
};
export default Signup;
We will make user of Auth method that is imported from amplify library to the Signup user.
After signup is complete, we will redirect the user to the email verification page, Verification code will be sent to the registered email.
import { Button, Input } from "@aws-amplify/ui-react";
import { notification } from "antd";
import { Auth } from "aws-amplify";
import { useRouter } from "next/router";
import React, { useState } from "react";
import styled from "styled-components";
const Container = styled.div`
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100vh;
background-color: white;
color: black;
form {
width: 50%;
}
input {
margin-top: 20px;
margin-bottom: 20px;
}
`;
const Login = () => {
const [code, setCode] = useState("");
const router = useRouter()
const {query} = router
const user = query.user
const handleSubmit = async (e: any) => {
e.preventDefault();
try {
await Auth.confirmSignUp(user, code);
notification.success({
message: `User verified successfully, now you can login`,
});
router.push("/custom-login")
} catch (error) {
notification.error({
message: `Failed to verify user ${error}`,
});
}
};
return (
<Container>
<div>Confirm Email</div>
<form onSubmit={handleSubmit}>
<Input
name="Verification COde"
placeholder="Enter Verification Cdde"
required={true}
type="text"
onChange={(e) => setCode(e.target.value)}
/>
<Button type="submit">Verify My Account</Button>
</form>
</Container>
);
};
export default Login;
Similarly, custom-login page
import { Button, Input } from "@aws-amplify/ui-react";
import { notification } from "antd";
import { Auth } from "aws-amplify";
import Link from "next/link";
import React, { useEffect, useState } from "react";
import styled from "styled-components";
const Container = styled.div`
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100vh;
background-color: white;
color: black;
form {
width: 50%;
}
input {
margin-top: 20px;
margin-bottom: 20px;
}
`;
const Login = () => {
const [email, setemail] = useState("");
const [password, setPassword] = useState("");
const [isLoggedIn, setisLoggedIn] = useState(false);
const [user, setUser] = useState<{name:string} | null>(null)
const handleSubmit = async (e: any) => {
e.preventDefault();
try {
await Auth.signIn(email, password);
notification.success({
message: "Logged in successfully",
});
setisLoggedIn(true);
} catch (error) {
notification.error({
message: `Failed to login ${error}`,
});
}
};
useEffect(() => {
const fetchUsers = async () => {
const {attributes} = await Auth.currentUserInfo();
setUser(attributes)
};
fetchUsers();
}, [isLoggedIn]);
if (isLoggedIn) {
return <Container>Hello, {user?.name}!!!!</Container>;
}
return (
<Container>
<div>AWS custom Login</div>
<form onSubmit={handleSubmit}>
<Input
name="Email"
placeholder="Enter Email"
type="email"
onChange={(e) => setemail(e.target.value)}
/>
<Input
name="Password"
placeholder="Enter Password"
type="password"
onChange={(e) => setPassword(e.target.value)}
/>
<Button type="submit">Login</Button>
</form>
<Link href={"/custom-signup"}>Go to Signup page</Link>
</Container>
);
};
export default Login;
Let’s see the above code output in UI.
That’s all for building a complete authentication system using Amplify and Next.js.
You can find the code in the below GitHub repository for references.