Integrazione OAuth 2.1 — Guida per sviluppatori

Questa guida descrive come collegare un'applicazione esterna alla piattaforma Cuborio tramite OAuth 2.1 con PKCE.


Prerequisiti

  • OAuth abilitato: la variabile OAUTH_ENABLED=true deve essere impostata nel .env del server Cuborio.

  • Accesso artisan: per creare i client serve accesso alla CLI del server.

  • Utente Cuborio: l'utente finale deve avere un account attivo sulla piattaforma.


1. Creazione del client

Ogni applicazione che si collega necessita di un client OAuth con le proprie credenziali.

Creare un client

php artisan oauth:client create \
  --name="Nome Applicazione" \
  --redirect-uri="https://example.com/callback"

Nota sul redirect-uri: deve essere l'URL dell'applicazione esterna che gestisce la callback OAuth, non un URL di Cuborio. E' l'indirizzo a cui l'utente viene reindirizzato dopo aver autorizzato l'accesso, e deve corrispondere a quello che l'applicazione esterna invia nel parametro redirect_uri durante il flusso di autorizzazione.

Esempio per Claude AI (CoWork):

php artisan oauth:client create \
  --name="Claude" \
  --redirect-uri="https://claude.ai/api/mcp/auth_callback"

Output:

Il client_secret viene mostrato una sola volta. E' hashato in database con bcrypt e non e' recuperabile. Se perso, occorre revocare il client e crearne uno nuovo.

Elencare i client

Revocare un client


2. Endpoint disponibili

Endpoint
Metodo
Descrizione

/.well-known/oauth-authorization-server

GET

Discovery metadata (RFC 8414)

/.well-known/oauth-protected-resource

GET

Protected resource metadata MCP (RFC 9728)

/authorize

GET

Pagina di consenso utente

/authorize

POST

Approvazione/rifiuto consenso

/token

POST

Scambio code per token / refresh

/revoke

POST

Revoca token (RFC 7009)

L'endpoint di discovery restituisce automaticamente tutti gli URL:


3. Flusso di autorizzazione (authorization_code + PKCE)

Il flusso OAuth 2.1 con PKCE si compone di 4 passi.

Passo 1 — Generare il PKCE code verifier e challenge

Il client genera un code_verifier casuale (43-128 caratteri URL-safe) e calcola il code_challenge con SHA-256:

Passo 2 — Redirect dell'utente alla pagina di consenso

Aprire nel browser dell'utente:

Parametro
Obbligatorio
Descrizione

response_type

Si

Sempre code

client_id

Si

Il client ID ottenuto alla creazione

redirect_uri

Si

Deve corrispondere esattamente a quello registrato

state

Si

Stringa casuale anti-CSRF, verificata dal client al ritorno

code_challenge

Si

Challenge PKCE calcolato al passo 1

code_challenge_method

Si

Sempre S256

scope

No

Default: mcp:tools

L'utente vede una pagina di consenso con il nome dell'applicazione e puo' autorizzare o negare.

Passo 3 — Ricevere l'authorization code

Dopo l'approvazione, l'utente viene reindirizzato a:

Verificare sempre che state corrisponda a quello inviato al passo 2.

Se l'utente nega, il redirect contiene error=access_denied.

Passo 4 — Scambiare il code per i token

In alternativa alle credenziali nel body, si puo' usare HTTP Basic Auth:

Risposta:


4. Usare l'access token

Includere il token nell'header Authorization di ogni richiesta API:


5. Rinnovare l'access token

L'access token scade dopo 1 ora (configurabile). Prima della scadenza, usare il refresh token per ottenerne uno nuovo:

Risposta: stessa struttura del passo 4, con nuovi access_token e refresh_token.

Refresh token rotation: ad ogni refresh, il vecchio refresh token viene revocato e ne viene emesso uno nuovo. Non riutilizzare il vecchio.


6. Revocare un token

Per disconnettere l'applicazione (logout), revocare il token:

Si puo' passare sia un access token che un refresh token. La revoca e' sempre a cascata: revocando uno si revoca anche l'altro della coppia. La risposta e' sempre 200 OK (RFC 7009).


7. Scadenze e configurazione

Parametro
Default
Variabile d'ambiente

Access token TTL

1 ora (3600s)

OAUTH_ACCESS_TOKEN_TTL

Refresh token TTL

30 giorni (2592000s)

OAUTH_REFRESH_TOKEN_TTL

Authorization code TTL

10 minuti (600s)

OAUTH_AUTH_CODE_TTL


8. Gestione degli errori

Tutte le risposte di errore seguono il formato standard OAuth 2.1:

Codice errore
HTTP
Causa

invalid_client

401

Client ID o secret errati

invalid_grant

400

Code scaduto, gia' usato, PKCE errato, refresh token invalido

invalid_request

400

Parametri mancanti, redirect URI non autorizzato

unsupported_response_type

400

Usato un response_type diverso da code

unsupported_grant_type

400

Usato un grant_type non supportato

access_denied

L'utente ha negato il consenso (redirect, non JSON)


9. Esempio completo (PHP)


10. Sicurezza

  • PKCE obbligatorio: non e' possibile ottenere token senza code_challenge + code_verifier (S256).

  • Authorization code monouso: un secondo utilizzo restituisce invalid_grant.

  • Refresh token rotation: ogni refresh invalida il token precedente.

  • Token hashati: access token, refresh token e authorization code sono salvati in database come hash SHA-256. I valori in chiaro esistono solo nella risposta HTTP.

  • Client secret hashato: salvato con bcrypt, non recuperabile.

  • Revoca a cascata: revocare un access token revoca anche il refresh associato, e viceversa.

  • Constant-time comparison: tutti i confronti di token usano hash_equals per prevenire timing attacks.

Ultimo aggiornamento

È stato utile?