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
Nextjs: Oauth and Credentials authentication with NextAuth
m0nm ・ Mar 21 '22
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>
)
}
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",
})
]
})
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..."
}
}
...
Here's how the form looks like
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()
}
...
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
}
}
...
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;
}
}
})
]
})
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)