Pular para o conteúdo principal

SDK TypeScript

Biblioteca cliente TypeScript/Node.js (hubsaude-cliente-js, consumível também por JavaScript puro). O uso é exclusivamente em servidor, nunca em navegador ou app móvel.

Instalação​

Ainda não publicado no registro npm público. Até a primeira publicação, instale a partir de um tarball gerado por npm pack no repositório, ou aponte para o Git diretamente.

npm install github:sesgo-ti/hubsaude-cliente-ts

Uso básico​

createSmartTokenClient é a única forma de construção (a classe não tem construtor público). Chame close() uma vez no encerramento, ou use await using client = await createSmartTokenClient(...).

Informe a base do servidor: a biblioteca consulta /.well-known/smart-configuration e resolve o endpoint de token. Não combine fhirBase com tokenEndpoint.

import { createSmartTokenClient } from "hubsaude-cliente-js";

const client = await createSmartTokenClient({
fhirBase: "https://hub.saude.go.gov.br",
clientId: "meu-sistema",
privateKeyPem: "chave-privada.pem",
certificatePem: "certificado.pem",
});

const token = await client.obtainToken("system/Patient.rs");

Endpoint de token explícito​

Se preferir fixar o endereço de token, use tokenEndpoint no lugar de fhirBase:

import { createSmartTokenClient } from "hubsaude-cliente-js";

const client = await createSmartTokenClient({
tokenEndpoint: "https://hub.saude.go.gov.br/auth/token",
clientId: "meu-sistema",
privateKeyPem: "chave-privada.pem",
certificatePem: "certificado.pem",
});

const token = await client.obtainToken("system/Patient.rs");

Testar com o Simulador​

O Simulador reproduz o HubSaúde no seu computador e permite testar a biblioteca antes de receber a credencial oficial. Ele exige os mesmos cuidados de segurança da produção, então a configuração é praticamente a mesma: muda apenas o endereço, a origem do certificado e a confiança no servidor.

Antes de executar o código​

Siga os passos de Preparar seu sistema para o Simulador. Ao final deles, você terá:

  1. o Simulador em execução, iniciado com hubsaude sim start;
  2. um certificado de teste (client-cert.pem) e a respectiva chave (client-key.pem), gerados com o OpenSSL;
  3. o sistema cadastrado no Simulador com o identificador meu-sistema e a permissão system/Patient.rs;
  4. o certificado do próprio Simulador (simulador-server.pem), baixado do endereço https://localhost:8443/certs/simulador-server.pem.

Configurar a biblioteca​

import { createSmartTokenClient } from "hubsaude-cliente-js";

const client = await createSmartTokenClient({
fhirBase: "https://localhost:8443",
clientId: "meu-sistema",
privateKeyPem: "client-key.pem",
certificatePem: "client-cert.pem",
serverTrustAnchor: "simulador-server.pem",
});

const token = await client.obtainToken("system/Patient.rs");

Em relação ao uso com a produção, há três diferenças:

  • fhirBase aponta para o Simulador, e a biblioteca descobre sozinha os demais endereços;
  • a chave e o certificado são os de teste, cadastrados no Simulador, e o identificador é o informado no cadastro;
  • serverTrustAnchor faz a biblioteca confiar no certificado do Simulador, que não é emitido por uma autoridade reconhecida.

Se você gerou o certificado de teste com o Java keytool, a chave fica dentro do arquivo client-keystore.p12. Nesse caso, use o PKCS#12, descrito em Fontes de chave suportadas.

Passar para a produção​

Depois que o credenciamento for aprovado, ajuste a mesma configuração:

  • troque o endereço do Simulador por https://hub.saude.go.gov.br;
  • use o client_id entregue no credenciamento;
  • substitua a chave e o certificado de teste pelos da instituição;
  • remova a linha da âncora de confiança: o certificado do HubSaúde já é reconhecido automaticamente.

Problemas comuns no Simulador​

SituaçãoCausa provávelO que fazer
Erro de certificado ao conectar, como falha na verificação da cadeiaO certificado do Simulador não foi informadoBaixe o simulador-server.pem e configure a âncora de confiança
401 invalid_client informando que o certificado não corresponde ao cadastradoO certificado usado é diferente do enviado no cadastroUse o mesmo par de chave e certificado do cadastro
401 invalid_client informando que o certificado de cliente é obrigatórioO certificado de cliente não foi configuradoInforme o certificado de teste na configuração da biblioteca
Erro de permissão ao pedir o tokenA permissão solicitada não foi liberada no cadastroCadastre o sistema novamente incluindo a permissão desejada
O sistema deixa de ser reconhecidoO Simulador foi reiniciado e apagou os cadastrosCadastre o sistema novamente

Fontes de chave suportadas​

Sua chave privada pode estar em diferentes lugares: um arquivo, um cofre de segredos ou um dispositivo de hardware. O SDK abstrai isso com o tipo SigningStrategy, uma função que recebe os bytes a assinar e devolve a assinatura, e já traz pronta a construção para as fontes mais comuns.

PEM com senha​

const client = await createSmartTokenClient({
tokenEndpoint: "https://hub.saude.go.gov.br/auth/token",
clientId: "meu-sistema",
privateKeyPem: "chave-encrypted.pem",
privateKeyPassword: Buffer.from("minha-senha"),
});

PKCS#12 direto (recomendado para produção)​

Um único arquivo (.pfx/.p12) já reúne a chave e o certificado, protegido por senha.

import { readFile } from "node:fs/promises";
import { createSmartTokenClient, fromPkcs12 } from "hubsaude-cliente-js";

const pfx = await readFile("certificado.pfx");

const client = await createSmartTokenClient({
tokenEndpoint: "https://hub.saude.go.gov.br/auth/token",
clientId: "meu-sistema",
signingStrategy: fromPkcs12(pfx, "senha-pfx"),
clientPfx: pfx,
clientPfxPassphrase: "senha-pfx",
});

HSM via PKCS#11​

Um HSM (Hardware Security Module) é um dispositivo dedicado que guarda a chave e nunca a expõe: toda assinatura acontece dentro dele. Node não tem suporte nativo a PKCS#11 (o padrão usado para acessar o HSM), então pkcs11js entra como peer dependency opcional (npm install github:sesgo-ti/hubsaude-cliente-ts pkcs11js).

import { createSmartTokenClient, fromPkcs11 } from "hubsaude-cliente-js";

const signingStrategy = await fromPkcs11({
library: "/usr/lib/softhsm/libsofthsm2.so",
tokenLabel: "meu-token",
keyLabel: "minha-chave-hsm",
pin: "123456",
jwtAlgorithm: "ES384",
});

const client = await createSmartTokenClient({
tokenEndpoint: "https://hub.saude.go.gov.br/auth/token",
clientId: "meu-sistema",
signingStrategy,
});

Configuração completa​

Todas as opções abaixo são propriedades do objeto passado a createSmartTokenClient(options).

OpçãoObrigatórioPadrãoObservações
tokenEndpointsim¹—URL completa do endpoint de token
fhirBasesim¹—Base FHIR para descoberta automática
clientIdsim—Emitido pelo Ganesha
privateKeyPemsim²—Caminho do PEM da chave privada
privateKeyPasswordnão—Senha do PEM criptografado (Buffer)
signingStrategysim²—Estratégia pronta (HSM, cofre etc.)
certificatePemnão³—Certificado do cliente (PEM)
clientPfx / clientPfxPassphrasenão—mTLS via bundle PKCS#12
serverTrustAnchornãotrust store do sistemaPEM ou certificado
tlsProtocolnãoTLSv1.3Ex.: TLSv1.2
jwtAlgorithmnãoRS384HubSaúde aceita RS384/ES384
keyIdnão—Inclui kid no header do JWT
hubContextnão—Inclui o claim hub_ctx ({ig, versao})
connectTimeoutMsnão10000Conexão TCP
requestTimeoutMsnão30000Requisição HTTP completa
assertionTtlSecondsnão60Deveria ser ≤300
maxRetriesnão3Tentativas totais
enableTokenCachenãotrueAtiva ou desativa o cache de tokens
tokenCacheMarginSecondsnão30Margem de renovação antes da expiração
tokenCacheMaxEntriesnão1000Descarte LRU por scope

¹ Exatamente um entre tokenEndpoint e fhirBase. ² Exatamente um entre privateKeyPem e signingStrategy. ³ Obrigatório apenas para mTLS via chave em memória.

Exceções​

TipoUso
SmartTokenErrorConfiguração criptográfica inválida, resposta HTTP/JSON inválida, algoritmo não suportado, ou rejeição confirmada do certificado de cliente
SigningErrorFalha da estratégia criptográfica ao assinar o client_assertion

Repositório e especificação​