Device Management Use Cases
Eclipse supports device attestation using the Google Play Integrity API, allowing tenants to cryptographically verify that API calls originate from unmodified, trusted devices. This enables detection of rooted devices, tampered APKs, and non-genuine Android installs before processing sensitive operations.
The attestation flow is:
- The mobile app requests a nonce from Eclipse, tied to a device ID.
- The app passes the nonce to the Google Play Integrity API, which returns a signed
integrityVerdicttoken. - The app sends the verdict back to Eclipse to verify.
- Eclipse decrypts and validates the verdict, returning an
isVerifiedflag the tenant app can act on.
Prerequisites
The following global properties must be set (by EFT Corporation) before attestation can be used:
{packageName}.decryption.key=<google-decryption-key>
{packageName}.verification.key=<google-verification-key>
Example:
com.ukheshe.eclipse.payment.service.decryption.key=XXXXX
com.ukheshe.eclipse.payment.service.verification.key=XXXXX
The decryption and verification keys are obtained from the Google Cloud project that owns the app's Play Integrity configuration.
Step 1 — Generate a Nonce
Before calling Google Play Integrity, the app must obtain a one-time nonce from Eclipse. The nonce is tied to the deviceId — a string identifier the app uses to identify itself (typically a stable device identifier or a UUID generated on first install).
GET /eclipse-conductor/rest/v1/global/attestations/{deviceId}
Authorization: Bearer {jwt}Response (200 OK):
{
"nonce": "MDk4MTI2MGE0MzRiMjE1MTVkOWI3MzJmNzZjNjEzYTgzZGNjMGFiM2NlNGZkOGI3MzgzOGNmZGJmZDNlYzA4ZA=="
}Pass this nonce value to the Google Play Integrity API when requesting the integrity verdict.
Each nonce can only be used once. A new nonce must be requested for each attestation.
Step 2 — Verify the Integrity Verdict
After receiving the signed integrityVerdict token from Google Play Integrity, send it to Eclipse for decryption and verification.
POST /eclipse-conductor/rest/v1/global/attestations/{deviceId}
Authorization: Bearer {jwt}
Content-Type: application/json
{
"integrityVerdict": "MDk4MTI2MGE0MzRiMjE1MTVkOWI3MzJmNzZjNjEzYTgzZGNjMGFiM2NlNGZkOGI3MzgzOGNmZGJmZDNlYzA4ZA",
"packageName": "com.example.myapp"
}Verification Responses
Successful verification — nonce matches:
{
"isVerified": true,
"info": "{\"requestDetails\":{\"requestPackageName\":\"com.example.myapp\",\"timestampMillis\":\"1661841706123\",\"nonce\":\"asdlkfjaseroitueoritueoirtueros=\"},\"appIntegrity\":{\"appRecognitionVerdict\":\"UNRECOGNIZED_VERSION\",\"packageName\":\"com.example.myapp\",\"certificateSha256Digest\":[\"2ihgOPNFiCGvHLTIiw6A-JSoK-xAj4YJkP-EDIPcViI\"],\"versionCode\":\"1\"},\"deviceIntegrity\":{\"deviceRecognitionVerdict\":[\"MEETS_DEVICE_INTEGRITY\"]},\"accountDetails\":{\"appLicensingVerdict\":\"LICENSED\"}}"
}When isVerified is true, the info field contains the full decrypted Play Integrity verdict as a JSON string. Key fields to inspect:
| Field | Description |
|---|---|
deviceIntegrity.deviceRecognitionVerdict | MEETS_DEVICE_INTEGRITY = genuine, unmodified device |
appIntegrity.appRecognitionVerdict | PLAY_RECOGNIZED = app signed by Play Store; UNRECOGNIZED_VERSION = sideloaded |
accountDetails.appLicensingVerdict | LICENSED = user obtained the app through Play Store |
Nonce mismatch — verification failed:
{
"isVerified": false,
"info": "{\"errorDescription\":\"There is error in decrypting verdict. Please provide valid play integrity verdict with valid package name.\"}"
}Error (no nonce found for device):
{
"errorDescription": "No nonce found for deviceID: abc123. Please create nonce first."
}This error occurs when Step 1 (nonce generation) was not completed for this deviceId before calling the verify endpoint.
Notes
- The generated nonce is consumed on the first verify call, whether the verification succeeds or fails. A fresh nonce is required for each attestation attempt.
- The
deviceIdin the URL must match between the nonce request and the verify request. - Eclipse does not enforce device integrity automatically — the tenant app receives the
isVerifiedresult and decides whether to block or allow the operation.
