Apple DeviceCheck API
The `devicecheck` Python library provides a wrapper for the Apple DeviceCheck API, allowing developers to manage device state and assert app integrity to reduce fraudulent use of services. It supports both synchronous and asynchronous operations. The library is actively maintained, with regular releases, currently at version 1.3.3.
Warnings
- breaking Decorators for web frameworks (`@validate_device`, etc.) were reworked in version 1.2.0. If you were using these decorators prior to this version, review the changes and update your implementation accordingly.
- gotcha The `dev_environment` parameter in `DeviceCheck` initialization is crucial. It defaults to `True` (development) for new instances. Ensure it is explicitly set to `False` in production to interact with Apple's production DeviceCheck environment. Incorrect setting will lead to validation failures or incorrect bit states.
- gotcha Apple's DeviceCheck API, and by extension this library, only works on physical iOS devices. It will not function correctly on simulators.
- gotcha Version 1.3.0 introduced dedicated asyncio support. When working with asynchronous code, ensure you import `AsyncioDeviceCheck` from `devicecheck.asyncio` instead of the top-level `DeviceCheck` class to leverage `async/await` functionality.
- gotcha The private key (`.p8` file) used for authentication with Apple's API is highly sensitive. It should never be hardcoded or committed directly into source control. Always load it securely, for example, from an environment variable or a secure vault at runtime.
Install
-
pip install devicecheck
Imports
- DeviceCheck
from devicecheck import DeviceCheck
- AsyncioDeviceCheck
from devicecheck.asyncio import AsyncioDeviceCheck
- validate_device
from devicecheck.decorators import validate_device
- DCSupportedFrameworks
from devicecheck.decorators import DCSupportedFrameworks
- async_validate_device
from devicecheck.decorators import async_validate_device
- DCSupportedAsyncFrameworks
from devicecheck.decorators import DCSupportedAsyncFrameworks
Quickstart
import os
from devicecheck import DeviceCheck
# Configure DeviceCheck client using environment variables for security
dc_client = DeviceCheck(
team_id=os.environ.get("APPLE_TEAM_ID", ""),
bundle_id=os.environ.get("APPLE_BUNDLE_ID", ""),
key_id=os.environ.get("APPLE_KEY_ID", ""),
private_key=os.environ.get("APPLE_PRIVATE_KEY_PATH", ""),
dev_environment=bool(os.environ.get("DC_DEV_ENVIRONMENT", "False").lower() == "true"),
# Set raise_on_error=True to get Python exceptions on API errors
raise_on_error=True
)
# IMPORTANT: Replace with an actual device token generated by your iOS app
# For testing, you might use a mocked token if the library supports it via env vars.
device_token = os.environ.get("TEST_DEVICE_TOKEN", "YOUR_ACTUAL_DEVICE_TOKEN_HERE")
if not device_token:
print("Error: TEST_DEVICE_TOKEN environment variable not set, or placeholder not replaced.")
print("Please provide a valid device token from your iOS app for real testing.")
else:
try:
# Validate the device token
validation_result = dc_client.validate_device_token(device_token)
if validation_result.is_ok:
print('Device is valid!')
# Example: Query bits data if needed
# bits_data = dc_client.query_two_bits(device_token)
# print(f'Bit 0: {bits_data.bit0}, Bit 1: {bits_data.bit1}')
else:
print(f'Device validation failed: {validation_result.description}')
except Exception as e:
print(f"An error occurred during DeviceCheck operation: {e}")