Apple DeviceCheck API. Reduce fraudulent use of your services by managing device state and asserting app integrity.
Project description
Apple DeviceCheck
Accessing and Modifying Per-Device Data
Use a token from your app to validate requests, query and modify two per-device binary digits stored on Apple servers.
Features
- Prevent API & Content abuse with validating requests via Apple device token
- Query and modify two bits of data to achieve up to four remote states saved on Apple servers
- Easy to use configuration
- Examples
- Integrations with modern web frameworks
Prepare
Visit https://developer.apple.com/account/resources/authkeys/list and create new Key with DeviceCheck permission
Install
pip install devicecheck
Usage (Python)
Setup
from devicecheck import DeviceCheck
device_check = DeviceCheck(
team_id="XX7AN23E0Z", # https://developer.apple.com/account/#/membership/
bundle_id="com.akentev.app",
key_id="JSAD983ENA", # Generated at https://developer.apple.com/account/resources/authkeys/list
private_key="/path/to/AuthKey_JSAD983ENA.p8",
# Generated file at https://developer.apple.com/account/resources/authkeys/list
dev_environment=True, # True if using development Apple environment, False if using in production.
# Remember to set dev_environment=False in production!
)
Asyncio setup
from devicecheck.asyncio import AsyncioDeviceCheck
The rest will be the same, except for network methods must be await
'ed
Validate device
result = device_check.validate_device_token(device_token)
if result.is_ok:
print('OK! Device is valid')
else:
print('Bad news. Unable to validate device')
Update bits data
# Can use both integers, strings and booleans. Will be converted with bool(value)
result = device_check.update_two_bits(device_token, bit_0=1, bit_1=False)
# Can update bits separately
result = device_check.update_two_bits(device_token, bit_0=True)
if result.is_ok:
print('Bits updated')
else:
print(f'Something went wrong. {result}')
Query bits data
# Can use both integers, strings and booleans
result = device_check.query_two_bits(device_token)
if result.is_ok:
print(f'First bit {result.bit_0}') # True
print(f'Second bit {result.bit_1}') # False
print(f'Last update time {result.bits_last_update_time}') # 2020-04
else:
print(f'Something went wrong. {result}')
Web server decorators
You can easily integrate devicecheck to your webserver using a decorator. Specify a supported framework, or leave None
to try universal parser.
from devicecheck.decorators import validate_device # for sync code
from devicecheck.decorators import DCSupportedFrameworks
from devicecheck import DeviceCheck
device_check = DeviceCheck(...)
# Set response that will be returned on invalid token
INVALID_TOKEN_RESPONSE = ('Invalid device_token', 403)
@app.route('/validate')
@validate_device(device_check, framework=DCSupportedFrameworks.flask, on_invalid_token=INVALID_TOKEN_RESPONSE)
def endpoint():
return 'Content'
Sync code
Use sync decorator
from devicecheck.decorators import validate_device
from devicecheck.decorators import DCSupportedFrameworks
Flask
INVALID_TOKEN_RESPONSE = ('Invalid device_token', 403)
framework = DCSupportedFrameworks.flask
Async code
Use Async decorator
from devicecheck.decorators import async_validate_device
from devicecheck.decorators import DCSupportedAsyncFrameworks
Sanic
from sanic.response import text
INVALID_TOKEN_RESPONSE = text('Invalid device_token', status=403)
framework = DCSupportedAsyncFrameworks.sanic
FastAPI
from fastapi.responses import PlainTextResponse
INVALID_TOKEN_RESPONSE = PlainTextResponse('Invalid device_token', status_code=403)
framework = DCSupportedAsyncFrameworks.fastapi
Tests & Mock
Well, it's kinda hard to automate testing, because Devicecheck requires real device (Simulators won't work). In case you
need to disable decorators, pass SKIP_DEVICE_CHECK_DECORATOR=True
environment variable.
You can also mock validation, pass MOCK_DEVICE_CHECK_DECORATOR_TOKEN=XXXXXXXXXXXXX
, it will be a hardcoded valid token
value.
MOCK_DEVICE_CHECK_DECORATOR_TOKEN="device-check-token" python -m unittest tests/integrational/main.py
For Debug logs, including requests body, pass a DEBUG
environment variable.
Exceptions
Library represents an AppleException
class with attributes status_code
and description
Requires raise_on_error=True
parameter for DeviceCheck
instance.
Usage (Swift)
Generate device token
import DeviceCheck
public func getDeviceToken(completion: @escaping (String?) -> ()) {
if #available(iOS 11.0, *) {
let currentDevice = DCDevice.current
if currentDevice.isSupported
{
currentDevice.generateToken(completionHandler: { (data, error) in
if let tokenData = data {
let tokenString = tokenData.base64EncodedString()
print("Received device token")
completion(tokenString)
} else{
print("Error generating token: \(error!.localizedDescription)")
}
})
} else {
print("Device is not supported") // Simulators or etc.
}
} else {
print("Device OS is lower than iOS 11")
}
}
Pass device token in HTTP request
Header or Body
getDeviceToken { deviceToken in
var request = URLRequest(url: "...")
request.httpMethod = "POST"
// Header
request.setValue(deviceToken, forHTTPHeaderField: "Device-Token")
// Body
request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
let json = ["device_token": deviceToken] as [String : Any]
let jsonData = try! JSONSerialization.data(withJSONObject: json)
request.httpBody = jsonData as Data
// Send it to server
let downloadTask = URLSession.shared.dataTask(with: request, completionHandler: { data, response, error in
...
})
}
License
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file devicecheck-1.3.3.tar.gz
.
File metadata
- Download URL: devicecheck-1.3.3.tar.gz
- Upload date:
- Size: 12.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/5.0.0 CPython/3.12.3
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | d7ade9006b84b47fc865c56c38f8b9600163d746a6bee9ac32c66536d4f1aadf |
|
MD5 | 87fecbfda2c1bbd0c28459b7564402a5 |
|
BLAKE2b-256 | 32e02d6da0d60f32a34dad0f25781b0e9b0ccd195297a3cde092c1629bd93d97 |
File details
Details for the file devicecheck-1.3.3-py3-none-any.whl
.
File metadata
- Download URL: devicecheck-1.3.3-py3-none-any.whl
- Upload date:
- Size: 12.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/5.0.0 CPython/3.12.3
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 682251d7a95e11974b1590637da40ef7c1cca49e304e8588817ffa8f42cd465b |
|
MD5 | 9929cd0248b729fa6cd7014dfa91f8a6 |
|
BLAKE2b-256 | c4dc4bc7f09a0f69b2d39ce88160ec7c17afd7736d6a058a930d582e0c28a8a1 |