diff --git a/lib/nextauth.ts b/lib/nextauth.ts index c4c4329..d17507a 100644 --- a/lib/nextauth.ts +++ b/lib/nextauth.ts @@ -1,5 +1,5 @@ import { PrismaAdapter } from "@auth/prisma-adapter" -import NextAuth, { NextAuthOptions, User } from "next-auth" +import NextAuth, { NextAuthOptions, TokenSet, User } from "next-auth" import Github from "next-auth/providers/github" import prisma from "./prisma" import { Adapter } from "next-auth/adapters" @@ -15,7 +15,7 @@ export const authOptions: NextAuthOptions = { name: profile.name, email: profile.email, image: profile.avatar_url, - username: profile.login, + username: profile.username, } as User; }, }), @@ -28,15 +28,55 @@ export const authOptions: NextAuthOptions = { strategy: "jwt", }, callbacks: { - session: ({ session, token }) => { - return { - ...session, - user: { - ...session.user, - id: token.id, - username: token.username, - }, - }; + session: async ({ session, token }) => { + const [github] = await prisma.account.findMany({ + where: { userId: session.user.id, provider: "github" }, + }) + if ((github.expires_at || 0) * 1000 < Date.now()) { + // If the access token has expired, try to refresh it + try { + const response = await fetch("https://github.com/login/oauth/access_token", { + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + client_id: process.env.GITHUB_ID as string, + client_secret: process.env.GITHUB_SECRET as string, + grant_type: "refresh_token", + refresh_token: github.refresh_token as string, + }), + method: "POST", + }) + + const tokens: TokenSet = await response.json() + + if (!response.ok) throw tokens + + await prisma.account.update({ + data: { + access_token: tokens.access_token, + expires_at: Math.floor(Date.now() / 1000 + (tokens.expires_at as number)), + refresh_token: tokens.refresh_token ?? github.refresh_token, + }, + where: { + provider_providerAccountId: { + provider: "github", + providerAccountId: github.providerAccountId, + }, + }, + }) + } catch (error) { + console.error("Error refreshing access token", error) + // The error property will be used client-side to handle the refresh token error + session.error = "RefreshAccessTokenError" + } + } + return { + ...session, + user: { + ...session.user, + id: token.id, + username: token.username, + }, + } }, jwt: ({ token, user }) => { if (user) { @@ -47,7 +87,8 @@ export const authOptions: NextAuthOptions = { username: u.username, }; } - return token; + console.log(token); + return { ...token, username: token.username }; }, }, events: {