Create articles from any YouTube video or use our API to get YouTube transcriptions
Start for freeIntroduction to AWS Cognito Authentication in Next.js
AWS Cognito is a powerful authentication and authorization service that can be seamlessly integrated with Next.js applications. This guide will walk you through the process of implementing Cognito authentication in a Next.js project, from initial setup to advanced features.
Setting Up AWS Cognito
To begin, you'll need to set up a Cognito User Pool in the AWS Console:
- Navigate to the Amazon Cognito service in the AWS Console
- Click "Create user pool"
- Choose "Email" as the sign-in option
- Configure password policies and MFA settings as needed
- Enable self-registration and email verification
- Select "Send email with Cognito" for message delivery (switch to Amazon SES for production)
- Name your user pool (e.g., "nextjs-tutorial")
- Create an app client without a client secret
- Ensure "Allow user SRP auth for Cognito" is selected in Advanced settings
Configuring Amplify in Next.js
Install the necessary packages:
npm install aws-amplify @aws-amplify/adapter-nextjs
Create a configuration file src/app/amplify-cognito-config.ts
:
import { Amplify } from 'aws-amplify';
import { type ResourcesConfig } from 'aws-amplify';
const config: ResourcesConfig = {
Auth: {
Cognito: {
userPoolId: process.env.NEXT_PUBLIC_USER_POOL_ID!,
userPoolClientId: process.env.NEXT_PUBLIC_USER_POOL_CLIENT_ID!,
},
},
};
Amplify.configure(config, { ssr: true });
export default function configureAmplifyClientSide() {
return null;
}
Update your root layout to include the Amplify configuration:
import ConfigureAmplifyClientSide from '@/app/amplify-cognito-config';
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
<ConfigureAmplifyClientSide />
{children}
</body>
</html>
);
}
Create a server-side utility src/utils/amplify-server.ts
:
import { createServerRunner } from '@aws-amplify/adapter-nextjs';
import config from '@/app/amplify-cognito-config';
export const { runWithAmplifyServerContext } = createServerRunner(config);
Implementing Sign Up, Sign In, and Sign Out
Create authentication forms for sign up, sign in, and sign out. Here's an example of a sign-up form:
import { useFormState } from 'react-dom';
import { handleSignUp } from '@/lib/cognito-actions';
export function SignUpForm() {
const [state, formAction] = useFormState(handleSignUp, null);
return (
<form action={formAction}>
<input type="email" name="email" required />
<input type="text" name="name" required />
<input type="password" name="password" required />
<button type="submit">Create Account</button>
{state?.error && <p>{state.error}</p>}
</form>
);
}
Implement the corresponding Cognito actions in lib/cognito-actions.ts
:
import { signUp, confirmSignUp, signIn, signOut } from 'aws-amplify/auth';
export async function handleSignUp(prevState: any, formData: FormData) {
const email = formData.get('email') as string;
const password = formData.get('password') as string;
const name = formData.get('name') as string;
try {
await signUp({
username: email,
password,
attributes: { email, name },
autoSignIn: { enabled: true },
});
return { redirect: '/auth/confirm-signup' };
} catch (error) {
return { error: getErrorMessage(error) };
}
}
// Implement similar functions for confirmSignUp, signIn, and signOut
Adding Authorization with Middleware
Create a middleware file src/middleware.ts
to protect routes:
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
import { authenticatedUser } from '@/utils/amplify-server';
export async function middleware(request: NextRequest) {
const response = NextResponse.next();
const user = await authenticatedUser({ request, response });
const isOnDashboard = request.nextUrl.pathname.startsWith('/dashboard');
const isInAdminArea = request.nextUrl.pathname.startsWith('/dashboard/admin');
if (isOnDashboard && !user) {
return NextResponse.redirect(new URL('/auth/login', request.url));
}
if (isInAdminArea && !user?.isAdmin) {
return NextResponse.redirect(new URL('/dashboard', request.url));
}
return response;
}
export const config = {
matcher: ['/((?!api|_next/static|_next/image|favicon.ico).*)'],
};
Managing User Profiles
Implement functions to update user attributes, email, and password:
import { updateUserAttribute, updatePassword } from 'aws-amplify/auth';
export async function handleUpdateUserAttribute(prevState: any, formData: FormData) {
const name = formData.get('name') as string;
const email = formData.get('email') as string;
try {
await updateUserAttribute({
userAttribute: {
attributeKey: email ? 'email' : 'name',
value: email || name,
},
});
return { success: true };
} catch (error) {
return { error: getErrorMessage(error) };
}
}
export async function handleUpdatePassword(prevState: any, formData: FormData) {
const oldPassword = formData.get('currentPassword') as string;
const newPassword = formData.get('newPassword') as string;
try {
await updatePassword({ oldPassword, newPassword });
return { success: true };
} catch (error) {
return { error: getErrorMessage(error) };
}
}
Implementing Password Reset
Add functionality for users to reset forgotten passwords:
import { resetPassword, confirmResetPassword } from 'aws-amplify/auth';
export async function handleResetPassword(prevState: any, formData: FormData) {
const email = formData.get('email') as string;
try {
await resetPassword({ username: email });
return { redirect: '/auth/reset-password/confirm' };
} catch (error) {
return { error: getErrorMessage(error) };
}
}
export async function handleConfirmResetPassword(prevState: any, formData: FormData) {
const email = formData.get('email') as string;
const newPassword = formData.get('newPassword') as string;
const confirmationCode = formData.get('confirmationCode') as string;
try {
await confirmResetPassword({ username: email, newPassword, confirmationCode });
return { redirect: '/auth/login' };
} catch (error) {
return { error: getErrorMessage(error) };
}
}
Conclusion
Implementing AWS Cognito authentication in a Next.js application provides a robust and scalable solution for user management. This guide covered the essential steps to set up Cognito, integrate it with Next.js using the Amplify library, and implement key features such as sign-up, sign-in, authorization, profile management, and password reset.
By following these steps, you can create a secure and user-friendly authentication system for your Next.js application. Remember to consult the AWS Amplify documentation for more advanced features and best practices in production environments.
As you continue to develop your application, consider implementing additional security measures, such as multi-factor authentication, and explore Cognito's integration with other AWS services to enhance your application's capabilities.
Article created from: https://youtu.be/wiWDOgIu7cU