Logo
Published on
เผยแพร่เมื่อ

ทำ Authentication ด้วย Github OAuth กับ NextAuth ใน Next.js

integrating-github-oauth-with-next-auth

การทำ Authentication ในแอปพลิเคชันเป็นสิ่งสำคัญที่ช่วยให้ผู้ใช้สามารถเข้าถึงระบบได้อย่างปลอดภัย ในบทความนี้ เราจะพาคุณทำระบบล็อกอินด้วย GitHub OAuth โดยใช้ NextAuth ใน Next.js ซึ่งเป็นวิธีที่ทั้งง่ายและทรงพลังสำหรับการจัดการผู้ใช้ในโปรเจกต์ของคุณ

ทำไมต้องใช้ GitHub OAuth และ NextAuth?

  • GitHub OAuth: ช่วยให้ผู้ใช้สามารถล็อกอินด้วยบัญชี GitHub ได้อย่างรวดเร็ว โดยไม่ต้องสร้างบัญชีใหม่
  • NextAuth: ไลบรารีที่ออกแบบมาเพื่อการจัดการ Authentication ใน Next.js รองรับผู้ให้บริการ OAuth หลายรายและใช้งานง่าย
  • Next.js: เฟรมเวิร์กที่ทันสมัยด้วย App Router และ Server Components ทำให้การพัฒนาเร็วและมีประสิทธิภาพ

ขั้นตอนการตั้งค่า

1. ตั้งค่าโปรเจกต์ Next.js

เริ่มต้นด้วยการสร้างโปรเจกต์ Next.js ใหม่ (ถ้ายังไม่มี):

npx create-next-app@latest my-auth-app
cd my-auth-app

เลือก App Router เมื่อตั้งค่าโปรเจกต์ เพื่อให้เข้ากันได้กับ Next.js

2. ติดตั้ง NextAuth

ติดตั้งแพ็กเกจ NextAuth:

# npm
npm install next-auth
# yarn
yarn add next-auth

3. สร้าง GitHub OAuth App

  1. ไปที่ GitHub Developer Settings
  2. คลิก New OAuth App
  3. กรอกข้อมูล:
  • Application name: ชื่อแอปของคุณ (เช่น "My Next.js App")
  • Homepage URL: URL ของแอป (เช่น http://localhost:3000)
  • Authorization callback URL: http://localhost:3000/api/auth/callback/github integrating-github-oauth-with-next-auth-01
  1. หลังจากสร้าง คุณจะได้รับ Client ID และ Client Secret เก็บไว้ใช้ในขั้นตอนถัดไป integrating-github-oauth-with-next-auth-02

Client Secret เก็บไว้ให้ดีเพราะหลังจาก generate แล้วจะไม่สามารถดูได้อีก แต่สามารถ generate ใหม่ได้

4. ตั้งค่า Environment Variables

สร้างไฟล์ .env.local ใน root ของโปรเจกต์และเพิ่มข้อมูลดังนี้:

.env.local
GITHUB_ID=your-github-client-id
GITHUB_SECRET=your-github-client-secret
NEXTAUTH_URL=http://localhost:3000
NEXTAUTH_SECRET=your-secret-key
  • NEXTAUTH_SECRET สามารถสร้างได้โดยใช้คำสั่ง:
openssl rand -base64 32

5. สร้าง API Route สำหรับ NextAuth

สร้างไฟล์ app/api/auth/[...nextauth]/route.ts และเพิ่มโค้ดต่อไปนี้:

app/api/auth/[...nextauth]/route.ts
import NextAuth from 'next-auth';
import GitHubProvider from 'next-auth/providers/github';

export const authOptions = {
    providers: [
        GitHubProvider({
            clientId: process.env.GITHUB_ID || '',
            clientSecret: process.env.GITHUB_SECRET || ''
        })
    ],
    secret: process.env.NEXTAUTH_SECRET,
    callbacks: {
        // https://next-auth.js.org/configuration/callbacks
    }
};

const handler = NextAuth(authOptions);
export { handler as GET, handler as POST };

โค้ดนี้ตั้งค่า NextAuth ให้ใช้ GitHub เป็นผู้ให้บริการ OAuth

6. สร้าง Client Component สำหรับ SessionProvider

สร้างไฟล์ใหม่ app/components/AuthSessionProvider.tsx

app/components/AuthSessionProvider.tsx
'use client'

import { SessionProvider } from 'next-auth/react';

export default function AuthSessionProvider({
    children
}: Readonly<{
    children: React.ReactNode;
}>) {
    return (
        <SessionProvider>{children}</SessionProvider>
    );
}

7. เพิ่ม Auth Session Provider ใน Root Layout

แก้ไขไฟล์ app/layout.tsx เพื่อให้ NextAuth จัดการ session ได้ทั่วทั้งแอป:

app/login/page.tsx
import AuthSessionProvider from '@/app/components/AuthSessionProvider';

export default function RootLayout({
    children
}: Readonly<{
    children: React.ReactNode;
}>) {
    return (
        <html lang="en">
            <body className={`${geistSans.variable} ${geistMono.variable} antialiased`}>
                <AuthSessionProvider>{children}</AuthSessionProvider>
            </body>
        </html>
    );
}

8. สร้างหน้า Login และ Logout

สร้างหน้า app/login/page.tsx สำหรับจัดการการล็อกอิน:

'use client';

import { signIn, signOut, useSession } from 'next-auth/react';

export default function Login() {
    const { data: session } = useSession();

    return (
        <div className="min-h-screen flex items-center justify-center bg-gradient-to-br from-blue-100 to-purple-100">
            <div className="bg-white p-8 rounded-xl shadow-lg max-w-md w-full">
                {session ? (
                    <div className="text-center">
                        <h1 className="text-2xl font-bold text-gray-800 mb-4">
                            ยินดีต้อนรับ, {session.user?.name}!
                        </h1>
                        <p className="text-gray-600 mb-6">คุณเข้าสู่ระบบเรียบร้อยแล้ว</p>
                        <button
                            onClick={() => signOut()}
                            className="w-full justify-center text-white bg-[#24292F] hover:bg-[#24292F]/90 focus:ring-4 focus:outline-none focus:ring-[#24292F]/50 font-medium rounded-lg text-sm px-5 py-2.5 text-center inline-flex items-center me-2 mb-2 cursor-pointer"
                        >
                            ออกจากระบบ
                        </button>
                    </div>
                ) : (
                    <div className="text-center">
                        <h1 className="text-2xl font-bold text-gray-800 mb-4">
                            เข้าสู่ระบบ
                        </h1>
                        <p className="text-gray-600 mb-6">กรุณาเลือกวิธีการเข้าสู่ระบบ</p>
                        <button type="button" className="w-full justify-center text-white bg-[#24292F] hover:bg-[#24292F]/90 focus:ring-4 focus:outline-none focus:ring-[#24292F]/50 font-medium rounded-lg text-sm px-5 py-2.5 text-center inline-flex items-center me-2 mb-2 cursor-pointer" onClick={() => signIn('github')}>
                            <svg className="w-5 h-5 me-2" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 20 20">
                                <path fillRule="evenodd" d="M10 .333A9.911 9.911 0 0 0 6.866 19.65c.5.092.678-.215.678-.477 0-.237-.01-1.017-.014-1.845-2.757.6-3.338-1.169-3.338-1.169a2.627 2.627 0 0 0-1.1-1.451c-.9-.615.07-.6.07-.6a2.084 2.084 0 0 1 1.518 1.021 2.11 2.11 0 0 0 2.884.823c.044-.503.268-.973.63-1.325-2.2-.25-4.516-1.1-4.516-4.9A3.832 3.832 0 0 1 4.7 7.068a3.56 3.56 0 0 1 .095-2.623s.832-.266 2.726 1.016a9.409 9.409 0 0 1 4.962 0c1.89-1.282 2.717-1.016 2.717-1.016.366.83.402 1.768.1 2.623a3.827 3.827 0 0 1 1.02 2.659c0 3.807-2.319 4.644-4.525 4.889a2.366 2.366 0 0 1 .673 1.834c0 1.326-.012 2.394-.012 2.72 0 .263.18.572.681.475A9.911 9.911 0 0 0 10 .333Z" clipRule="evenodd" />
                            </svg>
                            เข้าสู่ระบบด้วย GitHub
                        </button>
                    </div>
                )}
            </div>
        </div>
    );
}

9. ทดสอบการล็อกอิน

  1. รันโปรเจกต์ด้วยคำสั่ง:
# npm
npm run dev
# yarn
yarn dev
  1. ไปที่ http://localhost:3000/login integrating-github-oauth-with-next-auth-03
  2. คลิกปุ่ม "เข้าสู่ระบบด้วย GitHub" และล็อกอินด้วยบัญชี GitHub ของคุณ integrating-github-oauth-with-next-auth-04
  3. หลังจากล็อกอินสำเร็จ คุณจะเห็นข้อความ "ยินดีต้อนรับ, ชื่อผู้ใช้" และปุ่ม "ออกจากระบบ" integrating-github-oauth-with-next-auth-05

ข้อดีของการใช้ NextAuth กับ GitHub OAuth

  • ความปลอดภัย: รองรับการจัดการ Session และ JWT อย่างปลอดภัย
  • ความยืดหยุ่น: สามารถเพิ่มผู้ให้บริการ OAuth อื่น ๆ ได้ง่าย
  • ประสบการณ์ผู้ใช้: ล็อกอินด้วยบัญชี GitHub ลดขั้นตอนการสมัครสมาชิก

การปรับแต่งเพิ่มเติม

  • เก็บข้อมูลผู้ใช้ในฐานข้อมูล: คุณสามารถใช้ callbacks ใน authOptions เพื่อบันทึกข้อมูลผู้ใช้ลงฐานข้อมูล เช่น Prisma หรือ MongoDB
  • เพิ่มหน้าโปรไฟล์: สร้างหน้า app/profile/page.tsx เพื่อแสดงข้อมูลผู้ใช้ เช่น อีเมลหรือรูปโปรไฟล์

ข้อควรระวัง

  • ตรวจสอบให้แน่ใจว่า .env.local ไม่ถูก commit ขึ้น GitHub โดยเพิ่มใน .gitignore
  • ใช้ HTTPS ใน production เพื่อความปลอดภัย

สรุป

การใช้ GitHub OAuth ร่วมกับ NextAuth ใน Next.js เป็นวิธีที่ง่ายและมีประสิทธิภาพในการสร้างระบบ Authentication ให้กับแอปของคุณ ด้วยขั้นตอนเพียงไม่กี่ขั้นตอน

ลองนำโค้ดนี้ไปปรับใช้และพัฒนาแอปของคุณต่อได้เลย!

avatar
Username
@Kongkiat
Bio
เป็นนักพัฒนาเว็บไซต์โดยใช้ React เป็นหลัก และมีความรู้ด้าน Backend ด้วย Spring boot มุ่งเน้นการพัฒนาแอปพลิเคชันที่ดูแลรักษาง่าย และมีประสิทธิภาพ

Related Posts

post-title

Next.js ไม่อัปเดต? วิธีล้างแคชและ Build โปรเจกต์ใหม่

การพัฒนาเว็บแอปด้วย Next.js บางครั้งคุณอาจพบปัญหาว่าแอปไม่แสดงการอัปเดตล่าสุด เช่น สไตล์ไม่เปลี่ยน แม้จะมีการแก้ไขไฟล์แล้ว หรือคอมโพเนนต์ยังทำงานเหมือนเดิมแม้จะมีการปรับปรุงโค้ดใหม่ สาเหตุหลัก ๆ อาจมาจาก แคชที่ยังคงอยู่ และไม่ได้ถูกล้างอย่างถูกต้อง

PublishedAt

Comment