Rolling out: monitor to enforce
For the console admin and the backend developer together. At the end of this page, your API refuses unattested requests on the endpoints you chose, based on measurements rather than guesses, and you know when each policy change reaches devices.
Before you start
- A published policy in Monitor (recommended to start) mode. See Setting up apps and the policy.
- A verifier serving it. See Deploying the verifier.
- An API that verifies the
TrustPin-Attestationheader and logstp.resultandtp.reasons. See Verifying tokens in your API. - An app release with the SDK’s attestation module, in your users’ hands.
1. Monitor
In monitor mode the verifier issues a token even when a policy check fails, recording tp.result fail and the reasons in tp.reasons. Your API logs the result and allows every request.
Two outcomes are refused in both modes: an app the policy doesn’t list gets 403 app_not_allowed, and forged evidence never yields a token.
A key certificate whose attestation failed lives one Access token lifetime, so devices that fail are judged again at each refresh, under the policy current at that time.
2. Measure
Measure per endpoint, over a period that covers your release cycle:
- the share of requests without the header. They come from app versions without attestation, devices that can’t attest, attestation failures, and requests that went out while the app was still waiting for a token;
failresults, by reason code intp.reasons, by platform (tp.plat) and by app (tp.app).
3. Adjust the policy
Use the reasons to decide what the policy should accept. For example, dev_environment shows Xcode-run builds, security_level_insufficient or verified_boot_failed show Android devices below the chosen bar, and Play Integrity reasons show which verdicts devices fall short of. Change the settings on the Policy tab, then Sign and publish. The changes reach devices as described in When changes take effect.
4. Enforce
- Turn off Accept development builds and Allow debug tokens, and remove
TRUSTPIN_DEBUG_TOKEN_HASHESfrom production verifiers. - Switch Mode to Enforce, and Sign and publish. From then on, a device whose attestation fails gets no token.
- In the API, refuse requests without a valid token, the most sensitive endpoints first, one at a time.
Tokens issued before the switch keep tp.result fail until they expire, up to one Access token lifetime; the verifier can’t recall them. For an immediate cut-off, the API rejects tp.result == "fail" itself.
If you check tokens at a gateway, the gateway recipes refuse a request without the header, or with any failed check, whatever the policy’s mode. During monitor, check tokens in the API instead, or adapt the recipe to log and let the request through.
5. Keep a fallback
Requests without the header never stop arriving entirely: old app versions, devices that can’t attest, and attestation failures. The SDKs never block a request themselves, so your API decides, per endpoint: refuse sensitive operations, rate-limit harder, or flag the session.
When changes take effect
A new policy version first reaches each verifier within its refresh interval, 5 minutes by default. The table counts from then.
| Change | Takes effect on devices |
|---|---|
| Removing an app or a signing digest, turning off Accept development builds, switching monitor to enforce | At each device’s next token refresh, so within one Access token lifetime. The refresh answers invalid_key_certificate, and the device attests again under the new policy |
| Tightening a device check: security level, verified boot, bootloader, patch level, Play Integrity verdicts | At each device’s next attestation only, so within one Key certificate lifetime (30 days by default) |
| Turning on Require token binding | At the next attestation or refresh: one without a binding is refused with 400 binding_required |
| Access token lifetime or Key certificate lifetime | Tokens and key certificates issued from then on; existing ones keep their expiry |
| Listing an app again, or relaxing a check | At the device’s next attempt. A device the verifier refused waits the time the verifier set, TRUSTPIN_REFUSAL_RETRY_AFTER (10 minutes by default), before trying again |
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| Requests are refused while the policy is in monitor mode | A gateway recipe enforces whatever the mode | Check tokens in the API during monitor, or make the recipe log and pass |
tp.result fail still appears after switching to enforce | Tokens issued before the switch | Wait one Access token lifetime, or reject fail in the API |
| A tightened device check doesn’t show up | Device checks apply at the next attestation | Expect it within one Key certificate lifetime |