上下文
我用的是NextJS v12.0.7
,React v17.0.2
,NextAuth v4.1.0
和Typescript v4.3.5
。
我想要创建一个简单的auth系统,它基于NextAuth文档,登录后被重定向到主页,所以我在名为[...nextauth].ts
的pages/api/auth
文件夹中创建了一个文件,其中包含以下代码:
export default NextAuth({
providers: [
CredentialsProvider({
id: "credentials",
name: "Login",
credentials: {
username: { type: "email" },
password: { type: "password" },
},
async authorize(credentials) {
// [...]
},
}),
],
// [...]
callbacks: {
// [...]
redirect({ url, baseUrl }) {
console.log("redirect - url ", url, "baseUrl ", baseUrl); // This is what I was checking
if(url.startsWith(baseUrl)) {
return url
} else if(url.startsWith("/")) {
return new URL(url, baseUrl).toString();
}
return baseUrl;
}
},
})
对于我的NextJS项目,我使用在next.config.js
文件中定义的basepath /espace-personnel
,所以我在.env.local
文件中按照官方的NextAuth文档定义了NEXTAUTH_URL
:
NEXTAUTH_URL=http://localhost/espace-personnel/api/auth
我的问题
当我在重定向回调中检查url
和baseUrl
变量时,我可以看到,我的NEXTAUTH_URL
变量没有很好地定义,或者我遇到了一些问题。
以下是console.log("redirect - url ", url, "baseUrl ", baseUrl);
的结果:
redirect - url http://localhost:3000 baseUrl http://localhost
我做过研究,在谷歌或Stackoverflow上找不到任何像我这样的案例,我是NextAuth的新手,所以我可能误解了什么。有人知道我做错了什么吗?
编辑(15/01/2022)
经过反复考虑,我决定直接使用process.env.NEXTAUTH_URL检查env变量,因此我在前面的console.log()
之后添加了这一行:
console.log("NEXTAUTH_URL", process.env.NEXTAUTH_URL)
其结果是:
NEXTAUTH_URL http://localhost/espace-personnel/api/auth
所以,事实上,这不是定义NEXTAUTH_URL的问题,我想我误解了NextAuth的工作方式,我将继续尝试找到解决我的问题的方法,如果我发现了什么,就在那里分享。
编辑(16/01/2022)
经过一些研究,我发现我们可以使用callbackUrl方法传递signIn,所以我在[...nextauth].ts
中定义了这样的页面:
pages: {
signIn: process.env.NEXT_PUBLIC_BASE_URL + '/connexion',
signOut: process.env.NEXT_PUBLIC_BASE_URL + '/deconnexion',
error: process.env.NEXT_PUBLIC_BASE_URL + '/connexion/erreur', // Error code passed in query string as ?error=
},
这是我的登录表格的代码:
import React, { useState } from "react";
import Alert from "../../ui/Alert/Alert";
import Button from "../../ui/Button/Button";
import Card from "../../ui/Card/Card";
import Divider from "../../ui/Divider/Divider";
import { getCsrfToken, signIn } from "next-auth/react";
import Input from "../../ui/Input/Input";
import styles from "./LoginForm.module.scss";
import Router from 'next/router';
type TAlertTitle = string;
type TAlertMessage = string;
type TAlertType = "info" | "warning" | "success" | "error";
export default function LoginForm({ csrfToken }: { csrfToken: string }) {
const [alertTitle, setAlertTitle] = useState<TAlertTitle>("Information");
const [alertMessage, setAlertMessage] = useState<TAlertMessage>("Juste un exemple");
const [alertType, setAlertType] = useState<TAlertType>("info");
async function onSubmit(event: React.SyntheticEvent<HTMLFormElement>) {
const target = event.target as typeof event.target & {
username: { value: string },
password: { value: string },
};
// Login attempt
const result = signIn('credentials', {
callbackUrl: process.env.NEXT_PUBLIC_BASE_URL,
username: target.username.value,
password: target.password.value
});
console.log(result);
event.preventDefault();
}
return (
<Card className={styles.card}>
<p className={'textSize40 fontWeightExtraBold textAlignCenter'}>
Connexion à votre espace personnel
</p>
<Divider className={styles.divider} />
<form onSubmit={onSubmit}>
<Alert title={alertTitle} message={alertMessage} type={alertType}></Alert>
<input name="csrfToken" type="hidden" defaultValue={csrfToken} />
<Input id="username" name="username" className="width100" type="email" autoComplete="email" placeholder="Adresse mail" leftIconLib="line-awesome" leftIcon="envelope" required />
<Input id="password" name="password" className="width100" type="password" autoComplete="current-password" placeholder="Mot de passe" leftIconLib="line-awesome" leftIcon="key" required />
<Button className="width100" theme="accent" type="submit">Se connecter</Button>
<Button className="width100" type="submit">Identifiants oubliés</Button>
</form>
</Card>
);
}
新的问题是,当我尝试登录时,我被重定向到http://localhost/api/auth/error
,并获得了这个错误:
404 | This page could not be found.
我是不是做错什么了?
发布于 2022-01-16 20:22:05
经过几个小时的研究,我终于遇到了一个最近关于同一问题的讨论。
在NextAuth v4中使用自定义基路径的解决方案
这是简短的版本,更长的是在底部。
NEXTAUTH_URL
文件中定义.env
,用自己的basePath
替换/espace-personnel
:NEXTAUTH_URL=http://localhost/espace-personnel/api/auth
basePath
中定义<SessionProvider>
的_app.tsx
道具,用自己的basePath
替换/espace-personnel
:function App({ Component, pageProps: { session, ...pageProps } }: AppProps) {
return (
<SessionProvider session={session} basePath='/espace-personnel/api/auth'>
<Component {...pageProps} />
</SessionProvider>
);
}
export default App
与NextAuth v4一起使用自定义基路径的解决方案(以前的解决方案)
在本例中,使用的basePath
是/espace-personnel
,域是localhost
。
您需要在您的NEXTAUTH_URL
文件中设置.env
环境变量,包括您的basePath
和后面的/api/auth
,如下所示:
NEXTAUTH_URL=http://localhost/espace-personnel/api/auth
然后编辑_app.tsx
并使用<SessionProvider>
上的支持basePath
定义基本路径,下面是使用自定义路径/espace-personnel
的最后代码:
function App({ Component, pageProps: { session, ...pageProps} }: AppProps) {
return (
<SessionProvider session={session} basePath="/espace-personnel/api/auth">
<Component {...pageProps} />
</SessionProvider>
)
}
export default App
发布于 2022-03-19 12:10:48
如果您使用带有多个区域或自定义基路径的next.js auth,则需要进行一些更改以使NextAuth.js知道这一点。
更新rest路径库,.env文件
NEXTAUTH_URL=https://example.com
成为
NEXTAUTH_URL=https://example.com/{zone name or basePath}/api/auth
更新客户端api路径库,_app.tsx
<SessionProvider session={pageProps.session}>
成为
<SessionProvider session={pageProps.session} basePath="/{zone name or basePath}/api/auth">
https://stackoverflow.com/questions/70717224
复制相似问题