I am trying to check if my app was ever installed on a device using Device Check Api by apple. But it always returns error 400: Missing or incorrectly formatted payload
NOTE: I have already checked existing stackoverflow questions like:
Connecting to Apple Store Connect using Swift (with SwiftJWT) and REST API's - failing with 401
How do I generate a JWT to use in API authentication for Swift app
None of them helped my resolving the issue.
Instead of server side implementation, we are trying to fetch this information from swift code itself.
Below is the code to create a JWT token using SwiftJWT.
func generateJWT() -> String? {
let myHeader = Header(kid: "*********")
let myClaims = MyClaims(iss: "*******", iat: Int(Date().timeIntervalSince1970))
var myJWT = JWT(header: myHeader, claims: myClaims)
guard let privateKeyPath = Bundle.main.url(forResource: "AuthKey", withExtension: ".p8") else { return nil }
do {
let privateKey: Data = try Data(contentsOf: privateKeyPath, options: .alwaysMapped)
let jwtSigner = JWTSigner.es256(privateKey: privateKey)
let signedJWT = try myJWT.sign(using: jwtSigner)
return signedJWT
} catch {
print(error.localizedDescription)
}
return nil
}
To Fetch Device Token and call apple's Device check api:
private func generateIdentifier(completion: @escaping (_ token: String) -> Void) {
let device = DCDevice.current
if device.isSupported {
device.generateToken { data, error in
if let token = data?.base64EncodedString() {
completion(token)
}
}
}
}
func queryDeviceInfo() {
guard let jwtToken = generateJWT() else { return }
generateIdentifier { token in
let router = ServiceRouter<ReferralApi>()
router.alamofireRequest(.queryBits(deviceToken: token,
jwtToken: jwtToken)) { [weak self] (response) in
}
}
}
Here is what's inside .queryBits(deviceToken: token, jwtToken: jwtToken)
var url: String {
switch self {
case .queryBits:
return "https://api.development.devicecheck.apple.com/v1/query_two_bits"
default:
return "\(baseURL)\(path)"
}
}
var headers: HTTPHeaders? {
switch self {
case .queryBits(_, let jwt):
let dic: HTTPHeaders = [
"Accept": "application/json",
"Authorization" : "Bearer \(jwt)"
]
return dic
}
}
var parameters: [String: Any]? {
switch self {
case .queryBits(let deviceToken, _):
return [
"device_token": deviceToken,
"timestamp": Date().timeIntervalSince1970*1000,
"transaction_id": UUID().uuidString]
default:
return nil
}
}
Any help would be more than appreciated.
EDIT Here is the screenshot of the request payload: