modulo 04 / lezione 24

Architettura mentale di un'applicazione

API, autenticazione, autorizzazione, sessioni

Capire i concetti base che regolano accesso e scambio dati, prima di chiedere all'AI di implementarli.

60 minVibe Coding

API, autenticazione, autorizzazione, sessioni

Quattro concetti che chi inizia confonde sempre, e che il modello AI implementa con errori sistematici se non sai cosa stai chiedendo. API = contratto. Autenticazione = chi sei. Autorizzazione = cosa puoi fare. Sessione = continuità del tuo accesso. Sapere cosa è cosa permette di chiedere implementazioni corrette invece di generiche.

Perché questa lezione conta

Errori in questa area producono falle reali: token in localStorage rubabili via XSS, ruoli verificati solo lato client, autorizzazioni mancanti su endpoint, sessioni che non scadono. Sono errori comuni nei prototipi generati. Studiare i concetti — non i dettagli implementativi — ti permette di chiedere all’AI implementazioni sicure e di leggere il codice sapendo cosa cercare.

Obiettivo operativo

Alla fine devi saper:

  1. distinguere API, autenticazione, autorizzazione, sessione;
  2. progettare a parole un flusso login/logout e un endpoint protetto;
  3. identificare 5 anti-pattern di sicurezza tipici di prototipi AI.

Nucleo della lezione

1. API come contratto

Un’API (Application Programming Interface) è un contratto: un client manda una richiesta in un formato definito, riceve risposta in un formato definito.

Componenti:

  • Endpoint: indirizzo + metodo. GET /users/:id, POST /orders.
  • Request: metodo, URL, headers (incl. auth), query string, body. Dati in entrata.
  • Response: status code, headers, body. Dati in uscita + segnale di esito.
  • Status code: 2xx successo, 3xx redirect, 4xx errore client (richiesta sbagliata o non autorizzata), 5xx errore server.
  • Errori: messaggio strutturato, leggibile da macchina. Mai esporre stack trace o dettagli interni.
  • Versionamento: quando cambi un’API esistente, rompi i client. Versiona (/v1/..., /v2/...) o estendi senza rompere.

Stili principali:

  • REST: orientato a risorse, metodi HTTP standard. Maggioritario per molti casi.
  • GraphQL: query flessibili, un endpoint, schema fortemente tipato. Utile per UI complesse.
  • RPC (gRPC, JSON-RPC): orientato ad azioni. Usato in sistemi distribuiti interni.

Per la maggior parte dei progetti vibe coding, REST è il default ragionevole.

2. Autenticazione vs autorizzazione

Autenticazione (authn): dimostrare chi sei. Risponde a “sei davvero Carlo?”. Tipiche prove:

  • password (cosa sai);
  • magic-link via email (cosa hai accesso a);
  • TOTP/codice da app (qualcosa che hai);
  • biometria (qualcosa che sei);
  • passkey/WebAuthn (combinazione di sopra, criptograficamente forte).

Esito: il server stabilisce identità. Genera un token o crea sessione.

Autorizzazione (authz): cosa puoi fare. Risponde a “Carlo può eliminare questa risorsa?”. Modelli tipici:

  • Ruoli (RBAC): ogni utente ha 1+ ruoli (admin, editor, viewer); ogni ruolo ha permessi.
  • Ownership: utente può modificare solo le sue risorse.
  • Permessi granulari: regole esplicite per risorsa.
  • Policy-based (ABAC): condizioni complesse (ruolo + attributo risorsa + contesto).

Errore comune: confondere i due. Se sei autenticato non significa che sei autorizzato a tutto. Server deve verificare entrambi.

3. Sessione

Una sessione mantiene l’identità autenticata fra più richieste, perché HTTP è stateless.

Due approcci principali:

Cookie + sessione lato server: server crea sessione, salva in DB/Redis, manda cookie al client (id sessione). Client invia cookie a ogni richiesta. Vantaggi: revoca facile, controllo totale. Cookie deve avere flags: HttpOnly (no JS access, anti-XSS), Secure (solo HTTPS), SameSite=Lax o Strict (anti-CSRF). Sessione scade lato server.

Token (JWT) lato client: server firma JWT con identità e permessi. Client invia token in header Authorization: Bearer ... a ogni richiesta. Vantaggi: stateless. Rischi: revoca difficile (token valido fino a scadenza), token in localStorage rubabile via XSS. Buone pratiche: token corto (15 min) + refresh token in cookie HttpOnly.

Per la maggior parte dei vibe-coding project: cookie + sessione server, gestita da auth provider (Auth.js / NextAuth, Clerk, Supabase Auth, Auth0). Implementare auth a mano è zona dove l’AI sbaglia spesso.

4. Anti-pattern tipici

Cinque errori che il modello AI tende a produrre:

  • Token in localStorage: vulnerabile a XSS. Usa cookie HttpOnly.
  • Ruoli solo lato client: client invia “io sono admin” e server fida. Sempre verificare lato server, derivando ruolo da sessione.
  • Endpoint protetti solo via UI: bottone admin nascosto via CSS, ma endpoint /admin/delete aperto a tutti. Sempre middleware/decorator di autorizzazione sull’endpoint.
  • Errori troppo dettagliati: “user not found” vs “wrong password” → enumeration attack. Stesso errore generico per entrambi: “credenziali non valide”.
  • Sessione senza scadenza o senza revoca: utente logged forever, anche dopo cambio password. Sessione con TTL ragionevole, possibilità di revoca.

Procedura pratica

Per progettare auth in un’app:

  1. Decidi modello identità: email/password, magic-link, OAuth (Google/Apple/GitHub), passkey, MFA.
  2. Scegli provider o auth a mano: per quasi tutti i casi, provider (Clerk, Supabase, Auth.js).
  3. Definisci ruoli/permessi: cominci con 2-3 ruoli, espandi se servono.
  4. Specifica autorizzazione per endpoint: per ogni endpoint, chi può chiamarlo + quali risorse può toccare.
  5. Strategia sessione: cookie HttpOnly + scadenza, refresh, logout su tutti dispositivi.
  6. Test casi negativi: utente non autenticato, autenticato ma non autorizzato, token scaduto, token manipolato.

Laboratorio guidato

Progetta a parole un flusso login/logout + endpoint protetto.

Auth flow (magic-link):

  1. Utente inserisce email su /login.
  2. POST /auth/request-link → server genera token random firmato, salva con scadenza 15 min, invia email con link https://app/auth/verify?token=....
  3. Utente clicca link → GET /auth/verify?token=... → server verifica firma + scadenza, crea sessione, set cookie HttpOnly Secure SameSite=Lax, redirect a /dashboard.
  4. Da qui in poi, ogni richiesta include cookie sessione, server lo verifica.
  5. Logout: POST /auth/logout → server distrugge sessione lato server + clear cookie.

Endpoint protetto (esempio: cancella ordine):

  • DELETE /orders/:id.
  • Middleware autenticazione: verifica cookie sessione → se valido, attacca user a request; se no, 401.
  • Middleware autorizzazione: legge ordine da DB, verifica order.user_id === user.id (ownership) OR user.role === 'admin'. Se no, 403.
  • Esegui delete.
  • Risposta 204 (no content) su successo, 404 se non trovato (mai distinguere 404 da 403 per ridurre information leak).

Casi da gestire:

  • Token magic-link già usato → errore “link non valido o scaduto” (stesso messaggio per non rivelare).
  • Cookie scaduto → 401 con redirect a login.
  • Tentativo di delete ordine altrui → 404 (non 403, per non rivelare esistenza).

Output atteso

Una specifica API per auth + 1 endpoint protetto, con: metodo, URL, request, response, codici errore, regole di autorizzazione. Documento di una pagina, allegato al prompt prima di chiedere implementazione.

Studio passo passo

Studia questa lezione in tre passaggi, senza correre subito al prompt o al codice.

  1. Prima lettura: chiarisci l’obiettivo: capire i concetti base che regolano accesso e scambio dati, prima di chiedere all’AI di implementarli. Se non riesci a riscriverlo in una frase tua, rileggi il nucleo della lezione.
  2. Seconda lettura: trasforma i contenuti in domande operative:
  • API come contratto tra parti: endpoint, request, response, errori, versionamento implicito.
  • Autenticazione come identità, autorizzazione come permesso, sessione come continuità dell’accesso.
  • Rischi da non banalizzare: token esposti, controlli solo lato client, ruoli confusi, errori troppo dettagliati.
  1. Applicazione: svolgi il laboratorio: progettare a parole un flusso login/logout e un endpoint protetto, senza scrivere codice. L’output da ottenere è: una specifica di API essenziale con casi di successo, fallimento e permessi richiesti.

Prima di passare alla lezione successiva, controlla di avere un artefatto concreto: una tabella, un prompt, una checklist, un mini report, un diff commentato o una decisione scritta. Nel vibe coding la comprensione resta astratta finché non produce una traccia verificabile.

Checklist di verifica

  • distinguo authentication da authorization;
  • so quali cookie flags servono per sessione sicura;
  • ho una preferenza chiara fra cookie/sessione vs JWT, con motivazione;
  • riconosco i 5 anti-pattern e li evito nei prompt;
  • progetto i casi negativi prima dell’happy path.

Errori comuni

Implementare auth a mano da zero. Anche per progetti piccoli, raramente è la scelta giusta. Provider gestiscono dettagli (rate limit, lockout, MFA, password reset).

Non usare HTTPS in produzione. Senza HTTPS, qualsiasi sicurezza auth è teatro. Vercel, Netlify, Fly, Railway: HTTPS automatico. Self-hosting: Caddy, Traefik, Let’s Encrypt.

Verificare ruoli sul client. Rivelano rapidamente fragilità: bypass via DevTools.

Non testare casi negativi. “Login funziona” ≠ “auth è sicura”. Test: token mancante, token scaduto, token manipolato, ownership violata, ruolo insufficiente.

JWT senza refresh strategy. Token long-lived = se rubato, attaccante ha accesso a lungo. Token corto + refresh in cookie HttpOnly.

Prompt di lavoro

Voglio progettare auth + autorizzazione per: [descrizione app + utenti]

Vincoli:
- piattaforma: [web / mobile / entrambe]
- utenti: [scala stimata]
- compliance: [GDPR base / settoriale]
- budget: [con / senza provider esterno]

Aiutami in 4 fasi (rispondi una alla volta, aspetta mio OK):

Fase 1: scelta modello identità (password, magic-link, OAuth, passkey, MFA) con trade-off per il mio caso.

Fase 2: scelta sessione (cookie/sessione server vs JWT vs entrambi) con motivazione.

Fase 3: ruoli e permessi minimi. Tabella ruolo → permessi, con esempi su endpoint principali.

Fase 4: flusso login/logout completo + 2 endpoint protetti (uno con check ownership, uno con check ruolo). Specifica request/response/errori/casi negativi. NO codice ancora.

Concludi con anti-pattern da evitare specifici alla mia scelta.

Esercizio finale

Apri devtools di un’app che usi (la tua o di terze parti rispettando ToS). Cerca: dove è salvato il token? Cookie HttpOnly o localStorage? Quali flags ha il cookie? Cosa succede se cancelli il cookie e provi a chiamare l’API protetta? L’esercizio non è hacking: è osservazione. Vedi pattern reali, riconosci buone e cattive pratiche, calibri il tuo prompt per ottenere la prima e non la seconda.