[{"data":1,"prerenderedAt":1201},["ShallowReactive",2],{"blog-de-email-link-is-invalid-or-has-expired":3,"blog-index-de":674},{"id":4,"title":5,"body":6,"category":629,"cover":630,"coverAlt":631,"description":632,"draft":633,"extension":634,"faq":635,"image":654,"keywords":655,"meta":662,"navigation":663,"ogTitle":664,"path":665,"published":666,"seo":667,"stem":668,"tldr":669,"updated":666,"__hash__":673},"blog_de\u002Fblog\u002Femail-link-is-invalid-or-has-expired.md","Supabase \"Email link is invalid or has expired\" bei einem neuen Link",{"type":7,"value":8,"toc":616},"minimark",[9,13,24,27,30,38,43,46,61,85,92,96,99,114,117,123,126,142,146,149,161,178,190,194,197,206,209,215,222,226,233,240,246,257,321,329,333,336,342,348,381,387,393,404,408,411,421,427,430,436,442,455,458,464,471,490,495,498,504,510,514,517,526,540,549,569,573,605],[10,11,12],"p",{},"Ein neuer Nutzer registriert sich, öffnet die Bestätigungs-E-Mail eine Minute\nspäter und drückt auf den Knopf. Deine App öffnet sich auf der Startseite,\nimmer noch abgemeldet, und die Adresszeile endet so:",[14,15,20],"pre",{"className":16,"code":18,"language":19},[17],"language-text","#error=access_denied&error_code=otp_expired&error_description=Email+link+is+invalid+or+has+expired\n","text",[21,22,18],"code",{"__ignoreMap":23},"",[10,25,26],{},"Du registrierst dich zur Probe mit deiner eigenen Adresse. Der Link funktioniert\nbeim ersten Mal und bei jedem weiteren Versuch.",[10,28,29],{},"Supabase sagt \"Email link is invalid or has expired\", wenn das Token in einem\nE-Mail-Link schon benutzt wurde, ersetzt wurde oder seine Stunde überschritten\nhat. Bei einem Link, der vor einer Minute ankam, ist der übliche Grund, dass\netwas ihn vor deinem Nutzer benutzt hat: ein Mailfilter, der Links öffnet, um\nsie zu prüfen. Deine App aus Lovable, Bolt, v0, Cursor, Claude Code oder Replit\narbeitet so, wie sie gebaut ist, und die E-Mail, die sie verschickt, lässt sich\nso ändern, dass ein Filter nichts mehr verbrauchen kann.",[10,31,32,33,37],{},"Hier liegt der Teil, den der übliche Rat falsch macht: ",[34,35,36],"strong",{},"\"Bitte sie, es noch\neinmal zu versuchen\" und \"mach den Link länger gültig\" scheitern beide an einem\nFilter."," Ein zweiter Link läuft durch denselben Filter und endet genauso, egal\nwie lange er gegolten hätte.",[39,40,42],"h2",{"id":41},"was-bedeutet-email-link-is-invalid-or-has-expired-in-supabase","Was bedeutet \"Email link is invalid or has expired\" in Supabase?",[10,44,45],{},"Supabase Auth, der Teil von Supabase, der Leute anmeldet, hat hinter dem Link\nkein Token gefunden, das es annehmen wollte.",[10,47,48,49,56,57,60],{},"Die Meldung steht im Code des Auth-Servers selbst. In\n",[50,51,55],"a",{"href":52,"rel":53},"https:\u002F\u002Fgithub.com\u002Fsupabase\u002Fauth\u002Fblob\u002Fmaster\u002Finternal\u002Fapi\u002Fverify.go",[54],"nofollow","der Funktion, die einen E-Mail-Link prüft",",\nkommt sie an zwei Stellen zurück: wenn kein wartendes Token zu dem im Link\npasst, und wenn das passende Token vor längerer Zeit verschickt wurde, als dein\nProjekt erlaubt. Beide Antworten sind HTTP 403 mit dem Code ",[21,58,59],{},"otp_expired",", die\nMeldung allein sagt dir also nicht, welcher der beiden Fälle eingetreten ist.",[10,62,63,64,67,68,71,72,75,76,79,80,84],{},"Dein Nutzer sieht den 403 nie. Der Link in der E-Mail zeigt auf die eigene\nAdresse deines Supabase-Projekts, die das Token prüft und den Browser dann zu\ndeiner App weiterschickt. Scheitert die Prüfung, setzt Supabase drei Dinge in\nden Teil der Adresse deiner App hinter dem ",[21,65,66],{},"#",": ",[21,69,70],{},"error=access_denied",",\n",[21,73,74],{},"error_code=otp_expired"," und die Meldung selbst. Wurde deine App mit dem\nPKCE-Ablauf eingerichtet, stehen sie zusätzlich im Teil hinter dem ",[21,77,78],{},"?",". Solange\nkeine Seite deiner App sie liest, sieht die Person das, was deine App einem\nnicht angemeldeten Besucher zeigt, ohne ein Wort zum Warum. Eine Seite zum\nZurücksetzen des Passworts, die ihr Formular trotzdem zeigt, scheitert beim\nSpeichern mit \"Auth session missing!\", weil der Link niemanden angemeldet hat,\nund ",[50,81,83],{"href":82},"\u002Fblog\u002Fauth-session-missing","diese Meldung hat einen eigenen Beitrag",".",[10,86,87,88,84],{},"Stell dir den Link als Ticket vor, das eine Person einmal einlässt. Wer es\nzuerst abgibt, kommt durch, und das Ticket wird gelocht. \"Email link is invalid\nor has expired\" ist die Person an der Tür, die ein Ticket hochhält, in dem\nschon ein Loch ist, oder eines, dessen Zeit abgelaufen ist. Wenn deine Nutzer\nhineinkommen und später hinausgeworfen werden, ist das ein anderer Fehler mit\n",[50,89,91],{"href":90},"\u002Fblog\u002Fsupabase-users-logged-out","einer eigenen Seite",[39,93,95],{"id":94},"warum-ein-link-von-vor-einer-minute-schon-benutzt-ist","Warum ein Link von vor einer Minute schon benutzt ist",[10,97,98],{},"Weil etwas ihn geöffnet hat, bevor dein Nutzer es tat, und einen E-Mail-Link\nvon Supabase zu öffnen ist dasselbe, wie ihn zu benutzen.",[10,100,101,102,107,108,113],{},"Supabases\n",[50,103,106],{"href":104,"rel":105},"https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Fauth\u002Fauth-email-templates",[54],"Anleitung zu den E-Mail-Vorlagen","\nführt das unter ihren Einschränkungen auf: Manche E-Mail-Anbieter haben\nSpamerkennung oder andere Sicherheitsfunktionen, die Links in eingehenden\nE-Mails vorab abrufen. Als Beispiel nennt sie Safe Links in Microsoft Defender\nfor Office 365. Supabases\n",[50,109,112],{"href":110,"rel":111},"https:\u002F\u002Fsupabase.com\u002Fkb\u002Ftroubleshooting\u002Fotp-verification-failures-token-has-expired-or-otp_expired-errors",[54],"Seite zur Fehlersuche bei diesem Fehler","\nnennt dieses Vorabrufen den häufigsten Grund dafür, dass ein Token abgelaufen\noder ungültig wirkt, bevor ein Nutzer es überhaupt benutzen kann.",[10,115,116],{},"Der Standardlink hat keinen Schritt zwischen Öffnen und Benutzen. Seine\nAdresse ist der Verify-Endpunkt deines Projekts, der das Token prüft und beim\nersten Besuch verbraucht, egal wer ihn macht. Der Filter gibt das Ticket also\nab, während die Nachricht ankommt, und es geht durch. Dein Nutzer klickt eine\nMinute später und wird an der Tür abgewiesen.",[118,119],"diagram",{"alt":120,"caption":121,"src":122},"Eine E-Mail mit einem Ticket darin. Zwei Wege führen von ihr zur selben Tür. Der erste, von einer Lupe, die für den Mailfilter steht, erreicht die Tür sofort und bekommt einen Haken. Der zweite, von der Person, kommt später an und bekommt ein rotes Kreuz, weil im Ticket jetzt ein Loch ist.","Der erste Besuch benutzt den Link. Ein Mailfilter, der ihn zur Prüfung öffnet, ist vor der Person da.","\u002Fblog\u002Femail-link-is-invalid-or-has-expired\u002Fwho-used-it-first-1600x720.png",[10,124,125],{},"Daraus folgen zwei Dinge.",[127,128,129,136],"ul",{},[130,131,132,135],"li",{},[34,133,134],{},"Du siehst es selbst nicht."," Es trifft Menschen, deren Mail durch einen\nsolchen Filter läuft, und dein eigenes Postfach gehört vielleicht nie dazu.\nDeine Test-Registrierungen funktionieren weiter, während deine Nutzer dir\nschreiben.",[130,137,138,141],{},[34,139,140],{},"Das Konto ist meist schon bestätigt."," Bei einer Bestätigung der\nRegistrierung zählt der Besuch des Filters: Supabase bestätigt die Adresse\nfür den, der den Link öffnet. Hat ein Filter ihn geöffnet, ist das Konto\nbestätigt, wenn dein Nutzer den Fehler sieht, und er kann sich mit dem\nPasswort anmelden, das er gewählt hat.",[39,143,145],{"id":144},"die-drei-anderen-ursachen","Die drei anderen Ursachen",[10,147,148],{},"Jede davon erzeugt dieselbe Meldung, und jede verlangt etwas anderes von dir.",[10,150,151,154,155,160],{},[34,152,153],{},"Der Link wurde schon benutzt."," Dein Nutzer hat ihn einmal gedrückt,\nvielleicht auf dem Handy, und drückt jetzt dieselbe E-Mail auf dem Laptop. Wenn\nein Link funktioniert, löscht Supabase jeden Link, der für dieses Konto noch\nwartet. Sein\n",[50,156,159],{"href":157,"rel":158},"https:\u002F\u002Fgithub.com\u002Fsupabase\u002Fauth\u002Fblob\u002Fmaster\u002Finternal\u002Fmodels\u002Fuser.go",[54],"Code für Konten","\nführt dieselbe Bereinigung nach einer Bestätigung und nach einem Anmeldelink\naus, also findet ein zweiter Klick nichts mehr. Das Ticket wurde beim ersten\nBesuch gelocht.",[10,162,163,166,167,172,173,177],{},[34,164,165],{},"Eine neuere E-Mail hat ihn ersetzt."," Ein Druck auf \"erneut senden\" erzeugt\neinen neuen Link, und Supabase löscht den älteren derselben Art, bevor es den\nneuen speichert. Das passiert in\n",[50,168,171],{"href":169,"rel":170},"https:\u002F\u002Fgithub.com\u002Fsupabase\u002Fauth\u002Fblob\u002Fmaster\u002Finternal\u002Fmodels\u002Fone_time_token.go",[54],"dem Code, der das Token anlegt",".\nDie erste E-Mail liegt weiter unauffällig im Postfach, und ihr Link scheitert.\nNur die neueste E-Mail funktioniert. Supabase lässt eine Adresse außerdem nur\nalle 60 Sekunden nach dieser Art E-Mail fragen, was\n",[50,174,176],{"href":175},"\u002Fblog\u002Fsupabase-email-rate-limit-exceeded","das E-Mail-Limit"," ausführlich\nbehandelt.",[10,179,180,183,184,189],{},[34,181,182],{},"Er ist wirklich abgelaufen."," Supabases\n",[50,185,188],{"href":186,"rel":187},"https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Fauth\u002Fauth-email-passwordless",[54],"Anleitung zur Anmeldung ohne Passwort","\nsagt, dass Magic Links standardmäßig nach 1 Stunde ablaufen. Auf derselben\nSeite steht, dass die Einstellung Email OTP Expiration auch die Gültigkeit von\nMagic Links und anderen E-Mail-Links regelt, darunter Bestätigung,\nPasswort-Wiederherstellung, E-Mail-Änderung und Einladung. Wer sich abends\nregistriert und die E-Mail am nächsten Morgen öffnet, trifft auf diese Meldung,\negal was sein Mail-Dienst tut.",[39,191,193],{"id":192},"was-passiert-wenn-der-link-auf-einem-anderen-gerät-geöffnet-wird","Was passiert, wenn der Link auf einem anderen Gerät geöffnet wird?",[10,195,196],{},"Nutzt deine App den PKCE-Ablauf, scheitert das andere Gerät zuerst mit einer\nanderen Meldung, und diese folgt danach.",[10,198,199,200,205],{},"PKCE teilt das Ticket in zwei Teile. Supabases\n",[50,201,204],{"href":202,"rel":203},"https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Fauth\u002Fsessions\u002Fpkce-flow",[54],"PKCE-Anleitung","\nerklärt, dass der Code Verifier lokal erzeugt und gespeichert wird, wenn der\nAuth-Ablauf beginnt, und dass der Code-Austausch deshalb im selben Browser und\nauf demselben Gerät angestoßen werden muss, auf dem der Ablauf begonnen hat.\nDie E-Mail trägt die eine Hälfte. Der Browser, in dem dein Nutzer den Link\nangefordert hat, behält den Abschnitt.",[10,207,208],{},"Auf einem Handy geöffnet, läuft der Link trotzdem durch Supabases Prüfung, die\nihn verbraucht. Dann sucht deine App auf dem Handy nach dem Abschnitt und\nfindet keinen. Supabases JavaScript-Client meldet das mit eigenen Worten:",[14,210,213],{"className":211,"code":212,"language":19},[17],"PKCE code verifier not found in storage. This can happen if the auth flow was initiated in a different browser or device, or if the storage was cleared.\n",[21,214,212],{"__ignoreMap":23},[10,216,217,218,221],{},"Also geht die Person zurück an den Laptop und drückt dort dieselbe E-Mail, und\nSupabase antwortet \"Email link is invalid or has expired\", weil das Handy das\nTicket schon hat lochen lassen. Wenn die Adresse, auf der sich deine App nach\neinem funktionierenden Link öffnet, ",[21,219,220],{},"?code="," enthält, nutzt deine App PKCE, und\ndieser Fall betrifft dich.",[39,223,225],{"id":224},"wie-finde-ich-heraus-welcher-fall-es-war","Wie finde ich heraus, welcher Fall es war?",[10,227,228,229,232],{},"Frag deine eigene Datenbank. Jedes Konto in deinem Projekt ist eine Zeile in\neiner Tabelle namens ",[21,230,231],{},"auth.users",", und diese Zeile hält fest, wann jede Art\nE-Mail verschickt und wann die Adresse bestätigt wurde.",[10,234,235,236,239],{},"Öffne den ",[34,237,238],{},"SQL Editor"," in deinem Supabase-Dashboard und führ das mit der\nAdresse aus, die dir die Person genannt hat:",[14,241,244],{"className":242,"code":243,"language":19},[17],"select email,\n       confirmation_sent_at,\n       email_confirmed_at,\n       recovery_sent_at\nfrom auth.users\nwhere lower(email) = lower('person@example.com');\n",[21,245,243],{"__ignoreMap":23},[10,247,248,249,252,253,256],{},"Die Abfrage liest eine Zeile und ändert nichts. ",[21,250,251],{},"confirmation_sent_at"," ist der\nZeitpunkt, zu dem die letzte Bestätigung der Registrierung hinausging.\n",[21,254,255],{},"recovery_sent_at"," ist der Zeitpunkt, zu dem der letzte Magic Link oder das\nletzte Zurücksetzen des Passworts an ein Konto ging, das es schon gab. Ab diesen\nZeitpunkten misst Supabase die Stunde, in derselben Funktion, die den Fehler\nzurückgibt. Vergleich sie mit der Uhrzeit der E-Mail, die die Person gedrückt\nhat.",[258,259,260,273],"table",{},[261,262,263],"thead",{},[264,265,266,270],"tr",{},[267,268,269],"th",{},"Was du siehst",[267,271,272],{},"Was es bedeutet",[274,275,276,289,300,313],"tbody",{},[264,277,278,286],{},[279,280,281,282,285],"td",{},"Ein Bestätigungslink ist beim ersten Druck gescheitert, und ",[21,283,284],{},"email_confirmed_at"," ist gefüllt",[279,287,288],{},"Etwas hat den Link vor der Person geöffnet. Das Konto ist bestätigt, sie kann sich also mit ihrem Passwort anmelden",[264,290,291,297],{},[279,292,293,294,296],{},"Ein Bestätigungslink ist gescheitert, ",[21,295,284],{}," ist leer, und sie hat über eine Stunde nach dem Versand gedrückt",[279,298,299],{},"Er ist abgelaufen. Schick eine neue Bestätigung",[264,301,302,310],{},[279,303,304,306,307,309],{},[21,305,251],{}," oder ",[21,308,255],{}," liegt später als die E-Mail, die sie gedrückt hat",[279,311,312],{},"Eine neuere E-Mail hat sie ersetzt. Nur der Link in der neuesten funktioniert",[264,314,315,318],{},[279,316,317],{},"Ein Magic Link aus der neuesten E-Mail ist beim ersten Druck gescheitert, innerhalb der Stunde",[279,319,320],{},"Etwas hat ihn zuerst geöffnet: ein Mailfilter oder die Person auf einem anderen Gerät",[10,322,323,324,328],{},"Zeigt die Zeile die Adresse als bestätigt und die Person kommt trotzdem nicht\nmit einem Passwort hinein, ist\n",[50,325,327],{"href":326},"\u002Fblog\u002Fsupabase-invalid-login","Invalid login credentials"," die nächste Meldung,\nüber die du lesen solltest.",[39,330,332],{"id":331},"was-du-nicht-ändern-solltest-während-du-das-behebst","Was du nicht ändern solltest, während du das behebst",[10,334,335],{},"Die Gültigkeit, den Schalter Confirm email und wer einen Nutzer bestätigen\ndarf. Jede der naheliegenden Abkürzungen hier stoppt die Meldung und öffnet\netwas.",[10,337,338,341],{},[34,339,340],{},"Lass die Gültigkeit bei einer Stunde."," Ein Filter öffnet den Link, während\ndie Nachricht ankommt, also wird auch ein Link, der eine Woche hält, zuerst von\nihm benutzt. Supabases Anleitung zur Anmeldung ohne Passwort rät ausdrücklich\nvon mehr als 86.400 Sekunden, also einem Tag, ab. Ein Anmeldelink meldet jeden\nan, der ihn öffnet. Je länger er funktioniert, desto länger ist eine\nweitergeleitete E-Mail, ein geteiltes Postfach oder eine alte Nachricht in\njemandes Archiv ein Weg in dieses Konto.",[10,343,344,347],{},[34,345,346],{},"Lass Confirm email an."," Schaltest du es aus, verschicken Registrierungen gar\nkeinen Link mehr, und dieser Fehler hört auf. Es heißt aber auch, dass jeder\nein Konto mit einer Adresse anlegen kann, die ihm nie gehört hat.",[10,349,350,353,354,357,358,363,364,367,368,371,372,376,377,84],{},[34,351,352],{},"Bestätige Nutzer nicht aus dem Browser."," Bittest du einen Assistenten, \"sie\neinfach als bestätigt zu markieren\", greift er vielleicht zu den\nAdmin-Funktionen von Supabase, die ",[21,355,356],{},"email_confirm"," an einem Konto setzen können.\nSupabases ",[50,359,362],{"href":360,"rel":361},"https:\u002F\u002Fsupabase.com\u002Fdocs\u002Freference\u002Fjavascript\u002Fadmin-api",[54],"Admin-Referenz","\nsagt, dass jede Methode unter ",[21,365,366],{},"supabase.auth.admin"," einen ",[21,369,370],{},"secret","-Schlüssel\nbraucht und dass dieser Schlüssel nie im Browser auftauchen darf. Ein geheimer\nSchlüssel in deinem Frontend liest und schreibt jede Tabelle deiner Datenbank,\negal was deine Regeln sagen, für jeden, der den Code deiner Seite öffnet. Das\nist der Schlüssel, den\n",[50,373,375],{"href":374},"\u002Fblog\u002Fwhich-api-keys-are-safe-in-your-frontend","dieser Artikel über API-Schlüssel","\ndir zu rotieren rät. Wenn du nicht sicher bist, ob einer hineingerutscht ist:\nUnser kostenloser Scan liest den Code, den deine Live-App an jeden Besucher\nschickt, und meldet die geheimen Schlüssel, die er darin findet. Er dauert etwa\n20 Sekunden und braucht kein Konto: ",[50,378,380],{"href":379},"\u002Fsecurity-scanner","scanne deine App",[10,382,383,386],{},[34,384,385],{},"Prüf jede Adresse, die deine Bestätigungsseite weitergibt."," Supabases zweite\nvorgeschlagene Lösung ist eine eigene Seite mit einem Knopf, erreicht über einen\nLink dieser Form:",[14,388,391],{"className":389,"code":390,"language":19},[17],"\u003Ca href=\"{{ .SiteURL }}\u002Fconfirm-signup?confirmation_url={{ .ConfirmationURL }}\">\n",[21,392,390],{"__ignoreMap":23},[10,394,395,396,399,400,403],{},"Der Knopf führt dann dorthin, wohin ",[21,397,398],{},"confirmation_url"," sagt. Ohne Prüfung\ngebaut, schickt diese Seite jeden, der einem präparierten Link folgt, an eine\nbeliebige Adresse, unter dem Namen deiner App. Prüf entweder, dass die Adresse\nmit der deines eigenen Projekts beginnt,\n",[21,401,402],{},"https:\u002F\u002F\u003Cproject-ref>.supabase.co\u002Fauth\u002Fv1\u002Fverify",", oder nimm die Variante mit\ndem Token aus dem nächsten Abschnitt, die gar keine Adresse durch die Seite\nreicht.",[39,405,407],{"id":406},"so-verschickst-du-einen-link-den-ein-mailfilter-nicht-verbrauchen-kann","So verschickst du einen Link, den ein Mailfilter nicht verbrauchen kann",[10,409,410],{},"Sorg dafür, dass das Öffnen der Adresse nichts auslöst, sodass nur eine Person,\ndie einen Code eintippt oder einen Knopf drückt, sich anmeldet. Supabase\ndokumentiert beides, und du änderst es in den E-Mail-Vorlagen unter\nAuthentication in deinem Dashboard. Confirm signup und Magic Link sind die\nbeiden, die du bearbeitest.",[10,412,413,416,417,420],{},[34,414,415],{},"Schick einen Code."," Setz ",[21,418,419],{},"{{ .Token }}"," in die Vorlage. Supabases Anleitung\nbeschreibt es als ein Einmalpasswort mit 6 Ziffern, das statt des Links benutzt\nwerden kann. Deine Seite fragt nach der E-Mail-Adresse und dem Code und ruft\ndann auf:",[14,422,425],{"className":423,"code":424,"language":19},[17],"const { error } = await supabase.auth.verifyOtp({ email, token, type: 'email' })\n",[21,426,424],{"__ignoreMap":23},[10,428,429],{},"Ein Filter kann eine E-Mail öffnen. Einen Code in deine Seite tippen kann er\nnicht.",[10,431,432,435],{},[34,433,434],{},"Verlinke eine Seite mit einem Knopf."," Lass den Link auf eine Seite von dir\nzeigen und den Hash des Tokens mitnehmen, damit keine Adresse durchgereicht\nwerden muss:",[14,437,440],{"className":438,"code":439,"language":19},[17],"\u003Ca href=\"{{ .SiteURL }}\u002Fconfirm?token_hash={{ .TokenHash }}&type=email\">Confirm your email\u003C\u002Fa>\n",[21,441,439],{"__ignoreMap":23},[10,443,444,447,448,71,451,84],{},[21,445,446],{},"{{ .SiteURL }}"," ist die Site URL auf der Seite URL Configuration deines\nProjekts. Steht dort noch ",[21,449,450],{},"http:\u002F\u002Flocalhost:3000",[50,452,454],{"href":453},"\u002Fblog\u002Fsupabase-auth-redirects-to-localhost","korrigier das zuerst",[10,456,457],{},"Die Seite zeigt einen Knopf, und nur der Knopf erledigt die Arbeit:",[14,459,462],{"className":460,"code":461,"language":19},[17],"const params = new URLSearchParams(window.location.search)\n\nasync function onConfirmClick() {\n  const { error } = await supabase.auth.verifyOtp({\n    token_hash: params.get('token_hash'),\n    type: 'email',\n  })\n  if (error?.code === 'otp_expired') showSendNewLink()\n}\n",[21,463,461],{"__ignoreMap":23},[10,465,466,467,470],{},"Der Typ ",[21,468,469],{},"email"," deckt beide Vorlagen ab: Supabases Prüfung sucht den Hash unter\nBestätigungen der Registrierung und Anmeldelinks gleichermaßen.",[10,472,473,183,480,485,486,489],{},[34,474,475,476,479],{},"Die Seite darf ",[21,477,478],{},"verifyOtp"," nicht beim Laden aufrufen.",[50,481,484],{"href":482,"rel":483},"https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Fauth\u002Fpasswords",[54],"Anleitung zu Passwörtern","\nbaut ihren Bestätigungslink als\n",[21,487,488],{},"{{ .SiteURL }}\u002Fauth\u002Fconfirm?token_hash={{ .TokenHash }}&type=email&next={{ .RedirectTo }}","\nund prüft ihn in dem Moment, in dem diese Adresse geöffnet wird. Das ist wieder\nder Standardlink unter einer neuen Adresse, und ein Filter öffnet ihn genauso\nleicht.",[118,491],{"alt":492,"caption":493,"src":494},"Zwei E-Mails nebeneinander. Links führt der Link direkt zur Tür: Die Lupe öffnet ihn zuerst und bekommt einen Haken, die Person dahinter ein rotes Kreuz. Rechts öffnet der Link eine Seite mit einem Knopf: Die Lupe öffnet die Seite, und nichts passiert, das Ticket bleibt heil, und die Person drückt den Knopf und bekommt den Haken.","Beim Standardlink meldet schon das Öffnen an. Mit einem Knopf oder einem eingetippten Code tut es nur die Handlung der Person.","\u002Fblog\u002Femail-link-is-invalid-or-has-expired\u002Fopening-is-not-using-1600x760.png",[10,496,497],{},"Was du auch änderst, manche Leute treffen weiter auf einen alten Link, also gib\nihnen einen Weg weiter. Die Seite, auf der deine Links landen, kann den Fehler\nlesen und eine neue E-Mail anbieten:",[14,499,502],{"className":500,"code":501,"language":19},[17],"const hash = new URLSearchParams(window.location.hash.slice(1))\nif (hash.get('error_code') === 'otp_expired') showSendNewLink()\n",[21,503,501],{"__ignoreMap":23},[10,505,506,507,509],{},"Bei einer Registrierung schreib dazu, dass die Person vielleicht schon\nbestätigt ist und sich anzumelden versuchen kann. Wenn ein Builder deine\nAnmeldeseiten schreibt, bitte ihn um die Code- oder Knopf-Variante beider\nVorlagen, eine Landeseite, die ",[21,508,59],{}," liest und einen frischen Link\nanbietet, und keinen Admin-Schlüssel irgendwo in der App.",[39,511,513],{"id":512},"von-problemen-hören-bevor-deine-nutzer-dir-schreiben","Von Problemen hören, bevor deine Nutzer dir schreiben",[10,515,516],{},"Dieser Fehler erreicht deine Nutzer und nie dich, und andere Ausfälle erreichen\nsie ebenfalls zuerst: die App, die nachts ausfällt, oder ein späterer Prompt,\nder einen Schlüssel in den Code deiner App bringt.",[10,518,519],{},[34,520,521,525],{},[50,522,524],{"href":523},"\u002Fwebsite-monitoring","Reeve Monitor"," prüft deine Live-App weiter von außen:",[127,527,528,531,534,537],{},[130,529,530],{},"ob sie erreichbar ist, alle 60 Sekunden, damit sich \"der Link geht nicht\" von \"die Seite ist weg\" unterscheiden lässt",[130,532,533],{},"alle neun Prüfungen jede Stunde, für bis zu drei Apps, einschließlich geheimer Schlüssel im Code, den deine App an Besucher schickt",[130,535,536],{},"eine Nachricht, wenn sich ein Ergebnis ändert, damit dich ein Schlüssel, der mit einem späteren Deploy hinausgeht, erreicht, ohne dass du nachsehen musst",[130,538,539],{},"ein monatlicher Bericht in klarer Sprache über das, was er gesehen hat",[10,541,542],{},[34,543,544,548],{},[50,545,547],{"href":546},"\u002Fsupabase-backups","Reeve Care"," hält eine Kopie deiner Supabase-Datenbank,\nsamt Konten:",[127,550,551,554,557,560,563,566],{},[130,552,553],{},"eine verschlüsselte Kopie nach Zeitplan, auf Reeves eigenem Speicher in der EU, außerhalb deines Supabase-Kontos",[130,555,556],{},"das Auth-Schema, in dem die Konten deiner Nutzer liegen, damit sie mit allem anderen zurückkommen",[130,558,559],{},"jede Kopie geprüft, bevor sie zählt, durch Zählen der Zeilen in jeder Tabelle",[130,561,562],{},"auch deine hochgeladenen Dateien, sobald du einen Storage-Zugang verbindest",[130,564,565],{},"eine Wiederherstellung per Klick, mit einer Sicherheitskopie des aktuellen Stands vorab",[130,567,568],{},"alles, was Monitor tut",[39,570,572],{"id":571},"was-du-jetzt-tun-solltest","Was du jetzt tun solltest",[574,575,576],"key-takeaways",{},[127,577,578,587,590,596,602],{},[130,579,580,581,583,584,586],{},"Lies die Zeile der Person in ",[21,582,231],{},". Ein gefülltes ",[21,585,284],{}," bei einer gescheiterten Bestätigung heißt, dass ein Filter den Link geöffnet hat und sie sich anmelden kann.",[130,588,589],{},"Sag den Leuten, dass sie die neueste E-Mail nehmen sollen, und wenn deine App PKCE nutzt, dass sie sie auf dem Gerät öffnen, auf dem sie sie angefordert haben.",[130,591,592,593,595],{},"Stell die Vorlagen Confirm signup und Magic Link auf einen Code um oder auf eine Seite, auf der ein Knopf ",[21,594,478],{}," aufruft.",[130,597,598,599,601],{},"Lass die Seite, auf der deine Links landen, ",[21,600,74],{}," lesen und einen neuen Link anbieten.",[130,603,604],{},"Lass die Gültigkeit bei einer Stunde, lass Confirm email an und halte den geheimen Schlüssel aus dem Browser heraus.",[10,606,607,608,610,611,615],{},"Wenn die E-Mails gar nicht erst ankommen, ist\n",[50,609,176],{"href":175}," das Erste, was du\nausschließen solltest. Die ",[50,612,614],{"href":613},"\u002Fchecklist","10-Minuten-Sicherheits-Checkliste"," deckt\nab, was in einer frisch gestarteten App sonst oft offen bleibt.",{"title":23,"searchDepth":617,"depth":617,"links":618},3,[619,621,622,623,624,625,626,627,628],{"id":41,"depth":620,"text":42},2,{"id":94,"depth":620,"text":95},{"id":144,"depth":620,"text":145},{"id":192,"depth":620,"text":193},{"id":224,"depth":620,"text":225},{"id":331,"depth":620,"text":332},{"id":406,"depth":620,"text":407},{"id":512,"depth":620,"text":513},{"id":571,"depth":620,"text":572},"Sicherheitsgrundlagen","\u002Fblog\u002Femail-link-is-invalid-or-has-expired\u002Fcover-1200x630.png","Ein offener Umschlag, aus dem ein Ticket halb herausragt, und durch das Ticket ist schon ein Loch gestanzt.","Bei einem Link von vor einer Minute heißt Supabases \"Email link is invalid or has expired\" meist: Ein Mailfilter hat ihn zuerst benutzt. Prüfen und beheben.",false,"md",[636,639,642,645,648,651],{"q":637,"a":638},"Warum sagt ein Magic Link von Supabase gleich nach dem Versand, er sei abgelaufen?","Meist, weil etwas ihn vor der Person geöffnet hat. Manche E-Mail-Dienste öffnen die Links in einer eingehenden Nachricht, um sie zu prüfen, und Supabase nennt Safe Links in Microsoft Defender for Office 365 als Beispiel. Einen E-Mail-Link von Supabase zu öffnen heißt, ihn zu benutzen. Klickt die Person eine Minute später, ist das Token weg, und Supabase antwortet \"Email link is invalid or has expired\".",{"q":640,"a":641},"Ist das Konto bestätigt, obwohl der Link abgelaufen sein soll?","Wenn ein Mailfilter einen Bestätigungslink zur Registrierung zuerst geöffnet hat, ja. Supabase bestätigt die Adresse für den, der den Link öffnet, also hat der Besuch des Filters sie bestätigt. Sieh in auth.users nach email_confirmed_at: Ist das Feld gefüllt, kann sich die Person mit dem Passwort anmelden, das sie gewählt hat.",{"q":643,"a":644},"Wie lange ist ein E-Mail-Link von Supabase gültig?","Standardmäßig eine Stunde. Die Einstellung Email OTP Expiration regelt das, und dieselbe Einstellung gilt für Magic Links, Bestätigungen der Registrierung, das Zurücksetzen von Passwörtern, E-Mail-Änderungen und Einladungen. Von mehr als 86.400 Sekunden, also einem Tag, rät Supabase ausdrücklich ab.",{"q":646,"a":647},"Soll ich die Links länger gültig machen?","Nein. Ein Mailfilter öffnet den Link, sobald die Nachricht ankommt, also hält ihn eine längere Gültigkeit nicht davon ab, ihn zuerst zu benutzen. Sie sorgt nur dafür, dass jeder unbenutzte Link in jedem Postfach länger funktioniert, und ein Link meldet jeden an, der ihn öffnet, auch jemanden, an den die E-Mail weitergeleitet wurde.",{"q":649,"a":650},"Warum funktioniert der Link auf meinem Computer und auf dem Handy nicht?","Wenn deine App den PKCE-Ablauf nutzt, behält der Browser, in dem die Person den Link angefordert hat, die Hälfte dessen, was die Anmeldung braucht. Auf einem anderen Gerät scheitert die E-Mail deshalb mit \"PKCE code verifier not found in storage\". Dieser Versuch verbraucht den Link außerdem, und darum sagt ein erneuter Klick auf dem ersten Gerät danach \"Email link is invalid or has expired\".",{"q":652,"a":653},"Was bedeutet error_code=otp_expired in der Adresse meiner App?","So meldet Supabase Auth einen gescheiterten E-Mail-Link. Es schickt die Person weiter zu deiner App, mit error=access_denied, error_code=otp_expired und der Meldung im Teil der Adresse hinter dem Zeichen #. Deine App kann error_code dort lesen und eine Seite zeigen, die anbietet, einen neuen Link zu schicken.","\u002Fblog\u002Femail-link-is-invalid-or-has-expired\u002Fcard-800x500.png",[656,657,658,659,660,661,74],"email link is invalid or has expired supabase","email link is invalid or has expired","otp_expired supabase","supabase magic link sofort abgelaufen","supabase bestätigungslink funktioniert nicht","outlook safe links magic link",{},true,"\"Email link is invalid or has expired\" in Supabase","\u002Fblog\u002Femail-link-is-invalid-or-has-expired","2026-11-01",{"title":5,"description":632},"blog\u002Femail-link-is-invalid-or-has-expired",[670,671,672],"Supabase zeigt \"Email link is invalid or has expired\", wenn das Token in einem Anmelde- oder Bestätigungslink schon benutzt wurde, durch eine neuere E-Mail ersetzt wurde oder älter als eine Stunde ist. Der Fehlercode ist otp_expired.","Bei einem Link, den die Person gerade erst bekommen hat, ist die übliche Ursache ein Mailfilter, der den Link zur Prüfung geöffnet und ihn dabei verbraucht hat. Supabases eigene Seite zur Fehlersuche nennt das den häufigsten Grund.","Eine längere Gültigkeit ändert nichts. Ändere die E-Mail so, dass das Öffnen der Adresse nichts auslöst: Schick einen Code zum Eintippen oder verlinke eine Seite, auf der ein Knopf die Anmeldung erledigt.","6dXoFH-oW1CZT5hljvAscAuDtGCqR7JjWiGj7GrgfxU",[675,681,687,693,699,704,710,716,721,722,728,735,741,746,752,758,764,770,776,782,788,793,798,804,810,816,822,828,834,840,846,852,858,864,870,876,882,888,894,900,906,912,918,924,930,936,941,947,953,959,965,971,977,983,989,995,1001,1007,1013,1019,1025,1031,1037,1043,1049,1055,1061,1067,1073,1079,1085,1091,1097,1103,1109,1115,1121,1127,1133,1139,1145,1151,1157,1163,1168,1174,1180,1186,1191,1197],{"path":676,"title":677,"description":678,"published":679,"category":629,"image":680,"draft":633},"\u002Fblog\u002Fmax-client-connections-reached","Supabase \"max client connections reached\" erklärt","Supabase \"max client connections reached\": Der Pooler hat keinen Platz für noch einen Client. Der Port in deinem Connection String setzt das Limit.","2026-11-09","\u002Fblog\u002Fmax-client-connections-reached\u002Fcard-800x500.png",{"path":682,"title":683,"description":684,"published":685,"category":629,"image":686,"draft":633},"\u002Fblog\u002Funsupported-provider-provider-is-not-enabled","Supabase-Fehler: \"Unsupported provider: provider is not enabled\"","\"Unsupported provider: provider is not enabled\" heißt: Google-Login ist in deinem Supabase-Projekt aus. Die Lösung, und was bei redirect_uri_mismatch hilft.","2026-11-08","\u002Fblog\u002Funsupported-provider-provider-is-not-enabled\u002Fcard-800x500.png",{"path":688,"title":689,"description":690,"published":691,"category":629,"image":692,"draft":633},"\u002Fblog\u002Fviolates-foreign-key-constraint","Supabase-Fehler \"violates foreign key constraint\" beim Einfügen","Supabase \"insert or update on table violates foreign key constraint\": Deine Zeile zeigt auf eine, die es nicht gibt. Welche, warum, und die Lösung.","2026-11-07","\u002Fblog\u002Fviolates-foreign-key-constraint\u002Fcard-800x500.png",{"path":694,"title":695,"description":696,"published":697,"category":629,"image":698,"draft":633},"\u002Fblog\u002Fnull-value-violates-not-null-constraint","Supabase-Fehler \"null value in column violates not-null constraint\"","Supabase \"null value in column violates not-null constraint\": Eine Pflichtspalte kam leer an. Woher die Null kommt, und die Lösung.","2026-11-06","\u002Fblog\u002Fnull-value-violates-not-null-constraint\u002Fcard-800x500.png",{"path":82,"title":700,"description":701,"published":702,"category":629,"image":703,"draft":633},"Supabase \"Auth session missing!\": wo die Sitzung geblieben ist","\"Auth session missing!\" heißt: supabase-js fand keine angemeldete Sitzung und fragte Supabase gar nicht erst. Wo die Sitzung blieb, und die Lösung je Fall.","2026-11-05","\u002Fblog\u002Fauth-session-missing\u002Fcard-800x500.png",{"path":705,"title":706,"description":707,"published":708,"category":629,"image":709,"draft":633},"\u002Fblog\u002Finvalid-claim-missing-sub-claim","Supabase \"invalid claim: missing sub claim\": niemand ist angemeldet","\"invalid claim: missing sub claim\" heißt: Supabase Auth bekam ein echtes Token ohne Nutzer darin, deinen Projektschlüssel statt einer Sitzung.","2026-11-04","\u002Fblog\u002Finvalid-claim-missing-sub-claim\u002Fcard-800x500.png",{"path":711,"title":712,"description":713,"published":714,"category":629,"image":715,"draft":633},"\u002Fblog\u002Ffailed-to-send-a-request-to-the-edge-function","\"Failed to send a request to the Edge Function\": der echte Grund","\"Failed to send a request to the Edge Function\" heißt: Der Browser hat keine lesbare Antwort bekommen. Seine Konsole sagt, warum, und ob deine Funktion lief.","2026-11-03","\u002Fblog\u002Ffailed-to-send-a-request-to-the-edge-function\u002Fcard-800x500.png",{"path":453,"title":717,"description":718,"published":719,"category":629,"image":720,"draft":633},"Warum Supabase-E-Mail-Links auf localhost:3000 weiterleiten","Leitet Supabase auf localhost:3000 um, ist die Site URL unverändert, oder deine Adresse fehlt in Redirect URLs. Die Lösung und der Platzhalter, den du meidest.","2026-11-02","\u002Fblog\u002Fsupabase-auth-redirects-to-localhost\u002Fcard-800x500.png",{"path":665,"title":5,"description":632,"published":666,"category":629,"image":654,"draft":633},{"path":723,"title":724,"description":725,"published":726,"category":629,"image":727,"draft":633},"\u002Fblog\u002Fcanceling-statement-due-to-statement-timeout","Supabase \"canceling statement due to statement timeout\" erklärt","Supabase \"canceling statement due to statement timeout\": Eine Abfrage lief länger als ihre Rolle darf, 3 Sekunden für Besucher. Prüf zuerst die RLS-Regel.","2026-10-31","\u002Fblog\u002Fcanceling-statement-due-to-statement-timeout\u002Fcard-800x500.png",{"path":729,"title":730,"description":731,"published":732,"category":733,"image":734,"draft":633},"\u002Fblog\u002Fdatabase-error-deleting-user","\"Database error deleting user\" in Supabase und was mitgelöscht wird","\"Database error deleting user\" in Supabase heißt: Deine Datenbank hat das Löschen abgelehnt. Der Grund steht im Log, die Lösung entscheidet, was mitgeht.","2026-10-30","Backups","\u002Fblog\u002Fdatabase-error-deleting-user\u002Fcard-800x500.png",{"path":736,"title":737,"description":738,"published":739,"category":629,"image":740,"draft":633},"\u002Fblog\u002Fstripe-webhook-no-signatures-found","\"No signatures found matching the expected signature\" bei Supabase","Ein Stripe-Webhook in einer Supabase Edge Function meldet \"No signatures found matching the expected signature\"? Zwei Ursachen. Prüfe weiter.","2026-10-29","\u002Fblog\u002Fstripe-webhook-no-signatures-found\u002Fcard-800x500.png",{"path":326,"title":742,"description":743,"published":744,"category":629,"image":745,"draft":633},"\"Invalid login credentials\" in Supabase: die drei Ursachen","Supabase sagt \"Invalid login credentials\" bei falschem Passwort, unbekannter E-Mail und Google-Konto. So erkennst du, welcher Fall es ist.","2026-10-28","\u002Fblog\u002Fsupabase-invalid-login\u002Fcard-800x500.png",{"path":747,"title":748,"description":749,"published":750,"category":629,"image":751,"draft":633},"\u002Fblog\u002Fedge-function-returned-a-non-2xx-status-code","\"Edge Function returned a non-2xx status code\": der echte Fehler","\"Edge Function returned a non-2xx status code\" heißt: Deine Supabase-Funktion hat mit einem Fehler geantwortet. So liest du den echten.","2026-10-27","\u002Fblog\u002Fedge-function-returned-a-non-2xx-status-code\u002Fcard-800x500.png",{"path":753,"title":754,"description":755,"published":756,"category":629,"image":757,"draft":633},"\u002Fblog\u002Fcertificate-not-trusted","Zertifikat nicht vertrauenswürdig: drei Ursachen außer Ablauf","Zertifikat nicht vertrauenswürdig, obwohl das Datum stimmt? Es nennt eine andere Adresse, hat sich selbst signiert oder seiner Kette fehlt ein Glied.","2026-10-26","\u002Fblog\u002Fcertificate-not-trusted\u002Fcard-800x500.png",{"path":759,"title":760,"description":761,"published":762,"category":629,"image":763,"draft":633},"\u002Fblog\u002Finvalid-input-syntax-for-type-uuid","Supabase \"invalid input syntax for type uuid\": was im Zitat steht","Supabase \"invalid input syntax for type uuid\" heißt: Deine App hat etwas geschickt, das keine ID ist. Zitat lesen, Abfrage zurückhalten, Spalte behalten.","2026-10-25","\u002Fblog\u002Finvalid-input-syntax-for-type-uuid\u002Fcard-800x500.png",{"path":765,"title":766,"description":767,"published":768,"category":629,"image":769,"draft":633},"\u002Fblog\u002Fduplicate-key-value-violates-unique-constraint","Supabase \"duplicate key value violates unique constraint\" erklärt","Supabase \"duplicate key value violates unique constraint\" heißt: Der Wert ist schon vergeben. Spalte finden, Lösung wählen, Wert vom Bildschirm fernhalten.","2026-10-24","\u002Fblog\u002Fduplicate-key-value-violates-unique-constraint\u002Fcard-800x500.png",{"path":771,"title":772,"description":773,"published":774,"category":629,"image":775,"draft":633},"\u002Fblog\u002Fsupabase-relation-does-not-exist","Supabase \"relation does not exist\", obwohl die Tabelle da ist","Supabase \"relation does not exist\" oder PGRST205: Keine Tabelle passt zu Name und Schema deiner Abfrage. Vier Prüfungen, und was eine Freigabe öffnet.","2026-10-23","\u002Fblog\u002Fsupabase-relation-does-not-exist\u002Fcard-800x500.png",{"path":777,"title":778,"description":779,"published":780,"category":629,"image":781,"draft":633},"\u002Fblog\u002Fsupabase-function-not-found","Supabase PGRST202: \"Could not find the function in the schema cache\"","Supabase \"Could not find the function in the schema cache\" nennt die Argumente, die deine App geschickt hat. Vergleich sie mit der Funktion.","2026-10-22","\u002Fblog\u002Fsupabase-function-not-found\u002Fcard-800x500.png",{"path":783,"title":784,"description":785,"published":786,"category":629,"image":787,"draft":633},"\u002Fblog\u002Fsupabase-schema-cache-column-error","Supabase PGRST204: \"Could not find the column in the schema cache\"","Supabase \"Could not find the column in the schema cache\" heißt meist: Der Name passt nicht. Vier Prüfungen und der Einzeiler zum Neuladen.","2026-10-21","\u002Fblog\u002Fsupabase-schema-cache-column-error\u002Fcard-800x500.png",{"path":175,"title":789,"description":790,"published":791,"category":629,"image":792,"draft":633},"Supabase \"Email Rate Limit Exceeded\": zwei Limits, ein Fehlercode","Supabase \"Email Rate Limit Exceeded\" begrenzt jede E-Mail deines Projekts: 2 pro Stunde beim eingebauten Absender. Was zählt und wie du es anhebst.","2026-10-20","\u002Fblog\u002Fsupabase-email-rate-limit-exceeded\u002Fcard-800x500.png",{"path":90,"title":794,"description":795,"published":796,"category":629,"image":797,"draft":633},"Supabase \"Invalid Refresh Token: Refresh Token Not Found\": 3 Ursachen","Supabase \"Invalid Refresh Token: Refresh Token Not Found\" meldet deine Nutzer ab. Drei Ursachen, und wie das Auth-Log sie trennt.","2026-10-19","\u002Fblog\u002Fsupabase-users-logged-out\u002Fcard-800x500.png",{"path":799,"title":800,"description":801,"published":802,"category":629,"image":803,"draft":633},"\u002Fblog\u002Fpermission-denied-for-schema-public","Supabase \"permission denied for schema public\": drei Ursachen","Supabase \"permission denied for schema public\" heißt: Ein Grant auf das Schema fehlt. Was ihn entfernt hat und welche Zeile ihn zurückbringt.","2026-10-18","\u002Fblog\u002Fpermission-denied-for-schema-public\u002Fcard-800x500.png",{"path":805,"title":806,"description":807,"published":808,"category":629,"image":809,"draft":633},"\u002Fblog\u002Fsupabase-bucket-not-found","Supabase \"Bucket not found\": die drei Dinge, die es bedeutet","Supabase \"Bucket not found\" ist eins von drei Dingen: ein öffentlicher Link zu einem privaten Bucket, ein ungenauer Name oder das falsche Projekt.","2026-10-17","\u002Fblog\u002Fsupabase-bucket-not-found\u002Fcard-800x500.png",{"path":811,"title":812,"description":813,"published":814,"category":629,"image":815,"draft":633},"\u002Fblog\u002Fsupabase-invalid-jwt","Supabase invalid JWT: Welcher Schlüssel streikt hier?","Ein Supabase invalid JWT ist PGRST301: ein signiertes Token hat die Prüfung nicht bestanden. In neueren Projekten ist das die Sitzung, nicht der API-Schlüssel.","2026-10-16","\u002Fblog\u002Fsupabase-invalid-jwt\u002Fcard-800x500.png",{"path":817,"title":818,"description":819,"published":820,"category":629,"image":821,"draft":633},"\u002Fblog\u002Fsupabase-single-row-error","Supabase \"multiple (or no) rows returned\" heißt meist: keine Zeilen","Supabase gibt PGRST116 zurück, \"JSON object requested, multiple (or no) rows returned\", wenn die Abfrage nichts fand. Versteckte Zeilen wirken fehlend.","2026-10-15","\u002Fblog\u002Fsupabase-single-row-error\u002Fcard-800x500.png",{"path":823,"title":824,"description":825,"published":826,"category":629,"image":827,"draft":633},"\u002Fblog\u002Fdatabase-error-saving-new-user","\"Database error saving new user\" in Supabase: wo du nachsiehst","\"Database error saving new user\" heißt: etwas an deiner Supabase-Registrierung ist fehlgeschlagen. Der echte Fehler steht in deinen Logs.","2026-10-14","\u002Fblog\u002Fdatabase-error-saving-new-user\u002Fcard-800x500.png",{"path":829,"title":830,"description":831,"published":832,"category":629,"image":833,"draft":633},"\u002Fblog\u002Fwhat-is-supabase","Was ist Supabase? Die Datenbank, die dein Builder ausgesucht hat","Was ist Supabase: die Datenbank, der Login und der Dateispeicher hinter deiner App. Supabase betreibt die Server, die Regeln zu deinen Zeilen gehören dir.","2026-10-13","\u002Fblog\u002Fwhat-is-supabase\u002Fcard-800x500.png",{"path":835,"title":836,"description":837,"published":838,"category":629,"image":839,"draft":633},"\u002Fblog\u002Faws-access-key-exposed-in-frontend","Ein offengelegter AWS-Schlüssel im Frontend ist kein OpenAI-Key","Ein im Frontend offengelegter AWS-Zugriffsschlüssel liest und schreibt deinen Speicher. Die Lösung ist meist eine presigned URL, kein neuer Schlüssel.","2026-10-12","\u002Fblog\u002Faws-access-key-exposed-in-frontend\u002Fcard-800x500.png",{"path":841,"title":842,"description":843,"published":844,"category":629,"image":845,"draft":633},"\u002Fblog\u002Fstorage-upload-violates-row-level-security","\"Row-level security policy for table objects\" beim Upload","\"New row violates row-level security policy for table objects\" heißt: Deinem Upload fehlt eine insert-Regel. Ein öffentlicher Bucket fügt keine hinzu.","2026-10-11","\u002Fblog\u002Fstorage-upload-violates-row-level-security\u002Fcard-800x500.png",{"path":847,"title":848,"description":849,"published":850,"category":629,"image":851,"draft":633},"\u002Fblog\u002Fbase44-security-scan","Base44 Security Scan: das, was nur er sehen kann","Der Base44 Security Scan prüft sieben Arten von Problemen von innen. Hier ist die Hälfte, die er liest und sonst niemand, und die Hälfte, die er nie ansieht.","2026-10-10","\u002Fblog\u002Fbase44-security-scan\u002Fcard-800x500.png",{"path":853,"title":854,"description":855,"published":856,"category":629,"image":857,"draft":633},"\u002Fblog\u002Fapi-key-leaked-what-to-do","Dein API-Key wurde geleakt. Die richtige Reihenfolge","Ein API-Key wurde geleakt und du weißt nicht, was zuerst zu tun ist. Nicht jeder Key im Frontend ist ein Leck, und die Reihenfolge zählt mehr als das Tempo.","2026-10-09","\u002Fblog\u002Fapi-key-leaked-what-to-do\u002Fcard-800x500.png",{"path":859,"title":860,"description":861,"published":862,"category":629,"image":863,"draft":633},"\u002Fblog\u002Finfinite-recursion-in-policy-for-relation","\"Infinite recursion detected in policy\" ohne RLS abzuschalten","\"Infinite recursion detected in policy for relation\" heißt: Deine Policy hat die Tabelle gefragt, die sie schützt. So brichst du den Kreis.","2026-10-08","\u002Fblog\u002Finfinite-recursion-in-policy-for-relation\u002Fcard-800x500.png",{"path":865,"title":866,"description":867,"published":868,"category":629,"image":869,"draft":633},"\u002Fblog\u002Fno-api-key-found-in-request","\"No API key found in request\" in Supabase, und die falsche Lösung","\"No API key found in request\" heißt, deine Supabase-Anfrage kam ohne Schlüssel an. Die meisten Antworten zeigen stattdessen auf deine Datenbankregeln.","2026-10-07","\u002Fblog\u002Fno-api-key-found-in-request\u002Fcard-800x500.png",{"path":871,"title":872,"description":873,"published":874,"category":629,"image":875,"draft":633},"\u002Fblog\u002Fis-base44-safe","Ist Base44 sicher? Was 5.442 echte Base44-Apps zeigten","Ist Base44 sicher? Wir haben 5.442 laufende Base44-Apps mit neun Checks geprüft. Fast alle bekamen ein B, aus Gründen, die der Inhaber nie gewählt hat.","2026-10-06","\u002Fblog\u002Fis-base44-safe\u002Fcard-800x500.png",{"path":877,"title":878,"description":879,"published":880,"category":629,"image":881,"draft":633},"\u002Fblog\u002Fmove-a-secret-to-an-edge-function","API-Schlüssel verstecken: ab in eine Supabase Edge Function","Einen API-Schlüssel verstecken heißt, ihn aus dem Browser zu nehmen. Eine Supabase Edge Function ist der kleinste Ort dafür, und zwei Schritte zählen mehr.","2026-10-05","\u002Fblog\u002Fmove-a-secret-to-an-edge-function\u002Fcard-800x500.png",{"path":883,"title":884,"description":885,"published":886,"category":629,"image":887,"draft":633},"\u002Fblog\u002Fenv-file-exposed-on-your-server","Ist deine .env-Datei öffentlich? Zwölf Pfade zum Prüfen","Ist deine .env-Datei auf deinem eigenen Webserver öffentlich? Zwölf Adressen sagen es dir, und ein Treffer heißt: alles darin ist längst öffentlich.","2026-10-04","\u002Fblog\u002Fenv-file-exposed-on-your-server\u002Fcard-800x500.png",{"path":889,"title":890,"description":891,"published":892,"category":629,"image":893,"draft":633},"\u002Fblog\u002Fis-v0-safe","v0-Sicherheit: alle 1.790 gescannten v0-Apps bekamen ein A","v0-Sicherheit, gemessen an 1.790 laufenden v0-Apps: Jede bekam ein A. Nur 17 nannten eine Datenbank, und genau das misst das A vor allem.","2026-10-03","\u002Fblog\u002Fis-v0-safe\u002Fcard-800x500.png",{"path":895,"title":896,"description":897,"published":898,"category":629,"image":899,"draft":633},"\u002Fblog\u002Fis-bolt-safe","Ist Bolt sicher? Was 1.123 echte Bolt-Apps zeigten","Ist Bolt sicher? Wir haben 1.123 laufende Bolt-Apps mit neun Checks geprüft. Das Hosting war sauber. Die Funde waren Schlüssel und offene Tabellen in den Apps.","2026-10-02","\u002Fblog\u002Fis-bolt-safe\u002Fcard-800x500.png",{"path":901,"title":902,"description":903,"published":904,"category":629,"image":905,"draft":633},"\u002Fblog\u002Fis-supabase-down-or-your-app","Ist Supabase down oder liegt es an deiner App? So erkennst du es","Ist Supabase down oder liegt es an deiner App? Ein pausiertes Projekt, eine volle Datenbank und ein eigener Fehler sehen gleich aus. Vier Prüfungen helfen.","2026-10-01","\u002Fblog\u002Fis-supabase-down-or-your-app\u002Fcard-800x500.png",{"path":907,"title":908,"description":909,"published":910,"category":629,"image":911,"draft":633},"\u002Fblog\u002Fdoes-supabase-encrypt-my-data","Verschlüsselt Supabase meine Daten? Ja. Wovor das schützt","Verschlüsselt Supabase Daten? Ja: AES-256 im Ruhezustand, TLS bei der Übertragung, SOC 2 und ISO 27001. Was jedes abdeckt und welches Leck keines stoppt.","2026-09-30","\u002Fblog\u002Fdoes-supabase-encrypt-my-data\u002Fcard-800x500.png",{"path":913,"title":914,"description":915,"published":916,"category":629,"image":917,"draft":633},"\u002Fblog\u002Fsupabase-free-plan-limits","Supabase Gratis-Tarif: die Limits und was an jedem passiert","Die Limits des Supabase-Gratis-Tarifs: 500 MB Datenbank, 5 GB Egress und keine Backups. Was an jeder Grenze passiert und was $25 für Pro ändern.","2026-09-29","\u002Fblog\u002Fsupabase-free-plan-limits\u002Fcard-800x500.png",{"path":919,"title":920,"description":921,"published":922,"category":733,"image":923,"draft":633},"\u002Fblog\u002Ftest-your-supabase-backup","Teste dein Supabase-Backup, bevor du es brauchst","So testest du dein Supabase-Backup: in ein Übungsprojekt einspielen, Zeilen zählen, anmelden und die Zeile suchen, die einer abgeschnittenen Datei fehlt.","2026-09-28","\u002Fblog\u002Ftest-your-supabase-backup\u002Fcard-800x500.png",{"path":925,"title":926,"description":927,"published":928,"category":733,"image":929,"draft":633},"\u002Fblog\u002Fsupabase-backup-github-action","Kostenloses Supabase-Backup per GitHub Action, mit Haken","Eine Supabase-Backup-GitHub-Action kostet nichts und passt für viele Apps. Der Workflow, der richtige Connection String und das Egress pro Lauf.","2026-09-27","\u002Fblog\u002Fsupabase-backup-github-action\u002Fcard-800x500.png",{"path":931,"title":932,"description":933,"published":934,"category":733,"image":935,"draft":633},"\u002Fblog\u002Fdownload-your-supabase-backup","Warum du dein Supabase-Backup nicht herunterladen kannst","Dein Supabase-Backup kannst du auf aktuellen Projekten nicht herunterladen, weil die Tageskopie physisch ist. Wie du es prüfst und selbst eine Kopie hältst.","2026-09-26","\u002Fblog\u002Fdownload-your-supabase-backup\u002Fcard-800x500.png",{"path":937,"title":938,"description":939,"published":934,"category":629,"image":940,"draft":633},"\u002Fblog\u002Fsupabase-permission-denied-for-table","Supabase \"permission denied for table\": der fehlende Grant","Ab 30. Oktober antwortet eine neue Supabase-Tabelle mit \"permission denied for table\", bis du Zugriff erteilst. Der Grant aus der E-Mail ist die halbe Lösung.","\u002Fblog\u002Fsupabase-permission-denied-for-table\u002Fcard-800x500.png",{"path":942,"title":943,"description":944,"published":945,"category":629,"image":946,"draft":633},"\u002Fblog\u002Fopen-api-endpoint-exposed","Ist ein offener API-Endpunkt ein Sicherheitsproblem? Sieh ins JSON","Dein Scan hat einen offenen API-Endpunkt gemeldet. Ob das zählt, hängt davon ab, was zurückkam, und die meisten hier gehörten der Plattform.","2026-09-25","\u002Fblog\u002Fopen-api-endpoint-exposed\u002Fcard-800x500.png",{"path":948,"title":949,"description":950,"published":951,"category":629,"image":952,"draft":633},"\u002Fblog\u002Flovable-security-scan","Lovable Security Scan: das Eine, was er nicht beweist","Lovable Security Scan: was Quick Scan und Deep Scan prüfen, wann welcher läuft, und das Eine, was kein Scan von innen beweisen kann.","2026-09-24","\u002Fblog\u002Flovable-security-scan\u002Fcard-800x500.png",{"path":954,"title":955,"description":956,"published":957,"category":733,"image":958,"draft":633},"\u002Fblog\u002Fsupabase-backup-auth-users","Warum in deinem Supabase-Dump keine Nutzer stehen","Führe supabase db dump allein aus und du bekommst die Form deiner Datenbank und keine einzige Zeile, und das auth-Schema mit deinen Nutzern fehlt ganz.","2026-09-23","\u002Fblog\u002Fsupabase-backup-auth-users\u002Fcard-800x500.png",{"path":960,"title":961,"description":962,"published":963,"category":629,"image":964,"draft":633},"\u002Fblog\u002Fdomain-and-certificate-expiry","Domain abgelaufen, Website offline: was jetzt passiert","Deine Domain ist abgelaufen und deine Website ist offline. Welche Frist jetzt läuft, warum das Zertifikat das kleinere Problem ist, und wie du beides prüfst.","2026-09-22","\u002Fblog\u002Fdomain-and-certificate-expiry\u002Fcard-800x500.png",{"path":966,"title":967,"description":968,"published":969,"category":629,"image":970,"draft":633},"\u002Fblog\u002Fis-lovable-safe","Ist Lovable sicher? Was 18.554 echte Lovable-Apps zeigten","Ist Lovable sicher? Wir haben 18.554 laufende Lovable-Apps mit neun Checks geprüft. Die Plattform war die sauberste von fünf. Die Funde saßen in den Apps.","2026-09-21","\u002Fblog\u002Fis-lovable-safe\u002Fcard-800x500.png",{"path":972,"title":973,"description":974,"published":975,"category":629,"image":976,"draft":633},"\u002Fblog\u002Fvibe-coded-app-security-checklist","Die Sicherheits-Checkliste für Vibe-Coding, in neun Prüfungen","Eine Sicherheits-Checkliste für Vibe-Coding mit neun Punkten, die jeder von außen an deiner Live-App nachprüfen kann, jeder mit einem Test in einer Zeile.","2026-09-20","\u002Fblog\u002Fvibe-coded-app-security-checklist\u002Fcard-800x500.png",{"path":978,"title":979,"description":980,"published":981,"category":629,"image":982,"draft":633},"\u002Fblog\u002Fstripe-secret-key-in-frontend","Ein geheimer Stripe-Schlüssel im Frontend kann Geld bewegen","Ein geheimer Stripe-Schlüssel im Frontend kann erstatten, abbuchen und jeden Kundendatensatz lesen, den du hast. Dein pk_live_-Schlüssel gehört dorthin.","2026-09-19","\u002Fblog\u002Fstripe-secret-key-in-frontend\u002Fcard-800x500.png",{"path":984,"title":985,"description":986,"published":987,"category":629,"image":988,"draft":633},"\u002Fblog\u002Fvite-and-next-public-env-vars","Vite-Env-Variablen offengelegt: der Präfix heißt veröffentlichen","Vite-Env-Variablen offengelegt: Deine App hat getan, was der Präfix verlangt. VITE_ und NEXT_PUBLIC_ heißen veröffentlichen, und die KI kannte den Preis nie.","2026-09-18","\u002Fblog\u002Fvite-and-next-public-env-vars\u002Fcard-800x500.png",{"path":990,"title":991,"description":992,"published":993,"category":629,"image":994,"draft":633},"\u002Fblog\u002Fbase44-source-maps","Base44-Sicherheit: was ein Scan meldet und was du ändern kannst","Base44-Sicherheit auf 5.438 gescannten Apps: Drei Befunde auf fast jeder gehören der Plattform, die Source Map ist das Base44-Badge, und deine Liste ist kurz.","2026-09-17","\u002Fblog\u002Fbase44-source-maps\u002Fcard-800x500.png",{"path":996,"title":997,"description":998,"published":999,"category":629,"image":1000,"draft":633},"\u002Fblog\u002Fis-cursor-ai-safe","Ist Cursor AI sicher? Editor, Code und die App, die du veröffentlichst","Ist Cursor AI sicher? Drei Fragen in einer Suche: was Cursor behält, was sein Code falsch macht und ob deine veröffentlichte App offen steht.","2026-09-16","\u002Fblog\u002Fis-cursor-ai-safe\u002Fcard-800x500.png",{"path":1002,"title":1003,"description":1004,"published":1005,"category":629,"image":1006,"draft":633},"\u002Fblog\u002Fis-replit-safe","Ist Replit sicher? Was wir in 3.042 Replit-Apps gefunden haben","Ist Replit sicher? Wir haben 3.042 laufende Replit-Apps mit neun externen Checks geprüft. Die Funde saßen in der veröffentlichten App, nicht im Hosting.","2026-09-15","\u002Fblog\u002Fis-replit-safe\u002Fcard-800x500.png",{"path":1008,"title":1009,"description":1010,"published":1011,"category":733,"image":1012,"draft":633},"\u002Fblog\u002Fsupabase-storage-backup","Supabase Storage Backup: deine Datenbankkopie hat keine Dateien","Ein Supabase Storage Backup ist eine eigene Aufgabe. Datenbank-Backups enthalten die Liste deiner Dateien und keine davon, also bleibt jeder Upload kaputt.","2026-09-14","\u002Fblog\u002Fsupabase-storage-backup\u002Fcard-800x500.png",{"path":1014,"title":1015,"description":1016,"published":1017,"category":733,"image":1018,"draft":633},"\u002Fblog\u002Fsupabase-point-in-time-recovery","Supabase Point-in-Time Recovery: Kosten und Grenzen","Supabase Point-in-Time Recovery spult deine Datenbank auf jede Sekunde der letzten Woche zurück. $100 im Monat zusätzlich zu Pro, und nur die Datenbank.","2026-09-13","\u002Fblog\u002Fsupabase-point-in-time-recovery\u002Fcard-800x500.png",{"path":1020,"title":1021,"description":1022,"published":1023,"category":733,"image":1024,"draft":633},"\u002Fblog\u002Fsupabase-project-paused-recover","Supabase-Projekt pausiert? Deine Daten sind noch da","Supabase hat dein Projekt nach einer Woche ohne Aktivität pausiert. Gelöscht ist nichts, Wiederherstellen steht neben dem Namen, und du hast ein Jahr.","2026-09-12","\u002Fblog\u002Fsupabase-project-paused-recover\u002Fcard-800x500.png",{"path":1026,"title":1027,"description":1028,"published":1029,"category":629,"image":1030,"draft":633},"\u002Fblog\u002Fsafest-ai-app-builder","Welcher KI-App-Builder ist am sichersten? 30.998 Apps im Test","Welcher KI-App-Builder ist am sichersten? Wir haben 30.998 aktive Apps von Lovable, Base44, Replit, v0 und Bolt gescannt. Der Builder entscheidet das nicht.","2026-09-11","\u002Fblog\u002Fsafest-ai-app-builder\u002Fcard-800x500.png",{"path":1032,"title":1033,"description":1034,"published":1035,"category":629,"image":1036,"draft":633},"\u002Fblog\u002Fenable-rls-on-every-supabase-table","Row Level Security für jede Supabase-Tabelle aktivieren und prüfen","Row Level Security in Supabase ohne Policy sperrt eine Tabelle komplett. Eine Policy ohne den Schalter bringt gar nichts. Hier ist das SQL, und der Test.","2026-09-10","\u002Fblog\u002Fenable-rls-on-every-supabase-table\u002Fcard-800x500.png",{"path":1038,"title":1039,"description":1040,"published":1041,"category":629,"image":1042,"draft":633},"\u002Fblog\u002Fsupabase-rls-disabled-in-public","Supabase \"RLS disabled in public\": was die Warnung übersieht","Supabase meldet \"RLS disabled in public\" als Fehler. Zur Lese-Policy, die deine Tabelle genauso offen lässt, sagt der Advisor gar nichts.","2026-09-09","\u002Fblog\u002Fsupabase-rls-disabled-in-public\u002Fcard-800x500.png",{"path":1044,"title":1045,"description":1046,"published":1047,"category":629,"image":1048,"draft":633},"\u002Fblog\u002Frotate-supabase-service-role-key","Geleakten Supabase-service_role-Schlüssel richtig tauschen","Supabase sagt: erst das Leck schließen. Andere Anleitungen: sofort tauschen. Was richtig ist, hängt davon ab, wohin dein service_role-Schlüssel gelangt ist.","2026-09-08","\u002Fblog\u002Frotate-supabase-service-role-key\u002Fcard-800x500.png",{"path":1050,"title":1051,"description":1052,"published":1053,"category":629,"image":1054,"draft":633},"\u002Fblog\u002Fvibe-coding-security-scanners-compared","Vibe-Coding-Security-Scanner im Vergleich, unserer eingeschlossen","Der beste Vibe-Coding-Security-Scanner hängt an drei Fragen, die keine Funktionsliste beantwortet. Acht Tools im Vergleich, mit Preisen und unseren Lücken.","2026-09-07","\u002Fblog\u002Fvibe-coding-security-scanners-compared\u002Fcard-800x500.png",{"path":1056,"title":1057,"description":1058,"published":1059,"category":629,"image":1060,"draft":633},"\u002Fblog\u002Fsupabase-security-checker","Supabase Security Checker: die fünf Prüfungen selbst machen","Ein Supabase Security Checker liest deine veröffentlichte App statt deiner Projekteinstellungen. Hier sind die fünf Prüfungen und wie du jede selbst ausführst.","2026-09-06","\u002Fblog\u002Fsupabase-security-checker\u002Fcard-800x500.png",{"path":1062,"title":1063,"description":1064,"published":1065,"category":629,"image":1066,"draft":633},"\u002Fblog\u002Fvibe-coding-security-scanner","Vibe-Coding-Security-Scanner: was ein URL-Scan übersieht","Ein Vibe-Coding-Security-Scanner liest deine laufende App von außen. Was das abdeckt, die vier Dinge, die er nicht sehen kann, und wie du das Ergebnis liest.","2026-09-05","\u002Fblog\u002Fvibe-coding-security-scanner\u002Fcard-800x500.png",{"path":1068,"title":1069,"description":1070,"published":1071,"category":629,"image":1072,"draft":633},"\u002Fblog\u002Fmissing-security-headers","Fehlende Sicherheitsheader: wann sie wirklich zählen","Fehlende Sicherheitsheader ist unser häufigster Befund. Wogegen sie schützen, und wann sie die unwichtigste Zeile in deinem Bericht sind.","2026-09-04","\u002Fblog\u002Fmissing-security-headers\u002Fcard-800x500.png",{"path":1074,"title":1075,"description":1076,"published":1077,"category":629,"image":1078,"draft":633},"\u002Fblog\u002Fopenai-api-key-exposed-in-frontend","Dein OpenAI-API-Schlüssel liegt im Frontend. Tausch ihn aus.","Ein OpenAI-API-Schlüssel im Frontend lässt sich an keine Domain binden. Tausch ihn heute, leg den Aufruf hinter deinen Server und begrenze das Budget.","2026-09-03","\u002Fblog\u002Fopenai-api-key-exposed-in-frontend\u002Fcard-800x500.png",{"path":1080,"title":1081,"description":1082,"published":1083,"category":629,"image":1084,"draft":633},"\u002Fblog\u002Fwhat-secrets-leak-from-vibe-coded-apps","API-Schlüssel im Frontend: was 30.998 Apps wirklich ausliefern","Ein API-Schlüssel im Frontend ist meistens ein Google-Maps-Schlüssel. Wir haben 30.998 aktive Vibe-Coding-Apps gescannt und gezählt, was wirklich austritt.","2026-09-02","\u002Fblog\u002Fwhat-secrets-leak-from-vibe-coded-apps\u002Fcard-800x500.png",{"path":1086,"title":1087,"description":1088,"published":1089,"category":733,"image":1090,"draft":633},"\u002Fblog\u002Fsupabase-backup-tools-compared","Supabase-Backup-Tools im Vergleich, unseres eingeschlossen","Vier Arten von Supabase-Backup-Tool, was jedes wirklich kopiert und wann eine kostenlose GitHub Action jeden Anbieter schlägt, uns eingeschlossen.","2026-09-01","\u002Fblog\u002Fsupabase-backup-tools-compared\u002Fcard-800x500.png",{"path":1092,"title":1093,"description":1094,"published":1095,"category":629,"image":1096,"draft":633},"\u002Fblog\u002Freplit-secrets-explained","Secrets in Replit nutzen, und was trotzdem veröffentlicht wird","Secrets in Replit nutzen: anlegen, auslesen und die zwei Gründe beheben, warum undefined zurückkommt. Dazu die Schlüssel, die das Werkzeug nicht schützt.","2026-08-31","\u002Fblog\u002Freplit-secrets-explained\u002Fcard-800x500.png",{"path":1098,"title":1099,"description":1100,"published":1101,"category":733,"image":1102,"draft":633},"\u002Fblog\u002Fback-up-supabase-free-tier","Supabase Gratis-Tarif: Backup ohne Terminal selbst machen","Im Supabase Gratis-Tarif gibt es keine Backups, die Kopie musst du selbst machen. Wie das im Dashboard geht und was der CSV-Weg auslässt.","2026-08-30","\u002Fblog\u002Fback-up-supabase-free-tier\u002Fcard-800x500.png",{"path":1104,"title":1105,"description":1106,"published":1107,"category":629,"image":1108,"draft":633},"\u002Fblog\u002Fis-supabase-secure","Ist Supabase sicher? Ja. Dein Projekt ist eine eigene Frage","Ist Supabase sicher? Die Plattform ist auditiert, verschlüsselt und pentestet. Supabase schreibt selbst auf, wo das aufhört und deine Einstellungen anfangen.","2026-08-29","\u002Fblog\u002Fis-supabase-secure\u002Fcard-800x500.png",{"path":1110,"title":1111,"description":1112,"published":1113,"category":629,"image":1114,"draft":633},"\u002Fblog\u002Fwhere-to-find-supabase-api-keys","Wo du deine Supabase API-Keys findest: anon, service_role, URL","Projekt-URL, anon-Schlüssel und service_role-Schlüssel liegen auf einer Seite im Dashboard. Wo sie ist, und welcher der vier Werte in deine App gehört.","2026-08-28","\u002Fblog\u002Fwhere-to-find-supabase-api-keys\u002Fcard-800x500.png",{"path":1116,"title":1117,"description":1118,"published":1119,"category":629,"image":1120,"draft":633},"\u002Fblog\u002Fnew-row-violates-row-level-security-policy","New row violates row-level security policy in Supabase: was jetzt?","\"New row violates row-level security policy\" heißt, Supabase hat einen Schreibvorgang abgelehnt. Die schnelle Lösung öffnet die Tabelle wieder für alle.","2026-08-27","\u002Fblog\u002Fnew-row-violates-row-level-security-policy\u002Fcard-800x500.png",{"path":1122,"title":1123,"description":1124,"published":1125,"category":629,"image":1126,"draft":633},"\u002Fblog\u002Fcors-wildcard-security-risk","Ist eine CORS-Wildcard ein Sicherheitsrisiko? Meist nicht.","Ist eine CORS-Wildcard ein Sicherheitsrisiko? Meist ist sie die Voreinstellung deines Builders und gibt nichts preis, was dein Server nicht ohnehin herausgab.","2026-08-26","\u002Fblog\u002Fcors-wildcard-security-risk\u002Fcard-800x500.png",{"path":1128,"title":1129,"description":1130,"published":1131,"category":733,"image":1132,"draft":633},"\u002Fblog\u002Fsupabase-branching-is-not-a-backup","Supabase Branching ist kein Backup. Es geht nur vorwärts.","Warum Supabase Branching kein Backup ist: Ein Branch startet ohne deine Daten, und ein Merge bringt nur das Schema. Wofür es gut ist und was stattdessen hilft.","2026-08-25","\u002Fblog\u002Fsupabase-branching-is-not-a-backup\u002Fcard-800x500.png",{"path":1134,"title":1135,"description":1136,"published":1137,"category":733,"image":1138,"draft":633},"\u002Fblog\u002Fhow-to-restore-a-supabase-backup","Supabase-Backup wiederherstellen, und was danach kaputt ist","Wie du ein Supabase-Backup aus dem Dashboard oder aus einer Dump-Datei wiederherstellst, was ersetzt wird und warum die App danach kaputt sein kann.","2026-08-24","\u002Fblog\u002Fhow-to-restore-a-supabase-backup\u002Fcard-800x500.png",{"path":1140,"title":1141,"description":1142,"published":1143,"category":629,"image":1144,"draft":633},"\u002Fblog\u002Fsupabase-storage-bucket-public","Dein Supabase-Storage-Bucket ist öffentlich. Ist das ein Problem?","Ein öffentlicher Supabase-Storage-Bucket heißt: Wer die URL einer Datei hat, kann sie öffnen. Er heißt nicht, dass jemand den Inhalt auflisten darf.","2026-08-23","\u002Fblog\u002Fsupabase-storage-bucket-public\u002Fcard-800x500.png",{"path":1146,"title":1147,"description":1148,"published":1149,"category":629,"image":1150,"draft":633},"\u002Fblog\u002Fgoogle-api-key-exposed-in-frontend","Ist ein Google-API-Schlüssel im Frontend ein Problem?","Ein Google-API-Schlüssel im Frontend ist der Fund unseres Scanners Nummer eins, und meistens unbedenklich. Eine kostenlose Einstellung entscheidet darüber.","2026-08-22","\u002Fblog\u002Fgoogle-api-key-exposed-in-frontend\u002Fcard-800x500.png",{"path":1152,"title":1153,"description":1154,"published":1155,"category":733,"image":1156,"draft":633},"\u002Fblog\u002Fai-agent-deleted-my-database","Ein KI-Agent hat meine Supabase-Daten gelöscht. Was hole ich zurück?","Ein KI-Agent hat Daten aus deiner Datenbank gelöscht. Was du zurückholst, stand schon vorher fest, und die nächsten Minuten entscheiden über den Rest.","2026-08-21","\u002Fblog\u002Fai-agent-deleted-my-database\u002Fcard-800x500.png",{"path":1158,"title":1159,"description":1160,"published":1161,"category":629,"image":1162,"draft":633},"\u002Fblog\u002Fcan-anyone-read-your-supabase-database","Kann jeder deine Supabase-Datenbank lesen? 3.680 Apps im Test","Kann jeder deine Supabase-Datenbank ohne Login lesen? Wir haben 30.998 aktive Apps aus KI-Buildern gescannt und gemessen, wie oft die Antwort ja lautet.","2026-08-18","\u002Fblog\u002Fcan-anyone-read-your-supabase-database\u002Fcard-800x500.png",{"path":1164,"title":1165,"description":1166,"published":1161,"category":629,"image":1167,"draft":633},"\u002Fblog\u002Fsource-maps-exposed-in-production","Source-Maps öffentlich: deine App veröffentlicht ihren Quellcode","Eine öffentliche Source-Map lässt jeden den Originalcode deiner App lesen, Kommentare inklusive. Der 30-Sekunden-Check, und was wirklich zählt.","\u002Fblog\u002Fsource-maps-exposed-in-production\u002Fcard-800x500.png",{"path":1169,"title":1170,"description":1171,"published":1172,"category":629,"image":1173,"draft":633},"\u002Fblog\u002Fsupabase-new-api-keys","Supabase publishable key: ist er derselbe wie der anon key?","Supabase hat anon und service_role durch öffentliche und geheime Schlüssel ersetzt. Welcher gehört in deine App, und welcher nie?","2026-08-12","\u002Fblog\u002Fsupabase-new-api-keys\u002Fcard-800x500.png",{"path":1175,"title":1176,"description":1177,"published":1178,"category":733,"image":1179,"draft":633},"\u002Fblog\u002Fdoes-supabase-back-up-my-database","Sichert Supabase meine Datenbank? Das hängt von deinem Tarif ab.","Sichert Supabase deine Datenbank? Auf bezahlten Tarifen täglich, im Gratis-Tarif gar nicht. So findest du heraus, was du hast und was es nicht abdeckt.","2026-08-11","\u002Fblog\u002Fdoes-supabase-back-up-my-database\u002Fcard-800x500.png",{"path":1181,"title":1182,"description":1183,"published":1184,"category":629,"image":1185,"draft":633},"\u002Fblog\u002Fsupabase-rls-on-but-table-still-public","Supabase Row Level Security ist an. Die Tabelle ist trotzdem offen.","Supabase Row Level Security anzuschalten schützt keine Tabelle. Erst deine Policies tun das, und die, die deine App repariert hat, lässt oft alle herein.","2026-08-10","\u002Fblog\u002Fsupabase-rls-on-but-table-still-public\u002Fcard-800x500.png",{"path":1187,"title":1188,"description":1189,"published":1184,"category":733,"image":1190,"draft":633},"\u002Fblog\u002Fversion-history-is-not-a-backup","Der Versionsverlauf ist kein Backup. Er holt keine Tabelle zurück.","Lovable und Bolt führen einen Versionsverlauf für deinen Code. Deine Datenbank ist ein eigener Dienst, und ein Rücksprung holt deine Daten nicht zurück.","\u002Fblog\u002Fversion-history-is-not-a-backup\u002Fcard-800x500.png",{"path":1192,"title":1193,"description":1194,"published":1195,"category":733,"image":1196,"draft":633},"\u002Fblog\u002Fthree-ways-to-back-up-a-supabase-database","Drei Wege, eine Supabase-Datenbank zu sichern, und was fehlt","Das Dashboard, pg_dump und ein verwalteter Dienst. Was jeder Weg wirklich sichert, was er stillschweigend auslässt und welcher den Kontoverlust übersteht.","2026-08-09","\u002Fblog\u002Fthree-ways-to-back-up-a-supabase-database\u002Fcard-800x500.png",{"path":374,"title":1198,"description":1199,"published":1195,"category":629,"image":1200,"draft":633},"Welche API-Schlüssel im Frontend sicher sind, und welche nicht","Dein Supabase-anon-Schlüssel darf öffentlich sein. Der service_role-Schlüssel nicht. Er ignoriert jede Regel, die du setzt. So erkennst du den Unterschied.","\u002Fblog\u002Fwhich-api-keys-are-safe-in-your-frontend\u002Fcard-800x500.png",1794213638672]