Documentos digitais em carteiras mobile: o que devs precisam entender (e o que o caso AMIM revela)
Na minha experiência construindo integrações com sistemas públicos, percebo que cada vez que um governo adiciona um documento oficial a uma carteira digital, há muito mais por trás do que uma simples “adição de feature”. O anúncio do Sapo.pt sobre o Atestado Médico de Incapacidade Multiuso (AMIM) na app gov.pt é um excelente exemplo para destrinchar a arquitetura real desse tipo de sistema — e o que devs e arquitetos podem aprender com ele.
O ponto central não é “mais um documento no telemóvel”. É a consolidação de uma infraestrutura de identidade digital que já opera há anos com PKI governamental, autenticação federada e carteiras baseadas em padrões como o ISO mDL (mobile driving licence) que está a tornar-se referência mundial.
Por que a app gov.pt é mais do que uma app
A app gov.pt funciona, tecnicamente, como um agregador de carteiras digitais (digital wallet aggregator) ligado ao Portal das Finanças, à Segurança Social Direta, ao cartão de cidadão e à Chave Móvel Digital (CMD). Cada documento digital que entra nela não é “carregado como um PDF” — é um credential verificável emitido por uma autoridade emissora e apresentado sob demanda.
Quando o AMIM aparece na tua carteira, existem (pelo menos) três entidades a falar entre si:
- Entidade emissora: o serviço de saúde que emite o atestado (via SNS / SPMS).
- Entidade titular: o cidadão autenticado, normalmente via Chave Móvel Digital ou Cartão de Cidadão.
- Entidade verificadora: quem vai pedir o documento (empregador, serviços sociais, etc.).
Esse modelo é praticamente o mesmo do European Digital Identity Wallet (EUDI) que está a ser regulado pelo eIDAS 2.0. Por isso, trabalhar com a stack portuguesa dá-te uma vantagem real se quiseres entrar em projetos de identidade digital na UE.
Como funciona tecnicamente uma carteira de documentos oficiais
Devs costumam achar que mostrar “um documento” no telemóvel é só renderizar uma imagem. Está errado. Um credential verificável tem, no mínimo, estes componentes:
- Schema: o formato dos dados (ex.:
name,birthdate,incapacidade,validade). - Issuer DID: o identificador descentralizado de quem emitiu.
- Prova criptográfica: assinatura digital + Merkle proof ou SD-JWT.
- Proof of possession: confirmação de que o dispositivo do titular tem a chave privada.
Na prática, a app gov.pt lida com isto por baixo dos panos — tu só vês um cartão bonito. Mas se fores integrar como terceira parte (uma empresa que precisa validar o documento), terás que implementar o lado verificador.
Na Prática — Simular uma integração estilo “AMIM digital”
Vamos montar um exemplo funcional em Node.js que simula uma wallet a pedir e apresentar um credential. Não é o código exato da app gov.pt (esse é proprietário), mas segue os mesmos padrões abertos que a stack europeia está a padronizar.
// issuer.js — emite um "credential" estilo AMIM
import { SignJWT, generateKeyPair, exportJWK } from 'jose';
import { createHash } from 'crypto';
const { privateKey, publicKey } = await generateKeyPair('ES256');
async function issueAMIM({ citizenId, type, issuedAt, validityMonths = 12 }) {
const payload = {
iss: 'https://issuer.gov.pt',
sub: citizenId,
vc: {
'@context': ['https://www.w3.org/2018/credentials/v1'],
type: ['VerifiableCredential', 'AMIMCredential'],
credentialSubject: {
id: `did:gov:${citizenId}`,
documentType: type, // ex.: "Incapacidade Parcial 60%"
issuedAt,
expiresAt: new Date(Date.now() + validityMonths * 30 * 86400000).toISOString()
}
}
};
const jwt = await new SignJWT(payload)
.setProtectedHeader({ alg: 'ES256', typ: 'vc+jwt' })
.setIssuedAt()
.setExpirationTime('1y')
.sign(privateKey);
return { jwt, publicKey: await exportJWK(publicKey) };
}
// exemplo de uso
const credential = await issueAMIM({
citizenId: 'PT-12345678',
type: 'Incapacidade Multiuso — Grau 60%',
issuedAt: new Date().toISOString()
});
console.log(credential.jwt);
E do lado da app (wallet), o pedido para apresentar o documento passaria por algo como:
// wallet.ts — pede e apresenta o credential
async function presentCredential(credentialJwt: string, verifierOrigin: string) {
const presentation = {
'@context': ['https://www.w3.org/2018/credentials/v1'],
type: ['VerifiablePresentation'],
verifiableCredential: [credentialJwt],
proof: {
challenge: crypto.randomUUID(),
domain: verifierOrigin,
proofPurpose: 'authentication'
}
};
// Aqui o SDK nativo (Apple Wallet, Google Wallet ou SDK próprio da gov.pt)
// renderiza o documento já validado criptograficamente.
return presentation;
}
O ponto pedagógico: o documento é prova criptográfica, não um ficheiro. Quando mostrar o AMIM a um empregador, nenhum dado sensível sai do telemóvel sem o teu consentimento explícito. Isso é o que está por trás do “evita transportar o documento físico” que a notícia do Sapo.pt menciona — não é só conveniência, é selective disclosure.
Erros Comuns (e o que devs costumam fazer mal)
Quando integro sistemas deste tipo ou revejo código de terceiros, vejo três erros recorrentes:
- Tratar o documento como ficheiro. Muitos devs tentam “fazer upload” do AMIM em PDF para um servidor. Isso quebra toda a cadeia de confiança. O correto é armazenar a referência ao credential (o JWT ou o pointer) e validar a assinatura localmente.
- Confundir autenticação com apresentação. A app gov.pt não é só “autenticação”; é também “apresentação seletiva”. Mostrar a idade ≥ 18 não requer revelar a data de nascimento. Selective disclosure é uma feature, não um bónus.
- Ignorar revogação. Um credential pode estar expirado, revogado ou suspenso. Em produção, precisas de uma StatusList2021 endpoint do issuer. Já vi wallets “stockear” AMIMs antigos sem verificar se foram suspensos — isso é um risco legal real.
- Hardcodar URLs de serviços públicos. O endpoint do SNS de hoje pode mudar amanhã. Usa configuration discovery via
/.well-known/openid-configurationsempre que possível. - Esquecer o offline-first. Carteiras digitais precisam funcionar em modo avião. O credential deve estar em secure storage do dispositivo (Keychain no iOS, Keystore no Android), não só em cache HTTP.
Implicações práticas para quem desenvolve em Portugal
Se trabalhas em web, mobile ou backend em PT, esta novidade abre três frentes de oportunidade reais:
- Integração via Autenticação.Gov: se o teu SaaS lida com utilizadores portugueses, integra a Chave Móvel Digital via OAuth2/OpenID Connect. É gratuita, está documentada e elimina passwords.
- Validação de documentos oficiais: empresas de RH, banca, seguradoras e healthtech podem (e devem) aceitar credenciais digitais em vez de pedir scans de PDFs — é compliance mais barato e antifraude melhor.
- White-label wallet: se fores uma entidade emissora, podes emitir creds diretamente via SDKs compatíveis com W3C VC e SD-JWT. Evita o “lock-in” com a app gov.pt e mantém o credential portável.
Quando testei uma integração com a CMD há dois anos, num projeto de cliente, o “tempo real” da autenticação era aceitável (~800ms) mas a curva de onboarding do citizen card auth era o verdadeiro blocker. Hoje, com carteiras mobile maduras, a fricção caiu drasticamente — e é por isso que lançamentos como o AMIM digital importam: cada documento novo reduz o custo de integração para todos os outros serviços.
FAQ — Perguntas que devs realmente fazem
A app gov.pt está disponível em iOS e Android?
Sim. Ambas as versões suportam o AMIM digital, segundo a informação divulgada pelo Sapo.pt. Em iOS é construída com Wallet extensions e Secure Enclave; em Android com o Android KeyStore e credential manager.
Posso integrar a Chave Móvel Digital no meu projeto como developer?
Podes, via Autenticação.Gov usando OAuth2/OIDC. É free tier e há SDKs em várias linguagens. O segredo é configurar corretamente o redirect_uri e validar o id_token contra as chaves JWKS do issuer.
O AMIM digital tem a mesma validade legal do físico?
Sim. Documentos digitais emitidos pela app gov.pt mantêm validade legal. Para teres isto em código, valida sempre o iss, o aud, o exp e o status de revogação antes de confiar.
Vale a pena implementar EUDI Wallet já agora no meu produto?
Se o teu B2B é europeu, vale começar a prototipar. O regulamento eIDAS 2.0 força interoperabilidade até 2026/2027 em vários estados-membros. Estar pronto cedo dá-te uma vantagem competitiva óbvia.
Qual a diferença entre a carteira da gov.pt e a Apple/Google Wallet?
As carteiras da Apple e Google suportam pass types genéricos, mas o credential oficial é emitido por autoridade governamental e validado por elas. A app gov.pt é tanto emitter quanto wallet; a Apple/Google Wallet é só o último elo (a “carteira de couro”) onde podes instalar passes emitidos por terceiros.
Considerações finais
Segundo o Sapo.pt, a novidade do AMIM na app gov.pt é “mais uma integração” — mas, na minha leitura, é mais um passo de um país que está anos à frente da média europeia em identidade digital. Para devs, isso significa: estuda estas integrações, mesmo que o teu produto não seja PT-first. Os padrões que Portugal está a aplicar hoje serão a norma da UE amanhã, e entrar tarde custa caro.
Se quiseres prototipar uma wallet em casa, recomendo começar pelo W3C Verifiable Credentials Data Model e pelo SD-JWT draft da IETF. Dois documentos, dez dias de leitura, e vais entender 80% do que se passa debaixo da app gov.pt.
Gostou? Me segue no GitHub e deixa um comentário se tiver dúvida ou quiser aprofundar algum ponto.