ScaleRocket/Web

Authentification

Configuration de l'authentification avec email/mot de passe, fournisseurs OAuth, gestion des sessions et protection des routes.

Vue d'ensemble

ScaleRocket utilise Supabase Auth pour l'authentification. Il prend en charge la connexion par email/mot de passe, les fournisseurs OAuth (Google, GitHub), la réinitialisation du mot de passe et la gestion automatique des sessions.

Supabase gère toute la logique d'authentification côté serveur. Le SDK client gère les tokens et le rafraîchissement des sessions automatiquement.

ScaleRocket utilise Convex Auth pour l'authentification. Il prend en charge la connexion par email/mot de passe, les fournisseurs OAuth (Google, GitHub) et la gestion automatique des sessions.

Convex Auth est construit sur la bibliothèque @convex-dev/auth et gère toute la logique d'authentification côté serveur.

Les pages d'authentification se trouvent dans apps/app/src/pages/auth/.

Architecture d'authentification

User -> Login Page -> Supabase Auth -> JWT Token -> App
                                    -> Trigger: create profile
                                    -> Session stored in browser
User -> Login Page -> Convex Auth -> Session Token -> App
                                  -> Mutation: create profile
                                  -> Session managed by Convex

Pages de connexion et d'inscription

Inscription

Située dans apps/app/src/pages/auth/register.tsx :

import { supabase } from "@/lib/supabase";

const { data, error } = await supabase.auth.signUp({
  email,
  password,
  options: {
    data: {
      full_name: name,
    },
  },
});

Située dans apps/app/src/pages/auth/register.tsx :

import { useAuthActions } from "@convex-dev/auth/react";

const { signIn } = useAuthActions();

await signIn("password", { email, password, name, flow: "signUp" });

Connexion

Située dans apps/app/src/pages/auth/login.tsx :

const { data, error } = await supabase.auth.signInWithPassword({
  email,
  password,
});

Située dans apps/app/src/pages/auth/login.tsx :

import { useAuthActions } from "@convex-dev/auth/react";

const { signIn } = useAuthActions();

await signIn("password", { email, password, flow: "signIn" });

Fournisseurs OAuth

Google et GitHub

const { data, error } = await supabase.auth.signInWithOAuth({
  provider: "google", // or "github"
  options: {
    redirectTo: `${window.location.origin}/auth/callback`,
  },
});
import { useAuthActions } from "@convex-dev/auth/react";

const { signIn } = useAuthActions();

// Google
await signIn("google");

// GitHub
await signIn("github");

Ajouter un nouveau fournisseur OAuth

  1. Activez le fournisseur dans votre tableau de bord Supabase sous Authentication > Providers.
  2. Ajoutez l'identifiant client et le secret depuis la console développeur du fournisseur.
  3. Ajoutez un bouton dans les pages de connexion/inscription :
<Button onClick={() => signInWithOAuth("discord")}>
  Continue with Discord
</Button>
  1. Configurez le fournisseur dans convex/auth.config.ts.
  2. Ajoutez l'identifiant client et le secret comme variables d'environnement.
  3. Ajoutez un bouton dans les pages de connexion/inscription :
<Button onClick={() => signIn("discord")}>
  Continue with Discord
</Button>

Callback d'authentification

La page de callback dans apps/app/src/pages/auth/callback.tsx échange le code OAuth contre une session :

const { data, error } = await supabase.auth.exchangeCodeForSession(code);

Convex gère le callback OAuth automatiquement. Aucun échange de code manuel n'est nécessaire -- la bibliothèque @convex-dev/auth gère le flux de callback.

Flux de réinitialisation du mot de passe

  1. L'utilisateur demande une réinitialisation depuis la page de connexion :
await supabase.auth.resetPasswordForEmail(email, {
  redirectTo: `${window.location.origin}/auth/reset-password`,
});
import { useAuthActions } from "@convex-dev/auth/react";

const { signIn } = useAuthActions();

await signIn("password", { email, flow: "reset" });
  1. L'utilisateur clique sur le lien dans l'email et arrive sur la page de réinitialisation.

  2. L'utilisateur définit un nouveau mot de passe :

await supabase.auth.updateUser({ password: newPassword });
await signIn("password", { email, password: newPassword, code, flow: "reset-verification" });

Gestion des sessions

Le client Supabase gère automatiquement les sessions :

// Get current session
const { data: { session } } = await supabase.auth.getSession();

// Listen for auth state changes
supabase.auth.onAuthStateChange((event, session) => {
  if (event === "SIGNED_IN") {
    // redirect to dashboard
  }
  if (event === "SIGNED_OUT") {
    // redirect to login
  }
});

Les sessions sont stockées dans localStorage et rafraîchies automatiquement avant expiration.

Convex gère les sessions automatiquement via le ConvexAuthProvider :

import { useConvexAuth } from "convex/react";

const { isAuthenticated, isLoading } = useConvexAuth();

// Côté serveur (dans les fonctions Convex) :
import { getAuthUserId } from "@convex-dev/auth/server";

const userId = await getAuthUserId(ctx);

Les sessions sont gérées côté serveur par Convex. Aucune gestion manuelle des tokens n'est nécessaire.

Protection des routes

Protégez les routes en utilisant un composant de garde d'authentification :

// apps/app/src/components/auth-guard.tsx
import { useAuth } from "@/hooks/use-auth";
import { Navigate } from "react-router-dom";

export function AuthGuard({ children }: { children: React.ReactNode }) {
  const { user, loading } = useAuth();

  if (loading) return <LoadingSpinner />;
  if (!user) return <Navigate to="/auth/login" />;

  return children;
}

Protégez les routes en utilisant le hook d'authentification Convex :

// apps/app/src/components/auth-guard.tsx
import { useConvexAuth } from "convex/react";
import { Navigate } from "react-router-dom";

export function AuthGuard({ children }: { children: React.ReactNode }) {
  const { isAuthenticated, isLoading } = useConvexAuth();

  if (isLoading) return <LoadingSpinner />;
  if (!isAuthenticated) return <Navigate to="/auth/login" />;

  return children;
}

Encapsulez les routes protégées :

<Route
  path="/dashboard"
  element={
    <AuthGuard>
      <Dashboard />
    </AuthGuard>
  }
/>

Le hook useAuth

// apps/app/src/hooks/use-auth.ts
export function useAuth() {
  const [user, setUser] = useState<User | null>(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    supabase.auth.getSession().then(({ data: { session } }) => {
      setUser(session?.user ?? null);
      setLoading(false);
    });

    const { data: { subscription } } = supabase.auth.onAuthStateChange(
      (_event, session) => {
        setUser(session?.user ?? null);
      }
    );

    return () => subscription.unsubscribe();
  }, []);

  return { user, loading };
}
// apps/app/src/hooks/use-auth.ts
import { useConvexAuth } from "convex/react";
import { useQuery } from "convex/react";
import { api } from "../../convex/_generated/api";

export function useAuth() {
  const { isAuthenticated, isLoading } = useConvexAuth();
  const user = useQuery(api.users.getMe);

  return {
    user: isAuthenticated ? user : null,
    loading: isLoading,
  };
}

Suppression de compte

ScaleRocket inclut une fonctionnalité de suppression de compte qui gère le nettoyage complet du compte. Les utilisateurs peuvent supprimer leur compte depuis Settings > Danger Zone dans le tableau de bord.

Fonctionnement

La Edge Function delete-account effectue les étapes suivantes dans l'ordre :

  1. Annule l'abonnement Stripe -- Si l'utilisateur a un abonnement actif, il est annulé immédiatement via l'API Stripe.
  2. Supprime les données utilisateur -- Supprime tous les enregistrements liés à l'utilisateur de la base de données (profil, abonnement, crédits, etc.).
  3. Supprime l'utilisateur auth -- Supprime l'utilisateur de Supabase Auth en utilisant le client service role.

L'action Convex deleteAccount effectue les étapes suivantes dans l'ordre :

  1. Annule l'abonnement Stripe -- Si l'utilisateur a un abonnement actif, il est annulé immédiatement via l'API Stripe.
  2. Supprime les données utilisateur -- Supprime tous les enregistrements liés à l'utilisateur de la base de données (profil, abonnement, crédits, etc.).
  3. Supprime l'utilisateur auth -- Supprime la session et les données d'authentification de l'utilisateur.

Utilisation

La fonction nécessite un paramètre confirmEmail qui doit correspondre à l'adresse email de l'utilisateur pour éviter une suppression accidentelle :

const { data, error } = await supabase.functions.invoke("delete-account", {
  body: {
    confirmEmail: user.email,
  },
});

Si l'email fourni ne correspond pas à l'email de l'utilisateur authentifié, la fonction renvoie une erreur 400.

La mutation nécessite un paramètre confirmEmail qui doit correspondre à l'adresse email de l'utilisateur pour éviter une suppression accidentelle :

import { useMutation } from "convex/react";
import { api } from "../../convex/_generated/api";

const deleteAccount = useMutation(api.users.deleteAccount);

await deleteAccount({ confirmEmail: user.email });

Personnalisation des pages d'authentification

Les pages d'authentification utilisent des composants de packages/ui. Pour personnaliser :

  1. Style : Modifiez les composants de formulaire dans apps/app/src/pages/auth/.
  2. Champs : Ajoutez des champs au formulaire d'inscription -- ils sont stockés dans raw_user_meta_data.
  3. Redirection : Changez la redirection post-connexion dans le gestionnaire de callback d'authentification.
  4. Modèles d'email : Personnalisez les emails de confirmation/réinitialisation dans le tableau de bord Supabase sous Authentication > Email Templates.

Fini ? Marquez cette page comme terminée.

On this page