OAuth, PKCE & consentimento no TouchDesigner
O tdmcp pode proteger o endpoint Streamable HTTP /mcp com um authorization server opt-in no processo Node. O Node é dono de discovery, registro de clientes, authorization codes e tokens. O TouchDesigner só apresenta uma decisão limitada Allow / Deny na inbox não modal de Interactions. Codes, verifier PKCE, state OAuth e bearer tokens nunca entram no projeto TD.
Esse modo atende um deployment tdmcp de owner único. Para identidade compartilhada, federada ou multiusuário, use um authorization server/IdP externo.
Compatibilidade e modos
TDMCP_HTTP_AUTH_MODE aceita:
| Modo | Significado |
|---|---|
auto | Default compatível: usa static quando TDMCP_HTTP_AUTH_TOKEN existe; caso contrário, none. OAuth nunca é ativado implicitamente. |
none | Sem bearer no HTTP. O startup recusa um token estático que seria ignorado. |
static | Bearer pré-compartilhado legado. Isso não é OAuth. |
oauth | Authorization code com PKCE S256 obrigatório. O startup recusa token estático. |
hybrid | Migração explícita que aceita access tokens OAuth e o bearer estático configurado. |
Não existe downgrade silencioso: combinações inválidas falham no startup. O bearer do bridge (TDMCP_BRIDGE_TOKEN) é outra credencial e continua autenticando as requests REST do Node para o TD.
Setup local em loopback
HTTP sem TLS só é aceito como exceção explícita de desenvolvimento em loopback numérico. localhost, bind wildcard e HTTP fora de loopback são recusados.
export TDMCP_TRANSPORT=http
export TDMCP_HTTP_HOST=127.0.0.1
export TDMCP_HTTP_PORT=3939
export TDMCP_HTTP_AUTH_MODE=oauth
export TDMCP_PUBLIC_BASE_URL=http://127.0.0.1:3939
export TDMCP_OAUTH_ALLOW_INSECURE_LOOPBACK=1
export TDMCP_BRIDGE_TOKEN='segredo-separado-do-bridge'
tdmcpUso público/produção exige uma origem HTTPS canônica em TDMCP_PUBLIC_BASE_URL, Host externo exato, diretório de estado privado e terminação TLS num reverse proxy confiável na mesma máquina. O listener HTTP do Node continua em loopback numérico; binds OAuth wildcard/LAN falham no startup para impedir exposição cleartext direta.
Política de clientes e redirects
A Wave 11 expõe Dynamic Client Registration limitado somente para clientes públicos:
- authorization code e refresh token rotativo;
token_endpoint_auth_method: "none";- scope exato
tdmcp:accesse resource exato<public-base>/mcp; code_challenge_method=S256obrigatório; PKCE plain ou ausente é recusado;- callbacks HTTP em loopback numérico com porta explícita;
- callbacks fora de loopback somente em HTTPS e em origins listadas em
TDMCP_OAUTH_REDIRECT_ORIGINS.
Clientes públicos registrados têm sete dias de validade de inatividade por default (limitada internamente entre uma hora e 365 dias). O relógio começa no registro e avança na emissão/renovação de tokens relevante para segurança, não num lookup de cliente não autenticado. Ao vencer, um cliente sem token vivo é podado. No limite de 128 clientes, um novo registro primeiro remove o cliente tokenless mais antigo; qualquer cliente que ainda seja dono de access/refresh token não vencido e não revogado é preservado. Essa validade existe na construção da policy deste código-fonte, não como variável de ambiente documentada.
O DCR não autenticado usa um bucket de recarga contínua por origem opaca (20 registros/hora por default), sob um teto global separado de 16 vezes essa taxa, limitado a 3.600. O estado é limitado a 256 origens e expira após duas horas. Requests diretas usam o peer numérico do socket. Headers de forwarding só são aceitos quando o peer imediato e cada hop de proxy removido estão fixados em TDMCP_OAUTH_TRUSTED_PROXY_HOPS; forwarding ambíguo, não numérico, não confiável ou divergente do host/protocolo canônico falha fechado. As chaves por origem são hashes locais do processo e nunca são retornadas ou registradas.
Client ID Metadata Documents não entram nesta wave. DCR é o caminho suportado para registro de cliente público; clientes que exigem CIMD dependem de uma wave posterior com threat model próprio.
O discovery do resource existe somente em /.well-known/oauth-protected-resource/mcp; o endpoint legado na raiz retorna 404 intencionalmente. Metadata do authorization server fica em /.well-known/oauth-authorization-server.
Consentimento nativo e falhas
Abrir /authorize devolve imediatamente uma página pequena 202; a request original não fica aberta aguardando o TouchDesigner. A inbox do TD mostra nome limitado e autoafirmado do cliente, redirect, resource e scope com choices exatas Allow / Deny. Somente um Allow consumido e vinculado ao alvo pode criar o code.
O contrato fail-closed mapeia close, timeout, disconnect, consumo duplicado, fila cheia, Perform Mode, UI ausente/headless, erro de agendamento ou shutdown do Node para Deny. Uma sandbox descartável TD 2025.32820 passou Allow, Deny, timeout, close, disconnect e negação em Perform Mode pelo transporte de callback nativo. TD realmente headless, clique físico do ponteiro e deployment HTTPS/TLS de produção seguem UNVERIFIED. Panic, blackout e emergências nunca esperam consentimento OAuth. TDMCP_BRIDGE_ALLOW_EXEC=0 segue suportado porque o fluxo usa routes estruturadas e autenticadas, não /api/exec.
O diretório OAuth guarda metadata pública de clientes e digests HMAC de access/refresh tokens em arquivos privados e promovidos atomicamente. Tokens raw, authorization codes e consentimentos pendentes não são persistidos. Access tokens duram 15 minutos por default; refresh tokens duram 30 dias e rotacionam a cada uso.
Exemplos de evidência
{
"status": "PASS",
"evidence": "o fluxo offline emitiu token com scope somente após Allow simulado; o DCR podou rows tokenless vencidas, removeu a tokenless mais antiga na capacidade e reteve a owner de token vivo"
}{
"status": "FAIL",
"evidence": "o startup recusou oauth junto com bearer estático em vez de fazer downgrade silencioso"
}{
"status": "UNVERIFIED",
"reason": "o prompt TD-native integrado final não foi exercitado numa sandbox descartável nova",
"checks": ["Allow e Deny no TD 2025.32820", "UI Perform/headless", "deployment HTTPS de produção"]
}Prova offline não é prova live no TouchDesigner. Mantenha as linhas finais como UNVERIFIED até uma sandbox isolada executar o fluxo sem alerta de thread conflict.
Referência de configuração
Veja Variáveis de ambiente para limites de body, origins de redirect, paths de estado e TTLs limitados. Hoje não existe variável de ambiente pública para a inatividade do cliente registrado. tdmcp status informa somente o modo HTTP resolvido; nunca imprime tokens ou o bearer do bridge.