Uwierzytelnianie

Aplikacje OAuth

Dla aplikacji działających w imieniu innych użytkowników Gravl. Standardowy OAuth 2.0 authorization code z PKCE: użytkownicy przyznają Twojej aplikacji konkretne scope’y, Ty dostajesz krótkotrwałe tokeny dostępu z rotowanym tokenem odświeżania, a grant można odwołać w każdej chwili.

1. Zarejestruj aplikację

Dopóki API jest w becie, rejestracja odbywa się ręcznie. Napisz na developers@gravl.ai i podaj:

  • Nazwę aplikacji i krótki opis tego, co robi
  • Adresy redirect URI Twojej aplikacji: bezwzględne adresy https (http://localhost dozwolony na czas developmentu)
  • Scope’y, których potrzebuje Twoja aplikacja. Proś o minimum; użytkownicy widzą dokładnie to, o co prosisz

Otrzymasz client_id (gci_…) oraz client_secret (gcs_…, pokazywany tylko raz; przechowuj go jak hasło).

2. Wyślij użytkownika na ekran zgody

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

Użytkownik loguje się na swoje konto Gravl, widzi nazwę Twojej aplikacji i żądane scope’y opisane prostym językiem, po czym zatwierdza. Jego przeglądarka wraca na Twój redirect_uri z ?code=gac_…&state=… (lub z error=access_denied, jeśli anuluje).

  • Kody mają prefiks gac_, są ważne 10 minut, jednorazowe i powiązane z Twoją aplikacją oraz z redirect_uri, dla którego zostały wydane
  • PKCE (S256) jest wymagane dla klientów publicznych (aplikacje przeglądarkowe lub natywne, które nie mają client_secret) i mocno zalecane wszystkim
  • Zawsze weryfikuj, że state zgadza się z tym, co wysłano. To Twoja ochrona przed CSRF

Klienci publiczni pomijają client_secret na endpoincie tokenów; ich uwierzytelnieniem klienta jest PKCE. Przy rejestracji powiedz nam, którego typu jest Twoja aplikacja.

3. Wymień kod

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"
}
TokenCzas życiaUwagi
access_token6 godzinToken typu Bearer do żądań na /api/v1.
refresh_tokenDo 180 dniJednorazowy. Każde odświeżenie unieważnia go i wydaje nową parę (rotacja).

4. Odśwież

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

Odpowiedź ma ten sam kształt co wymiana kodu. Przedstawiony token odświeżania jest unieważniany w tej samej transakcji, więc zawsze zapisz nowy refresh_token, zanim odrzucisz stary. Ponowne użycie zużytego tokena odświeżania zwraca invalid_grant.

5. Unieważnij

POST /oauth/revoke
curl -X POST https://api.gravl.ai/oauth/revoke \
  -d token=grt_… \
  -d client_id=gci_… \
  -d client_secret=gcs_…
  • Unieważnienie tokena dostępu ubija tylko ten token
  • Unieważnienie tokena odświeżania unieważnia cały grant: każdy aktywny token dla tej pary użytkownik + aplikacja
  • Zgodnie z RFC 7009 endpoint zwraca 200 nawet dla nieznanych tokenów. Błąd powodują tylko złe poświadczenia klienta
  • Użytkownicy mogą też odebrać Twojej aplikacji dostęp z poziomu swojego konta

Błędy endpointu tokenów

Błędy są zgodne z RFC 6749: { "error": "…", "error_description": "…" }:

BłądStatusZnaczenie
invalid_request400Brakuje wymaganego parametru (np. code, refresh_token).
invalid_client401Nieznany client_id, zły client_secret albo aplikacja jest zawieszona.
invalid_grant400Kod lub token odświeżania wygasł, został unieważniony, już użyty, należy do innej aplikacji albo nie przeszła walidacja PKCE/redirect_uri.
unsupported_grant_type400grant_type musi być authorization_code lub refresh_token.