DEV Community

Cover image for Nextjs: Oauth and Credentials authentication with NextAuth - Part 2
m0nm
m0nm

Posted on

Nextjs: Oauth and Credentials authentication with NextAuth - Part 2

Welcome to the second part of NextJs with NextAuth, In the first part we've seen how to integrate Oauth2 authentication to your application, Here is the first part if you haven't seen it

Today we are going to look at how to implement username and password authentication. Let's get started!

If we take a look at NextAuth big list of providers we have a Credentials provider. The Credentials provider allows you to handle signing in with credentials, such as a username and password, domain, or two factor authentication or hardware device.

Credentials provider is used when you have a backend database setup you wish to authenticate against.

The default drawback is that the authenticated users sessions can not persisted in the database. (because the credentials provider uses the JWT strategy, Only other Oauth providers sessions can be stored through a database adapter)

Let's Get Started

create a nextjs app :
npx create-next-app credentials-auth

install NextAuth:
npm i next-auth

inside pages/_app.js add SessionProvider


import { SessionProvider } from "next-auth/react"

export default function App({ Component, pageProps: { session, ...pageProps }}) { 

    return (
        <SessionProvider session={session}> 
            <Component {...pageProps} />
        </SessionProvider> 
     )
    }
Enter fullscreen mode Exit fullscreen mode

And finally add the api route in pages/api/auth/[...nextauth].js

Setting up Credential Provider

Now we're ready to set up the credentials provider, So inside [nextauth].js Add this:

import NextAuth from "next-auth"
import CredentialsProvider from "next-auth/providers/credentials";

export default NextAuth({ 

    // any secret word like: "i am a stegosaurus"
    secret: process.env.SECRET,

    // enabe JWT
    session: {
        strategy: "jwt",
    },

    providers = [

        CredentialsProvider({ 
        // the button text displayed on the sign in form
            name: "Sign In With Credentials",
        })

    ]

})
Enter fullscreen mode Exit fullscreen mode

Adding the credentials fields

Now specify the input fields that would be displayed on the default sign in form

you can use your custom login page as well

    ...
        credentials: {

            username: { 
                            label: "Username", 
                            type: "text", 
                     placeholder:"Enter Your Username..." 
                   },

            password: { 
                            label: "Password", 
                            type: "password", 
                     placeholder:"Enter Your Password..." 
                   }
        }
    ...
Enter fullscreen mode Exit fullscreen mode

Here's how the form looks like

login form

The authorize function

Now we need to setup the authorize function

The authorize function is where we validate the user input against the database records

Inside the authorize function you add authentication logic to look for the user, compare the passwords...

For example:

    ...
        async authorize(credentials, req) { 

            const res = await fetch('www.server.com', {
                method: "post",

                headers: {
                                "Content-Type": "application/json",
                            },

                body: JSON.stringify({
                        username: req.body.username
                        password: req.body.password
                })

            })
            // and then you may or may not get the user 
            const user = await res.json()

        }
    ...
Enter fullscreen mode Exit fullscreen mode

Now the important part: the data you return from the authorize function:

If you return a user object

Then it means the credentials are valid, The returned object will be persisted to the JSON Web Token and the user will be signed in

If you return null

 then an error will be displayed advising the user to check their details.

If you throw an error

the user will be sent to the error page with the error message as a query parameter.

...

async authorize() {

    // if credentials are valid
    if (user) {  
        return user  
    } else {
        return null
    }
}
...
Enter fullscreen mode Exit fullscreen mode

And that's it!

Here is the full code:

import NextAuth from "next-auth"
import CredentialsProvider from "next-auth/providers/credentials";

export default NextAuth({ 

    // any secret word like: "i am a stegosaurus"
    secret: process.env.SECRET,

    // enable JWT
    session: {
        strategy: "jwt",
    },

    providers: [

        CredentialsProvider({ 

            // the button text displayed on the sign in form
            // so this would be: sign in with Credentials
            name: "Credentials",

            // the input fields on the default sign in form
            // you can use your custom login page instead 
            credentials: {

                username: { 
                                label: "Username", 
                                type: "text", 
                         placeholder:"Enter Your Username..." 
                       },

                password: { 
                                label: "Password", 
                                type: "password", 
                         placeholder:"Enter Your Password..." 
                       }
            },

        // The authorize function is where we validate the user input 
        // against the database records
        async authorize(credentials, req) { 

            // Here you add authentication logic: 
            // look for the user, compare the passwords... 
            const res = await fetch('www.server.com', {
                method: "post",

                headers: {
                                "Content-Type": "application/json",
                            },

                body: JSON.stringify({
                        username: req.body.username,
                        password: req.body.password
                })

            })

            // and then you may or may not get the user 
            const user = await res.json()

            // if credentials are valid
            if (user) {  
                    return user  
                } 

            else {
                // if not
                return null;
                }
        }

    })

    ]
})
Enter fullscreen mode Exit fullscreen mode

Conclusion

We've reached the end of this post, Hopefully it was helpful to you. If you liked this post then consider giving me a  ❤️, And don't forget to follow me if you want more of my content!

Till next time, Happy coding!

Top comments (0)