2.5 KiB
2.5 KiB
android-safetynet attestation verifier
(no submodules)
Purpose
Implements the W3C WebAuthn L3 §8.5 android-safetynet attestation format. Google's SafetyNet API issues a JWS attestation token whose payload binds the credential creation challenge (nonce = base64(sha256(authData || clientDataHash))) to a Google-signed claim that the device passed the SafetyNet integrity checks. The verifier delegates JWS structural parsing to @suaveplan/jws, confirms the nonce, and surfaces the x5c chain for the caller to bind to the Google attestation root.
Features
- JWS parsing via
@suaveplan/jws— no inline JWT/JOSE decoding. nonceclaim cross-bind via constant-time compare againstbase64(sha256(authData || clientDataHash)).x5cchain extracted from the JWS header, decoded into raw DER bytes, and surfaced viatrustPath.- Constant-time
rpIdHashcompare. - Reports
attestationType: "basic".
Usage: Basic Example
import { verifyAndroidSafetynetAttestation } from "@suaveplan/webauthn/attestation/android-safetynet";
const result = await verifyAndroidSafetynetAttestation({
attestationObject,
clientDataHash,
expectedRpIdHash,
});
Usage: Advanced Example
import {
verifyAndroidSafetynetAttestation,
type AttestationFormatRegistry,
} from "@suaveplan/webauthn";
function strictSafetynetRegistry(): AttestationFormatRegistry {
return new Map([
[
"android-safetynet",
async (input) => {
const r = await verifyAndroidSafetynetAttestation(input);
await assertGoogleAttestationRoot(r.trustPath);
return r;
},
],
]);
}
API Reference
verifyAndroidSafetynetAttestation: AttestationFormatVerifier— the format verifier.
Implementation Notes
- Google has deprecated SafetyNet in favour of the Play Integrity API. The format is retained because Android devices still emit it during the transition window; new deployments SHOULD NOT depend on it for new policy.
- Full JWS signature verification against the Google attestation root is intentionally NOT performed here — the root cert pool changes and the caller's metadata layer is the right place for it. The verifier surfaces the x5c chain via
trustPathand confirms the nonce binding so the caller can do the full chain check with the correct trust anchor. - The
nonceis base64 (not base64url) per the SafetyNet spec; the verifier explicitly encodes viabtoarather than viatoBase64Urlto match.