<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Louie Heaton</title>
    <description>The latest articles on DEV Community by Louie Heaton (@louieheaton).</description>
    <link>https://dev.to/louieheaton</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1089901%2Fc8545821-8cc9-44b0-86d3-3145e908e87b.jpeg</url>
      <title>DEV Community: Louie Heaton</title>
      <link>https://dev.to/louieheaton</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/louieheaton"/>
    <language>en</language>
    <item>
      <title>NextJS User Login &amp; Registration (AWS Cognito)</title>
      <dc:creator>Louie Heaton</dc:creator>
      <pubDate>Sun, 28 May 2023 21:19:36 +0000</pubDate>
      <link>https://dev.to/louieheaton/nextjs-user-login-registration-aws-cognito-5c07</link>
      <guid>https://dev.to/louieheaton/nextjs-user-login-registration-aws-cognito-5c07</guid>
      <description>&lt;p&gt;The purpose of this project is to build a boilerplate for NextJS which will allow me to quickly start with a base which already has a login and register system built. Sounds great hey! P.S this project will be available as an open source on Github and any contributions are more than welcome!&lt;/p&gt;




&lt;h2&gt;
  
  
  Getting started
&lt;/h2&gt;

&lt;p&gt;To begin with I started by creating just a basic NextJS using the NPX command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx create-next-app next-auth-boilerplate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I created the project using typescript, eslint and left the rest as default. (I'm not using tailwind in this example).&lt;/p&gt;

&lt;p&gt;After doing so I opened up the folder in VS Code, you can also do &lt;code&gt;code next-auth-boilerplate&lt;/code&gt; as well to make it quicker 😉&lt;/p&gt;




&lt;h2&gt;
  
  
  Housekeeping
&lt;/h2&gt;

&lt;p&gt;Of course, we want to make sure that everything is pretty and follows standards in the code so I went ahead and installed prettier, commitlint and husky. (Not going to go into depth about these here for this article but you can view the git repo to view all the config files I setup etc...)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i -D husky @commitlint/cli @commitlint/config-conventional prettier
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  File structure
&lt;/h2&gt;

&lt;p&gt;So the structure I went for, is as follows...&lt;/p&gt;

&lt;p&gt;(I have only included files and folders I have made so config files, package.json files etc.. should be there regardless)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;├── layouts
│   ├── Footer.tsx
│   ├── Head.tsx
│   └── Header.tsx
├── pages
│   ├── _app.tsx
│   ├── _document.tsx
│   ├── register.tsx
│   └── login.tsx
├── styles
│   ├── Global.scss
│   └── Reset.scss
├── utils
│   ├── Global.scss
│   └── Reset.scss
├── public
├── templates
└── .env
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Prepping for AWS Cognito
&lt;/h2&gt;

&lt;p&gt;So I am going to use AWS Cognito to handle the user database. AWS Cognito has a very generous free tier which allows for 50,000 monthly active users for free! Seeing as that is quite a lot, I don't think I'll be paying a single penny on any of my projects for years to come... It's a good, safe option if you are looking for something and just makes it so much easier to build login systems.&lt;/p&gt;

&lt;p&gt;I'm starting off by installing the Amplify SDK..&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i @aws-amplify/ui-react aws-amplify
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After doing this, I am then going to go into my &lt;code&gt;.env&lt;/code&gt; file and add the following variables.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AWS_COGNITO_REGION='{ENTER YOUR REGION e.g eu-west-1}'
AWS_COGNITO_POOL_ID='{ENTER POOL ID}'
AWS_COGNITO_APP_CLIENT_ID='{ENTER CLIENT ID}'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So head on over to Cognito and setup a user pool. Notes on each of these variables...&lt;/p&gt;

&lt;p&gt;AWS_COGNITO_REGION - You should be able to see this in the pool ID in the overview section of the user pool.&lt;/p&gt;

&lt;p&gt;AWS_COGNITO_POOL_ID - This should be visible after clicking on your user pool in the overview.&lt;/p&gt;

&lt;p&gt;AWS_COGNITO_APP_CLIENT_ID - You can find this in your user pool overview under the tab "App integration" and scroll down to the bottom and it should be there.&lt;/p&gt;

&lt;p&gt;Setting up a Cognito User Pool for the first time is a struggle, but there are plenty of guides from AWS to assist with this. If you want me to adapt this tutorial to include setting up Cognito, let me know in the comments!&lt;/p&gt;

&lt;p&gt;We just need to do a slight change to the &lt;code&gt;next.config.js&lt;/code&gt; file to include your ENV to make it available where required. In your module exports add the following...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;env: {
    AWS_COGNITO_REGION: process.env.AWS_COGNITO_REGION,
    AWS_COGNITO_POOL_ID: process.env.AWS_COGNITO_POOL_ID,
    AWS_COGNITO_APP_CLIENT_ID: process.env.AWS_COGNITO_APP_CLIENT_ID,
},
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, I'm going to just setup the Amplify config... Create a file in &lt;code&gt;/utils/aws/Amplify.ts&lt;/code&gt; and then copy in the following code to construct a Amplify Auth instance...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Amplify } from 'aws-amplify';

Amplify.configure({
    Auth: {
        region: process.env.AWS_COGNITO_REGION,
        userPoolId: process.env.AWS_COGNITO_POOL_ID,
        userPoolWebClientId: process.env.AWS_COGNITO_APP_CLIENT_ID,
    },
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and then go into &lt;code&gt;/pages/_app.tsx&lt;/code&gt; and add an import statement at the top as follows...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import '@/utils/aws/Amplify';
import type { AppProps } from 'next/app';

export default function App({ Component, pageProps }: AppProps) {
    return &amp;lt;Component {...pageProps} /&amp;gt;;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Creating the login/register page
&lt;/h2&gt;

&lt;p&gt;Next is to create the login and signup page. In &lt;code&gt;/pages/login.tsx&lt;/code&gt; copy in this premade code from AWS with a few modifications...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Authenticator, useAuthenticator } from '@aws-amplify/ui-react';
import '@aws-amplify/ui-react/styles.css';
import { Auth } from 'aws-amplify';
import { useRouter } from 'next/router';
import { useEffect } from 'react';

const Login = () =&amp;gt; {
    const router = useRouter();
    const { user } = useAuthenticator((context) =&amp;gt; [context.user]);

    useEffect(() =&amp;gt; {
        const checkUser = async () =&amp;gt; {
            try {
                const user = await Auth.currentAuthenticatedUser();
                if (user) {
                    router.push('/dashboard');
                }
            } catch (error) {
                // User is not logged in
            }
        };
        checkUser();
    }, [router, user]);

    return &amp;lt;Authenticator /&amp;gt;;
};

export default Login;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Creating an authentication HOC
&lt;/h2&gt;

&lt;p&gt;Now we are going to go ahead and create HOC... (Basically, just a wrapper).&lt;/p&gt;

&lt;p&gt;Create a file as such &lt;code&gt;/utils/withAuth.tsx&lt;/code&gt; and copy and paste the following code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useAuthenticator } from '@aws-amplify/ui-react-core';
import { Auth } from 'aws-amplify';
import { useRouter } from 'next/router';
import { useEffect } from 'react';

const withAuth = (WrappedComponent: any) =&amp;gt; {
    const WrapperComponent = (props: any) =&amp;gt; {
        const router = useRouter();
        const { user } = useAuthenticator((context) =&amp;gt; [context.user]);

        useEffect(() =&amp;gt; {
            const checkAuth = async () =&amp;gt; {
                try {
                    await Auth.currentAuthenticatedUser();
                } catch (err) {
                    router.push('/login');
                }
            };

            checkAuth();
        }, [router, user]);

        return &amp;lt;WrappedComponent {...props} /&amp;gt;;
    };

    return WrapperComponent;
};

export default withAuth;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Basically, what we are doing here is adding a default useEffect to monitor if the users status changes, i.e logged in/logged out and then redirect them to the login page if they need to log in again. We are using the Amplify Authenticator context here to manage states.&lt;/p&gt;




&lt;h2&gt;
  
  
  Add Authenticator Provider Context
&lt;/h2&gt;

&lt;p&gt;Talking about context's, we need to wrap the Authenticator Provider to the &lt;code&gt;/pages/_app.tsx&lt;/code&gt; file. And update to look like the following code 👀..&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import '@/utils/aws/Amplify';
import { Authenticator } from '@aws-amplify/ui-react';
import type { AppProps } from 'next/app';

export default function App({ Component, pageProps }: AppProps) {
    return (
        &amp;lt;Authenticator.Provider&amp;gt;
            &amp;lt;Component {...pageProps} /&amp;gt;
        &amp;lt;/Authenticator.Provider&amp;gt;
    );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Protected pages
&lt;/h2&gt;

&lt;p&gt;Finally, all you have to do now is add all the protected pages you wish but make sure that your export function has the &lt;code&gt;withAuth()&lt;/code&gt; HOC wrapped around it! Here's an example of the dashboard...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import withAuth from '@/utils/withAuth';
import { Auth } from 'aws-amplify';

const Dashboard = () =&amp;gt; {
    return (
        &amp;lt;div&amp;gt;
            &amp;lt;h1&amp;gt;Dashboard Page&amp;lt;/h1&amp;gt;
            &amp;lt;button onClick={() =&amp;gt; Auth.signOut()}&amp;gt;Sign out&amp;lt;/button&amp;gt;
        &amp;lt;/div&amp;gt;
    );
};

export default withAuth(Dashboard);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Find the code on Github :)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/by-Digital/Sphinx/tree/auth-tutorial"&gt;Sphinx ByDigital&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hope you enjoyed 🎉&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>node</category>
      <category>tutorial</category>
      <category>aws</category>
    </item>
  </channel>
</rss>
