iOS DeviceCheck API call returning 400 all the time

Hi,

I'm getting 400 Missing or badly formatted authorization token everytime I call the following API from my local Server ( I tried calling this API from my app itself as well)

curl --location 'https://api.development.devicecheck.apple.com/v1/query_two_bits' \
--header 'Authorization: Bearer <<JWT-token>>' \
--header 'Content-Type: application/json' \
--data '{
    "device_token": Token_fetched_from_Device_Check,
    "transaction_id":"c6bdb659-0ee6-443d-88cb-a8f036dfc551", 
    "timestamp": 1721300244267
}'

"device_token" - I have generated from DeviceCheck framework

JWT-token - I generated using key from .p8 file generated from Apple developer portal, keyId of the same and the team Id ( I have individual account)

IMP Points-

  1. I have created this .p8 file from apple developer account, and I did enable Device check option while creating the key.
  2. I also tried calling this API after 7 hours ( and more then that as well) of creating key from the developer portal as I have read somewhere that the key gets activated after few hours.
  3. I understand (again read somewhere) that the token created by DeviceCheck framework has some expiration time so I tried with freshly created token several times as well.

This is how I'm generating token using DeviceCheck -

if curDevice.isSupported{
     DCDevice.current.generateToken { (data, error) in
           if let data = data {
           }
     }
 }

JWT token generation -

func createJWTToken(privateKey: String, keyID: String, teamID: String) -> String? {
        // Set up the JWT header
        var jwtHeader = Header()
        jwtHeader.kid = keyID
        
        // Set up the JWT claims
        let jwtClaims = MyClaims(iss: teamID, iat: Date())
        
        // Create the JWT
        var jwt = JWT(header: jwtHeader, claims: jwtClaims)
        
        // Convert the private key to Data
        guard let privateKeyData = Data(base64Encoded: privateKey) else {
            print("Invalid private key")
            return nil
        }
        
        
        // Sign the JWT
        let jwtSigner = JWTSigner.es256(privateKey: privateKeyData)
        
        do {
            let signedJWT = try jwt.sign(using: jwtSigner)
            return signedJWT
        } catch {
            print("Failed to sign JWT: \(error)")
            return nil
        }
    }

But no luck, please suggest something. any sort of help is much appreciated.

Thank you

There could be many reasons that your JWT is malformed or has invalid information.

Have you checked it against the https://jwt.io Debugger and see if anything looks out of place?

iOS DeviceCheck API call returning 400 all the time
 
 
Q