close
close

Use App Attest and DeviceCheck to prevent iOS fraud

App developers can minimize fraud by using App Attest and DeviceCheck, two tools provided by Apple. Here’s how to use them to prevent unauthorized modifications to apps and prevent users from illegally obtaining premium content.

App Attest and DeviceCheck are important for maintaining revenue.

As an app creator, there are several ways you can monetize your creations. However, not everyone may want to pay but still want access to some premium paid features.

Developers try to avoid this type of behavior. This is where Apple’s App Attest and DeviceCheck come in.

By using Apple’s DeviceCheck platform, you can ensure that only authorized users have access to premium content and promotions.

Checking the device

Apple provides DeviceCheck to help your app limit fraudulent use of paid app features.

DeviceCheck helps reduce in-app promotional offer fraud.

For example, if your app offers promotions or premium content, some users may try to abuse the feature to get lots of free items. They may do this by uninstalling and then reinstalling your app.

Thanks to the DeviceCheck infrastructure, your application can check whether a promotional offer has already been prepared for a given hardware device.

These controls are tied to the Secure Enclave on each Apple device. They are linked to your Apple account and private cryptographic key to provide authorization.

The inspection includes:

  1. Two bits of device status stored by Apple along with a timestamp
  2. Per device, per programmer
  3. Persistent after hardware device reset

The two bits stored by Apple bind each Apple together developer to a known state for all previously registered app promotions. Along with the timestamp, you can use bits in any way you like so your app can determine the promotion status.

DeviceCheck monitors devices individually for each device and each app developer.

The DeviceCheck state is saved each time the device is reset, for example when you completely restore an Apple device to factory settings.

These types of checks may be used by your app to verify that a given promotion has not been previously redeemed by any app on any Apple account on any Apple device.

Application Certification

App Attest is also part of DeviceCheck.framework and allows you to track any service exposed by your app to determine if it is recognized by your app.

To use App Attest, you need a server or cloud service to receive hardware tokens from the user’s device, along with an App Attest request. The server then needs to forward these app requests to Apple’s App Attest server for verification.

If the Apple server returns that the application and service are valid, the server informs the sending device that the request is valid.

Because each request is tied to specific hardware information, it cannot be faked or copied for other devices.

App Attest also prevents illegal copies of premium app features or services from being copied from one device to another.

Three easy pieces

App Attest provides three key pieces of information your app can use to verify that the request is coming from a genuine, authorized Apple device:

  1. Original Apple device
  2. Authentic application identity
  3. Reliable cargo

Checking if your Apple device is genuine helps ensure that your app and premium content are actually running on a real Apple device.

Authentic App Identity ensures that the app making the request is your app and that it is a legitimate copy. One that was downloaded from the App Store.

You can review legitimate payloads to confirm that the premium feature or promotional content is authorized, has been purchased, and has not been tampered with.

Using these three pieces of information, your app can make sure that the content should be accessible to the user. This prevents hackers and jailbreakers from trying to download or reuse premium content that you paid for and authorized on another Apple device.

True device checking is performed by examining the secure key pair on the device that is used by the Secure Enclave. This is combined with an App Attest request from the device that is generated using the correct key pair.

Secure key pairs are part of what is called Public Key Infrastructure (PKI) uses encryption to create secure keys and transmit them over a network.

By using secure keys and digital signatures, the app and device can confirm that the request comes from the person it claims to be addressed to.

PKI infrastructure is extremely secure and even the world’s most powerful supercomputers take years to crack it.

When your app makes an App Attest request, it can use secure keys to do so, which can then be verified by the server. Each secure key is unique to each installation and is not synced or copied across devices.

A hard-coded copy of each requesting application Package ID is also sent with each verification request.

Generating key authentication.

Adding App Attest to an App

To add App Attest to your app in Xcode, you first need to add DeviceCheck.framework in the Build Info tab of the Frameworks panel of each target project.

To use App Attest in your app, the app must be running on a device with Secure Enclave. Therefore, you should always check the possibility of using App Attest in your app before you actually do it.

Adding App Attest to your app consists of three parts:

  1. Generating AppAttest Key
  2. Key verification
  3. Generating and verifying assertions

To create the AppAttest key in your application code, use .shared property on DCAppAttestService class object like this:

let appAttestService = DCAppAttestService.shared

Creates a local variable named appAttestService With .shared and stores a copy of the shared service object.

Once you have an instance .shared property, you can use it to create a key:

Generating device key for App Attest.

In the above code you first get a shared instance DCAppAttestService class. Then you check her .isSupported property to make sure AppAttest is available on this device, then generate the key using .generatekey method.

If .generatekey returns an error, you check it and handle it, otherwise the key is returned keyId.

Once you have a key, you can save it for later use—most likely in an object that you defined and created earlier.

DeviceCheck.framework also supports Objective-C interfaces if you still use that language instead of Swift.

If .isSupported property returns NO or the key returns nil you cannot use AppAttest in your app.

Please note that in some cases the code may still return NO For .isSupported. Even if the device has a Secure Enclave in it (usually if the code is called from an app extension).

Your app needs to be prepared to handle these cases. In these cases, assume the caller is not trustworthy, and then develop your own code logic based on a set of risk assessment rules to determine whether premium features should be allowed.

This approach is the second best method of verification when .isSupported property returns NO.

Check the key

Assuming you have the correct key from the above code, the next step is to verify it or attest key.

To do this, your app will need to create a one-time server challenge. This challenge is intended to validate the key generated using a challenge from your server that verifies the key against the user’s account information.

You will also need to develop server-side code to do the same for each occurrence of the attest key.

Key certification provides an additional level of security by preventing man-in-the-middle attacks and replay attacks.

The first step in this process is to generate a key attestation. You use the same application attestation server object as above, but with .attestKey method.

By using this method you are passing on the original keyIDcustomer data digest, attestationObjectand an optional error variable that .attestKey the method takes as input.

After returning, attestationObject can be used for a server challenge.

Objective .attestKey method involves using the device’s private key to create an opaque hardware credential request. One tied to the key and that specific device.

This hardware credential is then sent to the Apple Credential Server for hardware verification. Once verified, the Apple server will return an anonymous credential object to your app.

Only the Apple server can verify the device at the hardware level based on the information sent to it, making it much more difficult for hackers to intercept the request and return a false positive to enable premium features.

Once the app receives the response from Apple and is satisfied that it is valid, it should send the response along with any custom data to the server for final verification.

This rather complicated process, combined with Apple hardware verification and a private key, makes it incredibly difficult for anyone to hack your premium features and enable unauthorized content.

Apple’s WWDC 2021 video titled Reduce Fraud with App Attest and DeviceCheck explains this process in more detail.

There is also a section Create DeviceCheck Private Keyunder Configure Apple Developer Account Documentation Capabilities.

There are four additional sections in the DeviceCheck documentation that are worth checking out:

  1. Accessing and modifying data on your device
  2. Fraud Risk Assessment
  3. Determining Application Integrity
  4. Validation of applications connecting to the server

Error handling

In the above code, we saw that some of Apple’s DeviceCheck APIs return an optional error code.

Your application should handle these codes and inform the user when errors occur.

Check the documentation for DCDevice AND DCError classes in the DeviceCheck environment.

You can also get the error codes displayed by the user from any DeviceCheck API that returns DCError obtaining its value .Code Real estate. This is defined as enum (number) that can be mapped to a set of predefined Apple error codes.

Using the standard Swift/C language case command, you can then map the error code to a user-visible string that your application displays to the user.

There are currently five predefined DCError Codes set by Apple:

  1. functionUnsupported
  2. invalid input
  3. Wrong key
  4. server unavailable
  5. UnknownSystemFailure

featureUnsupported

means that part or all of the DeviceCheck API is unavailable. invalidKey means the key you tried to use did not work.

Whenever an Apple API or key authentication returns an error, your app should display an appropriate localized text string to the user informing them why the app failed.

You can also check the global variable DCErrorDomain after errors occur to determine the domain of the last error that occurred.

Think of fault domains as categories errors are organized in. Using DCErrorDomain string, you can provide users with additional, useful information about the type of error they are experiencing.

DeviceCheck and AppAttest are welcome additions to Apple’s app development. By using them in your app, you can secure your premium features and revenue without too much extra effort.