🚀 Next.js + NextAuth 实现 GitHub 登录功能全记录

最近给我的博客系统接入了 GitHub 登录,顺利实现了用户通过 GitHub 授权快速登录的功能。本文记录完整的实现步骤和踩坑经历,方便自己复盘,也希望能帮到你。


🧱 技术栈简介

  • Next.js 15(使用 App Router)

  • next-auth(用于实现 OAuth)

  • GitHub OAuth App(作为第三方登录提供者)

  • TypeORM + MySQL(作为用户数据存储)


🪜 步骤一:配置 GitHub OAuth App

前往 GitHub 开发者设置 创建一个新的 OAuth App:

  • 应用名称:随便起一个

  • Homepage URLhttp://localhost:3000

  • Authorization callback URLhttp://localhost:3000/api/auth/callback/github

创建完成后会得到:

  • Client ID

  • Client Secret

把这两个值放入 .env.local 文件中:

GITHUB_CLIENT_ID=your_client_id
GITHUB_CLIENT_SECRET=your_client_secret

🪜 步骤二:配置 NextAuth

app/api/auth/[...nextauth]/route.ts 中设置 next-auth 配置:

// 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_CLIENT_ID!,
      clientSecret: process.env.GITHUB_CLIENT_SECRET!,
    }),
  ],
  callbacks: {
    async signIn({ user, account }) {
      // 你可以在这里将 GitHub 用户信息保存到数据库
      if (account.provider === 'github') {
        console.log('GitHub 用户信息:', user);
      }
      return true;
    },
    async jwt({ token, user }) {
      if (user) token.githubId = user.id;
      return token;
    },
    async session({ session, token }) {
      if (token?.githubId) session.user.id = token.githubId;
      return session;
    },
  },
};

const handler = NextAuth(authOptions);
export const GET = handler;
export const POST = handler;

⚠️ 注意事项:

  • 使用 App Router 的 API Routes 必须导出 GETPOST 方法,不能用默认导出。

  • 路由应为 /api/auth/[...nextauth]/route.ts


🪜 步骤三:前端调用登录

在登录组件中使用 signIn('github') 触发 GitHub 登录:

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

const githubLogin = () => {
  signIn('github', {
    callbackUrl: '/', // 登录成功后的跳转地址
  });
};

常见误区

  • 如果你写了 redirect: false,GitHub 页面不会跳转。

  • 第一次登录成功后,如果未退出,再次点按钮不会跳转,因为 next-auth 会判断已登录。


💥 踩坑记录

❌ 登录后不跳转 GitHub

原因:使用了 signIn('github', { redirect: false }),这种方式适合“弹窗登录”或静默获取 session,不适合 OAuth 跳转。

✅ 修复:直接用 signIn('github', { callbackUrl: '/' }) 即可。


🔐 登录后保存用户信息(可选)

你可以在 signIn 回调里将 GitHub 用户信息写入数据库,比如结合你原来的手机号登录逻辑,添加一个 identity_type = 'github' 的用户认证记录:

async signIn({ user, account }) {
  if (account.provider === 'github') {
    const db = AppDataSource;
    if (!db.isInitialized) await db.initialize();

    const userRepo = db.getRepository(Users);
    const userAuthRepo = db.getRepository(UserAuths);

    // 检查是否已经注册
    let userAuth = await userAuthRepo.findOne({
      where: {
        identity_type: 'github',
        identifier: account.providerAccountId, // GitHub 的 user id
      },
    });

    if (!userAuth) {
      // 创建用户
      const newUser = userRepo.create({
        nickname: user.name || user.login,
        avatar: user.image || '/default-avatar.png',
      });
      const savedUser = await userRepo.save(newUser);

      const newUserAuth = userAuthRepo.create({
        user_id: savedUser.id,
        identity_type: 'github',
        identifier: account.providerAccountId,
        credential: '', // 不需要密码
      });
      await userAuthRepo.save(newUserAuth);
    }
  }

  return true;
}

✅ 总结

GitHub 登录在 Next.js + NextAuth 中配置其实非常顺滑,只要注意几点:

  • App Router 要显式导出 GET/POST

  • 登录跳转要用 signIn('github', { callbackUrl })

  • GitHub 回调 URL 必须精确匹配 OAuth App 设置

  • 登录成功后按需存入数据库


有问题欢迎留言讨论!如果你想了解如何用 session 驱动头像/昵称显示,也可以看我另一篇笔记「Next.js + Zustand 实现登录用户信息共享」。