DEV Community

Cover image for The Complete Guide to Next.js Authentication

The Complete Guide to Next.js Authentication

Nader Dabit on September 21, 2020

Cover image by Kai Pilger In this guide you will learn how to implement authentication in a Next.js app. I will cover client authentication, aut...
Collapse
 
justincy profile image
Justin • Edited

UPDATE: support for redirects in getServerSideProps was released in v10. See the docs for more information about redirects: nextjs.org/docs/basic-features/dat...

OLD: FYI, redirects in getServerSideProps aren't 100% supported and a side-effect of that is they currently cause a full page reload. There's an RFC for redirects to be fully supported.

Collapse
 
wataruoguchi profile image
Wataru Oguchi

For a workaround, I found this comment.

I made the catch to return the following snippet, and I removed res.writeHead(302, { Location: '/profile' }) and res.end().

return {
  redirect: {
    destination: "/profile",
    statusCode: 302,
  },
};
Enter fullscreen mode Exit fullscreen mode
Collapse
 
paragbaxi profile image
Parag Baxi

I can't even get it to work with the code above.

Collapse
 
jamescarr profile image
James Carr

This was really great and easy to follow, thanks for the tutorial!

One small bit of feedback would be to change the check-user.js api route to use a non-200 statusCode for an unauthenticated user.

export default async (req, res) => {
  const { Auth } = withSSRContext({ req })
  try {
    const user = await Auth.currentAuthenticatedUser()
    res.json({ user: user.username })
  } catch (err) {
    res.statusCode = 401
    res.json({ user: null })
  }
}
Enter fullscreen mode Exit fullscreen mode
Collapse
 
oahmaro profile image
Osama Ahmaro

Do i have to deploy the app with serverless framework? can i just use amplify to deploy nextjs app, and what about deploying API routes?

Collapse
 
michael_webdev profile image
Michael B.

I'm currently working on the same stack and have the exact same question!

Collapse
 
dabit3 profile image
Nader Dabit

Hi Osama & Michael,

Amplify is releasing SSR support sometime soon, but for now if you need SSR or API routes on AWS you need to use the Serverless Framework. If you are running a completely static Next.js build, you can use the Amplify hosting service.

docs.amplify.aws/guides/hosting/ne...

Thread Thread
 
michael_webdev profile image
Michael B.

Really glad to know it will be available on Amplify! I have my frontend on Vercel right now but I will be happy to move everything on Amplify in the foreseeable future.

Collapse
 
gregfullard profile image
Greg Fullard

Great article and thanks a lot. I've been running into some issues with the protected server side rendered page.

When trying to access the page the whole app crashes with the following in the console:

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
Enter fullscreen mode Exit fullscreen mode

I tested from many angles, and even when cloning your source code I ran into the issue.

There are some discussions on the Next.js GitHub (github.com/vercel/next.js/discussi...) on the same topic. Not sure if it's a Next.js version thing

For now, I'll continue to dig for a better understanding of what's going on.

Collapse
 
sotomaque profile image
sotomaque

same. any luck with this bug?

Collapse
 
ahmadawais profile image
Ahmad Awais ⚡️ • Edited

Excellent intro, Nader. I've just switched to npm@7 CLI and I'm having issues installing the dependencies in the second step.

This works fine on npm v6.14.8

error

npm ERR! code ERESOLVE
npm ERR! ERESOLVE unable to resolve dependency tree
npm ERR!
npm ERR! Found: react@16.14.0
npm ERR! node_modules/react
npm ERR!   react@"16.14.0" from the root project
npm ERR!
npm ERR! Could not resolve dependency:
npm ERR! peer react@"16.13.1" from react-native@0.63.3
npm ERR! node_modules/react-native
npm ERR!   peer react-native@">=0.56" from react-native-get-random-values@1.5.0
npm ERR!   node_modules/@aws-sdk/middleware-retry/node_modules/react-native-get-random-values
npm ERR!     react-native-get-random-values@"^1.4.0" from @aws-sdk/middleware-retry@1.0.0-gamma.7
npm ERR!     node_modules/@aws-sdk/middleware-retry
npm ERR!       @aws-sdk/middleware-retry@"1.0.0-gamma.7" from @aws-sdk/client-cognito-identity@1.0.0-gamma.8
npm ERR!       node_modules/@aws-sdk/client-cognito-identity
npm ERR!       2 more (@aws-sdk/client-lex-runtime-service, @aws-sdk/client-s3)
npm ERR!
npm ERR! Fix the upstream dependency conflict, or retry
npm ERR! this command with --force, or --legacy-peer-deps
npm ERR! to accept an incorrect (and potentially broken) dependency resolution.
npm ERR!
Enter fullscreen mode Exit fullscreen mode
Collapse
 
geraudi profile image
geraudi

Hi Nader, Thanks for this great tutorial.
For now, we need have to add ssr configuration in all pages/* as mentioned in Amplify documentation :

Once vercel/next.js#16977 is resolved, you can hoist Amplify.configure into pages/_app.js. Until then, be sure that all pages/* run Amplify.configure({ ...awsExports, ssr: true })

Collapse
 
ibrahimcesar profile image
Ibrahim Cesar

Great content as usual! Waiting for part 2!

Collapse
 
dabit3 profile image
Nader Dabit

Thanks Ibrahim!

Collapse
 
francisco profile image
Francisco M. Delgado • Edited

@dabit currently trying to deploy via the cli and I get this error

pages with `getServerSideProps` can not be exported

. Does anyone have a workaround? The app works as expected when developing locally.

Collapse
 
eusholli profile image
Geoff Hollingworth

Hi I have tried to add Facebook as a federated identity provider and I also want to carry on using the default withAuthenticator and associated UI. The first strange thing I notice is that there is a new button a the top of my login panel but it says "Sign in with AWS". When I click I get taken to a new login screen with Facebook at the top. When I try to login in though there is a URL error in the debug on the following API call:
cognito-identity.us-east-1.amazona...
Response error: 400
{"__type":"ValidationException","message":"1 validation error detected: Value '{cognito-idp.us-east-1.amazonaws.com/us-east-1_XXXXX=}' at 'logins' failed to satisfy constraint: Map value must satisfy constraint: [Member must have length less than or equal to 50000, Member must have length greater than or equal to 1]"}

I appreciate any directions on how to start debugging. I have tried googling but cannot find where to start. I can see the user has been added to the AWS Cognito user pool in AWS Console. I upload some screen captures of the initial flow.
dev-to-uploads.s3.amazonaws.com/up...
dev-to-uploads.s3.amazonaws.com/up...

Collapse
 
uuykay profile image
William Kuang

I have this exact same problem!

Collapse
 
eherms profile image
eherms

I'm getting an error:

TypeError: Object(...) is not a function

pointing to the code below.

export async function getServerSideProps(context) {

372 | const { Auth } = withSSRContext(context)
| ^
373 | try {
374 | const user = await Auth.currentAuthenticatedUser()
375 | console.log('user: ', user)

Any suggestions?

Collapse
 
jerocosio profile image
Jerónimo Cosío • Edited

Amazing guidee, thanks for posting this! Any chance that for the second part you could add some examples around handling data based on roles?

Collapse
 
marcostreng profile image
Marco Streng

Great post!

I am still struggling with a problem: If a protect a route on server-side the request to Cognito (Auth.currentAuthenticatedUser()) takes about 400-500ms. Doing the same on client-side the request takes only < 15ms. Both ways are implemented like in this example.

Maybe someone has got an idea or made a similar experience?

Collapse
 
vfulco profile image
Vincent Fulco (It / It's)

Really strange, trying to hit the 'protected' page reroutes me back to 'profile' even though all my authenticated info pops up in the console and I can reach the 'protected-client-route'. Tried this a few times and looking at the code.

Collapse
 
szymonkochanski profile image
Szymon Kochanski

A small suggestion for importing emotion:

npm i @emotion/css
Enter fullscreen mode Exit fullscreen mode

Then, to use it:

import { css } from '@emotion/css'
Enter fullscreen mode Exit fullscreen mode
Collapse
 
vfulco profile image
Vincent Fulco (It / It's)

Thanks for this mention. For some reason, I couldn't get it to work but did so using "import { css } from '@emotion/react'; "

Collapse
 
keefdrive profile image
Keerthi

Thanks..I have just started to learn about next.js, I was looking for something like this

Collapse
 
rpostulart profile image
rpostulart

Great Job have you done again :)

Collapse
 
rashmivabbigeri profile image
Rashmi Abbigeri

where can i find part 2 ?

Collapse
 
jayraj profile image
Jayraj-R

on running "amplify init", I get the following ERROR "'amplify' is not recognized as an internal or external command,
operable program or batch file."

Collapse
 
thomassalty profile image
Thomas Soos

You probably haven't installed the CLI yet...

npm i -g @aws-amplify/cli

Collapse
 
charanduggina profile image
charanduggina

Hey nader great work ! can someone post how to assign roles to user and authenticate using amazon amplify in nextjs, thanks!