Hemmelig API-nøgle i en Expo-app: hvad skal beskyttes?
Af Mehdi Azizi
Opdateret , 7 min.
Offentlig Supabase-nøgle, servernøgle, Expo-variabler: se hvad der må ligge i din iPhone-app, og test adgangen med to testkonti.
En miljøvariabel er ikke nødvendigvis en hemmelighed
I en Expo-app er en variabel med præfikset EXPO_PUBLIC_ beregnet til appens kode. Den må ikke indeholde en serverhemmelighed. Expo forklarer, at disse værdier bliver bygget ind i det kompilerede JavaScript og kan læses af appens brugere. Det er altså ikke nok at flytte en nøgle over i en .env-fil for at beskytte den. Kilde: miljøvariabler i Expo.
Før du beder en AI om at "koble API'et på", så sortér det, du giver den: en tjenesteadresse, en nøgle der er lavet til at være offentlig, eller en nøgle der giver adgang til privilegerede handlinger. Den sortering afgør, hvor koden skal køre.
Tabellen herunder er et designskema, ikke en revision af din app.
| Element | Hvor den skal ligge | Hvad du skal tjekke |
|---|---|---|
| Backendens offentlige adresse | Appens konfiguration | Den peger på det rigtige miljø. |
| Supabase publishable-nøgle, eller gammel anon-nøgle | I appen, hvis tilladelserne er sat korrekt op | Datareglerne blokerer reelt adgang til en anden brugers konto. |
| Supabase secret- eller service_role-nøgle | Kun på serveren | Den optræder hverken i mobil-bundlen eller i logs, som klienten har adgang til. |
| Hemmelig nøgle fra en AI-udbyder | Kun på serveren | Appen kalder din server, som tjekker brugeren og grænserne, før udbyderen bliver kaldt. |
Supabase skelner mellem nøgler beregnet til klienter og hemmelige nøgler til betroede miljøer. En offentlig nøgle identificerer projektet. Den erstatter ikke tilladelserne på dataene. Kilde: API-nøgler i Supabase.
Eksempel: en fiktiv læsedagbogs-app
Forestil dig en app, hvor Léa og Sami gemmer deres bøger og private noter. Eksemplet er til at forberede testene. Det beskriver ikke resultater fra en Devoria-app.
Det normale flow ser fint ud: Léa logger ind og ser sine noter. Men det svarer endnu ikke på det vigtige spørgsmål: afviser serveren en forespørgsel fra Léa, der går efter en af Samis noter?
Et filter i brugerfladen, som "vis den indloggede brugers noter", gør visningen bedre. Men autorisationen skal også håndhæves på dataniveau. I Supabase kan du med Row Level Security-regler begrænse, hvilke rækker der er adgang til ud fra sessionen. Supabase anbefaler at slå det til for tabeller, der eksponeres via API'et, og forklarer politikkerne for læsning og skrivning. Kilde: Row Level Security.
I dit eget testprojekt skal du knytte hver note til sin ejer og definere hver for sig, hvem der må læse, oprette, ændre og slette den. Tjek også filerne: at en databaserække er beskyttet, beviser ikke, at et billede er privat.
Testplanen du skal køre med to testkonti
Lav to konti, som du selv styrer, med en forskellig bog i hver og en lille note, du kan genkende. Brug fiktive data i et testmiljø, hvor du har lov at teste.
- Læs din egen note. Konto A finder note A.
- Læs B's note fra A. Forespørgslen afslører ikke det private indhold.
- Ret B's note fra A. Serveren afviser, og note B er uændret.
- Opret i B's navn fra A. Serveren afviser tildelingen.
- Læs uden session. Der returneres intet privat indhold.
- Åbn B's private fil fra A. Filen er ikke tilgængelig.
Notér det faktiske resultat, den testede version og en eventuel fejl. "Reglerne er slået til" er ikke et testresultat. Testskemaet under ressourcer kan bruges som udgangspunkt til at gemme den dokumentation.
Send betalte kald gennem din server
Til en funktion, der opsummerer en bog med et AI-API, kan flowet være: app → din server → udbyder → din server → app. Den hemmelige nøgle bliver på serveren. Den arkitektur er ikke nok i sig selv: adgangen til serveren skal også kontrolleres.
I det fiktive eksempel skal serveren blandt andet tjekke sessionen, tjekke at bogen tilhører personen, begrænse gentagne forespørgsler og returnere en forståelig fejl, hvis udbyderen ikke svarer. Klienten bestemmer ikke selv, at en bruger har betalt adgang.
Forbered fire forsøg: bruger der ikke er logget ind, en bog fra en anden konto, grænse nået og udbyder utilgængelig. Det sidste viser, om appen kommer ud af sin indlæsningstilstand uden at miste det, brugeren har skrevet.
Hvad du kan bede din kodeassistent om
Her er en review-instruks, du kan tilpasse til dit repo. Indsæt ikke dine hemmelige værdier i den:
Lav en oversigt over de variabler, der bruges af mobilkoden og af serveren, og vis kun deres navne. Find privilegerede kald på klientsiden. For private data skal du beskrive kontrollerne for læsning og skrivning og derefter foreslå en testplan med to testkonti. Lav ingen nøglerotation eller ændringer i produktion uden godkendelse.
Læs svaret sammen med den tilhørende kode. En assistent kan opdage en uoverensstemmelse, men dens svar erstatter ikke, at du kører testene. Guiden lav en app med Claude Code forklarer, hvordan du deler arbejdet op.
Før du arbejder videre på din app
Du skal kunne forklare tre ting enkelt: hvilke værdier der er offentlige, hvilke handlinger der går gennem serveren, og hvilke tests der viser, at en konto ikke ser en andens data. Hvis et af punkterne stadig er uklart, så få det på plads, før du tilføjer flere funktioner.
Siden lav en iPhone-app sætter dette trin ind i det samlede projekt. Vil du tage tingene i den rigtige rækkefølge, giver iOS Kit dig et forløb i fire trin og en Starter Code, der allerede har konti og AI med. Hvis du ikke ved, hvilket trin du skal fortsætte fra, sætter den gratis diagnose dit projekt i rækkefølge og sender dig min tjekliste mod afvisninger fra Apple.
Ofte stillede spørgsmål
Hvor skal en hemmelig API-nøgle ligge i en Expo-app?
På din server, aldrig i appen. Supabase secret- eller service_role-nøglen skal, ligesom den hemmelige nøgle fra en AI-udbyder, kun ligge på serveren. Appen kalder din server, som tjekker brugeren og grænserne, før den kalder udbyderen. Tjek, at ingen af nøglerne optræder i mobil-bundlen eller i logs, som klienten har adgang til.
Beskytter en .env-fil min API-nøgle i Expo?
Ikke i sig selv. En variabel med præfikset EXPO_PUBLIC_ er beregnet til appens kode og må ikke indeholde en serverhemmelighed. Expo forklarer, at disse værdier bliver bygget ind i det kompilerede JavaScript og kan læses af appens brugere. Det er altså ikke nok at flytte en nøgle over i en .env-fil for at beskytte den.
Hvad er forskellen på en offentlig og en hemmelig API-nøgle?
En offentlig nøgle er lavet til at blive leveret i appen: den identificerer projektet, men den erstatter ikke tilladelserne på dataene. En hemmelig nøgle giver adgang til privilegerede handlinger og er forbeholdt betroede miljøer. Hos Supabase kan publishable-nøglen, eller den gamle anon-nøgle, ligge i appen, hvis tilladelserne er sat korrekt op. Secret- og service_role-nøglerne bliver på serveren.
Hvordan kalder jeg et AI-API fra en Expo-app uden at afsløre nøglen?
Send kaldet gennem din server: appen kalder serveren, som kalder udbyderen og sender svaret tilbage til appen. Den hemmelige nøgle bliver på serveren. Serveren skal også tjekke sessionen, begrænse gentagne forespørgsler og returnere en forståelig fejl, hvis udbyderen ikke svarer. Klienten bestemmer ikke selv, at en bruger har betalt adgang.
Hvordan tjekker jeg, at hver bruger kun ser sine egne data?
Lav to testkonti, som du selv styrer, med en note du kan genkende i hver. Fra konto A prøver du at læse, ændre og oprette i konto B's navn og derefter åbne B's private fil. Lav også forsøgene uden session: hver forespørgsel skal afvises eller ikke afsløre noget. Notér det faktiske resultat, for "reglerne er slået til" er ikke et testresultat.
Hvordan beder jeg en AI om at tjekke nøglerne i min app?
Bed den om at lave en oversigt over variablerne i mobilkoden og på serveren og kun vise deres navne, uden at du indsætter dine hemmelige værdier. Bed den også finde privilegerede kald på klientsiden og foreslå en testplan med to testkonti. Forbyd nøglerotation og ændringer i produktion uden godkendelse. Dens svar erstatter ikke, at du kører testene.