Autenticazione

App OAuth

Per le app che agiscono per conto di altri utenti Gravl. OAuth 2.0 authorization-code standard con PKCE: gli utenti concedono alla tua app scope specifici, tu ottieni access token a vita breve con un refresh token a rotazione, e il grant è revocabile in qualsiasi momento.

1. Registra la tua app

Finché l'API è in beta la registrazione è manuale. Scrivi a developers@gravl.ai indicando:

  • Il nome della tua app e una breve descrizione di cosa fa
  • Le tue redirect URI OAuth: URL https assoluti (http://localhost è consentito per lo sviluppo)
  • Gli scope di cui la tua app ha bisogno: chiedi il minimo; gli utenti vedono esattamente ciò che richiedi

Riceverai un client_id (gci_…) e un client_secret (gcs_…, mostrato una sola volta: conservalo come una password).

2. Manda l'utente alla schermata di consenso

GET /oauth/authorize
https://api.gravl.ai/oauth/authorize
  ?client_id=gci_…
  &redirect_uri=https://yourapp.example/callback   // must be registered exactly
  &scope=workouts:read stats:read                  // omit for all allowed scopes
  &state=<random value you verify on return>
  &code_challenge=<S256(code_verifier)>
  &code_challenge_method=S256

L'utente accede con il suo account Gravl, vede il nome della tua app e gli scope richiesti in linguaggio chiaro e approva: il suo browser torna alla tua redirect_uri con ?code=gac_…&state=… (oppure error=access_denied se annulla).

  • I codici hanno prefisso gac_, valgono 10 minuti, sono monouso e sono legati alla tua app e alla redirect_uri per cui sono stati emessi
  • PKCE (S256) è obbligatorio per i client pubblici (app browser o native, che non hanno un client_secret) e fortemente consigliato per tutti
  • Verifica sempre che state corrisponda a quello che hai inviato: è la tua protezione CSRF

I client pubblici omettono client_secret all'endpoint dei token: PKCE è la loro autenticazione client. Dicci di che tipo è la tua app al momento della registrazione.

3. Scambia il codice

POST /oauth/token — authorization_code
curl -X POST https://api.gravl.ai/oauth/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d grant_type=authorization_code \
  -d code=gac_… \
  -d client_id=gci_… \
  -d client_secret=gcs_… \
  -d code_verifier=<your PKCE verifier> \
  -d redirect_uri=https://yourapp.example/callback

{
  "access_token": "gat_…",
  "token_type": "Bearer",
  "expires_in": 21600,
  "refresh_token": "grt_…",
  "scope": "workouts:read stats:read"
}
TokenDurataNote
access_token6 oreBearer token per le richieste /api/v1.
refresh_tokenFino a 180 giorniMonouso: ogni refresh lo revoca ed emette una nuova coppia (rotazione).

4. Rinnova

POST /oauth/token — refresh_token
curl -X POST https://api.gravl.ai/oauth/token \
  -d grant_type=refresh_token \
  -d refresh_token=grt_… \
  -d client_id=gci_… \
  -d client_secret=gcs_…

La risposta ha la stessa forma dello scambio del codice. Il refresh token presentato viene revocato nella stessa transazione: salva sempre il nuovo refresh_token prima di scartare il vecchio. Riutilizzare un refresh token già usato restituisce invalid_grant.

5. Revoca

POST /oauth/revoke
curl -X POST https://api.gravl.ai/oauth/revoke \
  -d token=grt_… \
  -d client_id=gci_… \
  -d client_secret=gcs_…
  • Revocare un access token elimina solo quel token
  • Revocare un refresh token revoca l'intero grant: ogni token in circolazione per quella coppia utente + app
  • Come da RFC 7009 l'endpoint restituisce 200 anche per token sconosciuti: solo credenziali client errate producono un errore
  • Gli utenti possono anche revocare l'accesso della tua app dal loro account

Errori dell'endpoint dei token

Gli errori seguono la RFC 6749: { "error": "…", "error_description": "…" }

ErroreStatusSignificato
invalid_request400Manca un parametro obbligatorio (es. code, refresh_token).
invalid_client401client_id sconosciuto, client_secret errato o app sospesa.
invalid_grant400Il codice o il refresh token è scaduto, revocato, già usato, appartiene a un'altra app, oppure la validazione PKCE/redirect_uri è fallita.
unsupported_grant_type400grant_type deve essere authorization_code o refresh_token.