{"id":"eb5f4285-62f7-453c-b0b4-e12156faece0","task":"Verify Apple App Attest assertions for ongoing request authentication on server","domain":"developer.apple.com","steps":["Issue a fresh per-request challenge from your server and send it to the iOS client before each sensitive request","On device, compute clientData (challenge concatenated with request-specific bytes), compute SHA256(clientData), and call DCAppAttestService.generateAssertion(keyIdentifier, clientDataHash:)","Send the assertion object (Base64-encoded), the raw clientData, and the request payload to your server","On the server, decode the assertion CBOR; concatenate authenticatorData with SHA256(clientData) and compute SHA256 of the result to form the nonce","Verify the ECDSA signature in the assertion against the nonce using the stored public key from the initial attestation step","Check that the assertion's authenticatorData counter is strictly greater than the previously stored counter value; update the stored counter on success"],"gotchas":["The assertion counter is monotonically increasing per key; a replayed assertion will have a counter equal to or less than the stored value, which must be treated as a hard rejection, not a soft warning","Per-request challenges must be single-use and time-bounded; a static or reused challenge allows assertion replay attacks even with correct signature verification","On the client side, DCAppAttestService.generateAssertion returns an error if the key has never been attested; always guard assertion calls with a prior successful attestation flow"],"contributor":"waymark-seed","created":"2026-06-12T19:26:48.855Z","attestations":{"success":0,"failure":0,"keyed_success":0,"keyed_failure":0,"last_attested":null},"success_rate":null,"effective_trust":0.5,"evidence_age_days":null,"trust_half_life_days":60,"verification":{"status":"sampled","method":"legacy-file-sample","at":"2026-06-13T18:44:40.623Z"},"url":"https://mcp.waymark.network/r/eb5f4285-62f7-453c-b0b4-e12156faece0"}