Files
app_fideliter_client/server/pb_hooks/google_native_auth.pb.js
T
2026-07-18 13:11:03 +02:00

106 lines
3.3 KiB
JavaScript

/// Connexion native Google (Credential Manager) pour l'app cliente.
///
/// L'app obtient un « ID token » Google via le sélecteur de compte natif, puis
/// l'envoie ici. On le vérifie auprès de Google, on retrouve (ou on crée) le
/// compte `users`, on s'assure qu'une fiche fidélité `clients` existe (créée
/// automatiquement à partir du nom/prénom Google), et on renvoie une session.
///
/// Endpoint : POST /api/google-native-auth body: { "idToken": "..." }
/// Réponse : { "token": "<jwt pocketbase>", "record": { ...compte... } }
routerAdd("POST", "/api/google-native-auth", (e) => {
// ID client OAuth « Web » (celui passé comme serverClientId côté app).
const WEB_CLIENT_ID =
"831733439319-45cergb7cf8r728fja4m0kcvu2r7fbj9.apps.googleusercontent.com";
const body = new DynamicModel({ idToken: "" });
e.bindBody(body);
const idToken = (body.idToken || "").trim();
if (!idToken) {
throw new BadRequestError("idToken manquant");
}
// Vérification de l'ID token auprès de Google (signature + expiration).
const res = $http.send({
url:
"https://oauth2.googleapis.com/tokeninfo?id_token=" +
encodeURIComponent(idToken),
method: "GET",
timeout: 15,
});
if (res.statusCode !== 200) {
throw new BadRequestError("ID token Google invalide");
}
const p = res.json;
if (p.aud !== WEB_CLIENT_ID) {
throw new BadRequestError("audience inattendue");
}
if (
p.iss !== "accounts.google.com" &&
p.iss !== "https://accounts.google.com"
) {
throw new BadRequestError("issuer inattendu");
}
const email = (p.email || "").toLowerCase();
if (!email) {
throw new BadRequestError("email absent du token");
}
if (String(p.email_verified) !== "true") {
throw new BadRequestError("email Google non verifie");
}
// Compte existant ?
let user = null;
try {
user = $app.findFirstRecordByFilter("users", "email = {:email}", {
email: email,
});
} catch (_) {
user = null;
}
// Sinon création d'un compte client (is_staff = false).
if (!user) {
const collection = $app.findCollectionByNameOrId("users");
user = new Record(collection);
user.set("email", email);
user.set("emailVisibility", false);
user.set("verified", true);
user.set("name", p.name || "");
user.set("is_staff", false);
user.setPassword($security.randomString(30));
$app.save(user);
}
// Fiche fidélité déjà présente ? Sinon on la crée à partir du nom/prénom
// Google → l'app cliente arrive directement sur sa carte (pas de saisie).
let hasProfile = false;
try {
$app.findFirstRecordByFilter("clients", "user = {:uid}", { uid: user.id });
hasProfile = true;
} catch (_) {
hasProfile = false;
}
if (!hasProfile) {
const prenom = p.given_name || "";
let nom = p.family_name || "";
if (!nom) {
nom = p.name || prenom || email.split("@")[0];
}
const code =
"FID-" +
$security.randomStringWithAlphabet(6, "ABCDEFGHJKLMNPQRSTUVWXYZ23456789");
const clientsCol = $app.findCollectionByNameOrId("clients");
const client = new Record(clientsCol);
client.set("user", user.id);
client.set("nom", nom);
client.set("prenom", prenom);
client.set("code", code);
$app.save(client);
}
const token = user.newAuthToken();
return e.json(200, { token: token, record: user.publicExport() });
});