next-auth 不断因凭证提供程序错误而重定向
2022-09-13
11528
我正在尝试使用 Credentials 提供程序在我的下一个 js 应用程序中实现 next-auth。但是,每次我登录失败时,它都会继续尝试访问
/api/auth/error
路由。我尝试通过停留在登录页面并在网址末尾添加一个参数(如
/login?status=Failed
)来自定义处理错误。我做错了什么,它一直尝试进入
/api/auth/error
路由而不是遵循我的流程?
我的代码:
/pages/api/auth/[...nextauth].js
import { authenticate } from "api/login";
import NextAuth from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";
export default NextAuth({
session: {
strategy: 'jwt'
},
providers: [
CredentialsProvider({
id: 'credentials',
name: 'Credentials',
credentials: {
username: { type: 'text', label: 'Username'},
password: { type: 'text', label: 'Password' }
},
async authorize(credentials, req) {
const res = await authenticate(credentials); // custom function that returns an object with a jwt if auth is successful
if(res.status !== 200) {
return null;
}
return res.user;
}
})
],
pages: {
signIn: '/login'
},
callbacks: {
async signIn(user) {
console.log('user: ' + user);
if (!user) return '/login?status=fail';
return '/'
}
}
});
登录页面(我知道这不是最佳实践)
/pages/login.js
import { useState } from 'react';
import { signIn } from 'next-auth/react';
import Container from 'react-bootstrap/Container';
import Row from 'react-bootstrap/Row';
import Col from 'react-bootstrap/Col';
import Form from 'react-bootstrap/Form';
import Button from 'react-bootstrap/Button';
export default function Login() {
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const onSubmit = async () => {
signIn('credentials', {
username: username,
password: password,
redirect: false,
})
.then(res => {
console.log(res);
})
.catch(err => {
console.error(err);
});
};
return (
<Container>
<Row>
<Col lg={6} className="offset-lg-3">
<Form>
<Row>
<Col>
<Form.Group controlId="loginUsername">
<Form.Label>Username</Form.Label>
<Form.Control
type="text"
onChange={(e) => setUsername(e.target.value)}
value={username} />
</Form.Group>
</Col>
</Row>
<Row>
<Col>
<Form.Group controlId="loginPassword">
<Form.Label>Password</Form.Label>
<Form.Control
type="text"
onChange={(e) => setPassword(e.target.value)}
value={password} />
</Form.Group>
</Col>
</Row>
<Row className="pt-3">
<Col lg={4}>
<Button onClick={onSubmit}>Login</Button>
</Col>
</Row>
<Row>
<Col>
</Col>
</Row>
</Form>
</Col>
</Row>
</Container>
)
}
_app.js
import React from 'react';
import 'bootstrap/dist/css/bootstrap.min.css';
import { SessionProvider } from 'next-auth/react';
function MyApp({
Component,
pageProps: { session, ...pageProps } }) {
return (
<SessionProvider session={session}>
<Component {...pageProps} />
</SessionProvider>
);
}
export default MyApp;
此外,这是我设置的受保护页面
import React from 'react';
import { getSession } from 'next-auth/react';
import Container from 'react-bootstrap/Container';
import Row from 'react-bootstrap/Row';
import Col from 'react-bootstrap/Col';
export default function Home() {
return (
<Container fluid>
<Row>
<Col>
<h1>Hello World</h1>
</Col>
</Row>
</Container>
);
}
export async function getServerSideProps(context) {
const session = await getSession({ req: context.req });
if (!session) {
return {
redirect: {
destination: '/login',
permanent: false
}
}
}
return {
props: { session }
}
}
3个回答
您还需要指定错误页面,因为您想在登录页面上显示错误,它应该是这样的:
pages: {
signIn: '/login',
error: '/login'
},
您可以尝试我从此 博客文章 中获得的这种方法来自定义登录页面以处理不同的登录错误:
// pages/login.js
import { useState } from 'react';
import { signIn } from 'next-auth/react';
import { useRouter } from 'next/router';
import Container from 'react-bootstrap/Container';
import Row from 'react-bootstrap/Row';
import Col from 'react-bootstrap/Col';
import Form from 'react-bootstrap/Form';
import Button from 'react-bootstrap/Button';
export default function Login() {
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const { error } = useRouter().query;
const onSubmit = async () => {
signIn('credentials', {
username: username,
password: password,
redirect: false,
})
.then((res) => {
console.log(res);
})
.catch((err) => {
console.error(err);
});
};
return (
<Container>
<Row>
<Col lg={6} className="offset-lg-3">
{/* Error message */}
<Row>
<Col>{error && <SignInError error={error} />}</Col>
</Row>
<Form>
<Row>
<Col>
<Form.Group controlId="loginUsername">
<Form.Label>Username</Form.Label>
<Form.Control
type="text"
onChange={(e) => setUsername(e.target.value)}
value={username}
/>
</Form.Group>
</Col>
</Row>
<Row>
<Col>
<Form.Group controlId="loginPassword">
<Form.Label>Password</Form.Label>
<Form.Control
type="text"
onChange={(e) => setPassword(e.target.value)}
value={password}
/>
</Form.Group>
</Col>
</Row>
<Row className="pt-3">
<Col lg={4}>
<Button onClick={onSubmit}>Login</Button>
</Col>
</Row>
<Row>
<Col></Col>
</Row>
</Form>
</Col>
</Row>
</Container>
);
}
const errors = {
Signin: 'Try signing with a different account.',
OAuthSignin: 'Try signing with a different account.',
OAuthCallback: 'Try signing with a different account.',
OAuthCreateAccount: 'Try signing with a different account.',
EmailCreateAccount: 'Try signing with a different account.',
Callback: 'Try signing with a different account.',
OAuthAccountNotLinked:
'To confirm your identity, sign in with the same account you used originally.',
EmailSignin: 'Check your email address.',
CredentialsSignin:
'Sign in failed. Check the details you provided are correct.',
default: 'Unable to sign in.',
};
const SignInError = ({ error }) => {
const errorMessage = error && (errors[error] ?? errors.default);
return <div>{errorMessage}</div>;
};
您可以根据需要自定义错误的显示方式
mocherfaoui
2022-09-13
对我来说,问题在于我在开发和生产环境中使用了相同的 MongoDB 实例。意识到这一点后,我删除了 MongoDB 中的用户帐户和会话信息,一切正常。
kiefx
2023-07-03