自定义登录页面
要添加自定义登录页面,您需要在 Auth.js 配置中的 pages
对象中定义页面的路径。确保在此处定义的路径确实存在路由/页面!
此外,我们将必须导出一个包含 provider.id
和 provider.name
的映射,以便在我们的自定义页面中轻松使用,如果我们想根据我们在 auth.ts
配置中定义的内容动态呈现正确的按钮。因为您可以将提供者作为函数或调用该函数的结果传递给 providers
数组,所以此示例 providerMap
处理这两种情况。
./auth.ts
import NextAuth from "next-auth"
import GitHub from "next-auth/providers/github"
import Credentials from "next-auth/providers/credentials"
import type { Provider } from "next-auth/providers"
const providers: Provider[] = [
Credentials({
credentials: { password: { label: "Password", type: "password" } },
authorize(c) {
if (c.password !== "password") return null
return {
id: "test",
name: "Test User",
email: "[email protected]",
}
},
}),
GitHub,
]
export const providerMap = providers
.map((provider) => {
if (typeof provider === "function") {
const providerData = provider()
return { id: providerData.id, name: providerData.name }
} else {
return { id: provider.id, name: provider.name }
}
})
.filter((provider) => provider.id !== "credentials")
export const { handlers, auth, signIn, signOut } = NextAuth({
providers,
pages: {
signIn: "/signin",
},
})
现在我们可以构建自己的自定义登录页面。
app/signin/page.tsx
import { redirect } from "next/navigation"
import { signIn, auth, providerMap } from "@/auth.ts"
import { AuthError } from "next-auth"
export default async function SignInPage(props: {
searchParams: { callbackUrl: string | undefined }
}) {
return (
<div className="flex flex-col gap-2">
<form
action={async (formData) => {
"use server"
try {
await signIn("credentials", formData)
} catch (error) {
if (error instanceof AuthError) {
return redirect(`${SIGNIN_ERROR_URL}?error=${error.type}`)
}
throw error
}
}}
>
<label htmlFor="email">
Email
<input name="email" id="email" />
</label>
<label htmlFor="password">
Password
<input name="password" id="password" />
</label>
<input type="submit" value="Sign In" />
</form>
{Object.values(providerMap).map((provider) => (
<form
action={async () => {
"use server"
try {
await signIn(provider.id, {
redirectTo: props.searchParams?.callbackUrl ?? "",
})
} catch (error) {
// Signin can fail for a number of reasons, such as the user
// not existing, or the user not having the correct role.
// In some cases, you may want to redirect to a custom error
if (error instanceof AuthError) {
return redirect(`${SIGNIN_ERROR_URL}?error=${error.type}`)
}
// Otherwise if a redirects happens Next.js can handle it
// so you can just re-thrown the error and let Next.js handle it.
// Docs:
// https://nextjs.net.cn/docs/app/api-reference/functions/redirect#server-component
throw error
}
}}
>
<button type="submit">
<span>Sign in with {provider.name}</span>
</button>
</form>
))}
</div>
)
}
然后,当您在应用程序的任何位置不带任何参数调用 signIn
时,自定义登录页面将出现。