Rag*_*hav 18 session node.js jwt next.js next-auth
我已经为我的 Next.js 应用程序实现了 next-auth 身份验证系统。在提供程序中,我选择了凭据,因为我有一个 Node.js 后端服务器。
我面临的问题是下一个身份验证会话的到期时间与我后端的 jwt 令牌的到期时间不同步。这会导致不一致。请帮助我。
下面是我的下一个授权代码
import NextAuth, {
NextAuthOptions,
Session,
SessionStrategy,
User,
} from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";
import { login } from "@actions/auth";
import { toast } from "react-toastify";
import { JWT } from "next-auth/jwt";
import { NextApiRequest, NextApiResponse } from "next";
import { SessionToken } from "next-auth/core/lib/cookie";
// For more information on each option (and a full list of options) go to
// https://next-auth.js.org/configuration/options
const nextAuthOptions = (req: NextApiRequest, res: NextApiResponse) => {
return {
providers: [
CredentialsProvider({
name: "Credentials",
credentials: {
email: { label: "Email", type: "text" },
password: { label: "Password", type: "password" },
},
async authorize(
credentials: Record<"email" | "password", string> | undefined,
req
): Promise<Omit<User, "id"> | { id?: string | undefined } | null> {
// Add logic here to look up the user from the credentials supplied
const response = await login(
credentials?.email!,
credentials?.password!
);
const cookies = response.headers["set-cookie"];
res.setHeader("Set-Cookie", cookies);
if (response) {
var user = { token: response.data.token, data: response.data.user };
return user;
} else {
return null;
}
},
}),
],
refetchInterval: 1 * 24 * 60 * 60,
secret: process.env.NEXTAUTH_SECRET,
debug: true,
session: {
strategy: "jwt" as SessionStrategy,
maxAge: 3 * 24 * 60 * 60,
},
jwt: {
maxAge: 3 * 24 * 60 * 60,
},
callbacks: {
jwt: async ({ token, user }: { token: JWT; user?: User }) => {
user && (token.accessToken = user.token);
user && (token.user = user.data);
return token;
},
session: async ({ session, token }: { session: Session; token: JWT }) => {
session.user = token.user;
session.accessToken = token.accessToken;
return session;
},
},
};
};
export default (req: NextApiRequest, res: NextApiResponse) => {
return NextAuth(req, res, nextAuthOptions(req, res));
};
Run Code Online (Sandbox Code Playgroud)
小智 6
我有一个类似的设置:在客户端上使用带有 jwt 和单独后端会话令牌的凭证身份验证的 NextAuth(版本 4)和 Next.js(带有 App Router 的版本 13)。
这就是我们保持会话同步的方法:
正如其他人提到的,在 NextAuthOptions 中,将maxAge属性设置为与后端服务器上的令牌相同的过期时间。
const nextAuthOptions = {
providers: [...],
session: {
strategy: 'jwt',
maxAge: 4 * 60 * 60 // 4 hours
},
...
}
Run Code Online (Sandbox Code Playgroud)
在经过身份验证的页面的路由树的顶层,检查您的客户端会话是否即将过期,如果是,请刷新令牌。我使用 NextAuth useSession更新函数刷新客户端上的令牌,并向后端 API 发送请求以更新服务器上的令牌过期时间。这将添加到layout.tsx顶层层次结构中的文件中,以供任何需要经过身份验证才能查看的视图。
--layout.tsx--
'use client';
import { useSession } from 'next-auth/react';
export default function Layout() {
const { data: session, status, update } = useSession();
useEffect(() => {
const interval = setInterval(() => {
update(); // extend client session
// TODO request token refresh from server
}, 1000 * 60 * 60)
return () => clearInterval(interval)
}, [update]);
return (
{children}
)
}
Run Code Online (Sandbox Code Playgroud)
如果您还想添加功能来确定用户在延长会话之前是否处于空闲状态,您可以使用react-idle-timer。
--完整的layout.tsx文件--
'use client';
import React, { useEffect } from 'react';
import { useSession, signOut } from 'next-auth/react';
import { useIdleTimer } from 'react-idle-timer';
export default function Layout({ children }: { children: React.ReactNode
}) {
const { data: session, status, update } = useSession();
const CHECK_SESSION_EXP_TIME = 300000; // 5 mins
const SESSION_IDLE_TIME = 300000; // 5 mins
const BASE_URL = process.env.NEXT_PUBLIC_BASE_URL;
const onUserIdle = () => {
console.log('IDLE');
};
const onUserActive = () => {
console.log('ACTIVE');
};
const { isIdle } = useIdleTimer({
onIdle: onUserIdle,
onActive: onUserActive,
timeout: SESSION_IDLE_TIME, //milliseconds
throttle: 500
});
useEffect(() => {
const checkUserSession = setInterval(() => {
const expiresTimeTimestamp = Math.floor(new Date(session?.expires || '').getTime());
const currentTimestamp = Date.now();
const timeRemaining = expiresTimeTimestamp - currentTimestamp;
// If the user session will expire before the next session check
// and the user is not idle, then we want to refresh the session
// on the client and request a token refresh on the backend
if (!isIdle() && timeRemaining < CHECK_SESSION_EXP_TIME) {
update(); // extend the client session
// request refresh of backend token here
} else if (timeRemaining < 0) {
// session has expired, logout the user and display session expiration message
signOut({ callbackUrl: BASE_URL + '/login?error=SessionExpired' });
}
}, CHECK_SESSION_EXP_TIME);
return () => {
clearInterval(checkUserSession);
};
}, [update]);
return (
<main>
{children}
</main>
);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
28100 次 |
| 最近记录: |