1. Overview

Using the DeviceCheck APIs, in combination with server-to-server APIs, you can set and query two bits of data per device, while maintaining user privacy. You might use this data to identify devices that have already taken advantage of a promotional offer that you provide, or to flag a device that you've determined to be fraudulent. The DeviceCheck APIs also let you verify that the token you receive comes from an authentic Apple device on which your app has been downloaded.

Your app uses the DeviceCheck APIs to generate an ephemeral token that identifies a device. Your associated server combines this token with an authentication key that you receive from Apple, and uses the result to request access to the per-device bits. After successful authentication, Apple passes the current values of the bits, along with the date they were last modified, to your server. Your server applies its business logic to this information and communicates the results to your app as appropriate.

2. Generate Token

Method generateToken(completionHandler:) generates a token that identifies the current device.

let currentDevice = DCDevice.current
if currentDevice.isSupported {
    currentDevice.generateToken(completionHandler: { (data, error) in
        if let tokenData = data {
            print("Token: \(tokenData)")
        } else {
            print("Error: \(error?.localizedDescription ?? "")")
        }
    })
}

Code available on Github.

Your server uses the generated token in its requests to get or set the persistent bits for the current device. You should treat the token you receive in the completion block as single-use. Although the token remains valid long enough for your server to retry a specific request if necessary, you should not use a token multiple times. Instead, use this method to generate a new token.

Note - The app you use to generate the token must be associated with your developer account; otherwise, the generation request fails.

3. Accessing and Modifying Per-Device Data

After you use the DeviceCheck APIs to generate an ephemeral token that identifies a device, your server uses HTTP POST commands to send requests to the query and update endpoints. The HTTP header field in each request must contain the authentication key you receive from Apple in a JSON web token (JWT). To create this token, you can use the same steps you use to create a provider authentication token for Apple Push Notification service (APNs)

3.1 Create an APNs authentication token signing key

  1. In your developer account, go to Certificates, Identifiers & Profiles.
  2. Under Keys, select All and click the Add button (+) in the upper-right corner.
  3. Under Key Description, enter a unique name for the signing key.
  4. Under Key Services, select the APNs checkbox, then click Continue.
  5. Review the key configuration, then click Confirm.
  6. Optionally, click Download to generate and download the key now.
    If you download the key, it is saved as a text file with a .p8 file extension. Save the file in a secure place because the key is not saved in your developer account and you won’t be able to download it again.
  7. Click Done.

3.2 Create the Payload for a Query Request

To query the bits, you create a JSON payload that contains the fields listed in the table below.

Field name Type Description Required
device_token String Base 64–encoded representation of encrypted device information Yes
transaction_id String Unique transaction identifier from the associated server Yes
timestamp Long UTC timestamp from the associated server, in milliseconds since the Unix epoch Yes

Here's an example of a payload included in a query request:

{
   "device_token" : "qpkCFA2Yy/DFrNpVAWhs4BRA/0PAIuRiUn0jQg1a..."
   "transaction_id" : "6r456df4-w3d4-567u-o435-2376674f8uj8",
   "timestamp" : 1487716472000 
}

When your query request succeeds, you receive a response that contains the fields listed in the table below.

Field name Type Description
bit0 Boolean The value of the first bit
bit1 Boolean The value of the second bit
last_update_time String The date of the last modification, in YYYY-MM format

3.3 Create the Payload for an Update Request

To update the bits, you create a JSON payload that contains the fields listed in the table below.

Field name Type Description Required
device_token String Base 64–encoded representation of encrypted device information Yes
transaction_id String Unique transaction identifier from the associated server Yes
timestamp Long UTC timestamp from the associated server, in milliseconds since the Unix epoch Yes
bit0 Boolean Value to set for the first bit No
bit1 Boolean Value to set for the second bit No

Here's an example of a payload included in an update request:

{
   "device_token" : "qpkCFA2Yy/DFrNpVAWhs4BRA/0PAIuRiUn0jQg1a..."
   "transaction_id" : "6r456df4-w3d4-567u-o435-2376674f8uj8",
   "timestamp" : 1487716472000,
   "bit0" : true,
   "bit1" : false 
}

So, you’re able to store :

bit0 bit1 bit0 & bit1 combination
false false 00
false true 01
true false 10
true true 11

When you set that information, it remains valid and stored by Apple until you manually reset it or until you update it.

If the update was successful, you receive the HTTP response code 200. For a full list of the response codes you can receive, see Understand the HTTP Response Codes.

3.4 Create the Payload for a Device Validation Request

To validate a device, you create a JSON payload that contains the fields listed in the table below.

Field name Type Description Required
device_token String Base 64–encoded representation of encrypted device information Yes
transaction_id String Unique transaction identifier from the associated server Yes
timestamp Long UTC timestamp from the associated server, in milliseconds since the Unix epoch Yes

Here's an example of a payload included in a device-validation request:

{
   "device_token" : "wlkCDA2Hy/CfMqVAShslBAR/0sAiuRIUm5jQg0aJJ2gZl1cs..." 
   "transaction_id" : "6r456df4-w3d4-567u-o435-2376674f8uj8",
   "timestamp" : 1487716472000 
} 

If the request was successful, you receive the HTTP response code 200. For a full list of response codes you can receive, see Understand the HTTP Response Codes.

3.5 Send the Request

Each request you send to the query and update endpoints must include an authorization header that contains your authentication key. The authentication key must must use the ES256 algorithm and be in the Base 64 URL–encoded JSON web token format. If your token doesn't use this format, you receive a BAD_AUTHENTICATION_TOKEN HTTP error.

In the curl command you create to send a request, you specify the authorization header and include your authentication key using Bearer , like this:

-H "Authorization: Bearer <GeneratedJWT>" \

Important
Use the base URL shown in the example curl commands—that is, https://api.development.devicecheck.apple.com—only for testing during development. When you're ready to transition to a production environment, you must use the production base URL https://api.devicecheck.apple.com.

To send a query request, your curl command might look similar to the one shown here:

curl -i --verbose -H "Authorization: Bearer <GeneratedJWT>" \ -X POST --data-binary @ValidQueryRequest.json \ 
https://api.development.devicecheck.apple.com/v1/query_two_bits 

To send an update request, your curl command might look similar to the one shown here:

curl -i --verbose -H "Authorization: Bearer <GeneratedJWT>" \ -X POST --data-binary @ValidUpdateRequest.json \ https://api.development.devicecheck.apple.com/v1/update_two_bits 

To send a device-validation request, your curl command might look similar to the one shown here:

curl -i --verbose -H "Authorization: Bearer <GeneratedJWT>" \ -X POST --data-binary @ValidValidateDeviceToken Request.json \ https://api.development.devicecheck.apple.com/v1/validate_device_token 

4. Understand the HTTP Response Codes

When you use the query and update endpoints to communicate with the server, you may receive one of the response codes listed in the table below.

Code Descriptive string Meaning
200 OK The transaction was successful
200 Bit State Not Found The bit state wasn't found
400 Bad Device Token The device token is missing or badly formatted
400 Bad Bits The bits are missing or badly formatted
400 Bad Timestamp The timestamp is missing or badly formatted
400 Bad Authorization Token The authentication token is missing or badly formatted
400 Bad Payload The payload is missing or badly formatted
401 Invalid Authorization Token The authentication token can't be verified
401 Authorization Token Expired The authentication token has expired
403 Forbidden The specified action isn't allowed
405 Method Not Allowed The endpoint was used incorrectly
429 Too Many Requests Too many requests were sent to the server
500 Server Error An error occurred on the server
503 Service Unavailable The service is unavailable

Reference
https://developer.apple.com/documentation/devicecheck