CloudKit Server-to-Server Authentication Fails with 401 Error

I'm trying to set up server-to-server authentication with CloudKit Web Services, but keep getting AUTHENTICATION_FAILED errors. I've tried multiple environment settings and debugging approaches without success.

What I've Tried I created a Swift script to test the connection. Here's the key part that handles the authentication:

// Get current ISO 8601 date
let iso8601Formatter = ISO8601DateFormatter()
iso8601Formatter.formatOptions = [.withInternetDateTime]
let dateString = iso8601Formatter.string(from: Date())
// Create SHA-256 hash of request body
let bodyHash = SHA256.hash(data: bodyData).compactMap { String(format: "%02x", $0) }.joined()
// Get path from URL
let path = request.url?.path ?? "/"
// String to sign
let method = request.httpMethod ?? "POST"
let stringToSign = "\(method):\(path):\(dateString):\(bodyHash)"
// Sign the string with EC private key
let signature = try createSignature(stringToSign: stringToSign)
// Add headers
request.setValue(dateString, forHTTPHeaderField: "X-Apple-CloudKit-Request-ISO8601Date")
request.setValue(KEY_ID, forHTTPHeaderField: "X-Apple-CloudKit-Request-KeyID")
request.setValue(signature, forHTTPHeaderField: "X-Apple-CloudKit-Request-SignatureV1")
}

I've made a request to this endpoint:

What's Happening I get a 401 status with this response:

"uuid" : "173179e2-c5a5-4393-ab4f-3cec194edd1c",
"serverErrorCode" : "AUTHENTICATION_FAILED",
"reason" : "Authentication failed"
}

What I've Verified

The key validates correctly and generates signatures The date/time is synchronized with the server The key ID matches what's in CloudKit Dashboard I've tried all three environments: development, Development (capital D), and production The container ID is formatted correctly

Debug Information My debugging reveals:

The EC key is properly formatted (SEC1 format) Signature generation works No time synchronization issues between client and server All environment tests return the same 401 error

Questions

Has anyone encountered similar issues with CloudKit server-to-server authentication? Are there specific container permissions needed for server-to-server keys? Could there be an issue with how the private key is formatted or processed? Are there any known issues with the CloudKit Web Services API that might cause this?

Any help would be greatly appreciated!

Answered by DTS Engineer in 830642022

The way to set up a CloudKit server-to-server key is detailed in the following sample:

  • Server-side CloudKit with node.js (https://cdn.apple-cloudkit.com/cloudkit-catalog/#readme/Server-side-CloudKit-with-node-js).

You can start with going through the process to set up a key that works before applying it to your Swift code. That should help confirm that the key is correct.

If the key works with JS, but not with Swift, it is likely the the data format in your HTTP request has something wrong.

Best,
——
Ziqiao Chen
 Worldwide Developer Relations.

The way to set up a CloudKit server-to-server key is detailed in the following sample:

  • Server-side CloudKit with node.js (https://cdn.apple-cloudkit.com/cloudkit-catalog/#readme/Server-side-CloudKit-with-node-js).

You can start with going through the process to set up a key that works before applying it to your Swift code. That should help confirm that the key is correct.

If the key works with JS, but not with Swift, it is likely the the data format in your HTTP request has something wrong.

Best,
——
Ziqiao Chen
 Worldwide Developer Relations.

CloudKit Server-to-Server Authentication Fails with 401 Error
 
 
Q