supabase-integrity-attest
Server-side Apple App Attest verification for Supabase Edge Functions, built entirely on WebCrypto.
New to App Attest?
Understand the problem this library solves and get set up in minutes.
Ready to integrate?
Jump straight to setting up verification in your Supabase Edge Functions.
API reference
Full function signatures, parameter details, and error code reference.
Design & architecture
Understand the implementation: why WebCrypto, why not pkijs, and the verification pipeline.
What this library does
Mobile apps embed API keys that are trivially extractable via MITM tools like mitmproxy. IP-based rate limiting is just as easily bypassed with rotating proxies. Apple's App Attest solves this by leveraging the Secure Enclave to create hardware-backed cryptographic proof that requests originate from a genuine app on a real device.
This library verifies those proofs server-side. It handles the full attestation verification pipeline (CBOR decoding, X.509 certificate chain validation, nonce verification, key extraction) and the per-request assertion signature check — all using the WebCrypto API so it runs natively in Deno and Supabase Edge Functions without any Node.js compatibility issues.
- WebCrypto only — zero dependency on
node:crypto. Runs in Deno Deploy, Supabase Edge Functions, and any runtime withcrypto.subtle. - Full verification pipeline — CBOR decode, X.509 certificate chain validation, nonce check, key extraction, ECDSA signature verify. Nothing is skipped or stubbed.
- Supabase-native — designed for Supabase Edge Functions from day one, but works with any Deno or Node.js server.
- No compatibility hacks — no
pkijs(crashes in Supabase's edge runtime), no@peculiar/x509(global side effects fromtsyringe). Just standards-based crypto.
Assertion middleware
Once a device is attested, use withAssertion() to verify every subsequent request with a single wrapper:
import { withAssertion } from '@bradford-tech/supabase-integrity-attest/assertion'
Deno.serve(
withAssertion(
async (req, ctx) => {
// ctx.deviceKey is verified — the request is from a genuine device
return new Response('OK')
},
{
getDeviceKey: async (keyId) => {
/* look up public key + sign count from your database */
},
updateSignCount: async (keyId, counter) => {
/* persist the new counter value */
},
},
),
)
withAssertion() extracts the assertion from the request, verifies the signature against the stored public key, checks the counter to prevent replay attacks, and hands you a verified ctx.deviceKey. See the assertion verification guide and API reference for the full details.
Install
# Deno / JSR
deno add jsr:@bradford-tech/supabase-integrity-attest
# Node.js / npm
npm install @bradford-tech/supabase-integrity-attest

