Test possession, not a label
A random device identifier stored in app preferences can identify an installation, but it does not prove the device holds a secret. Test enrollment by challenging a key kept in the platform key store. Copying app storage to another phone should leave that proof behind. During replacement, record which old device remains active, what the customer sees, and what happens to pending transfers. Repeat after a backup restore and after the customer reports the phone lost.
Test cases and proof
| Case | Expected result | Proof to keep |
|---|---|---|
| Copied device identifier on phone B | Do not treat as bound device | Enrollment result |
| Phone A is marked lost | Stop its privileged sessions | Session trace |
| Phone B replaces A | Require recorded approval and notice | Enrollment audit |
Synthetic example
The app labels a device as trusted using a local ID. Copy that ID to a second test phone. If the second phone inherits trusted status, replace the ID-only check with proof from a device-held key and review replacement approvals.
Evidence to keep
Keep the public key ID, device label, enrollment time, and proof result separate in the test record. Never copy a production private key for a test. A failed enrollment on a copied app should include the server reason and whether the old phone stayed trusted. Check customer notices and support records after a replacement, since device control affects account recovery.
Try both a fresh install and a restored install on the replacement phone. A fresh install tests enrollment; restore tests whether old local state wrongly carries trust. Record whether pending transfers on the old phone remain valid. Device replacement should have one clear result for every active session.
Decide what replacement does to the old phone
A customer can lose a phone, replace it, then find it again. The product needs a clear rule for old sessions and pending payments. When B replaces A, record whether A can still read balance, approve a transfer, or refresh a session. A device-held key protects the binding, but support can undo it through a reset; test that path too. Keep a customer notice with the time and device label so an unknown enrollment can be reported.
Related reading
Why these checks matter
NIST describes authenticator binding and recovery as separate parts of account life. Android Keystore controls key use and can protect keys in hardware when the device and key support it. Together they support the test distinction between a device label, which can be copied, and proof from a key held on the enrolled phone.
Check the key’s actual protection level
Android Keystore does not mean every key is backed by secure hardware. Check the key’s security level on the test device. On API 29 and later, KeyInfo.getSecurityLevel can distinguish software, trusted environment, and StrongBox levels. Record the level and the fallback rule when hardware support is absent. Do not describe a software-backed fallback as hardware binding.
If the server relies on Android attestation, validate its certificate chain, fresh server challenge, permitted application identity, and security claims on the server. Reading an attestation boolean supplied by the app is not validation. Test one accepted device and one unsupported or rejected device under the policy. Local key protection and server enrollment are separate gates.
Bind proof to a fresh action
Synthetic enrollment gives device D1 a random single-use challenge CH-11 bound to account A and an expiry. D1 signs it with its enrolled key. Replay the signature on D2, against account B, after expiry, and for CH-12. Each should fail. For transfer proof, bind the challenge to the immutable transfer version too; a generic “device present” signature must not approve a different destination.
Copy visible installation files without private keys, then restore the app on D2. Test the expected replacement route; a device-bound design should not inherit trust from labels alone. A synced credential has different intended behavior and must be named as such. Keep public key ID, protection level, challenge result, enrollment actor, and old-device revocation state. Android’s Keystore documentation describes its protection levels.