|
|
| import NextAuth, { NextAuthOptions } from "next-auth"; |
| import GoogleProvider from "next-auth/providers/google"; |
| import { PrismaAdapter } from "@next-auth/prisma-adapter"; |
| import { prisma } from "./prisma"; |
|
|
|
|
| export const authOptions: NextAuthOptions = { |
| adapter: PrismaAdapter(prisma), |
| providers: [ |
| GoogleProvider({ |
| clientId: process.env.GOOGLE_CLIENT_ID!, |
| clientSecret: process.env.GOOGLE_CLIENT_SECRET!, |
| allowDangerousEmailAccountLinking: true, |
| authorization: { |
| params: { |
| prompt: "consent", |
| access_type: "offline", |
| response_type: "code", |
| scope: "openid email profile https://www.googleapis.com/auth/drive.readonly https://www.googleapis.com/auth/drive.metadata.readonly https://www.googleapis.com/auth/drive.file", |
| }, |
| }, |
| }), |
| ], |
| callbacks: { |
| async session({ session, token }) { |
| if (session.user && token) { |
| |
| session.user.id = token.sub; |
|
|
| |
| |
| |
| if (token.user) { |
| |
| session.user.name = token.user.name; |
| |
| session.user.email = token.user.email; |
| |
| session.user.image = token.user.image; |
| } |
|
|
| |
| session.accessToken = token.accessToken; |
| |
| session.error = token.error; |
| } |
| return session; |
| }, |
| async jwt({ token, account, user }) { |
| |
| if (account && user) { |
| return { |
| accessToken: account.access_token, |
| accessTokenExpires: Date.now() + (account.expires_in as number) * 1000, |
| refreshToken: account.refresh_token, |
| user, |
| sub: user.id, |
| } |
| } |
|
|
| |
| if (token.accessTokenExpires && Date.now() < (token.accessTokenExpires as number)) { |
| return token |
| } |
|
|
| |
| if (!token.refreshToken) { |
| return { ...token, error: "RefreshAccessTokenError" } |
| } |
|
|
| |
| return refreshAccessToken(token) |
| } |
| }, |
| session: { |
| strategy: "jwt", |
| }, |
| debug: true, |
| secret: process.env.NEXTAUTH_SECRET, |
| }; |
|
|
| async function refreshAccessToken(token: any) { |
| try { |
| const url = |
| "https://oauth2.googleapis.com/token?" + |
| new URLSearchParams({ |
| client_id: process.env.GOOGLE_CLIENT_ID!, |
| client_secret: process.env.GOOGLE_CLIENT_SECRET!, |
| grant_type: "refresh_token", |
| refresh_token: token.refreshToken, |
| }) |
|
|
| const response = await fetch(url, { |
| headers: { |
| "Content-Type": "application/x-www-form-urlencoded", |
| }, |
| method: "POST", |
| }) |
|
|
| const refreshedTokens = await response.json() |
|
|
| if (!response.ok) { |
| throw refreshedTokens |
| } |
|
|
| return { |
| ...token, |
| accessToken: refreshedTokens.access_token, |
| accessTokenExpires: Date.now() + refreshedTokens.expires_in * 1000, |
| refreshToken: refreshedTokens.refresh_token ?? token.refreshToken, |
| } |
| } catch (error) { |
| console.log(error) |
|
|
| return { |
| ...token, |
| error: "RefreshAccessTokenError", |
| } |
| } |
| } |
|
|