API OAuth 2.1
A VDClip opera um Servidor de Autorização OAuth 2.1 (issuer https://api.vdclip.com) para servidores MCP, agentes de IA e integrações de terceiros que agem em nome de um usuário. Em vez de uma chave de API estática, esses clientes obtêm um access token de curta duração pelo fluxo authorization-code com PKCE e chamam a API com Authorization: Bearer <JWT>.
Quando usar OAuth
- Token Bearer OAuth 2.1. Quando um cliente age em nome de um usuário: um servidor MCP, agente de IA ou integração de terceiros. O usuário faz login e dá o consentimento, o cliente recebe um JWT, e cada requisição leva
Authorization: Bearer <JWT>. Authorization Bearerestática. Para suas próprias chamadas servidor-a-servidor que não representam um usuário. Veja Autenticação.
Como o fluxo funciona
- Descubra os metadados do servidor em
/.well-known/oauth-authorization-servere as chaves de assinatura em/.well-known/jwks.json. - Registre um cliente com o Registro Dinâmico de Cliente (
POST /oauth2/application), declarando os escopos de que precisa. - Autorize: envie o usuário para a URL de autorização do dashboard indicada pelo discovery, usando PKCE. O dashboard controla consentimento e callback.
- Troque o authorization code por tokens em
POST /oauth2/token. - Chame os endpoints
/v1/*comAuthorization: Bearer <JWT>e renove ou revogue os tokens conforme necessário.
Exemplo completo de cliente público
Exemplo usa cliente público com PKCE. Não adicione client secret. Guarde
CLIENT_ID, REGISTRATION_ACCESS_TOKEN, ACCESS_TOKEN e REFRESH_TOKEN em secret
manager ou memória do processo.
1. Discovery e registro
ISSUER="https://api.vdclip.com"
curl -sS "$ISSUER/.well-known/oauth-authorization-server" | jq .
REGISTRATION=$(curl -sS -X POST "$ISSUER/oauth2/application" \
-H "Content-Type: application/json" \
-d '{
"token_endpoint_auth_method": "none",
"grant_types": ["authorization_code", "refresh_token"],
"response_types": ["code"],
"redirect_uris": ["https://app.example.com/oauth/callback"],
"client_name": "Example App",
"scope": "vdclip:projects:read vdclip:results:read"
}')
CLIENT_ID=$(jq -r '.client_id' <<<"$REGISTRATION")
REGISTRATION_ACCESS_TOKEN=$(jq -r '.registration_access_token' <<<"$REGISTRATION")registration_access_token aparece uma vez. Armazene-o. Ele serve para ler o
registro do cliente e não é um access token de usuário.
2. PKCE e troca do código
REDIRECT_URI="https://app.example.com/oauth/callback"
STATE=$(openssl rand -hex 16)
CODE_VERIFIER=$(openssl rand -base64 64 | tr -dc 'A-Za-z0-9-._~' | cut -c1-64)
CODE_CHALLENGE=$(printf '%s' "$CODE_VERIFIER" | openssl dgst -sha256 -binary | openssl base64 -A | tr '+/' '-_' | tr -d '=')
AUTHORIZATION_ENDPOINT=$(curl -sS "$ISSUER/.well-known/oauth-authorization-server" | jq -r '.authorization_endpoint')
echo "$AUTHORIZATION_ENDPOINT?response_type=code&client_id=$CLIENT_ID&redirect_uri=$REDIRECT_URI&scope=vdclip%3Aprojects%3Aread%20vdclip%3Aresults%3Aread&state=$STATE&code_challenge=$CODE_CHALLENGE&code_challenge_method=S256"Abra a URL no navegador. Valide state no callback antes de aceitar code.
Depois troque o código. Cliente público envia client_id no corpo form.
TOKEN_RESPONSE=$(curl -sS -X POST "$ISSUER/oauth2/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
--data-urlencode "grant_type=authorization_code" \
--data-urlencode "client_id=$CLIENT_ID" \
--data-urlencode "code=$AUTHORIZATION_CODE" \
--data-urlencode "redirect_uri=$REDIRECT_URI" \
--data-urlencode "code_verifier=$CODE_VERIFIER")
ACCESS_TOKEN=$(jq -r '.access_token' <<<"$TOKEN_RESPONSE")
REFRESH_TOKEN=$(jq -r '.refresh_token' <<<"$TOKEN_RESPONSE")3. Chamada, refresh e revogação
curl -sS "$ISSUER/v1/projects?limit=20" -H "Authorization: Bearer $ACCESS_TOKEN"
curl -sS -X POST "$ISSUER/oauth2/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
--data-urlencode "grant_type=refresh_token" \
--data-urlencode "client_id=$CLIENT_ID" \
--data-urlencode "refresh_token=$REFRESH_TOKEN"
curl -sS -X POST "$ISSUER/oauth2/revoke" \
-H "Content-Type: application/x-www-form-urlencoded" \
--data-urlencode "token=$REFRESH_TOKEN" \
--data-urlencode "token_type_hint=refresh_token" \
--data-urlencode "client_id=$CLIENT_ID"Endpoints OAuth usam respostas RFC, não envelope errors[] de /v1.
Campos opcionais e condicionais
Validados contra os schemas e handlers atuais da API:
| Requisição | Obrigatórios | Comportamento opcional ou condicional |
|---|---|---|
DCR POST /oauth2/application | client_name e chave redirect_uris | token_endpoint_auth_method padrão é none; grant_types padrão é authorization_code; response_types padrão é code; URLs de metadata, scope e allowed_resources podem ser omitidos. Lista redirect_uris vazia só funciona em registro apenas para refresh token. |
| Token por authorization code | grant_type, client_id ou HTTP Basic, code, redirect_uri | code_verifier depende de PKCE. Cliente público deve sempre enviá-lo. scope e resource não são usados nesse grant. |
| Token por refresh token | grant_type, client_id ou HTTP Basic, refresh_token | scope e resource são opcionais. code, redirect_uri e code_verifier não são usados. |
| Revogação | token | token_type_hint e client_id são opcionais. Resposta sempre HTTP 200 com objeto JSON vazio. |
Opcional no schema não significa válido em todos os fluxos. Handler valida depois do parse do formulário.
Convenções
Esses endpoints ficam em /oauth2/* e /.well-known/* e usam corpos no formato padrão das RFCs, não o envelope /v1. Trate suas respostas e erros separadamente. Discovery e JWKS são públicos; autorização, consentimento e token conduzem o login interativo.
Assim que um cliente possui um Bearer token, ele chama os endpoints /v1/* exatamente como documentado em outros lugares. Os escopos seguem a convenção vdclip:<resource>:<action>, com o mesmo gating de plano: render:execute e social:publish dependem do plano do usuário. O catálogo completo de escopos está em Servidores MCP. Veja pricing para detalhes dos planos.
Padrões e RFCs
A VDClip implementa o OAuth 2.1. Cada endpoint segue o padrão correspondente:
| RFC | Especificação | Usado por |
|---|---|---|
| RFC 6749 | OAuth 2.0 Authorization Framework | Endpoints de autorização e token |
| RFC 6750 | Bearer Token Usage | Authorization: Bearer <JWT> nas chamadas /v1 |
| RFC 7636 | Proof Key for Code Exchange (PKCE) | Endpoint de autorização |
| RFC 8414 | Authorization Server Metadata | Discovery (/.well-known/oauth-authorization-server) |
| RFC 7517 | JSON Web Key Set (JWKS) | /.well-known/jwks.json |
| RFC 7591 | Dynamic Client Registration | POST /oauth2/application |
| RFC 7592 | Client Registration Management | GET /oauth2/application/{client_id} |
| RFC 9068 | JWT Profile for Access Tokens | Access tokens (at+jwt, ES256) |
| RFC 7009 | Token Revocation | POST /oauth2/revoke |
Endpoints
Metadados do servidor
GET /.well-known/oauth-authorization-server
Chaves públicas
GET /.well-known/jwks.json
Registrar um cliente
POST /oauth2/application
Ler registro do cliente
GET /oauth2/application/{client_id}