Authentifizierung

OAuth-Apps

Für Apps, die im Namen anderer Gravl-Nutzer handeln. Standard-OAuth-2.0-Authorization-Code mit PKCE: Nutzer gewähren deiner App bestimmte Scopes, du bekommst kurzlebige Access Tokens mit einem rotierenden Refresh Token, und der Grant ist jederzeit widerrufbar.

1. App registrieren

Solange die API in der Beta ist, läuft die Registrierung manuell. Schreib an developers@gravl.ai mit:

  • Dem Namen deiner App und einer kurzen Beschreibung, was sie tut
  • Deiner/deinen OAuth Redirect URI(s): absolute https-URLs (http://localhost ist für die Entwicklung erlaubt)
  • Den Scopes, die deine App braucht. Fordere das Minimum an; Nutzer sehen genau, was du anfragst

Du erhältst eine client_id (gci_…) und ein client_secret (gcs_…, wird nur einmal angezeigt; behandle es wie ein Passwort).

2. Nutzer zum Consent-Screen schicken

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

Der Nutzer meldet sich mit seinem Gravl-Account an, sieht den Namen deiner App und die angefragten Scopes in verständlicher Sprache und stimmt zu. Sein Browser kommt zu deiner redirect_uri zurück, mit ?code=gac_…&state=… (oder error=access_denied, wenn er abbricht).

  • Codes haben das Präfix gac_, sind 10 Minuten gültig, einmalig verwendbar und an deine App sowie die redirect_uri gebunden, für die sie ausgestellt wurden
  • PKCE (S256) ist für Public Clients erforderlich (Browser- oder native Apps, die kein client_secret haben) und für alle anderen dringend empfohlen
  • Prüfe immer, ob state mit dem übereinstimmt, was du gesendet hast; das ist dein CSRF-Schutz

Public Clients lassen client_secret am Token-Endpoint weg; PKCE ist ihre Client-Authentifizierung. Sag uns bei der Registrierung, welcher Typ deine App ist.

3. Code einlösen

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"
}
TokenLebensdauerHinweise
access_token6 StundenBearer Token für /api/v1-Requests.
refresh_tokenBis zu 180 TageEinmalig verwendbar; jeder Refresh widerruft es und stellt ein neues Paar aus (Rotation).

4. Refresh

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_…

Die Response hat dieselbe Form wie beim Code-Austausch. Das vorgelegte Refresh Token wird in derselben Transaktion widerrufen; speichere also immer erst das neue refresh_token, bevor du das alte verwirfst. Das erneute Einreichen eines bereits benutzten Refresh Tokens gibt invalid_grant zurück.

5. Widerrufen

POST /oauth/revoke
curl -X POST https://api.gravl.ai/oauth/revoke \
  -d token=grt_… \
  -d client_id=gci_… \
  -d client_secret=gcs_…
  • Der Widerruf eines Access Tokens beendet nur dieses Token
  • Der Widerruf eines Refresh Tokens widerruft den gesamten Grant: jedes ausstehende Token für dieses Nutzer-App-Paar
  • Gemäß RFC 7009 gibt der Endpoint auch bei unbekannten Tokens 200 zurück; nur falsche Client-Credentials erzeugen einen Fehler
  • Nutzer können den Zugriff deiner App auch aus ihrem Account heraus widerrufen

Fehler am Token-Endpoint

Fehler folgen RFC 6749: { "error": "…", "error_description": "…" }:

FehlerStatusBedeutung
invalid_request400Ein erforderlicher Parameter fehlt (z. B. code, refresh_token).
invalid_client401Unbekannte client_id, falsches client_secret, oder die App ist gesperrt.
invalid_grant400Code/Refresh Token ist abgelaufen, widerrufen, bereits benutzt, gehört zu einer anderen App, oder die PKCE-/redirect_uri-Prüfung schlug fehl.
unsupported_grant_type400grant_type muss authorization_code oder refresh_token sein.