From 18efc1e708821fd1f36532d659b928c320f4a143 Mon Sep 17 00:00:00 2001 From: JustZvan Date: Mon, 6 Apr 2026 14:25:51 +0200 Subject: feat: google signin --- src/account/google.ts | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 src/account/google.ts (limited to 'src/account/google.ts') diff --git a/src/account/google.ts b/src/account/google.ts new file mode 100644 index 0000000..2194a18 --- /dev/null +++ b/src/account/google.ts @@ -0,0 +1,42 @@ +import * as jose from "jose"; +import { logger } from "../lib/pino"; + +const googleJwks = jose.createRemoteJWKSet( + new URL("https://www.googleapis.com/oauth2/v3/certs"), +); + +export interface GoogleUserProfile { + email: string; + emailVerified: boolean; + subject: string; +} + +export async function verifyGoogleIdToken( + token: string, +): Promise { + const googleClientId = process.env.GOOGLE_CLIENT_ID; + + if (!googleClientId) { + logger.error("GOOGLE_CLIENT_ID environment variable not set"); + throw new Error("GOOGLE_CLIENT_ID not configured"); + } + + const { payload } = await jose.jwtVerify(token, googleJwks, { + issuer: ["https://accounts.google.com", "accounts.google.com"], + audience: googleClientId, + }); + + if (typeof payload.email !== "string" || payload.email.length === 0) { + throw new Error("Google token is missing email"); + } + + if (typeof payload.sub !== "string" || payload.sub.length === 0) { + throw new Error("Google token is missing subject"); + } + + return { + email: payload.email, + emailVerified: payload.email_verified === true, + subject: payload.sub, + }; +} -- cgit v1.2.3