Voltar para Central de ajuda
FT-CERT-DIGITAL· 1.1.0Integrações

Upload de certificado digital (.pfx/.p12) em integrações

Como anexar/trocar certificado digital A1 (.pfx/.p12) ao criar OU editar integração SOAP/REST. Inclui alerta automático 30/14/7/1d antes do vencimento e badge na UI.

Atualizado em 06/10/2026
Integrações que exigem mTLS — webservices SEFAZ (NF-e, NFC-e, CT-e), bancos europeus, parceiros B2B com client cert — aceitam upload de certificado digital A1 no formato PKCS#12 (.pfx/.p12).

Onde aparece



No formulário de criar ou editar integração manual, ao escolher protocolo SOAP, REST/HTTP, OData, Webhook/HTTP ou AS2:
  • Campo Certificado .pfx/.p12 (mTLS) — upload do arquivo
  • Campo Senha do certificado — passphrase do .pfx


A1 (arquivo .pfx) é suportado. Quando você seleciona "SEFAZ" no campo Plataforma, o protocolo muda automaticamente pra SOAP (padrão dos webservices NF-e/NFC-e/CT-e) e um aviso lembra de anexar o certificado. A3 (token físico/cartão) não está suportado — token requer driver/middleware no servidor, fora de escopo no SaaS.

O que acontece no servidor



  1. Frontend lê o arquivo, converte pra base64 e envia junto com a senha
  2. Backend chama parsePkcs12(base64, senha) (lib src/lib/integrations/certificate.ts, lê o PKCS#12 com asn1js + node:crypto)
  3. Se senha errada ou arquivo inválido, retorna HTTP 400 "Certificado inválido". Só é aceito o arquivo que a conexão segura (mTLS) consegue usar: .pfx exportado com cifra antiga (RC2/RC4/DES — padrão do OpenSSL 1.x, Java e Windows antigos) é recusado com o aviso para exportar de novo em AES-256:
- OpenSSL: openssl pkcs12 -export -in cert.pem -inkey chave.pem -keypbe AES-256-CBC -certpbe AES-256-CBC -macalg sha256 -out novo.pfx (de um .pfx antigo, primeiro openssl pkcs12 -in antigo.pfx -nodes -legacy -out tudo.pem)
- Windows: certmgr → Exportar → "Sim, exportar a chave privada" → criptografia AES256-SHA256 - Java 11.0.12+ ou 8u301+: keytool -importkeystore -srckeystore antigo.pfx -srcstoretype PKCS12 -destkeystore novo.pfx -deststoretype PKCS12
  1. Se válido, extrai metadata: subject, issuer, serial, validade, fingerprint SHA-256
  2. Criptografa o blob (.pfx em base64) e a senha separadamente com AES-256-GCM (src/lib/crypto.ts, chave em CREDENTIALS_ENCRYPTION_KEY)
  3. Armazena tudo em connections.certificates (jsonb)


A senha NUNCA fica em texto puro — só decifra no momento de abrir conexão TLS.

Onde o certificado é usado (mTLS de saída)



Com certificado anexado, toda chamada à conexão apresenta o certificado no handshake TLS: envio e "Testar conexão" de REST, OData (leitura, escrita e $metadata), SOAP, Webhook/HTTP e AS2, e a consulta de status da entrega assíncrona. No Testar conexão antes de salvar vale o certificado recém-anexado; na edição sem anexo novo, o já salvo.

  • O certificado só vai ao servidor da conexão: um redirecionamento ou uma página seguinte em outro endereço sai sem ele.
  • Certificado vencido (ou ainda não válido): nada é enviado — a mensagem diz a data e pede o renovado.
  • O parceiro recusou o handshake: a mensagem diz se ele exige certificado (nenhum foi apresentado) ou recusou o apresentado (confira emissor e validade com o parceiro).
  • Só em HTTPS: URL http:// com certificado é recusada.
  • A conexão mostra mTLS ativo e o card da integração o selo mTLS (vermelho quando vencido).


Editar / trocar / remover certificado



No card da integração, clique em Editar. A seção de protocolo mostra:
  • O subject e a data de validade do cert atual (badge amarelo se < 30d, vermelho se < 7d ou expirado)
  • Botão Remover certificado (apaga o cert sem deletar a integração)
  • Campo de upload pra subir um novo .pfx (sobrescreve o anterior na próxima save)


Alerta de vencimento (cron diário)



O cron /api/cron/cert-expiry-alerts roda diariamente às 07:00 UTC e cria 1 alerta por bucket atravessado:
  • 30 dias antes — primeiro warning amarelo
  • 14 dias — warning amarelo
  • 7 dias — alerta vermelho
  • 1 dia — alerta crítico vermelho
  • 0 dias — cert expirado, urgent


Dedup via UNIQUE (connection_id, days_bucket) em cert_expiry_alerts. Quando o cert é renovado (não_after muda), um trigger no DB apaga os alerts antigos automaticamente — buckets resetam.

Canais (na ordem):
  1. Slack se SLACK_ALERTS_WEBHOOK_URL setado — bloco com subject + bucket + link pra integração
  2. UI badge na integration-card mostrando "Cert vence em Xd" (sempre visível)


Limitações conhecidas



  • Apenas A1 (arquivo). A3 (token físico) requer Lefia Agent on-prem ou Cloud HSM — fora desta versão.
  • AS4 e EBICS continuam com PEM texto separado (não unificado nesta versão).
  • Validação de cadeia/CRL/OCSP não é feita. Se o emissor revogou o cert, só notará na primeira chamada TLS (erro 4xx do servidor da contraparte).
  • O cron de alerta roda 1x/dia. Se o cert vence em < 24h depois da última execução, o alerta sai no próximo ciclo.


Schema SQL



  • connections.certificates (jsonb): metadata + ciphertexts do client cert
  • cert_expiry_alerts (table): dedup de buckets, RLS super_admin select-only
  • Trigger connections_cert_expiry_alerts_reset: limpa dedup quando cert renovado


Veja também



  • pipeline-mensagens-fluxos — fluxos completos de mensagem incluindo o cenário SEFAZ + cert
  • pii-redaction-llm — privacidade de dados em payloads enviados pra IA
  • ai-toggle-hierarchy — toggle de IA por scope

Histórico de versões

  • 1.1.0

    O certificado digital do cliente (.pfx/.p12) anexado na conexão agora é apresentado de verdade na conexão segura (mTLS) em toda chamada ao parceiro: envio e teste de REST, OData (leitura, escrita e $metadata), SOAP, Webhook/HTTP e AS2, a consulta de status da entrega e o "Testar conexão" — inclusive antes de salvar, com o certificado recém-anexado. Antes ele era aceito, validado e vigiado, mas não ia no handshake. Certificado vencido é recusado antes de enviar, com aviso claro; o certificado só vai ao servidor da conexão (nunca a um redirecionamento para outro endereço). O campo do certificado passa a existir também em OData, Webhook/HTTP e AS2, e a conexão mostra "mTLS ativo". Conexões sem certificado continuam exatamente como antes.

    06/10/2026 · updated

  • 1.0.1

    Leitura do certificado digital (.pfx/.p12) refeita sem o node-forge (aviso de segurança sem correção). Passa a aceitar exatamente o que a conexão segura (mTLS) consegue usar: arquivo exportado com cifra antiga (RC2/RC4/DES — padrão de OpenSSL 1.x, Java e Windows antigos) é recusado na hora do upload, com o passo a passo para exportar de novo em AES-256, em vez de ser aceito e falhar só na conexão. Os demais arquivos abrem como antes; assunto e emissor com acento passam a sair certos e certificado de curva elíptica passa a ser lido. Erros do certificado aparecem traduzidos (PT/EN/ES).

    03/10/2026 · updated

  • 1.0.0

    Upload de certificado digital A1 (.pfx/.p12) em integrações SOAP/REST. Lib parsePkcs12 com node-forge extrai metadata (subject/issuer/serial/validade/fingerprint). API create-integration valida senha e encripta blob+senha com AES-256-GCM, gravando em connections.certificates jsonb. UI file input + password. Documentado em /security e help (slug=certificado-digital-mtls).

    06/05/2026 · new