下一个身份验证凭据

时间:2021-02-24 11:09:24

标签: next.js next-auth

我正在尝试使用 next-auth 进行凭据身份验证。我必须使用自定义登录页面,而且我绝对不能让它工作大约一整周。

我有:

// [...nextauth.js]

import NextAuth from 'next-auth';
import Providers from 'next-auth/providers';

import axios from '@api/axios';

const options = {
  providers: [
    Providers.Credentials({
      async authorize(credentials) {
        const { data: user, status } = await axios.post('/users/authentication', credentials);

        if (user && status === 200) {
          return user;
        } else {
          throw new Error('error message');
        }
      }
    })
  ],
  pages: {
    signIn: '/profil/authentication/login',
    error: '/profil/authentication/login'
  },
  session: {
    jwt: true,
    maxAge: 30 * 24 * 60 * 60 // 30 days
  },
  debug: true
};

export default (req, res) => NextAuth(req, res, options);

和:

// profil/authentication/login

import { signOut, useSession } from 'next-auth/client';

import AuthenticationForm from '@components/auth/authenticationForm';
import Layout from '@components/layout';

const Login = () => {
  const [session] = useSession();
  const intl = useIntl();

  return (
    <Layout>
      {!session && <AuthenticationForm />}
      {session && (
        <>
          Signed in as {session.user.email}
          <br />
          <button onClick={signOut}>Sign out</button>
        </>
      )}
    </Layout>
  );
};

export default Login;

// authenticationForm.js

import { signIn, csrfToken } from 'next-auth/client';
import { useRouter } from 'next/router';
import { useEffect, useState } from 'react';

import PasswordInput from '@components/auth/passwordInput';
import Button from '@components/form/button';
import TextInput from '@components/form/textInput';

const AuthenticationForm = ({ csrf }) => {
  const [username, setUsername] = useState('');
  const [password, setPassword] = useState('');
  const [error, setError] = useState('');
  const router = useRouter();

  const handleChangeUsername = ({ target: { value } }) => setUsername(value);

  const handleChangePassword = ({ target: { value } }) => setPassword(value);

  const handleLogin = () => {
    signIn('credentials', {
      username,
      password,
      callbackUrl: `${window.location.origin}/profil`
    })
      .then((res) => {
        console.log('form::res -> ', res);
        router.back();
      })
      .catch((e) => {
        console.log('form::e -> ', e);
        setError('login error');
      });
  };

  useEffect(() => {
    if (router.query.error) {
      setError(router.query.error);
      setUsername(router.query.username);
    }
  }, [router]);

  return (
    <form onSubmit={handleLogin}>
      <TextInput
        name="username"
        value={username}
        onChange={handleChangeUsername}
      />
      <PasswordInput handleChange={handleChangePassword} />
      {error && <div>{error}</div>}
      <Button type="submit">
      connexion
      </Button>
      <input name="csrfToken" type="hidden" defaultValue={csrf} />
    </form>
  );
};

AuthenticationForm.getInitialProps = async (context) => {
  return {
    csrf: await csrfToken(context)
  };
};

export default AuthenticationForm;

当然还有 NEXTAUTH_URL=http://localhost:3000 中的 .env.local

如果我继续/profil/authentication/login,我会看到我的表单,当我点击连接时,我总是出现一些错误,例如:"Failed to fetch",仅此而已,或者:

<块引用>

[next-auth][error][client_fetch_error] (2) ["/api/auth/csrf", TypeError: Failed to fetch] https://next-auth.js.org/errors#client_fetch_error

即使我尝试删除表单中的所有 csrf 处理并让登录“自己做”。

我真的被这个库困住了,我很可能会换另一个库,但我想知道我做错了什么?是否有一个完整的示例,其中包含自定义登录页面和在同一登录页面上处理的错误。这太基础了,我不明白为什么我不容易找到。

1 个答案:

答案 0 :(得分:0)

@Tralgar

我认为这个问题与您后端的 CSRF 策略有关,如果您在 localhost 上,那么 localhost:3000 和 localhost:2000 就像两个不同的域。只需确保您的后端 cors 策略中是否有前端域(如果在 localhost 上,它必须带有端口)

相关问题