Next.js 14: Cách Sử Dụng Next Auth cơ bản để xác thực
Next.js 14: Cách Sử Dụng Next Auth cơ bản để xác thực
Bạn đã bao giờ gặp khó khăn trong việc xác thực người dùng trên ứng dụng web của mình? Bạn có muốn tìm hiểu về cách sử dụng Next Auth trong Next.js 14 để giải quyết vấn đề này một cách dễ dàng và nhanh chóng? Nếu câu trả lời là có, thì bạn đã đến đúng nơi!
Trong bài viết này, chúng tôi sẽ giới thiệu về Next Auth và cách sử dụng nó trong Next.js 14 để xác thực người dùng. Bạn sẽ được tìm hiểu về các khổ đau và vấn đề liên quan đến việc xác thực, cũng như những lợi ích mà Next Auth có thể mang lại cho ứng dụng web của bạn.
Hãy tiếp tục đọc để khám phá thêm về Next.js 14 và Next Auth, và cách chúng có thể giúp bạn giải quyết các vấn đề xác thực người dùng một cách hiệu quả.
Takeaways:
- Next.js 14 là một phiên bản mới nhất của framework Next.js, mang lại nhiều cải tiến và tính năng mới.
- Next Auth là một thư viện xác thực mạnh mẽ, giúp bạn xác thực người dùng một cách đơn giản và linh hoạt.
- Việc sử dụng Next Auth trong Next.js 14 sẽ giúp bạn tiết kiệm thời gian và công sức trong việc xây dựng hệ thống xác thực trong ứng dụng web của mình.
Hãy truy cập nextjs 14 next auth để tìm hiểu thêm về cách sử dụng Next Auth trong Next.js 14 và làm cho việc xác thực người dùng trở nên dễ dàng hơn bao giờ hết.
Giới thiệu về Next.js 14 và Next Auth
Next.js 14 - Framework Next.js tiên tiến hơn
Next.js 14 là phiên bản mới nhất của framework Next.js, được phát triển để cung cấp một trải nghiệm phát triển web tiên tiến hơn cho các nhà phát triển. Với Next.js 14, nhà phát triển có thể tận dụng các tính năng như tạo trang tĩnh, tối ưu hóa SEO, tải trang nhanh, và nhiều hơn nữa. Với việc hỗ trợ TypeScript và API Routes, Next.js 14 là một lựa chọn mạnh mẽ cho việc phát triển ứng dụng web hiệu suất cao.
Next Auth - Thư viện xác thực người dùng cho Next.js
Next Auth là một thư viện xác thực người dùng dễ sử dụng và mạnh mẽ cho Next.js. Với Next Auth, việc xây dựng hệ thống xác thực và đăng nhập cho ứng dụng web trở nên đơn giản hơn bao giờ hết. Thư viện này hỗ trợ nhiều phương thức xác thực như đăng nhập bằng email và mật khẩu, đăng nhập bằng mạng xã hội, và nhiều hơn nữa. Next Auth cung cấp tích hợp dễ dàng với các nhà cung cấp xác thực phổ biến như Google, Facebook, và Twitter.
Tóm lại, Next.js 14 và Next Auth cung cấp cho nhà phát triển một bộ công cụ mạnh mẽ để phát triển ứng dụng web hiệu suất cao với khả năng xác thực người dùng dễ dàng.
Cài đặt Next.js 14 và Next Auth
Cài đặt Next.js 14 bằng npm
Next.js là một framework JavaScript phía máy chủ được sử dụng để xây dựng các ứng dụng web hiệu suất cao. Phiên bản Next.js 14 là phiên bản mới nhất và đi kèm với nhiều cải tiến và tính năng mới. Để cài đặt Next.js 14, bạn có thể sử dụng npm.
npm install next@14
Sau khi cài đặt thành công, bạn có thể bắt đầu sử dụng Next.js 14 để xây dựng ứng dụng web của mình.
Tạo ứng dụng Next.js 14
Mở terminal và chạy lệnh sau để tạo một ứng dụng Next.js 14 mới.
npx create-next-app@latest my-nextjs-app
my-nextjs-app
là tên thư mục cho ứng dụng của bạn. Bạn có thể đổi tên nếu muốn.
Di chuyển vào thư mục ứng dụng
Di chuyển vào thư mục ứng dụng với lệnh:
cd my-nextjs-app
Cài đặt Next Auth bằng npm
Next Auth là một thư viện xác thực phổ biến cho Next.js. Nó cung cấp các phương pháp xác thực đơn giản và linh hoạt như xác thực qua email, xác thực qua mạng xã hội và xác thực qua API. Để cài đặt Next Auth, bạn có thể sử dụng npm.
npm install next-auth
Sau khi cài đặt thành công, bạn có thể sử dụng Next Auth để xác thực người dùng trong ứng dụng Next.js của mình.
Việc cài đặt Next.js 14 và Next Auth sẽ giúp bạn xây dựng các ứng dụng web hiệu suất cao và cung cấp các phương pháp xác thực linh hoạt cho người dùng. Với Next.js 14, bạn sẽ có các tính năng mới và cải tiến để tăng cường trải nghiệm người dùng. Next Auth sẽ giúp bạn quản lý việc xác thực và bảo mật trong ứng dụng của mình một cách dễ dàng và tiện lợi.
Chạy ứng dụng
Chạy ứng dụng Next.js với lệnh:
npm run dev
Ứng dụng sẽ chạy ở http://localhost:3000/
. Bạn có thể mở trình duyệt và kiểm tra ứng dụng của mình.
Sửa lại trang
Bây giờ chúng ta sẽ sửa lại một chút giao diện trang chủ
'use client'
import Link from "next/link";
export default function Home() {
return (
<main className="flex min-h-screen flex-col items-center justify-between p-24">
<div className="z-10 max-w-5xl w-full items-center justify-between font-mono text-sm lg:flex">
<p className="fixed left-0 top-0 flex w-full justify-center border-b border-gray-300 bg-gradient-to-b from-zinc-200 pb-6 pt-8 backdrop-blur-2xl dark:border-neutral-800 dark:bg-zinc-800/30 dark:from-inherit lg:static lg:w-auto lg:rounded-xl lg:border lg:bg-gray-200 lg:p-4 lg:dark:bg-zinc-800/30">
Hi, <code className="font-mono font-bold">Guest</code>
</p>
<div className="fixed bottom-0 left-0 flex h-48 w-full items-end justify-center bg-gradient-to-t from-white via-white dark:from-black dark:via-black lg:static lg:h-auto lg:w-auto lg:bg-none">
<Link
className="pointer-events-none flex place-items-center gap-2 p-8 lg:pointer-events-auto lg:p-0"
href="/login"
>
Login
</Link>
</div>
</div>
</main>
);
}
Cấu hình Next Auth
Tạo một file cấu hình cho Next Auth
Để bắt đầu sử dụng Next Auth, chúng ta cần tạo một file cấu hình để thiết lập các thông tin cần thiết. Trong file này, chúng ta có thể thiết lập các cài đặt liên quan đến xác thực và quản lý người dùng.
Tại thư mục app, các bạn tạo file cấu hình theo đường dẫn /app/api/auth/[...nextauth]/route.ts
import NextAuth from "next-auth"
const handler = NextAuth({})
export { handler as GET, handler as POST }
Thiết lập thông tin xác thực (providers)
Next Auth hỗ trợ nhiều nhà cung cấp thông tin xác thực như Google, Facebook, GitHub, và nhiều hơn nữa. Chúng ta có thể cấu hình các nhà cung cấp này trong file cấu hình bằng cách cung cấp các thông tin như clientId
, clientSecret
, và scope
.
Trong bài viết này, chúng ta sẽ xác thực theo kiểu Credential
, nghĩa là các bạn có thể xác thực tuỳ ý như là xác thực bằng email và password, đó có thể là một service backend dùng để login và có trả về access token hoặc các thông tin khác của user.
Trong file route.ts, sẽ thiết lập như sau
import NextAuth from "next-auth"
import Credentials from "next-auth/providers/credentials"
const handler = NextAuth({
providers: [
Credentials({
name: 'Credentials',
credentials: {},
async authorize(credentials, req) {
const { email, password } = credentials as any
if (email === 'user@lahotech.com' && password === '123456') {
return { id: 12345679, email, name: 'User', access_token: 'access_token' } as any
}
throw new Error("Invalid email or password")
// Có thể gọi tới api login ở đây.
// Example:
// const res = await fetch("/your/endpoint", {
// method: 'POST',
// body: JSON.stringify(credentials),
// headers: { "Content-Type": "application/json" }
// })
// const user = await res.json()
// if (res.ok && user) {
// return user
// }
},
})
],
})
export { handler as GET, handler as POST }
Ở đây chúng ta dùng provider là Credentials
. Sau đây mình sẽ giải thích sơ qua đoạn code trên:
name
: tên mô tả của provider Credentialscredentials
: một đối tượng dùng để xác thực, ở đây mình để trống vì không cần. Mình sẽ tạo trang login riêng.- Hàm
authorize
: Xử lý xác minh thông tin đăng nhập và ủy quyền người dùng
Trong hàm authorize
mình lấy thông tin email, password từ đối tượng credentials
. Sau đó mình giả định nếu email, password đúng như thông tin mình hardcode thì sẽ trả về một đối tượng có các thuộc tính như code ở trên. Các bạn có thể gọi api login tới backend service ở phần này, mình có để comment ví dụ ở dưới.
Thiết lập các tùy chọn xác thực khác (options)
Ngoài các thông tin cơ bản về xác thực, chúng ta còn có thể thiết lập các tùy chọn khác như callbacks
và pages
, session
. Các callbacks
cho phép chúng ta xử lý các sự kiện liên quan đến xác thực, trong khi pages
cho phép tùy chỉnh các trang liên quan đến xác thực, còn session
sẽ giúp chúng ta thiết lập khoảng thời gian mà phiên đăng nhập đó tồn tại cũng như phương thức để lưu user session
(mặc định là jwt
)
Các bạn thiết lập như dưới đây:
import NextAuth from "next-auth"
import Credentials from "next-auth/providers/credentials"
const handler = NextAuth({
providers: [
Credentials({
name: 'Credentials',
credentials: {},
async authorize(credentials, req) {
const { email, password } = credentials as any
if (email === 'user@lahotech.com' && password === '123456') {
return { id: 12345679, email, name: 'User', access_token: 'access_token' } as any
}
throw new Error("Invalid email or password")
// Có thể gọi tới api login ở đây.
// Example:
// const res = await fetch("/your/endpoint", {
// method: 'POST',
// body: JSON.stringify(credentials),
// headers: { "Content-Type": "application/json" }
// })
// const user = await res.json()
// if (res.ok && user) {
// return user
// }
},
})
],
callbacks: {
async session({ session, token }) {
session.user = token as any
return session
},
async jwt({ token, user}) {
// Kiểm tra nếu tồn tại user thì gán đối tượng user vô token, để qua callback session gán đối tượng session.user
if (user) {
token = { ...token, ...user }
}
return token
}
},
session: {
strategy: "jwt", // Phương thức để lưu user session
maxAge: 7 * 24 * 60 * 60, // 7 days - neu khong khai bao o day thi no se lay maxAge trong jwt.maxAge
},
secret: process.env.NEXT_PUBLIC_NEXTAUTH_SECRET, // Mã secret để generate jwt token, có thể để mặc định không cần khai báo cũng được.
pages: {
signIn: '/login', // Đây là trang login của mình, chúng ta sẽ custom trang này ở phần tiếp theo
},
})
export { handler as GET, handler as POST }
Callback jwt
sẽ được gọi trước callback session
. Và ở trong callback jwt
, đối tượng user
sẽ tồn tại trong lần đầu tiên khi đăng nhập session
mới, trong những lần gọi tiếp theo thì chỉ còn đối tượng token
tồn tại. Và đối tượng token sẽ được truyền qua callback session
, nghĩa là những gì bạn thêm vào đối tượng token
ở jwt callback
sẽ tồn tại trong đối tượng token
ở session callbac
k
Next Auth cung cấp một cách dễ dàng để xây dựng chức năng xác thực trong ứng dụng Next.js của bạn. Bằng cách sử dụng cấu hình Next Auth, chúng ta có thể nhanh chóng thiết lập các nhà cung cấp xác thực và tùy chỉnh các tùy chọn xác thực khác một cách linh hoạt. Điều này giúp tiết kiệm thời gian và công sức trong việc xây dựng tính năng xác thực trong ứng dụng của chúng ta.
Đăng nhập người dùng
Tạo trang đăng nhập người dùng
Đăng nhập người dùng là quá trình cho phép người dùng truy cập vào tài khoản đã đăng ký trên hệ thống. Trang đăng nhập người dùng cung cấp một giao diện đơn giản và an toàn để người dùng nhập thông tin đăng nhập như email và mật khẩu. Sau khi nhập thông tin đúng, người dùng sẽ được chuyển hướng đến trang chính và có quyền truy cập vào các tính năng và dịch vụ của ứng dụng.
Tại thư mục app
chúng ta tạo thêm một thư mục có tên là login
và trong thư mục này tạo cho mình file page.tsx
có nội dung như sau
'use client'
import { SignInResponse, signIn } from 'next-auth/react'
import React, { useState } from 'react'
export default function Login() {
const [email, setEmail] = useState('')
const [password, setPassword] = useState('')
return (
<div className="flex min-h-full flex-col justify-center px-6 py-12 lg:px-8">
<div className="sm:mx-auto sm:w-full sm:max-w-sm">
<h2 className="mt-10 text-center text-2xl font-bold leading-9 tracking-tight text-white">Sign in to your account</h2>
</div>
<div className="mt-10 sm:mx-auto sm:w-full sm:max-w-sm">
<div className="space-y-6">
<div>
<label htmlFor="email" className="block text-sm font-medium leading-6 text-white">Email address</label>
<div className="mt-2">
<input id="email" onChange={(e) => setEmail(e.target.value)} name="email" type="email" autoComplete="email" required className="p-2 block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6" />
</div>
</div>
<div>
<div className="flex items-center justify-between">
<label htmlFor="password" className="block text-sm font-medium leading-6 text-white">Password</label>
</div>
<div className="mt-2">
<input id="password" onChange={(e) => setPassword(e.target.value)} name="password" type="password" autoComplete="current-password" required className="p-2 block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6" />
</div>
</div>
<div>
<button onClick={onSubmitLogin} className="flex w-full justify-center rounded-md bg-indigo-600 px-3 py-1.5 text-sm font-semibold leading-6 text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600">Sign in</button>
</div>
</div>
</div>
</div>
)
}
Trên trang chủ các bạn bấm vào login thì sẽ ra trang login như dưới đây:
Xử lý đăng nhập người dùng
Chúng ta sẽ xử lý đăng nhập bằng function signIn
của Next Auth, nó là một Client API. Function này cần truyền vô tham số đầu tiên là tên của provider
, ở đây chúng ta dùng credentials
nên sẽ truyền vô tham số đầu tiên là credentials
, tham số thứ 2 là options, là 2 field email và password mà chúng ta dùng để đăng nhập cùng với tuỳ chọn redirect
là false
.
Async function này sẽ trả về một đối tượng SignInResponse
hoặc undefined
, nếu đối tượng này trả về thuộc tính ok
là true
thì nghĩa là đã đăng nhập thành công. Các bạn có thể Ctrl click vô đối tượng SignInResponse
này để xem các thuộc tính còn lại của nó.
Dưới đây là đoạn code handle đăng nhập, nếu đăng nhập thành công thì sẽ chuyển về trang home
'use client'
import { SignInResponse, signIn } from 'next-auth/react'
import { useRouter } from 'next/navigation'
import React, { useState } from 'react'
export default function Login() {
const router = useRouter()
const [email, setEmail] = useState('')
const [password, setPassword] = useState('')
const onSubmitLogin = async () => {
try {
await signIn('credentials', {
email,
password,
redirect: false,
}).then((res: SignInResponse | undefined) => {
if (res?.ok) {
router.push('/')
}
}).catch(error => console.log('error', error))
} catch (error) {
console.log('error - ', error)
}
}
return (
...
)
}
Hiển thị tên user đã đăng nhập trên trang chủ
Bây giờ, khi đã đăng nhập thành công rồi thì làm sao chúng ta có thể lấy thông tin user đã đăng nhập? Câu trả lời ở đây là chúng ta sẽ dùng một Client API mà Next Auth cũng cấp để thực hiện việc này. Client API này là useSession()
, vì nó là một Client API nên chúng tra sẽ thêm 'use client' ở trên đầu file.
Các bạn mở lại file page.tsx
trong app/page.tsx
'use client'
import {signOut, useSession} from "next-auth/react";
import Link from "next/link";
import {useRouter} from "next/navigation";
export default function Home() {
const router = useRouter()
const {data: session} = useSession()
return (
<main className="flex min-h-screen flex-col items-center justify-between p-24">
<div className="z-10 max-w-5xl w-full items-center justify-between font-mono text-sm lg:flex">
<p className="fixed left-0 top-0 flex w-full justify-center border-b border-gray-300 bg-gradient-to-b from-zinc-200 pb-6 pt-8 backdrop-blur-2xl dark:border-neutral-800 dark:bg-zinc-800/30 dark:from-inherit lg:static lg:w-auto lg:rounded-xl lg:border lg:bg-gray-200 lg:p-4 lg:dark:bg-zinc-800/30">
Hi, <code className="font-mono font-bold">{!session?.user ? 'Guest' : session.user.name}</code>
</p>
<div className="fixed bottom-0 left-0 flex h-48 w-full items-end justify-center bg-gradient-to-t from-white via-white dark:from-black dark:via-black lg:static lg:h-auto lg:w-auto lg:bg-none">
{!session ? <Link
className="pointer-events-none flex place-items-center gap-2 p-8 lg:pointer-events-auto lg:p-0"
href="/login"
>
Login
</Link> : <button
onClick={handleLogout}
className="pointer-events-none flex place-items-center gap-2 p-8 lg:pointer-events-auto lg:p-0"
>
Logout
</button>}
</div>
</div>
</main>
);
}
useSession() sẽ trả về một đối tượng có 2 thuộc tính là data và status. Ở đây chúng ta sẽ quan tâm tới thuộc tính data. Thuộc tính data này có thể nhận ba giá trị: Session
, undefined
, hoặc null
:
undefined
: Khi chưa có session nào được đăng nhập, data sẽ làundefined
.null
: Nếu việc lấy session thất bại, data sẽ lànull
.Session
: Nếu thành công, data sẽ là một đối tượngSession
chứa thông tin về session hiện tại của user.
Ở dòng code thứ 16: {!session?.user ? 'Guest' : session.user.name}
sẽ kiểm tra xem nếu như không có session thì sẽ hiển thị là Guest, còn ngược lại thì hiển thị tên user đã đăng nhập.
Xử lý đăng xuất
Để xử lý việc đăng xuất user thì cúng ta cũng sẽ dùng một Client API đó là signOut
. Chúng ta sẽ tạop một function là handleLogout
sau đó gắn cho sự kiện onClick cho button. Khi user click vào sẽ gọi tới nào này thì khi đăng xuất thành công sẽ chuyển về trang home.
Dưới đây là code xử lý:
'use client'
import {signOut, useSession} from "next-auth/react";
import Link from "next/link";
import {useRouter} from "next/navigation";
export default function Home() {
const router = useRouter()
const {data: session} = useSession()
const handleLogout = () => {
signOut({redirect: false})
.then(() => router.push('/'))
.catch((err) => console.log(err))
}
return (
<main className="flex min-h-screen flex-col items-center justify-between p-24">
<div className="z-10 max-w-5xl w-full items-center justify-between font-mono text-sm lg:flex">
<p className="fixed left-0 top-0 flex w-full justify-center border-b border-gray-300 bg-gradient-to-b from-zinc-200 pb-6 pt-8 backdrop-blur-2xl dark:border-neutral-800 dark:bg-zinc-800/30 dark:from-inherit lg:static lg:w-auto lg:rounded-xl lg:border lg:bg-gray-200 lg:p-4 lg:dark:bg-zinc-800/30">
Hi, <code className="font-mono font-bold">{!session?.user ? 'Guest' : session.user.name}</code>
</p>
<div
className="fixed bottom-0 left-0 flex h-48 w-full items-end justify-center bg-gradient-to-t from-white via-white dark:from-black dark:via-black lg:static lg:h-auto lg:w-auto lg:bg-none">
{!session ? <Link
className="pointer-events-none flex place-items-center gap-2 p-8 lg:pointer-events-auto lg:p-0"
href="/login"
>
Login
</Link> : <button
onClick={handleLogout}
className="pointer-events-none flex place-items-center gap-2 p-8 lg:pointer-events-auto lg:p-0"
>
Logout
</button>}
</div>
</div>
</main>
);
}
Tổng kết về việc sử dụng Next.js 14 và Next Auth
Các lợi ích của việc sử dụng Next.js 14 và Next Auth
Next.js 14 là một trong những phiên bản mới nhất của Next.js framework, mang đến những cải tiến vượt trội về hiệu suất và trải nghiệm người dùng. Next.js cung cấp một cách tiếp cận hiện đại và dễ dàng trong việc xây dựng ứng dụng web, với khả năng xử lý tốt trong việc render trên phía máy chủ và phía khách hàng.
Next Auth là một thư viện xác thực mạnh mẽ dựa trên Next.js, giúp việc xây dựng hệ thống xác thực và quản lý người dùng trở nên dễ dàng hơn. Với Next Auth, việc tích hợp các phương thức xác thực như OAuth, JWT, hoặc xác thực bằng email và mật khẩu (credentials) trở nên đơn giản và tiện lợi.
Các khó khăn khi sử dụng Next Auth
Tuy nhiên, việc sử dụng Next Auth cũng đôi khi gặp phải một số khó khăn. Đầu tiên, việc cấu hình và tùy chỉnh Next Auth có thể đòi hỏi một số kiến thức về xác thực và quản lý người dùng. Ngoài ra, việc xử lý lỗi và gỡ rối cũng có thể gặp phải một số thách thức.
Kết luận
Next.js 14 và Next Auth là hai công nghệ mạnh mẽ và hữu ích trong việc xây dựng ứng dụng web. Tuy nhiên, việc sử dụng Next Auth có thể gặp phải một số khó khăn, nhưng các lợi ích mà nó mang lại vẫn là đáng giá. Hi vọng những thông tin trên sẽ giúp bạn hiểu rõ hơn về việc sử dụng Next.js 14 và Next Auth trong phát triển ứng dụng của mình.
Bài viết có thể có sai sót trong quá trình soạn, nếu có góp ý về bài viết các bạn vui lòng bình luận ở bên dưới nhé. Cảm ơn các bạn đã theo dõi bài viết này.
Tham gia cuộc trò chuyện