自訂登入頁面
若要新增自訂登入頁面,您需要在 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: "test@example.com",
}
},
}),
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.dev.org.tw/docs/app/api-reference/functions/redirect#server-component
throw error
}
}}
>
<button type="submit">
<span>Sign in with {provider.name}</span>
</button>
</form>
))}
</div>
)
}
然後,當在應用程式中的任何位置呼叫不帶任何引數的 signIn
時,將會出現自訂登入頁面。
