App Attest

RSS for tag

Validate the integrity of your app before your server provides access to sensitive data.

Posts under App Attest tag

26 Posts

Post

Replies

Boosts

Views

Activity

Errors with Attestation on App
We recently deployed Attestation on our application, and for a majority of the 40,000 users it works well. We have about six customers who are failing attestation. In digging through debug logs, we're seeing this error "iOS assertion verification failed. Unauthorized access attempted." We're assuming that the UUID is blocked somehow on Apple side but we're stumped as to why. We had a customer come in and we could look at the phone, and best we can tell it's just a generic phone with no jailbroken or any malicious apps. How can we determine if the UUID is blocked?
3
0
194
May ’25
App Attest not working in production - started today
Hi, For some reason all implemented (and working before) App Attest code has stopped working. iOS is unable to get attestation returning "Operations could not be completed. (com.apple.devicecheck.error error 4.) (serverUnavailable)" On https://developer.apple.com/system-status/ I can see green dot but I suspect that infrastructure is not OK. This is happening with multiple of our apps in multiple geographical regions. Can anyone confirm these problems or know whether it is strictly connected to App Attest service availability?
21
19
2.4k
May ’25
App Attest receipts response 400
I tried to send it on the nodejs server I built. No success received 200 My work steps are as follows: The app executes “DCAppAttestService.shared.attestKey” to get receiptData from the acquired attestation. The app sends "receiptData.base64EncodedString()" to the server (code-1) Nodejs code (code-2) Because the app has been uploaded to TestFlight, I set the server IP to "data.appattest.apple.com" Is there something wrong with my steps? code-1 public func attestData(receipt:Data) { if DCDevice.current.isSupported { let sesh = URLSession(configuration: .default) var req = URLRequest(url: URL(string: "http://10.254.239.27:3000/attestationData")!) print(req) req.addValue("application/json", forHTTPHeaderField: "Content-Type") req.httpMethod = "POST" let data = try! JSONSerialization.data(withJSONObject: ["receipt": receipt.base64EncodedString()], options: []) req.httpBody = data let task = sesh.dataTask(with: req, completionHandler: { (data, response, error) in if let data = data, let jsonString = String(data: data, encoding: .utf8) { print(jsonString) } }) task.resume() } else { print("Platform is not supported. Make sure you aren't running in an emulator.") //self.stopActivity() } } code-2 versionRouter.post('/attestationData', function(req, response) { console.log("\n\n\n\n\n"); console.log("receiptApi"); var receiptBase64 = req.body.receipt; if (!receiptBase64) { return response.status(400).send({ error: 'Missing receipt data' }); } let binaryReceipt; if (typeof receiptBase64 === 'string') { const cleaned = receiptBase64.trim(); binaryReceipt = Buffer.from(cleaned, 'base64'); } if (Buffer.isBuffer(binaryReceipt)) { //binaryReceipt = receiptBase64; console.log("receipt is base64 或 Buffer: "+ Buffer.isBuffer(binaryReceipt)); } else { console.error('⚠️ receipt is not base64 or Buffer'); response.status(400).send("Receipt format error"); return; } var jwToken = jwt.sign({}, cert, { algorithm: 'ES256',header: { typ: undefined }, issuer: teamId, keyid: keyId}); var post_options = { host: 'data.appattest.apple.com', port: '443', path: '/v1/attestationData', method: 'POST', headers: { 'Authorization': jwToken, 'Content-Type': 'application/octet-stream', 'Content-Length': binaryReceipt.length } }; var post_req = https.request(post_options, function(res) { res.setEncoding('utf8'); console.log("📨 Apple Response Header:", res.headers); console.log("📨 Apple StatusCode:", res.statusCode); var data = ""; res.on('data', function (chunk) { data += chunk; }); res.on('end', function() { console.log(data); response.send({"status": res.statusCode, data: data}); }); }); post_req.on('error', function(e) { console.error('error:', e); response.status(500).send({ error: e.message }); }); post_req.write(binaryReceipt); post_req.end(); });
1
0
216
Apr ’25
App Attest API – "DCErrorInvalidKey 3" after App or OS Update
Hi everyone, We are using the App Attest API to securely transition users to our new system. As part of this, we store the Key ID of the attestation key for each user to verify their identity later. However, we’ve noticed that some users are encountering the error “DCErrorInvalidKey 3” when calling generateAssertion. Importantly, the key was previously successfully attested, and generateAssertion has worked before for these users. Our questions: Could this error be caused by an app or iOS update? Is it problematic to link an attestation key's Key ID directly to a user, or are there scenarios where the key might change or become invalid? If there’s a way to mitigate this issue or recover affected users, what best practices would you recommend? Any help or shared experiences would be greatly appreciated! Thanks in advance.
0
4
247
Apr ’25
Issue with DCAppAttestService for offloaded app
Hi, When calling generateAssertion on DCAppAttestService.shared, it gives invalidKey error when there was an update for an offloaded app. The offloading and reinstall always works fine if it is the same version on app store that was offloaded from device, but if there is an update and the app tries to reuse the keyID from previous installation for generateAssertion, attestation service rejects the key with error code 3 (invalid key) for a significant portion of our user. In our internal testing it failed for more than a third of the update attempts. STEPS TO REPRODUCE: install v1 from app store generate key using DCAppAttestService.shared.generateKey Attest this key using DCAppAttestService.shared.attestKey Send the attestation objection to our server and verify with apple servers Generate assertions for network calls to backend using DCAppAttestService.shared.generateAssertion with keyID from step 2 Device offloads the app (manually triggered by user, or automatically by iOS) A new version v2 is published to App Store Use tries to open the app Latest version is download from the App Store App tries to use the keyID from step 2 to generate assertions DCAppAttestService throws invalidKey error (Error Domain=com.apple.devicecheck.error Code=3) Step 7 is critical here, if there is no new version of the app, the reinstalled v1 can reuse the key from step 2 without any issues Is this behaviour expected? Is there any way we can make sure the key is preserved between offloaded app updates? Thanks
4
0
489
Feb ’25