lucas-neynar 853c63e024
cleanup
2025-03-26 11:42:50 -07:00

96 lines
2.5 KiB
TypeScript

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);
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)