我有一个
NestJS
后端,它在 jwt 中有自己的身份验证
和 NextJs
+ next-auth
应用程序,我想实现通过 Google 功能登录,但下一个身份验证使用自己生成的令牌,我希望 next-auth
使用来自 NestJS
后端的我自己的访问令牌,我该怎么做?
我尝试将回调 URL 放置到后端,以将经过身份验证的用户发送到后端,并将请求重定向到使用自定义生成的令牌的数据库中的用户的下一个身份验证回调
下一个身份验证提供商
GoogleProvider({
clientId: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
authorization: {
params: {
request_uri: `${process.env.BACKEND_URL}/auth/google/callback`,
},
},
}),
在巢中
@Public()
@Get('google/callback')
@UseGuards(GoogleOAuthGuard)
@Redirect('f')
googleAuthRedirect(@Request() req) {
console.log('success');
return null;
// return this.appService.googleLogin(req);
}
但是用户使用他的Google帐户登录后,我从后端收到错误
missing code verifier
如何告诉
next-auth
存储来自 Google 验证的 Nest 后端数据库的用户,而不是 Google 返回的用户?
要解决 NextAuth 中安全管理刷新令牌的问题,您可以使用 [next-refresh-token](https://www.npmjs.com/package/next-refresh-token) 包。该包提供了一种安全有效的方法来处理刷新令牌,确保它们存储在服务器端的 httpOnly cookie 中,而不是将它们暴露给客户端。
首先,使用以下命令安装软件包:
npm install next-refresh-token
下面是如何将
next-refresh-token
集成到 Next.js 项目中以安全管理刷新令牌的分步实施。
next-refresh-token
next-refresh-token
包增强了 NextAuth,允许您安全地处理刷新令牌,而无需在客户端公开它们。按如下方式更新您的 NextAuth API 路由:
// pages/api/auth/[...nextauth].js
import NextAuth from "next-auth";
import { withRefreshToken } from "next-refresh-token";
export default withRefreshToken(
NextAuth({
providers: [
{
id: "credentials",
name: "Credentials",
authorize: async (credentials) => {
const user = await loginToYourBackend(credentials); // Custom login logic
if (user) {
return user;
} else {
return null;
}
},
},
],
callbacks: {
async jwt({ token, user }) {
if (user) {
token.accessToken = user.accessToken;
token.refreshToken = user.refreshToken;
}
return token;
},
async session({ session, token }) {
session.accessToken = token.accessToken;
return session;
},
},
secret: process.env.NEXTAUTH_SECRET, // Set a secure secret
}),
{
refreshTokenEndpoint: "/api/auth/refresh", // Endpoint to handle token refreshes
accessTokenExpiry: 60 * 15, // Access token expiry time in seconds (e.g., 15 minutes)
}
);
刷新端点用于使用存储在 httpOnly cookie 中的刷新令牌安全地生成新的访问令牌。
// pages/api/auth/refresh.js
import { refreshTokenHandler } from "next-refresh-token";
export default refreshTokenHandler({
async refresh(refreshToken) {
// Replace this with your backend API call to get a new access token
const response = await fetch("https://your-backend.com/api/refresh-token", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ refreshToken }),
});
if (response.ok) {
const data = await response.json();
return {
accessToken: data.accessToken, // Return the new access token
refreshToken: data.refreshToken, // Return a new refresh token if applicable
};
} else {
throw new Error("Failed to refresh token");
}
},
});
为了确保您的客户端 API 调用始终具有有效的访问令牌,您可以使用
getSession
中的 next-auth/react
检查会话并在需要时刷新令牌。
import { getSession } from "next-auth/react";
async function fetchData() {
const session = await getSession(); // Get the session object with the access token
const accessToken = session?.accessToken;
const response = await fetch("/api/protected-endpoint", {
headers: {
Authorization: `Bearer ${accessToken}`,
},
});
if (!response.ok) {
throw new Error("Failed to fetch data");
}
return response.json();
}
如果您的应用严重依赖受保护的路由,您可以创建中间件来确保所有 API 请求都经过身份验证并且访问令牌有效。
// middleware.js
import { withAuthMiddleware } from "next-refresh-token";
export default withAuthMiddleware({
tokenRefreshEndpoint: "/api/auth/refresh",
});
next-refresh-token
next-auth
的即插即用解决方案。通过使用
next-refresh-token
包,您可以安全地处理刷新令牌,而无需将它们暴露给客户端。这种方法增强了安全性并简化了令牌生命周期管理,使其成为生产就绪应用程序的绝佳选择。
更多详情请参考官方文档:next-refresh-token。