import { AuthOptions, getServerSession } from "next-auth" import CredentialsProvider from "next-auth/providers/credentials"; import { createAppClient, viemConnector } from "@farcaster/auth-client"; declare module "next-auth" { interface Session { user: { fid: number; }; } } function getDomainFromUrl(urlString: string | undefined): string { if (!urlString) { console.warn('NEXTAUTH_URL is not set, using localhost:3000 as fallback'); return 'localhost:3000'; } try { const url = new URL(urlString); return url.hostname; } catch (error) { console.error('Invalid NEXTAUTH_URL:', urlString, error); console.warn('Using localhost:3000 as fallback'); return 'localhost:3000'; } } export const authOptions: AuthOptions = { // Configure one or more authentication providers providers: [ CredentialsProvider({ name: "Sign in with Farcaster", credentials: { message: { label: "Message", type: "text", placeholder: "0x0", }, signature: { label: "Signature", type: "text", placeholder: "0x0", }, // In a production app with a server, these should be fetched from // your Farcaster data indexer rather than have them accepted as part // of credentials. // question: should these natively use the Neynar API? name: { label: "Name", type: "text", placeholder: "0x0", }, pfp: { label: "Pfp", type: "text", placeholder: "0x0", }, }, async authorize(credentials, req) { const csrfToken = req?.body?.csrfToken; const appClient = createAppClient({ ethereum: viemConnector(), }); const domain = getDomainFromUrl(process.env.NEXTAUTH_URL); console.log('Using domain for auth:', domain); const verifyResponse = await appClient.verifySignInMessage({ message: credentials?.message as string, signature: credentials?.signature as `0x${string}`, domain, nonce: csrfToken, }); const { success, fid } = verifyResponse; if (!success) { return null; } return { id: fid.toString(), }; }, }), ], callbacks: { session: async ({ session, token }) => { if (session?.user) { session.user.fid = parseInt(token.sub ?? ''); } return session; }, } } export const getSession = () => getServerSession(authOptions)