Перенаправить после успешного входа в систему или зарегистрироваться для ввода учетных данных при следующей авторизации

Есть ли какие-либо примеры и / или способ перенаправления на личную панель управления при успешном входе в систему или регистрации для ввода учетных данных в next-auth? Я не мог найти никаких четких документов по этому поводу.

Я хотел добавить редирект ниже, но не был уверен, что это правильный подход:

callbacks.signIn = async (data, account, profile) => {
  if ((account.provider === 'google' && profile.verified_email === true) || (account.type === 'credentials' && data.status === 200)) {
    return Promise.resolve(true)
  } else {
    return Promise.resolve(false)
  }
}

6 ответов

На самом деле это может произойти при инициации входа. Из документов вы можете передать URL-адрес обратного вызова для входа в систему. Ваш код будет выглядеть следующим образом.

        signIn(provider.id, {
      callbackUrl: `${window.location.origin}/protected`,
    })

В новых версиях Next.js вы можете выполнить перенаправление метода getStaticProps следующим образом:

Ресурс: https://nextjs.org/docs/basic-features/data-fetching#getstaticprops-static-generation

export async function getStaticProps(context) {
  // some imperative work..


  //
  if (!user) {
    return {
      redirect: {
        destination: '/', // some destination '/dashboard' Ex,
        permanent: false,
      },
    }
  }

  return {
    props: {},
  }
}

Использование пользовательского HTML

При использовании пользовательской страницы входа такое поведение недокументировано. Тем не менее, решение ниже работает для меня как шарм.

Чтобы внести ясность, другие ответы, связанные с параметром вsignIn/signOutфункций достаточно, если вы их используете. См. документацию здесь для получения этих инструкций.

Этот ответ для тех, кто используетgetCsrfTokenв пользовательском запросе POST.

Используйте скрытое<input />элемент

Ниже мы будем использовать скрытый элемент ввода для отправки POST-отправки формы.

Примечание. Далее предполагается, что вы правильно приобрели csrfToken.

      <form
  id="email-login"
  method="post"
  action="/api/auth/signin/email"
>
  <input name="csrfToken" type="hidden" defaultValue={csrfToken} />
  <input name="callbackUrl" type="hidden" defaultValue="/dashboard" />
  <input
    label="email"
    id="email"
    name="email"
    type="email"
    required
  />
  <div>
    <button
      type="submit"
    >
      <span>
        Email login
      </span>
    </button>
  </div>
</form>

В приведенном выше фрагменте ключевой строкой является

      <input name="callbackUrl" type="hidden" defaultValue="/dashboard" />

Это отправляетcallbackUrlпараметр body в запросе POST, чтобы вход перенаправлял пользователя наyour-site.tld/dashboard.

у меня это работает вот так

      "use client";
import Link from "next/link";
import { signIn } from "next-auth/react";
import { useState } from "react";
import { toast } from "react-toastify";

const Login = () => {
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");

  // handle submit event
  const handleSubmit = async (e) => {
    e.preventDefault();

    try {
      const isLoggedin = await signIn(
        "credentials",
        {
          email,
          password,
        },
        { callbackUrl: "/dashboard/profile" }
      );

      if (isLoggedin.error !== null) {
        toast.error("Incorrect Login Details!!");
      } else {
        toast.success("Login Successful!!");
        // router.replace("/dashboard/profile");
      }
    } catch (error) {
      toast.success(error);
    }
  };

  return (
    <div
      style={{ maxWidth: "480px" }}
      className="mt-10 mb-20 p-4 md:p-7 mx-auto rounded bg-white shadow-lg"
    >
      <form onSubmit={handleSubmit}>
        <h2 className="mb-5 text-2xl font-semibold">Login</h2>

        <div className="mb-4">
          <label className="block mb-1"> Email </label>
          <input
            className="appearance-none border border-gray-200 bg-gray-100 rounded-md py-2 px-3 hover:border-gray-400 focus:outline-none focus:border-gray-400 w-full"
            type="text"
            placeholder="Type your email"
            required
            onChange={(e) => setEmail(e.target.value)}
          />
        </div>

        <div className="mb-4">
          <label className="block mb-1"> Password </label>
          <input
            className="appearance-none border border-gray-200 bg-gray-100 rounded-md py-2 px-3 hover:border-gray-400 focus:outline-none focus:border-gray-400 w-full"
            type="password"
            placeholder="Type your password"
            minLength={6}
            required
            onChange={(e) => setPassword(e.target.value)}
          />
        </div>

        <button
          type="submit"
          className="my-2 px-4 py-2 text-center w-full inline-block text-white bg-blue-600 border border-transparent rounded-md hover:bg-blue-700"
        >
          Login
        </button> 
      </form>
    </div>
  );
};

export default Login;

Проблема со встроеннымcallbackUrl in signInзаключается в том, что он, похоже, перенаправляется, даже если ваши учетные данные неверны (по крайней мере, в моем случае)

Я думаю, что гораздо более простым и понятным подходом было бы установитьredirect: falseи самостоятельно обработать перенаправление с помощьюwindow.location.replace("...")так:

      function validate_login(event) {

    event.preventDefault()

    signIn("credentials", {
        username: username_input.value,
        password: password_input.value,
        redirect: false, // this will prevent redirect
    })
        .then((result) => {

            if (result?.error)
                alert("Invalid Credentials!")
            else
                window.location.replace("/private_dashboard") // if login successful
        })
        .catch(err => {
            ...
        })
        .finally(() => {
            ...
        })
}

Вот полный минимальный пример копирования и вставки, если вы ленивы, как я:

      "use client"
import { signIn } from "next-auth/react";

function validate_login(event: any) {

    event.preventDefault()

    const username_inp: HTMLInputElement = document.querySelector("#username")!
    const password_inp: HTMLInputElement = document.querySelector("#password")!
    const submit_btn: HTMLInputElement = document.querySelector(`#submit_btn`)!

    submit_btn.disabled = true

    signIn("credentials", {
        username: username_inp.value,
        password: password_inp.value,
        redirect: false,
    })
        .then((result) => {

            if (result?.error)
                alert("Invalid Credentials!")
            else
                window.location.replace("/user")
        })
        .catch(err => {
            alert(`Error Occured: ${err}`)
        })
        .finally(() => {
            submit_btn.disabled = false
        })
}

const LoginPage = () => {

    return (<form onSubmit={validate_login}>
        <label>Username</label>
        <input type="text" id="username" />

        <br />
        <br />

        <label>Password</label>
        <input type="password" id="password" />

        <br />
        <br />

        <input id="submit_btn" type="submit" value="Submit"></input>

    </form>)
}

export default LoginPage;

Примечание. Это было протестировано в Next.js 13.

Если вы перейдете к документации Next-Auth:https://next-auth.js.org/getting-started/client#signin

Вы обнаружите, что метод SignIn() принимает URL-адрес обратного вызова.

Это пример на основе версии, я использую версию 5.

V4

      const url = await signIn(provider, { redirect: false, redirectTo: '/dashboard' })

V5

      ...
'use server'
const url = await signIn(provider, { redirect: false, redirectTo: '/dashboard'})
...

Также более подробную информацию вы можете найти внутри упаковки.

      signIn<
    P extends BuiltInProviderType | (string & {}),
    R extends boolean = true
  >(
    /** Provider to sign in to */
    provider?: P, // See: https://github.com/microsoft/TypeScript/issues/29729
    options?: {
      /** The URL to redirect to after signing in. By default, the user is redirected to the current page. */
      redirectTo?: string
      /** If set to `false`, the `signIn` method will return the URL to redirect to instead of redirecting automatically. */
      redirect?: R
    } & Record<string, any>,
    authorizationParams?:
      | string[][]
      | Record<string, string>
      | string
      | URLSearchParams
  ): Promise<R extends false ? any : never>
Другие вопросы по тегам