Use Amplify categories APIs from Next.js
This guide walks through how to use Amplify Auth, GraphQL API, REST API, and Storage category APIs from Next.js server-side runtimes.
Before you begin, you will need:
Configure Amplify in Next.js
You will need to create a runWithAmplifyServerContext function to use Amplify APIs on the server-side of your Next.js app.
You can create an amplifyServerUtils.ts file under a utils folder in your codebase. In this file, you will import the Amplify configuration object from the amplifyconfiguration.json file that is generated by the Amplify CLI, and use the createServerRunner function to create the `runWithAmplifyServerContext function.
For example, the utils/amplifyServerUtils.ts file may contain the following content:
import { createServerRunner } from '@aws-amplify/adapter-nextjs';import config from '@/amplifyconfiguration.json';
export const { runWithAmplifyServerContext } = createServerRunner({ config});You can use the exported runWithAmplifyServerContext function to call Amplify APIs with in isolated request contexts. Usage examples see here.
When you use the Amplify library on the client-side of your Next.js app, you will need to configure Amplify by calling Amplify.configure as you would to use Amplify in a single-page application.
'use client';
import config from '@/amplifyconfiguration.json';import { Amplify } from 'aws-amplify';
Amplify.configure(config, { ssr: true // required when using Amplify with Next.js});
export default function RootLayoutThatConfiguresAmplifyOnTheClient({ children}: { children: React.ReactNode;}) { return children;}Learn moreConfigure Amplify in a Next.js App Router application
If you're using the Next.js App Router, you can create a client component to configure Amplify and import it into your root layout.
ConfigureAmplifyClientSide.tsx:
'use client';
import { Amplify } from 'aws-amplify';import config from '../amplifyconfiguration.json';
Amplify.configure(config, { ssr: true });
export default function ConfigureAmplifyClientSide() { return null;}layout.tsx:
import ConfigureAmplifyClientSide from '@/components/ConfigureAmplifyClientSide';import './globals.css';
import type { Metadata } from 'next';
export const metadata: Metadata = { title: 'Create Next App', description: 'Generated by create next app',};
export default function RootLayout({ children,}: { children: React.ReactNode;}) { return ( <html lang="en"> <body className="container pb-6"> <> <ConfigureAmplifyClientSide /> {children} </> </body> </html> );}Authentication with Next.js server-side runtime
(Experimental) Perform authentication on the server side and enable HttpOnly cookies
Additional setup is required to enable server-side authentication flows in your Next.js app.
Step 1 - Specify the origin of your app in environment variables
Add the following environment variable to your Next.js app. For example in a .env file:
AMPLIFY_APP_ORIGIN=https://myapp.comEnsure this environment variable is accessible in your Next.js app's server runtime.
Step 2 - Export the createAuthRouteHandlers function
The createAuthRouteHandlers function is created by the createServerRunner function call when you configure Amplify for server-side usage. You can export this function from your amplifyServerUtils.ts file. You can also configure cookie attributes with the runtimeOptions parameter.
import { createServerRunner } from '@aws-amplify/adapter-nextjs';import config from '@/amplifyconfiguration.json';
export const { runWithAmplifyServerContext, createAuthRouteHandlers,} = createServerRunner({ config, runtimeOptions: { cookies: { domain: '.myapp.com', // making cookies available to all subdomains sameSite: 'strict', maxAge: 60 * 60 * 24 * 7 // 7 days } }});Step 3 - Set up the Auth API routes
Create an API route using the createAuthRouteHandlers function. For example:
import { createAuthRouteHandlers } from "@/utils/amplifyServerUtils";
export const GET = createAuthRouteHandlers({ redirectOnSignInComplete: "/home", redirectOnSignOutComplete: "/sign-in",});import { createAuthRouteHandlers } from "@/utils/amplifyServerUtils";
export default createAuthRouteHandlers({ redirectOnSignInComplete: "/home", redirectOnSignOutComplete: "/sign-in",});With the above example, Amplify generates the following API routes:
| API Routes | What it does |
|---|---|
/api/auth/sign-up | Upon navigating an end user to this route, they’ll be redirected to the Amazon Cognito Managed Login sign-up form. After sign-up and sign-in, they’ll be redirected back to the route /api/auth/sign-in-callback. |
/api/auth/sign-in | Upon navigating an end user to this route, they’ll be redirected to the Amazon Cognito Managed Login sign-in form. After sign-in, they’ll be redirected back to the route /api/auth/sign-in-callback. |
/api/auth/sign-in?provider=<social-provider-name> | Upon navigating an end user to this route, they’ll be redirected first to the Amazon Cognito Managed Login and then the specified social provider sign-in page. After sign-in, they’ll be redirected back to the route /api/auth/sign-in-callback. |
/api/auth/sign-out | Upon navigating an end user to this route, the end user will be signed out and redirected to the route /api/auth/sign-out-callback. |
/api/auth/sign-in-callback | Amazon Cognito Managed Login redirects an end user back to this route after signing in. Amplify exchanges auth tokens and stores them as HttpOnly cookies in the browser cookie store, then redirects the end user back to the route specified by the redirectOnSignInComplete parameter. |
/api/auth/sign-out-callback | Amazon Cognito Managed Login redirects an end user back to this route after signing out, Amplify revokes access token and refresh token and removes token cookies from browser cookie store, then redirects the end user back to the route specified by the redirectOnSignOutComplete parameter. |
To customize the language of the Amazon Cognito Managed Login pages, you can add the lang query parameter to the /api/auth/sign-in and /api/auth/sign-up routes. For example, /api/auth/sign-in?lang=fr. Refer to the Managed login localization documentation for more information on the supported languages.
Step 4 - Provide the redirect URLs to the Auth Resource in Amplify
You can run amplify add auth or amplify update auth to provide the callback API routes as the redirect URLs. See Configure the Auth category for more details. With the above example, you can provide the following redirect URLs:
// redirect signin URI:https://myapp.com/api/auth/sign-in-callback
// redirect signout URI:https://myapp.com/api/auth/sign-out-callbackThis enables Amazon Cognito Hosted UI to support the server-side authentication flows. You may upgrade to the latest Amazon Cognito Managed Login Branding to customize the sign-in and sign-up pages. See Amazon Cognito user pool managed login for more information.
Step 5 - Use Anchor link for initiating server-side authentication flows
Use HTML anchor links to navigate users to the sign-in and sign-up routes. For example:
When an end user clicks on the buttons above, a corresponding server-side authentication flow will be initiated.
Validate user session with the Next.js Middleware
You can use the fetchAuthSession API to check the auth sessions that are attached to the incoming requests in the middleware of your Next.js app to protect your routes. For example:
import { fetchAuthSession } from 'aws-amplify/auth/server';import { NextRequest, NextResponse } from 'next/server';import { runWithAmplifyServerContext } from '@/utils/amplifyServerUtils';
export async function middleware(request: NextRequest) { const response = NextResponse.next();
const authenticated = await runWithAmplifyServerContext({ nextServerContext: { request, response }, operation: async (contextSpec) => { try { const session = await fetchAuthSession(contextSpec); return ( session.tokens?.accessToken !== undefined && session.tokens?.idToken !== undefined ); } catch (error) { console.log(error); return false; } } });
if (authenticated) { return response; }
return NextResponse.redirect(new URL('/sign-in', request.url));}
export const config = { matcher: [ /* * Match all request paths except for the ones starting with: * - api (API routes) * - _next/static (static files) * - _next/image (image optimization files) * - favicon.ico (favicon file) */ '/((?!api|_next/static|_next/image|favicon.ico|sign-in).*)' ]};In this example, if the incoming request is not associated with a valid user session the request will be redirected to the /sign-in route.
Calling Amplify category APIs on the server side
For the Auth, REST APIs, and Storage categories to use Amplify APIs on the server in your Next.js app, you will need to:
- Import the API from the
/serversub path. - Use the
runWithAmplifyServerContexthelper function created by calling thecreateServerRunnerfunction exported from@aws-amplify/adapter-nextjsto call the Amplify API in an isolated server context.
For the GraphQL API category, review Connect to GraphQL API from server-side runtimes.
With Next.js App Router
In React Server Component
Dynamic Rendering
Dynamic rendering is based on a user session extracted from an incoming request.
import { cookies } from 'next/headers';import { getCurrentUser } from 'aws-amplify/auth/server';import { runWithAmplifyServerContext } from '@/utils/amplifyServerUtils';
// This page always dynamically renders per requestexport const dynamic = 'force-dynamic';
export default async function AuthGetCurrentUserServer() { try { const currentUser = await runWithAmplifyServerContext({ nextServerContext: { cookies }, operation: (contextSpec) => getCurrentUser(contextSpec) });
return ( <p>{`Hello, ${currentUser.username}`}</p> ); } catch (error) { console.error(error); return <p>Something went wrong...</p>; }}Static Rendering
Static rendering doesn’t require a user session, so you can specify the nextServerContext parameter as null. This is useful for some use cases, for example, when you are using the Storage API with guest access (if you have enabled it in your backend).
import { getUrl } from 'aws-amplify/storage/server';import Image from 'next/image';import { runWithAmplifyServerContext } from '@/utils/amplifyServerUtils';
// Re-render this page every 60 minutesexport const revalidate = 60 * 60; // in seconds
export default async function StaticallyRenderedPage() { try { const splashUrl = await runWithAmplifyServerContext({ nextServerContext: null, operation: (contextSpec) => getUrl(contextSpec, { key: 'splash.png' }) });
return ( <Image src={splashUrl.url.toString()} alt="Splash Image" width={500} height={500} /> ); } catch (error) { console.error(error); return <p>Something went wrong...</p>; }}In Route Handlers
Take implementing an API route that enables GET /apis/get-current-user.
import { getCurrentUser } from 'aws-amplify/auth/server';import { cookies } from 'next/headers';import { NextResponse } from 'next/server';import { runWithAmplifyServerContext } from '@/utils/amplifyServerUtils';
export async function GET() { const user = await runWithAmplifyServerContext({ nextServerContext: { cookies }, operation: (contextSpec) => getCurrentUser(contextSpec) });
return NextResponse.json({ user });}When you call fetch('/apis/get-current-user') it return a payload that contains the user data for the currently signed-in user.
With Next.js Pages Router
In getServerSideProps
The following example extracts current user data from the request and provides them to a page react component via its props.
export const getServerSideProps: GetServerSideProps = async ({ req, res }) => { const currentUser = await runWithAmplifyServerContext({ nextServerContext: { request: req, response: res }, operation: (contextSpec) => getCurrentUser(contextSpec) });
return { props: { currentUser } };};In getStaticProps
Similar to static rendering with the App Router, you can pass null as the value of the nextServerContext parameter to use the Amplify Storage API with guest access.
export async function getStaticProps() { const splashUrl = await runWithAmplifyServerContext({ nextServerContext: null, operation: (contextSpec) => getUrl(contextSpec, { key: 'splash.png' }) });
return { props: { imageUrl: splashUrl.url.toString() }, revalidate: (splashUrl.expiresAt.getTime() - Date.now()) / 1000 // in seconds };}Supported APIs for Next.js server-side usage
All APIs that support use on the server are exported from the aws-amplify/<category>/server sub paths. You must use these APIs for any server side use cases.
| Category | APIs | Server (Node.js) Amplify Hosting/Vercel | Vercel Edge Runtime (middleware) |
|---|---|---|---|
| Auth | fetchAuthSession | ✅ | ✅ |
| Auth | fetchUserAttributes | ✅ | ✅ |
| Auth | getCurrentUser | ✅ | ✅ |
| API (GraphQL) | generateServerClientUsingCookies | ✅ | |
| API (GraphQL) | generateServerClientUsingReqRes | ✅ | |
| API (REST) | GET | ✅ | |
| API (REST) | POST | ✅ | |
| API (REST) | PUT | ✅ | |
| API (REST) | DEL | ✅ | |
| API (REST) | HEAD | ✅ | |
| API (REST) | PATCH | ✅ | |
| Storage | getUrl | ✅ | |
| Storage | getProperties | ✅ | |
| Storage | list | ✅ | |
| Storage | remove | ✅ | |
| Storage | copy | ✅ |
Migrate from Amplify JavaScript v5
The Amplify JS v5 withSSRContext utility is no longer available with Amplify JS v6. You will need to use the createServerRunner function exported from @aws-amplify/adapter-nextjs to create a runWithAmplifyServerContext function, and use this function to make Amplify API calls on the server side of your Next.js app. For usage examples, see here.