我目前正在使用 auth0 对 Next.js 应用程序中的用户进行身份验证。
我正在使用 @auth0/nextjs-auth0 SDK 并按照文档进行操作。
但是,我无法弄清楚如何根据用户访问登录表单的页面在登录后动态重定向用户。
在我当前正在尝试构建的应用程序中,用户可以从主页“/”以及“/browse”中的导航栏元素登录。然而,登录后,它总是重定向回“/”,而我想将用户重定向到“/browse”或“/browse/[id],如果这是他们开始登录过程的地方。
我尝试使用 https://community.auth0.com/t/redirecting-to-another-page-other-than-using-nextjs-auth0/66920 作为指南,但此方法只允许我重定向到预先定义的路线。我想知道如何使重定向 URL 动态化。
提前致谢!
编辑:通过深入研究 req 对象并将 returnTo 值设置为“referer”,我现在设法找到了解决方案。
import { handleAuth, handleLogin } from '@auth0/nextjs-auth0';
const getLoginState = (req, loginOptions) => {
return {
returnTo: req.headers.referer
};
};
export default handleAuth({
async login(req, res) {
try {
await handleLogin(req, res, { getLoginState });
} catch (err) {
res.status(err.status ?? 500).end(err.message)
}
}
});
到目前为止,我没有看到任何明显的问题,但我不完全确定这种方法是否有任何缺点,所以我将不胜感激任何反馈。
这个怎么样?
https://auth0.github.io/nextjs-auth0/modules/instance.html#initauth0
# /lib/auth0,js
import { initAuth0 } from "@auth0/nextjs-auth0";
export default initAuth0({
secret: process.env.SESSION_COOKIE_SECRET,
issuerBaseURL: process.env.NEXT_PUBLIC_AUTH0_DOMAIN,
baseURL: process.env.NEXT_PUBLIC_BASE_URL,
clientID: process.env.NEXT_PUBLIC_AUTH0_CLIENT_ID,
clientSecret: process.env.AUTH0_CLIENT_SECRET,
routes: {
callback:
process.env.NEXT_PUBLIC_REDIRECT_URI ||
"http://localhost:3000/api/auth/callback",
postLogoutRedirect:
process.env.NEXT_PUBLIC_POST_LOGOUT_REDIRECT_URI ||
"http://localhost:3000",
},
authorizationParams: {
response_type: "code",
scope: process.env.NEXT_PUBLIC_AUTH0_SCOPE,
},
session: {
absoluteDuration: process.env.SESSION_COOKIE_LIFETIME,
},
});
https://auth0.github.io/nextjs-auth0/modules/handlers_login.html#handlelogin
https://auth0.github.io/nextjs-auth0/interfaces/handlers_login.loginoptions.html#returnto
# /pages/api/auth/login.js
import auth0 from "../../../lib/auth0";
export default async function login(req, res) {
let options = {
returnTo: 'http://localhost:3000/dashboard'
}
try {
await auth0.handleLogin(req, res, options);
} catch (error) {
console.error(error);
res.status(error.status || 500).end(error.message);
}
}
认证成功后,您将进入仪表板页面。
使用以下内容创建
/pages/api/auth/callback.js
import auth0 from "../../../lib/auth0";
const afterCallback = (req, res, session, state) => {
// console.log(session)
console.log(state)
return session
};
export default async function callback(req, res) {
try {
console.log(auth0)
await auth0.handleCallback(req, res, { afterCallback });
} catch (error) {
console.error(error);
res.status(error.status || 500).end(error.message);
}
}
尝试登录并在控制台中查找状态,
{ returnTo: 'http://localhost:3000/dashboard' }
干杯!
这个库有一个内置的页面保护,会自动将浏览器重定向到保存的登录Url(默认为
/api/auth/login
,但您可以在<UserProvider loginUrl={*your_custom_login_path*}>
中自定义它。
所以
import { withPageAuthRequired } from "@auth0/nextjs-auth0/client";
和
export default withPageAuthRequired(*your_page_component*)
浏览器将在其重定向中获取一个查询参数 returnTo,您可以在自定义重定向中处理该参数,否则,如果您使用 auth0 的默认进程,它将在成功登录后自动重定向到此路径。
这是一个工作代码,我觉得它有一个非常干净的方法。
会话结束后,用户将首先注销 (
/api/auth/logout
),因此我们将在此处捕获 lastVisited
页面,发布哪个用户将被重定向到注销重定向页面(请阅读有关替代注销的信息此处) .
因为,在大多数项目中,用户都会返回到基本 URL (
localhost:3000
),我们可以再次捕获 lastVisited
,并将其作为 returnTo
参数自动传递到 handleLogin 中。如果您有自定义登录处理程序,请确保不要更改 returnTo
参数,并且一切都应该正常工作。
使用handleLogout中间件中的当前页面引用标头捕获lastVisited页面并作为查询参数传递。
// pages/api/auth/[auth0].ts
import { handleAuth, handleLogout } from 'lib/auth0'
export default handleAuth({
async logout(req, res) {
try {
let callingUrl
if (req.headers.referer) {
callingUrl = new URL(req.headers.referer)
}
await handleLogout(req, res, { returnTo: `/?lastVisited=${callingUrl?.pathname}` })
} catch (error) {
// TODO: Need to work on the 401, 404 errors pages
res.writeHead(401, { Location: `custom-error-page` })
res.end()
}
},
})
现在我们已经掌握了要重定向回的页面,我们可以使用
getServerSideProps
在 req.query
中捕获该页面,并将其自动作为 returnTo
API 中的 /login
参数传递。
// pages/index.tsx
import { ROUTES } from 'constants/routes'
import { GetServerSideProps, NextPage } from 'next'
const HomePage: NextPage = () => {
return <><This is the base url</>
}
export const getServerSideProps: GetServerSideProps = async ({ query }) => {
// Redirect based on the parameters or query
const destination = query?.lastVisited?.toString() || ROUTES.DASHBOARD
return {
redirect: {
destination,
permanent: false,
},
}
}
export default HomePage
希望这对您有所帮助并节省一些时间。我确实为此挠头好几个小时。