Vollständiger 1:1-Port des cloudflare-worker/ (dogfather-universe-postfach) auf server-internal/: Bewerbungs-Postfach mit Rollen/Rechten, Team- Zugangsverwaltung (verschlüsselte Owner-only-Codes), DogiCrew-Supporter-Abo (PayPal Subscriptions, Google-Login, Resend-E-Mail, 30-Monats-Prämienzyklus) und automatische TikTok-Live-Erkennung. D1 -> better-sqlite3, Cloudflare- Cron -> node-cron. Läuft ohne gesetzte Secrets weiter (PayPal/Google/Resend/ Ticketanizer/Discord bleiben "nicht konfiguriert" statt kaputt), bis die echten Zugangsdaten eingetragen werden.
46 lines
2.1 KiB
JavaScript
46 lines
2.1 KiB
JavaScript
/* =====================================================================
|
|
lib/google-auth.js — Verifiziert ein Google-ID-Token ("Mit Google
|
|
anmelden") serverseitig, für den öffentlichen Supporter-Login.
|
|
1:1 portiert aus cloudflare-worker/src/lib/google-auth.js, env.X → process.env.X.
|
|
|
|
Braucht GOOGLE_CLIENT_ID (öffentlich, KEIN Geheimnis). Ohne gesetzten
|
|
Wert bleibt "Mit Google anmelden" ausgeblendet (siehe getPublicConfig
|
|
in routes/supporter.js) statt kaputt zu sein.
|
|
|
|
Verifikation läuft über Googles offiziellen tokeninfo-Endpunkt
|
|
(https://oauth2.googleapis.com/tokeninfo) — Google prüft dort Signatur,
|
|
Ablaufzeit und Aussteller selbst und gibt die Nutzdaten zurück.
|
|
===================================================================== */
|
|
|
|
export class GoogleAuthNotConfiguredError extends Error {
|
|
constructor() {
|
|
super("Google-Login ist noch nicht eingerichtet (GOOGLE_CLIENT_ID fehlt).");
|
|
this.name = "GoogleAuthNotConfiguredError";
|
|
this.code = "GOOGLE_AUTH_NOT_CONFIGURED";
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Prüft ein von Google Identity Services im Browser ausgestelltes ID-Token.
|
|
* Gibt bei Erfolg die bestätigten Nutzerdaten zurück (E-Mail ist von Google
|
|
* selbst bereits verifiziert — braucht deshalb KEINEN zusätzlichen
|
|
* E-Mail-Bestätigungscode mehr, siehe routes/supporter.js).
|
|
*/
|
|
export async function verifyGoogleIdToken(credential) {
|
|
if (!process.env.GOOGLE_CLIENT_ID) throw new GoogleAuthNotConfiguredError();
|
|
if (!credential) return { ok: false, reason: "Kein Token übergeben." };
|
|
|
|
const res = await fetch(`https://oauth2.googleapis.com/tokeninfo?id_token=${encodeURIComponent(credential)}`);
|
|
if (!res.ok) return { ok: false, reason: "Google-Token konnte nicht geprüft werden." };
|
|
const data = await res.json();
|
|
|
|
if (data.aud !== process.env.GOOGLE_CLIENT_ID) return { ok: false, reason: "Token ist für eine andere App ausgestellt." };
|
|
if (!data.email || data.email_verified !== "true") return { ok: false, reason: "E-Mail-Adresse ist bei Google nicht bestätigt." };
|
|
|
|
return {
|
|
ok: true,
|
|
email: String(data.email).toLowerCase(),
|
|
name: data.name || data.given_name || data.email.split("@")[0],
|
|
};
|
|
}
|