Autenticação

Apps OAuth

Para apps que atuam em nome de outros utilizadores do Gravl. OAuth 2.0 padrão com authorization code e PKCE: os utilizadores concedem à sua app scopes específicos, recebe access tokens de curta duração com um refresh token rotativo e o grant é revogável a qualquer momento.

1. Registe a sua app

O registo é manual enquanto a API está em beta. Escreva para developers@gravl.ai com:

  • O nome da sua app e uma breve descrição do que faz
  • A(s) redirect URI(s) OAuth da sua app: URLs https absolutas (http://localhost permitido para desenvolvimento)
  • Os scopes de que a sua app precisa. Peça o mínimo; os utilizadores veem exatamente o que pedir

Vai receber um client_id (gci_…) e um client_secret (gcs_…, mostrado uma única vez; guarde-o como uma password).

2. Envie o utilizador para o ecrã de consentimento

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

O utilizador inicia sessão com a sua conta Gravl, vê o nome da sua app e os scopes pedidos em linguagem simples e aprova. O browser regressa à sua redirect_uri com ?code=gac_…&state=… (ou error=access_denied se cancelar).

  • Os códigos têm o prefixo gac_, são válidos por 10 minutos, de utilização única e ficam vinculados à sua app e à redirect_uri para a qual foram emitidos
  • O PKCE (S256) é obrigatório para clientes públicos (apps de browser ou nativas, que não têm client_secret) e fortemente recomendado para todos
  • Verifique sempre que state corresponde ao que enviou; é a sua proteção CSRF

Os clientes públicos omitem o client_secret no endpoint de token; o PKCE é a sua autenticação de cliente. Diga-nos qual é o tipo da sua app ao registá-la.

3. Troque o código

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"
}
TokenDuraçãoNotas
access_token6 horasBearer token para pedidos a /api/v1.
refresh_tokenAté 180 diasUtilização única: cada renovação revoga-o e emite um novo par (rotação).

4. Renovar

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

A resposta tem a mesma forma da troca de código. O refresh token apresentado é revogado na mesma transação, por isso persista sempre o novo refresh_token antes de descartar o antigo. Reutilizar um refresh token já usado devolve invalid_grant.

5. Revogar

POST /oauth/revoke
curl -X POST https://api.gravl.ai/oauth/revoke \
  -d token=grt_… \
  -d client_id=gci_… \
  -d client_secret=gcs_…
  • Revogar um access token elimina apenas esse token
  • Revogar um refresh token revoga o grant inteiro: todos os tokens em circulação para esse par utilizador + app
  • Conforme a RFC 7009, o endpoint devolve 200 mesmo para tokens desconhecidos; só credenciais de cliente inválidas produzem erro
  • Os utilizadores também podem revogar o acesso da sua app a partir da conta deles

Erros do endpoint de token

Os erros seguem a RFC 6749, no formato { "error": "…", "error_description": "…" }:

ErroEstadoSignificado
invalid_request400Falta um parâmetro obrigatório (p. ex. code, refresh_token).
invalid_client401client_id desconhecido, client_secret errado ou app suspensa.
invalid_grant400O código/refresh token expirou, foi revogado, já foi usado, pertence a outra app, ou a validação de PKCE/redirect_uri falhou.
unsupported_grant_type400grant_type tem de ser authorization_code ou refresh_token.