Attest (atestação de dispositivo)
O SDK de runtime roda no aparelho, então um aparelho totalmente comprometido pode mentir sobre o que reporta. O Attest fecha essa brecha: o app troca o relatório de runtime do SDK — mais uma atestação da plataforma (Play Integrity no Android, App Attest no iOS) — por um token assinado curto. O seu backend verifica esse token antes de uma ação sensível (uma transferência Pix, um login, uma troca de senha).
O Attest está disponível a partir do plano Startup.
Como funciona
- O seu backend gera um
noncepara a operação e envia ao app. - O app chama
Moatgator.attest(nonce). O SDK junta os achados, pede à plataforma uma atestação presa a esse nonce e troca os dois emPOST /v1/attest/token. - A Moatgator verifica a atestação da plataforma no servidor e devolve um token (um JWT EdDSA, válido por 5 minutos, preso ao seu app, à plataforma e ao nonce).
- O app envia o token ao seu backend. O seu backend o verifica — offline com o JWKS público, ou com
POST /v1/attest/verify.
O veredito é trusted, suspicious ou untrusted, com os motivos e a evidência que o sustentaram (rasp sozinho significa que não houve atestação da plataforma).
Configurar (console)
Em Console → o seu app → Attest:
- Play Integrity (Android): cole o JSON da conta de serviço do Google Cloud do seu projeto e o nome do pacote. Fica guardado cifrado e nunca mais é mostrado.
- App Attest (iOS): informe o Team ID da Apple e o bundle id.
- Exigir atestação da plataforma: quando ligado, um token só com o relatório de runtime (sem atestação da plataforma) é
untrusted.
No app
val r = Moatgator.attest(nonce = order.nonce, integrity = { challenge -> playIntegrityToken(challenge) })
if (!r.trusted) blockPayment()
O provedor integrity é onde você chama a API do Play Integrity; o SDK não depende da biblioteca do Google. Sem um provedor, o token carrega só o relatório de runtime.
Verificação no backend
import { createVerifier } from "@moatgator/attest";
const attest = createVerifier({ appId: process.env.MOATGATOR_APP_ID, env: "live" });
const r = await attest.verify(req.header("x-moatgator-attest"), { nonce: order.nonce, platform: "android" });
if (!r.trusted) return res.status(403).json({ error: "device_not_trusted", reasons: r.reasons });
Também há verificadores para Python e Go. Com qualquer biblioteca JOSE: busque /.well-known/jwks.json, aceite só alg: EdDSA e confira typ == "attest", iss, aud (o id do seu app), exp e nonce.
Limites
- O nonce é seu: gere um valor novo e imprevisível por operação no backend e confira na volta.
- O App Attest exige compilar no macOS com Xcode; o atalho
Moatgator.attest()está no Android hoje, com o iOS a seguir. - A atestação da plataforma vale só o que a plataforma oferece; o relatório de runtime soma sinais do aparelho, mas nenhum sinal sozinho é prova.