Authentication
Login, sessions, tokens og de typiske AI-feilene rundt dem.
Hva du kontrollerer
Gå gjennom hvert punkt i DevTools → Application og Network.
- ›Login: generiske feilmeldinger (ikke «bruker finnes ikke»), rate limiting
- ›Logout: blir token/refresh token faktisk ugyldig, eller bare slettet lokalt?
- ›Sessions/cookies: Secure, HttpOnly, SameSite, utløpstid
- ›Password reset / magic links: engangsbruk, kort levetid, redirect-URL låst til eget domene
- ›OAuth: state-parameter, redirect allowlist, ingen token i URL som logges
- ›JWT: signatur verifiseres på server, alg låst, exp sjekkes, ikke stol på claims som brukeren kan påvirke (user_metadata)
- ›Refresh tokens: rotasjon, revokering ved logout/passordbytte
Klassikeren: skjult Admin-knapp
AI-verktøy løser «bare admin skal se dette» ved å skjule knappen. Endpointet bak er fortsatt åpent for alle med en gyldig session — eller helt uten.
Å skjule UI er brukervennlighet, ikke sikkerhet. Test alltid endpointet direkte.
// UI
{user.role === "admin" && <Button onClick={() => deleteUser(id)}>Delete</Button>}
// server
export const deleteUser = createServerFn({ method: "POST" })
.inputValidator((d: { id: string }) => d)
.handler(async ({ data }) => {
await supabaseAdmin.from("profiles").delete().eq("id", data.id);
});export const deleteUser = createServerFn({ method: "POST" })
.middleware([requireSupabaseAuth])
.inputValidator(z.object({ id: z.string().uuid() }))
.handler(async ({ data, context }) => {
const { data: isAdmin } = await context.supabase
.rpc("has_role", { _user_id: context.userId, _role: "admin" });
if (!isAdmin) throw new Response("Forbidden", { status: 403 });
const { supabaseAdmin } = await import("@/integrations/supabase/client.server");
await supabaseAdmin.from("profiles").delete().eq("id", data.id);
});Rollen hentes fra en egen tabell på server — aldri fra localStorage, user_metadata eller request body.
Slik verifiserer du at backend håndhever
Logg inn som vanlig bruker, kopier en admin-request fra Network (høyreklikk → Copy as cURL) og kjør den med ditt eget token.
# Forventet: 401 uten token, 403 som vanlig bruker
curl -i -X POST https://din-app.test/_serverFn/deleteUser \
-H "Authorization: Bearer <TOKEN_FOR_VANLIG_BRUKER>" \
-H "Content-Type: application/json" \
-d '{"data":{"id":"<annen-bruker-id>"}}'Rolle i token eller localStorage
Hvis du ser role: "user" i localStorage eller i et JWT-claim brukeren kan redigere, endre det og last siden på nytt. Om serveren nå gir mer tilgang, har du en kritisk finding.
Quiz
Lovable har generert en Admin-knapp som bare vises dersom user.role === "admin". API-endepunktet /api/delete-user kontrollerer imidlertid ikke rollen. Er funksjonen sikker?
Appen lagrer isAdmin: true i localStorage etter login og bruker det til å vise adminpanelet, som henter data med supabaseAdmin i en server function uten auth. Hva er alvorligst?