Setting up apps and the policy
For the console admin, often the mobile lead. At the end of this page, your apps are registered with Apple and Google, a monitor-mode policy is published on the project’s Attestation page, and the verifier’s domain is registered for pinning.
Before you start
- A TrustPin project with pinning set up. See Project setup.
- The project signs with a cloud key (you need its master password) or with your own key (BYOK, you need the PEM file). Projects signed with FIDO can’t use app attestation in this release.
- Access to the Apple Developer portal for your Apple apps, and to Play Console and Google Cloud for Android apps that use Play Integrity.
Apple apps
Repeat for each app.
- In the Apple Developer portal, enable App Attest on the app’s App ID.
- In Xcode, add the App Attest capability. It adds the entitlement
com.apple.developer.devicecheck.appattest-environment:developmentfor builds run from Xcode,productionfor TestFlight and the App Store. - Note the app’s Team ID and Bundle ID. On the console form you can drop the app’s
Info.plistor a.mobileprovisionfile to fill them in. - Decide on Accept development builds. Builds run from Xcode attest in the development environment and are refused with
dev_environmentunless it is on. Leave it on while developing and turn it off for production.
On macOS, check which environment a build attests in: the token’s tp.env says production or development.
Android apps
Repeat for each app.
-
Package name, for example
com.example.app. -
Signing certificate SHA-256 for every certificate that signs a build you accept:
- the debug key, for builds run from Android Studio;
- the upload key, if you install builds signed with it;
- the Play app signing key, for installs from Google Play (Play Console, Test and release, App integrity).
keytoolprints the digest of a keystore entry:keytool -list -v -keystore <keystore> -alias <alias> | grep 'SHA256:'Paste the
SHA256:value into the console as printed, or drop a certificate file (.pem,.der,.crt,.cer) onto the form. -
Evidence: what a device must provide.
Console option Device must provide Fails on Either (the default) Every evidence it can: Key Attestation, plus Play Integrity when the app has a Google Cloud project number. Passes when at least one passes the policy Devices without hardware-backed attestation when the app has no project number, and devices that can provide neither Both Key Attestation and Play Integrity Devices missing either Play Integrity only Play Integrity Devices without Google Play, and apps without a project number Key Attestation only Key Attestation Devices without hardware-backed attestation, and emulators Key Attestation only needs no Google setup and is the simplest start. Under Either, an app configured with a project number spends one Play Integrity request on every attestation, not only as a fallback, so plan your Play Integrity quota for it.
-
Play Integrity, only with Either, Both or Play Integrity only:
- Enable the Play Integrity API in a Google Cloud project.
- Link that project to the app in Play Console (Test and release, App integrity, Play Integrity API).
- Turn on, in Play Console, any optional verdict the policy uses: app access risk, Play Protect, recent device activity.
- Create a service account for the verifier. Its JSON key goes into the verifier’s
TRUSTPIN_PLAY_INTEGRITY_CREDENTIALS; see Deploying the verifier. - Enter the Cloud project number in the policy’s Google Cloud project number (a dropped
google-services.jsonfills it in) and in the app; see Android.
Configure the project number in the app only when the policy uses Play Integrity: with a number configured, the app contacts Google Play services from setup on, which belongs in its Data safety declaration. Builds not installed from Google Play aren’t recognized by it, so keep Require an app recognized by Google Play off while you test them.
-
Key Attestation settings:
- Minimum security level:
TRUSTED_ENVIRONMENTorSTRONG_BOX. Software keys are never accepted. - Require verified boot and Require a locked bootloader: on for consumer production. With Require verified boot off, devices running a custom operating system with a relocked bootloader, such as GrapheneOS, are accepted; the bootloader must still be locked. In release builds, the pinning SDK refuses emulators and non-OEM operating system images unless the app’s manifest sets
cloud.trustpin.android.allowNonOemImages. - Minimum OS patch level (YYYYMM, optional).
- Minimum security level:
The console offers presets for these settings: Production and Production and development for Apple, and Recommended, Strict and Without Google Play for Android. A preset changes the settings only, never the apps you added.
Creating and publishing the policy
-
Open the project’s Attestation page. Before setup it shows Set up app attestation; choose Set up.
-
Add the apps under Attest Apple apps and Attest Android apps, with the settings above.
-
Set the rest of the policy:
Setting Start with Notes Mode Monitor (recommended to start) Tokens are issued even when checks fail, so you can measure before enforcing. See Rolling out Access token lifetime 1 h (default) Presets 15 min, 1 h, 6 h and 1 day Key certificate lifetime 30 days (default) Presets 1, 7, 30 and 90 days. It sets how often a device attests again Require token binding Off until your API checks bindWith it on, an app gets no token until it has a binding. See Verifying tokens in your API Allow debug tokens On for staging only Lets simulators and emulators attest with a debug token -
Finish the wizard with Create the policy, then choose Sign and publish. Cloud-key projects ask for the master password; BYOK projects sign with your key and the button reads Publish. The dialog lists what the new version makes stricter, and asks you to confirm before publishing.
Each publish raises the policy version. Running verifiers pick up the new version within their refresh interval (5 minutes by default), with no redeploy. An amber dot on the Policy tab marks changes not published yet.
Check: the Policy tab shows the version as published.
Registering the verifier’s domain
The SDKs pin their calls to the verifier, and in strict mode they refuse a host that isn’t registered. Add the verifier’s host, for example attest.example.com, as a domain of the same TrustPin project, as for any domain your app calls. See Add a domain, and sign and publish the pin configuration.
Check: the domain is listed in the project, and the published pin configuration includes it.
The other tabs
| Tab | Use |
|---|---|
| Deployment | Name each environment, give its verifier URL, and download the verifier bundle. See Deploying the verifier |
| Go-live guide | The Go-live checklist your organization shares, step-by-step snippets, and debug tokens |
| Status | Live policy, Verifier fleet and Verifier checks. The danger zone, for admins and owners, can disable or re-enable attestation, or abandon a setup that was never published |
Changing the policy with the CLI
Setting up attestation and its first publish happen in the console. After that, the TrustPin CLI can export, change, sign and publish the policy, for example from CI:
| Step | Console | CLI |
|---|---|---|
| Read the policy | Policy tab | trustpin-cli projects attestation get <organization id> <project id> --output json |
| Store a change | Edit the Policy tab | trustpin-cli projects attestation update <organization id> <project id> --file attestation.json |
| Sign and publish | Sign and publish | trustpin-cli projects attestation sign <organization id> <project id> (add -k key.pem for BYOK) |
| Rehearse signing | sign --dry-run | |
| Download the verifier bundle | Deployment tab | trustpin-cli projects attestation bundle <organization id> <project id> --format compose|kubernetes|env |
update stores and validates the change as a new, unpublished version; only sign changes what verifiers enforce. Running update and sign with an unchanged file does nothing. In the file, each signing digest is the unpadded base64url of the SHA-256, not the colon-separated hex keytool prints. To convert one:
echo '<SHA256 value from keytool>' | tr -d ':' | xxd -r -p | base64 | tr '+/' '-_' | tr -d '='The CLI needs a member’s personal access token: viewers can run get, config and bundle only. Disabling, re-enabling and abandoning stay in the console.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
The app’s attestation fails with app_not_allowed | The Team ID and Bundle ID, or the package name and signing digest, don’t match the build | Compare them with the build that runs, including which key signed it |
Builds run from Xcode fail with dev_environment | Accept development builds is off | Turn it on for development, and publish |
The app reports verifierUnavailable and sends no header | The verifier’s domain isn’t registered in the project | Register the domain |
| The CLI refuses to publish with “The first publish must be done in the TrustPin console.” | The policy was never published | Publish it once from the console |