Reddit的访问令牌有效期为1小时,但我希望登录到我的应用程序的用户能够在Reddit上发表评论。这意味着我需要在他们的访问令牌过期后刷新它。由于我使用的是数据库(PlanetScale + Prisma),而不是JWT策略,所以这里找到的文档https://next-auth.js.org/tutorials/refresh-token-rotation对我没有用处(从未调用jwt回调)。
据我所理解,这意味着在不每次访问数据库的情况下检查session回调中的过期并刷新令牌是不可能的。
如果我想刷新数据库中的访问令牌,我可以做什么?我是否应该使用JWT策略,即使我使用的是数据库?
发布于 2022-08-27 12:14:03
要在使用数据库策略时执行刷新令牌旋转,可以执行以下操作:
async function refreshAccessToken(session: Session) {
if (!session.user?.id) {
return;
}
const {
id,
refresh_token: refreshToken,
expires_at: expiresAt,
} = (await prisma.account.findFirst({
where: { userId: session.user.id, provider: "reddit" },
})) ?? {};
if (!id || !refreshToken) {
return;
}
// If expired refresh it
if (expiresAt && Date.now() / 1000 > expiresAt) {
const authorizationString = Buffer.from(
`${process.env?.["REDDIT_CLIENT_ID"]}:${process.env?.["REDDIT_CLIENT_SECRET"]}`,
).toString("base64");
const headers = {
Authorization: `Basic ${authorizationString}`,
"Content-Type": "application/x-www-form-urlencoded",
};
const urlSearchParams = new URLSearchParams();
urlSearchParams.append("grant_type", "refresh_token");
urlSearchParams.append("refresh_token", refreshToken);
urlSearchParams.append("redirect_uri", `${process.env?.["NEXTAUTH_URL"]}/api/auth/callback/reddit`);
const { data } = await axios.post<RedditResponse>("https://www.reddit.com/api/v1/access_token", urlSearchParams, {
headers,
});
await prisma.account.update({
where: { id },
data: {
access_token: data.access_token,
expires_at: Math.floor(Date.now() / 1000) + data.expires_in,
refresh_token: data.refresh_token,
token_type: data.token_type,
scope: data.scope,
},
});
}
}我想你可以在任何地方用这个。我不知道在session回调中使用它是否有意义,因为它可能会影响性能,所以每次您确实需要访问令牌时就调用它吧?我不知道这方面的最佳做法是什么.
发布于 2022-08-27 09:45:31
经过几个小时的修补,我才发现如何将刷新令牌放到数据库中!
在下一个令牌刷新教程的第一部分之后,将授权param添加到提供者选项中
const GOOGLE_AUTHORIZATION_URL =
"https://accounts.google.com/o/oauth2/v2/auth?" +
new URLSearchParams({
prompt: "consent",
access_type: "offline",
response_type: "code",
});和
export default NextAuth({
providers: [
GoogleProvider({
clientId: process.env.GOOGLE_ID,
clientSecret: process.env.GOOGLE_SECRET,
authorization: GOOGLE_AUTHORIZATION_URL,
}),这会让我很好的解决剩下的问题.希望它也适用于你!
https://stackoverflow.com/questions/73507135
复制相似问题