useRouter().push() from "next/navigation" doesn't work on custom signIn-Page with next-auth

huangapple go评论84阅读模式
英文:

useRouter().push() from "next/navigation" doesn't work on custom signIn-Page with next-auth

问题

After a successful login on my custom signIn-Page, I use with next-auth, I'm trying to redirect back to the callbackUrl, but that doesn't work. I'm using react 18.2.0, next 13.4.8-canary.2 and next-auth 4.22.1.

signIn-Page (\src\app\api\auth\signin\page.js):

"use client";

import { signIn } from "next-auth/react";
import { useSearchParams, useRouter } from "next/navigation";
import { useState } from "react";

export default function LoginPage() {
    const router = useRouter();
    const callbackUrl = useSearchParams().get("callbackUrl") || "/";
    const course = callbackUrl.split("/").pop();
    let [loading, setLoading] = useState(false);
    let [password, setPassword] = useState("");
    const [error, setError] = useState("");

    async function onSubmit(event) {
        event.preventDefault();
        try {
            setLoading(true);
            const res = await signIn("credentials", {
                redirect: false,
                courseName: course,
                password: password,
                callbackUrl
            });
            if (!res?.error) {
                setError("");
                console.log(`tryin to redirect to ${callbackUrl}`);
                router.push(callbackUrl);
            } else {
                setError("falsches Passwort");
            }
            setLoading(false);
        } catch (error) {
            setLoading(false);
            setError(error);
        }
    }

    function handleChange(event) {
        event.preventDefault();
        setPassword(event.target.value);
    }

    return (
        <main style={{ display: "flex", justifyContent: "center" }}>
            <div className="LoginContainer">
                <br />
                <div className="LoginBackgroundImage">
                    <h1 className="LoginHeading">Login</h1>
                </div>
                <form onSubmit={onSubmit}>
                    {error ? <strong className="w3-text-red">{error}</strong> : ""}
                    <div>
                        <p style={{ margin: 5 }}>
                            <strong>{course}</strong>
                        </p>
                    </div>
                    <div>
                        <input
                            className="passwordField"
                            required
                            type="password"
                            name="password"
                            value={password}
                            onChange={handleChange}
                            placeholder="Passwort"
                        />
                    </div>
                    <button className="loginButton" type="submit" disabled={loading}>
                        {loading ? "lädt..." : "Anmelden"}
                    </button>
                </form>
            </div>
        </main>
    );
}

As you can see from the path, I'm using the new /app directory for routing. I know the login process is working because I can then call the callbackUrl manually in the browser, and the content that requires authorization is displayed. I can also see in the developer console that the command

console.log(`tryin to redirect to ${callbackUrl}`);

is performed. But the page keeps showing the signIn-Page.

英文:

After a successful login on my custom signIn-Page, I use with next-auth, I'm trying to redirect back to the callbackUrl, but that doesn't work.
I'm using react 18.2.0, next 13.4.8-canary.2 and next-auth 4.22.1.

signIn-Page (\src\app\api\auth\signin\page.js):

&quot;use client&quot;;
import { signIn } from &quot;next-auth/react&quot;;
import { useSearchParams, useRouter } from &quot;next/navigation&quot;;
import { useState } from &quot;react&quot;;
export default function LoginPage() {
const router = useRouter();
const callbackUrl = useSearchParams().get(&quot;callbackUrl&quot;) || &quot;/&quot;;
const course = callbackUrl.split(&quot;/&quot;).pop();
let [loading, setLoading] = useState(false);
let [password, setPassword] = useState(&quot;&quot;);
const [error, setError] = useState(&quot;&quot;);
async function onSubmit(event) {
event.preventDefault();
try {
setLoading(true);
const res = await signIn(&quot;credentials&quot;, {
redirect: false,
courseName: course,
password: password,
callbackUrl
});
if (!res?.error) {
setError(&quot;&quot;);
console.log(`tryin to redirect to ${callbackUrl}`);
router.push(callbackUrl);
} else {
setError(&quot;falsches Passwort&quot;);
}
setLoading(false);
} catch (error) {
setLoading(false);
setError(error);
}
}
function handleChange(event) {
event.preventDefault();
setPassword(event.target.value);
}
return (
&lt;main style={{ display: &quot;flex&quot;, justifyContent: &quot;center&quot; }}&gt;
&lt;div className=&quot;LoginContainer&quot;&gt;
&lt;br /&gt;
&lt;div className=&quot;LoginBackgroundImage&quot;&gt;
&lt;h1 className=&quot;LoginHeading&quot;&gt;Login&lt;/h1&gt;
&lt;/div&gt;
&lt;form onSubmit={onSubmit}&gt;
{error ? &lt;strong className=&quot;w3-text-red&quot;&gt;{error}&lt;/strong&gt; : &quot;&quot;}
&lt;div&gt;
&lt;p style={{ margin: 5 }}&gt;
&lt;strong&gt;{course}&lt;/strong&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;input
className=&quot;passwordField&quot;
required
type=&quot;password&quot;
name=&quot;password&quot;
value={password}
onChange={handleChange}
placeholder=&quot;Passwort&quot;
/&gt;
&lt;/div&gt;
&lt;button className=&quot;loginButton&quot; type=&quot;submit&quot; disabled={loading}&gt;
{loading ? &quot;l&#228;dt...&quot; : &quot;Anmelden&quot;}
&lt;/button&gt;
&lt;/form&gt;
&lt;/div&gt;
&lt;/main&gt;
);
}

As you can see from the path, I'm using the new /app directory for routing. I know the login process is working because I can then call the callbackUrl manually in the browser and the content that requires authorization is displayed. I can also see in the developer console that the command

> console.log(`tryin to redirect to ${callbackUrl}`);

is performed. But the page keeps showing the signIn-Page.

答案1

得分: 0

我认为,我找到了原因。使用useRouter().push()跳转到的目标页面本身重定向到了登录页面。只有在您未登录为正确用户时,才应执行此重定向。由于重定向已经执行了一次以到达登录页面,尽管之后正确的用户已登录,但可能再次执行了重定向。造成这种情况的原因可能是目标页面是一个服务器页面,在登录后不会再次渲染。我现在通过直接链接到登录页面而不先访问目标页面来解决了这个问题,只有在登录后才首次访问目标页面。

英文:

I think, I found the reason. The target-page to which I useRouter().push() had a redirect itself to the loginpage. This redirect should only be executed if you are not logged in as the correct user. Since the redirect was already executed once to get to the login page, it was probably executed again afterwards, although the correct user was then logged in. The reason for this could be that the target-page is a server-page which is not rendered again after login. I have now solved this by linking directly to the login-page without calling up the target-page first and only after login is the target-page called up for the first time.

huangapple
  • 本文由 发表于 2023年6月29日 06:32:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/76577087.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定