Docs do Nodaro
DocumentaçãoReferência de nósModelosAgentes de IA (MCP)DesenvolvedoresSelf-hostingPesquisa

Apps OAuth

Registre um app OAuth, envie os usuários à tela de consentimento do Nodaro, troque o código por um token de acesso de 90 dias e chame a API em nome deles.

Disponível em Nodaro Cloud · Business edition

Um app OAuth permite que o seu produto chame a API do Nodaro em nome de outros usuários do Nodaro. Cada usuário aprova o seu app em uma tela de consentimento, o seu servidor troca o código resultante por um token de acesso, e toda chamada com esse token age como esse usuário, limitada aos escopos que ele concedeu. O Nodaro implementa o fluxo padrão de código de autorização do OAuth 2.0, com PKCE para clientes que não conseguem guardar um segredo.

Os apps de desenvolvedor estão disponíveis no Nodaro Cloud e nas instalações da Business edition.

OAuth ou token de API pessoal

Você está criandoUseFormato do token
Um script, um cron job, um job de CI ou um backend que usa a sua própria contaUm token de API pessoalndr_ seguido de 64 caracteres hexadecimais
Um produto hospedado cujos usuários têm as próprias contas do NodaroUm app OAuthndr_app_ seguido de 64 caracteres hexadecimais

Use um token de API pessoal quando só a sua própria conta se autentica e você não precisa de tela de consentimento nem de revogação por usuário. Veja Autenticação.

Use OAuth nestes casos:

  • Você cria um produto hospedado, como um app web, um SaaS ou um marketplace, e os seus usuários têm as próprias contas do Nodaro.
  • Cada usuário concede ao seu app só uma parte do que a conta dele pode fazer.
  • Cada usuário pode cortar o acesso do seu app a qualquer momento, sem afetar outros apps.

Como o fluxo funciona

  1. O usuário clica em Conectar ao Nodaro no seu site.
  2. O seu site envia o navegador para a página /oauth/authorize do Nodaro com o seu client_id, redirect_uri, scope e state.
  3. O Nodaro mostra a tela de consentimento, depois de um login, se necessário. A tela mostra o nome, o logotipo e os escopos solicitados do seu app, e a conta que vai conceder o acesso. Usar outra conta encerra a sessão do usuário e volta para a mesma tela.
  4. O usuário clica em Permitir, e o Nodaro cria um código de autorização de uso único.
  5. O navegador volta para o seu redirect_uri com ?code=...&state=....
  6. O seu servidor troca o código por um token de acesso em POST /v1/oauth/token, com o seu client_id e o seu client_secret.
  7. O seu servidor chama a API do Nodaro com Authorization: Bearer ndr_app_... em nome do usuário.

Registrar o seu app

Abrir Apps de desenvolvedor

Na instância do Nodaro que você quer usar, abra Configurações › Apps de desenvolvedor (/settings/developer-apps) e clique em Criar app.

Preencher o formulário

Informe o nome, as URIs de redirecionamento e os escopos. Os campos estão descritos na tabela abaixo.

Guardar o segredo do cliente

A caixa de diálogo App criado mostra o ID do cliente, que começa com app_, e o Segredo do cliente, que começa com sec_. O segredo aparece uma única vez. Copie-o para o seu gerenciador de segredos antes de fechar a caixa de diálogo: o Nodaro guarda só um hash dele e não consegue mostrá-lo de novo.

CampoObrigatórioRegras
NomeSimDe 1 a 100 caracteres. Aparece na tela de consentimento.
DescriçãoNãoAté 500 caracteres. Aparece abaixo do nome na tela de consentimento.
URIs de redirecionamentoSimDe 1 a 10, uma por linha. Cada uma é um endereço https://, ou um endereço http://localhost para desenvolvimento. O Nodaro as compara byte a byte, e curingas não são aceitos.
Origens permitidasNãoAté 5 origens simples, sem caminho, query ou fragmento. Necessárias só se o seu frontend chamar o Nodaro a partir de um navegador (CORS).
Escopos solicitadosSimPelo menos um. É o máximo que o seu app poderá pedir: os usuários podem conceder menos, e o seu app nunca pode pedir mais.
URL da página inicial, URL do logotipoNãoDefina-as na página do app depois de criá-lo. Cada uma é um endereço https:// ou http://localhost. Um logotipo quadrado fica melhor.

Gerenciar o app

  • Rotacione o segredo na página do app quando você o perder, ou como prática de segurança de rotina. O segredo antigo para de funcionar na hora, então atualize imediatamente a configuração de todos os serviços em execução.
  • Exclua o app para revogar todos os tokens de acesso que ele recebeu. Os usuários que o autorizaram precisam se conectar de novo.
  • Cinco apps por usuário. Os clientes MCP que se registraram sozinhos aparecem na mesma lista, mas não entram no limite.
  • Por código, o client.developerApps do SDK cria, atualiza e exclui apps e rotaciona os segredos deles. Veja o SDK.

Escopos

Um escopo é uma permissão que o seu app pede. Solicite só os escopos que você usa: os usuários veem todos os escopos solicitados na tela de consentimento, e uma lista curta conquista a confiança deles.

EscopoA tela de consentimento dizO que permite
workflows:readLer seus workflowsListar, ler e exportar workflows.
workflows:writeCriar e modificar workflowsCriar, atualizar, excluir, importar e mover workflows, e criar sub-workflows.
workflows:executeExecutar workflows em seu nomeExecutar workflows e apps publicados, executar nós de geração individuais pelo MCP e usar o assistente de prompt.
jobs:readLer o status e os resultados das tarefasLer os jobs, o status e os resultados deles.
assets:readLer as mídias que você enviouLer a galeria, os envios, os favoritos, as execuções de apps, os personagens, os locais, os objetos e as criaturas.
assets:writeEnviar mídias para sua contaEnviar mídia, marcar mídias como favoritas e criar e atualizar personagens, locais e objetos.
credits:readVer seu saldo de créditosLer o saldo de créditos e as transações de créditos.
apps:readLer apps publicadosListar os apps publicados e ler as entradas deles.
pipelines:readLer seus pipelinesLer os pipelines História → vídeo (Story → Video), o status deles e as aprovações pendentes.
pipelines:executeExecutar pipelines em seu nome (isso pode gastar seus créditos)Iniciar pipelines, executar as etapas deles e criar derivações a partir de uma etapa.
pipelines:approveAprovar etapas de pipelines em seu nomeAprovar a saída das etapas e usar o chat das etapas e os auxiliares de cena.
presets:readLer suas predefinições salvasLer as predefinições de nó e as predefinições favoritas do usuário.
workspaces:readVer os espaços de trabalho de que você faz parteListar os espaços de trabalho do usuário.
workspaces:writeEscolher em qual espaço de trabalho ele atuaEscolher o espaço de trabalho em que o app trabalha.
  • Alguns escopos controlam rotas REST, outros controlam ferramentas MCP, e alguns controlam as duas coisas. O servidor MCP oculta toda ferramenta cujo escopo falta ao token.
  • Um token sem o escopo de que uma rota precisa recebe 403 insufficient_scope, com o escopo que falta em missingScope. Veja Erros.
  • Os escopos de espaço de trabalho nunca são adicionados a um token emitido antes de as organizações existirem. O usuário precisa autorizar o seu app de novo para concedê-los.
  • Executar um app publicado exige workflows:execute para iniciar a execução e jobs:read para ler o progresso dela.

Quando o usuário clicar em Conectar ao Nodaro, envie o navegador para esta URL:

https://nodaro.example.com/oauth/authorize?
  client_id=app_...&
  redirect_uri=https://yourapp.com/oauth/callback&
  response_type=code&
  scope=workflows:read+workflows:execute&
  state=<random CSRF token>
ParâmetroRegra
client_idO ID do cliente do seu app.
redirect_uriExatamente uma das URIs de redirecionamento registradas, byte a byte. Uma divergência é recusada com 400 invalid_redirect_uri.
response_typeSempre code. A tela de consentimento recusa qualquer outro valor.
scopeOs escopos que você solicita, separados por espaços ou por +. Precisam ser um subconjunto dos escopos solicitados do app.
stateUm token aleatório que você cria para cada autorização e guarda na sessão do usuário. O Nodaro o devolve sem mudanças, e você precisa verificá-lo.

Crie o state no seu servidor:

import { randomBytes } from "node:crypto"

// In your /connect handler:
const state = randomBytes(32).toString("hex")
req.session.oauthState = state

const url = new URL("https://nodaro.example.com/oauth/authorize")
url.searchParams.set("client_id", process.env.NODARO_CLIENT_ID!)
url.searchParams.set("redirect_uri", "https://yourapp.com/oauth/callback")
url.searchParams.set("response_type", "code")
url.searchParams.set("scope", "workflows:read workflows:execute")
url.searchParams.set("state", state)
res.redirect(url.toString())
  • Se o usuário clicar em Cancelar, o Nodaro redireciona para o seu redirect_uri com error=access_denied, um error_description e o seu state. Trate isso como um resultado normal, não como uma falha.
  • Se a URI de redirecionamento não estiver registrada, a tela de consentimento mostra uma página de erro e não redireciona para lugar nenhum, tanto em Cancelar quanto em Permitir.

Trocar o código por um token

Depois que o usuário clica em Permitir, o Nodaro envia o navegador para o seu callback:

https://yourapp.com/oauth/callback?code=ndr_code_...&state=<your state>
  1. Verifique o state primeiro. Se ele não corresponder ao valor na sessão do usuário, pare: essa é a proteção contra falsificação de requisição entre sites.
  2. Troque o código no seu servidor. Nunca faça essa chamada em um navegador, onde qualquer pessoa com as ferramentas de desenvolvedor poderia ler o seu client_secret.
import { createClient, StaticTokenAuth } from "@nodaro/sdk"

// The token endpoint is public: your client ID and secret authenticate
// the request, so the client needs no token of its own.
const client = createClient({
  baseUrl: "https://nodaro.example.com",
  auth: new StaticTokenAuth(""),
})

const tokens = await client.oauth.exchangeCode({
  client_id: process.env.NODARO_CLIENT_ID!,
  client_secret: process.env.NODARO_CLIENT_SECRET!,
  code: req.query.code as string,
  redirect_uri: "https://yourapp.com/oauth/callback",
})
// tokens.access_token: "ndr_app_..."
// tokens.scope:        the scopes the user granted, separated by spaces
// tokens.expires_in:   7776000 (seconds, that is 90 days)
// tokens.token_type:   "Bearer"
curl -X POST https://nodaro.example.com/v1/oauth/token \
  -H "Content-Type: application/json" \
  -d '{
    "grant_type": "authorization_code",
    "client_id": "app_...",
    "client_secret": "sec_...",
    "code": "ndr_code_...",
    "redirect_uri": "https://yourapp.com/oauth/callback"
  }'

A resposta usa os nomes de campo padrão do OAuth:

{
  "access_token": "ndr_app_...",
  "token_type": "Bearer",
  "scope": "workflows:read workflows:execute",
  "expires_in": 7776000
}
  • Um código funciona uma única vez. Uma segunda troca do mesmo código retorna 400 invalid_grant.
  • Um código expira 10 minutos depois de ser emitido. Troque-o assim que o seu callback o receber.
  • O endpoint de token aceita corpos JSON e codificados como formulário. Clientes OAuth padrão que enviam application/x-www-form-urlencoded funcionam sem mudanças, com o método client_secret_post.

Clientes públicos: PKCE

Apps mobile, apps de página única e ferramentas de CLI não conseguem guardar um client_secret. Eles usam PKCE no lugar. O Nodaro aceita só o método S256; plain é recusado com 400 invalid_request.

Criar um verificador e um desafio

Antes do redirecionamento, crie um code_verifier aleatório e de alta entropia. Derive o code_challenge como a codificação base64url do hash SHA-256 do verificador.

Enviar o desafio na requisição de autorização

Adicione code_challenge e code_challenge_method=S256 à URL de autorização:

https://nodaro.example.com/oauth/authorize?
  client_id=app_...&
  redirect_uri=https://yourapp.com/oauth/callback&
  response_type=code&
  scope=workflows:read+workflows:execute&
  state=<random CSRF token>&
  code_challenge=<base64url SHA-256 of the verifier>&
  code_challenge_method=S256

Enviar o verificador na troca do token

Envie o code_verifier em vez do client_secret:

curl -X POST https://nodaro.example.com/v1/oauth/token \
  -H "Content-Type: application/json" \
  -d '{
    "grant_type": "authorization_code",
    "client_id": "app_...",
    "code": "ndr_code_...",
    "redirect_uri": "https://yourapp.com/oauth/callback",
    "code_verifier": "<the original verifier>"
  }'

Um cliente confidencial pode enviar tanto um segredo quanto um verificador PKCE. O Nodaro verifica cada um que estiver presente.

Chamar a API com o token

Crie um cliente por usuário, com o token de acesso desse usuário:

import { createClient, StaticTokenAuth } from "@nodaro/sdk"

const userClient = createClient({
  baseUrl: "https://nodaro.example.com",
  auth: new StaticTokenAuth(tokens.access_token),
})

// Every call acts as the user who authorized your app, within the granted scopes.
const projects = await userClient.projects.list()
const workflows = await userClient.workflows.list(projects.data[0].id)
const run = await userClient.workflows.run(workflows.data[0].id)

Sem o SDK, envie o token no cabeçalho Authorization: Bearer de cada chamada REST. Os endpoints estão na referência da API REST.

Quando um token expira

Um token de acesso dura 90 dias. O Nodaro não emite refresh tokens: há um único tipo de token, um único lugar para guardá-lo e uma única regra de expiração, ao custo de uma tela de consentimento a cada 90 dias.

  • Depois que o token expira ou é revogado, as chamadas à API retornam 401. Envie o usuário para /oauth/authorize de novo.
  • Quando o usuário autoriza o seu app de novo, o Nodaro atualiza a autorização dele e emite um token novo. Os tokens anteriores continuam válidos até expirarem ou serem revogados, então acompanhe quais tokens estão em uso.
  • Para adicionar um escopo, leve o usuário pela URL de autorização com o scope mais amplo. A autorização existente é ampliada.

Guardar tokens com segurança

  • Mantenha os tokens no seu servidor. Nunca coloque um token de acesso em localStorage, em sessionStorage ou em um cookie que o JavaScript consiga ler.
  • Criptografe os tokens em repouso se a sua plataforma permitir. O Nodaro guarda só um hash SHA-256 de cada token, então um vazamento do seu próprio banco de dados é a única forma de um token escapar.
  • Nunca compartilhe um token entre usuários. Cada token pertence a um usuário do Nodaro; usá-lo no contexto de outro usuário é um bug de autorização.

Revogar um token

Revogue um token quando o usuário sair do seu app, excluir a conta dele na sua plataforma ou clicar em Desconectar o Nodaro nas configurações do seu app.

await client.oauth.revoke(tokens.access_token)
// { success: true }
curl -X POST https://nodaro.example.com/v1/oauth/revoke \
  -H "Content-Type: application/json" \
  -d '{ "token": "ndr_app_..." }'

O endpoint de revogação sempre responde 200, mesmo para um token que não existe, então ninguém consegue usá-lo para testar se um token adivinhado é válido. Depois de uma revogação, as chamadas com o token retornam 401.

Quando o usuário revoga o acesso

Os usuários também podem encerrar o acesso do seu app por conta própria. Configurações › Apps conectados (/settings/connected-apps) lista todos os apps e assistentes de IA com acesso à conta do usuário. Cada item mostra o nome e o tipo, quando foi conectado, quando foi usado pela última vez e os escopos que tem. Revogar acesso pede confirmação e depois encerra na hora a autorização e todos os tokens emitidos com ela.

Depois disso, as chamadas com o seu token retornam 401. Trate isso como um token expirado: leve o usuário de novo pela tela de consentimento.

Só uma sessão de navegador com login pode listar ou revogar essas autorizações. Um token de acesso OAuth ou um token de API pessoal recebe 401 de GET /v1/me/connected-apps e de POST /v1/me/connected-apps/:id/revoke, então um app não consegue ler a lista nem alterá-la. Para encerrar o seu próprio acesso por código, use o endpoint de revogação acima.

Erros

O endpoint de token responde com erros OAuth padrão:

StatusErroQuandoO que fazer
400invalid_requestO corpo está malformado ou falta um campo.Corrija a requisição.
401invalid_client (Unknown client)O client_id não corresponde a nenhum app registrado.Confira o ID do cliente na sua configuração.
401invalid_client (Bad client_secret)O segredo está errado, muitas vezes um antigo depois de uma rotação.Carregue o segredo atual e reinicie o seu serviço.
400invalid_grantO código tem mais de 10 minutos, já foi usado ou o redirect_uri é diferente do usado na requisição de autorização.Leve o usuário de novo pelo consentimento, com URIs idênticas.

A etapa de autorização mostra estes erros na própria tela de consentimento e nunca redireciona com eles:

StatusCódigoQuandoO que fazer
400invalid_redirect_uriO redirect_uri não está registrado para o app.Adicione a URI na página do app.
400invalid_scopeUm escopo solicitado não está entre os escopos solicitados do app.Adicione o escopo ao app primeiro.
404invalid_clientO client_id é desconhecido, ou o app está suspenso.Confira o ID do cliente e o status do app.

As chamadas à API com o token de acesso podem falhar com:

StatusCódigoQuandoO que fazer
401unauthorizedO token expirou, foi revogado ou está malformado.Leve o usuário de novo pelo consentimento.
403insufficient_scopeFalta ao token o escopo de que a rota precisa. O corpo informa esse escopo em missingScope.Leve o usuário pelo consentimento com o escopo mais amplo.

O SDK lança o caso 403 como um ForbiddenError com um missingScope tipado, para que você possa oferecer um novo consentimento com um clique:

import { ForbiddenError } from "@nodaro/sdk"

try {
  await userClient.workflows.run(workflowId)
} catch (err) {
  if (err instanceof ForbiddenError && err.missingScope) {
    // Send the user back to /oauth/authorize with the broader scope list.
    redirectToConsent({ scopes: [...currentScopes, err.missingScope] })
    return
  }
  throw err
}

Checklist de segurança

  • HTTPS em tudo. A instância do Nodaro, o seu app e todas as URIs de redirecionamento usam https://. http://localhost é só para desenvolvimento local.
  • Verifique o state em todo callback. Crie um por autorização e guarde-o na sessão do usuário.
  • Mantenha o client_secret no seu servidor. Nunca o inclua em um app de navegador, nunca o registre em logs nem o repita em uma mensagem de erro.
  • Rotacione o segredo pelo menos uma vez por ano, e imediatamente se suspeitar de um vazamento.
  • Registre só as suas próprias URIs de redirecionamento. Registre só os endereços que você realmente usa.
  • Solicite o menor conjunto de escopos. Adicione um escopo quando criar o recurso que precisa dele.
  • Revogue no logout. Chame o endpoint de revogação quando um usuário sair do seu app, para que o token dele não possa ser reutilizado.
  • Trate o missingScope. Ofereça ao usuário um novo consentimento, não uma página genérica de “permissão negada”.

Testar o fluxo localmente

O ciclo de teste mais rápido precisa de uma instância do Nodaro com Apps de desenvolvedor, como o Nodaro Cloud ou uma instalação da Business edition, e de um pequeno servidor de callback na sua máquina.

Registrar um app de teste

Crie um app com a URI de redirecionamento http://localhost:8080/cb e os escopos workflows:read, workflows:execute e jobs:read.

Executar um servidor de callback na porta 8080

import express from "express"
import { createClient, StaticTokenAuth } from "@nodaro/sdk"

const NODARO_URL = "https://app.nodaro.ai" // or your Business edition install

const app = express()

app.get("/cb", async (req, res) => {
  const client = createClient({ baseUrl: NODARO_URL, auth: new StaticTokenAuth("") })
  const tokens = await client.oauth.exchangeCode({
    client_id: process.env.NODARO_CLIENT_ID!,
    client_secret: process.env.NODARO_CLIENT_SECRET!,
    code: req.query.code as string,
    redirect_uri: "http://localhost:8080/cb",
  })
  res.json(tokens)
})

app.listen(8080)

Abrir a URL de autorização e clicar em Permitir

Abra /oauth/authorize?client_id=app_...&redirect_uri=http://localhost:8080/cb&response_type=code&scope=workflows:read+workflows:execute&state=test123 na instância. Depois que você clicar em Permitir, o servidor de callback mostra o JSON do token.

Chamar uma rota real

Use o token em uma rota como GET /v1/projects/<id>/workflows e verifique se ela responde 200 com dados.

Descoberta e registro dinâmico para clientes MCP

Os clientes MCP, como Claude, ChatGPT e Cursor, encontram sozinhos os endpoints OAuth e podem se registrar em tempo de execução, sem que uma pessoa visite Apps de desenvolvedor. Veja Conectar um cliente para o lado do usuário.

Documentos de descoberta

EndpointPadrãoFinalidade
GET /.well-known/oauth-authorization-serverRFC 8414Onde autorizar, obter tokens, registrar e revogar.
GET /.well-known/oauth-protected-resourceRFC 9728Associa o recurso MCP, https://mcp.nodaro.ai/mcp, ao servidor de autorização dele.

Cada documento também é servido com o sufixo /mcp, porque alguns clientes mais rigorosos tentam essa forma primeiro. Os quatro endereços funcionam tanto no host do Nodaro quanto no host do MCP. O emissor é o PUBLIC_URL da instância, https://app.nodaro.ai no Nodaro Cloud.

Os metadados do servidor de autorização anunciam:

  • os endpoints de autorização, token, registro e revogação;
  • o tipo de resposta code e a concessão authorization_code;
  • PKCE só com S256;
  • o método de autenticação client_secret_post no endpoint de token;
  • cada escopo em scopes_supported.

Registro dinâmico de clientes

Um cliente se registra com POST /v1/oauth/register (RFC 7591) e recebe um client_id que começa com ndr_dcr_, além de um client_secret. O endpoint aceita 10 requisições por minuto por endereço IP. O operador da instância define MCP_DYNAMIC_REGISTRATION:

ModoComportamento
allowlist (padrão)Só os nomes de cliente em MCP_DCR_ALLOWLIST podem se registrar. Os outros recebem 403 client_not_allowed.
openQualquer cliente pode se registrar, até 5 registros não usados por nome de cliente e URIs de redirecionamento em 24 horas (429 too_many_open_registrations).
offO registro fica desativado (403 dcr_disabled). Em vez disso, o operador distribui um ID de cliente e um segredo fixos.

Um cliente que se registrou sozinho escolheu o próprio nome, então a tela de consentimento avisa o usuário de que o Nodaro não o verificou. Os escopos que ele declara são informativos: o consentimento do usuário é o verdadeiro controle, e o cliente pode solicitar qualquer escopo válido. Veja MCP em uma instalação self-hosted para as configurações do operador.

O plugin para Figma em uma instalação self-hosted

O plugin do Nodaro para Figma funciona dentro do Figma e não consegue receber um redirecionamento. Em vez disso, ele se conecta com um handshake no estilo de dispositivo: mostra um código curto ao usuário, que aprova o plugin na tela de consentimento comum e digita esse código, e então recebe o token. O token é um token comum de app de desenvolvedor, com os escopos jobs:read, assets:read, assets:write e credits:read, e pode ser revogado como qualquer outro.

Para permitir que o plugin se conecte à sua própria instalação:

  1. Registre um app de desenvolvedor, em Apps de desenvolvedor ou com POST /v1/developer-apps. Adicione <PUBLIC_URL>/v1/oauth/plugin/callback às URIs de redirecionamento dele e solicite os quatro escopos acima.
  2. Coloque o ID do cliente do app em FIGMA_PLUGIN_OAUTH_CLIENT_ID no servidor.

Sem essa configuração, todas as rotas de conexão do plugin respondem 503 plugin_connect_not_configured. Se faltar ao app a URI de callback ou um escopo, as rotas respondem 503 plugin_connect_misconfigured, e o log do servidor informa o que está faltando.

Perguntas frequentes

Última atualização

Nesta página