Я пытаюсь реализовать следующую аутентификацию с моим следующим js-приложением с поставщиком учетных данных. Однако каждый раз, когда мне не удается войти в систему, он продолжает пытаться получить доступ к маршруту /api/auth/error
. Я пытаюсь обработать ошибку, оставаясь на странице входа и добавляя параметр в конце URL-адреса, например /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.info('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.info(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 }
}
}
вам также нужно указать страницу ошибки, и, поскольку вы хотите показать ошибку на странице входа, она должна быть такой:
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.info(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>;
};
вы можете настроить способ отображения ошибки в соответствии с вашими потребностями