Next Auth 最新版已集成到 Auth.js ,可以很方便地集成账号登录、第三方登录等 Web 身份验证功能。
框架网站: https://authjs.dev/
安装
https://authjs.dev/getting-started/installation?framework=next.js
安装 beta 版本:
npm install next-auth@beta
安装教程配置:
- 初始化 AUTH_SECRET
- 创建 auth.ts 文件并导出
handlers, signIn, signOut, auth
- 创建
app/api/auth/[...nextauth]/route.ts
文件并从handlers
导出{ GET, POST }
- 创建
middleware.ts
并将auth
重命名为middleware
导出
Next 中间件与 matcher
https://nextjs.org/docs/app/building-your-application/routing/middleware
中间件在缓存内容和路由匹配之前运行。
可配置 matcher ,利用正则排除不需要权限限制的路径:
https://authjs.dev/reference/nextjs#in-middleware
export const config = {
matcher: ["/((?!api|_next/static|_next/image|favicon.ico).*)"],
}
凭据登录
https://authjs.dev/getting-started/providers/credentials
Next Auth 集成了大量的登录方式,包括最原始的账号密码凭据登录方式。
import NextAuth from "next-auth"
import Credentials from "next-auth/providers/credentials"
export const { handlers, signIn, signOut, auth } = NextAuth({
providers: [
Credentials({
credentials: {
username: { label: "Username" },
password: { label: "Password", type: "password" },
},
async authorize(credentials) {
if (credentials.username === 'admin' && credentials.password === 'admin') {
const user = {
name: credentials.username,
}
return user
}
return null
},
}),
],
})
身份验证
https://authjs.dev/reference/nextjs#callbacks
- 身份验证由 callbacks.authorized 回调完成,默认只会预定义的 User 接口,仅包含 id name email image 字段
- 可通过 callbacks.jwt 和 callbacks.session 将信息存到 session ,使 callbacks.authorized 中可获取
callbacks: {
async authorized({ request, auth }) {
const url = request.nextUrl
const user = auth?.user;
if (url.pathname.startsWith('/admin') && !user) {
return false
}
return true
}
}
自定义用户对象
providers.Credentials.authorize 想返回一个自定义的用户格式,如:
const user = {
id: "1",
username: credentials.username,
role: 'admin'
}
拓展 next-auth 的 Session、User、JWT 类型使得 ts 可正常运行:
https://stackoverflow.com/questions/74425533
import { Session } from "next-auth";
import { JWT } from "next-auth/jwt";
declare module "next-auth" {
interface Session {
id: string;
username: string;
role: string;
}
interface User {
id: string;
username: string;
role: string;
}
}
declare module "next-auth/jwt" {
interface JWT {
id: string;
username: string;
role: string;
}
}
如需补充额外字段,可参照基于角色的访问控制教程,如将角色写进来:
https://authjs.dev/guides/role-based-access-control
callbacks: {
jwt({ token, user }) {
if (user && user.id) {
token.id = user.id
token.username = user.username
token.role = user.role
}
return token
},
session({ session, token }) {
session.user.id = token.id
session.user.username = token.username
session.user.role = token.role
return session
},
// ... authorized
}
自定义登录页面
next-auth 配置增加:
pages: {
signIn: "/login",
},
这样就会默认走到 /login 路由,在 app 目录创建路由编写页面即可。
确认登录时,调用 @/auth.ts
中导出的 signIn 方法。
登出
调用 @/auth.ts
中导出的 signOut 方法即可。