Skip to content

Migration from WARDEN / WARDEN‑roboto

The most obvious change coming from WARDEN / WARDEN-roboto is dropped support for Nougat hybrid attestation on Android. It is simply not relevant any more.

Read This First: Footguns

The biggest upgrade hazards are about configuration loading and time checks:

  • Configuration loading should go through canonical config decoding. If you use Hoplite, add the config-hoplite module and register the provided hopliteDecoder(); avoid Spring Boot's direct binding. See Externalising Configuration.
  • Android leaf certificate validity is ignored by default and Android attestation statement validity defaults to null; ensure freshness through your challenge/nonce handling. See raw flow.
  • Verification time offset now defaults to five minutes and is applied to certificate and attestation time checks on both platforms.
  • When migrating to Roboto's new verify() be sure to deal with the result. This function does not throw!!!

If you do not handle freshness explicitly, you can accidentally accept stale attestations.

Warden Supreme enforces unified flows and a unified data model. Migration primarily means:

  • Adopt the unified request/response envelopes and binding semantics described in the Integration Guide.
  • Use the consolidated back‑end configuration (trust anchors, identities, policies).
  • Retain functionality via the integrated modules (Warden makoto / Warden roboto); legacy artefacts exist under new names — see Project Structure.

TL;DR: What do I use now?

  • If you used WARDEN-roboto: use Warden roboto (at.asitplus.warden:roboto) and the Roboto entry point.
  • If you used WARDEN: use Warden makoto (at.asitplus.warden:makoto) and the Makoto entry point.
  • If you want the recommended end-to-end flow (client + verifier + unified wire format): start with the Integration Guide (and its data model).

Cross-references: Project Structure (where the modules live), Usage without Integrated Clients (Makoto/Roboto directly), and Externalising Configuration (canonical config loading).

Changes (Makoto + Roboto APIs)

This section focuses on upgrades that keep using Makoto / Roboto directly, without adopting the integrated model.

Names, Entry Points, and Flow

  • Renames:
    • Warden → Makoto
    • AndroidAttestationChecker → Roboto.
  • Roboto is now the primary Android verifier. It can validate hardware and/or software attestations depending on configuration (disableHardwareAttestation, enableSoftwareAttestation).
    • Legacy HardwareAttestationVerifier / SoftwareAttestationVerifier remain as deprecated compatibility factories that return a Roboto instance.
  • Makoto can be configured for Android‑only or iOS‑only verification; attestations received from non‑configured platforms are treated as configuration errors. See Error Handling.
  • Roboto exposes a KmmResult-based verification API:
    • use verify(...) (suspending) or verifyBlocking(...) (blocking) and optioanlly chain it with getOrThrow(). The legacy verifyAttestation(...) API (returning ParsedAttestationRecord) is deprecated.
    • On success the result will contain the full certificate chain, on failure, it will contain an AndroidAttestationException.
    • Be sure to deal with the result. This function does not throw!!!
  • The parameters iosAttestationConfigurationJ and androidAttestationConfigurationJ in Makoto's Java-oriented constructor have been swapped to disambiguate it from the Kotlin constructors.

Results and Exceptions

Try the custom parser

To enable the custom Android attestation extension parser, set supremeParser = true in your configuration and run your usual Roboto/Makoto verification flow.

  • AttestationResult gains a Verified marker; NOOP results are distinct.
  • AttestationResult.Error always carries a cause.
  • AttestationValueException.Reason.TIME is renamed to STATEMENT_TIME.
  • Non-configured platforms return AttestationResult.Error with a configuration cause. See Error Handling.
  • Roboto verification now returns the verified certificate chain (List<X509Certificate>) wrapped in KmmResult. Downstream code should parse the extension from the resulting chain via androidAttestationExtension (preferred).
    • Be sure to deal with the result. This function does not throw!!!
  • ParsedAttestationRecord is considered legacy: it is still accessible via deprecated helpers (e.g. AttestationResult.Android.attestationRecord), but new code should use AttestationResult.Android.attestationExtension / androidAttestationExtension.
  • The supremeParser flag selects which verification engine/parser is used internally; it no longer changes the public return type.

Time Handling and Validity

  • Verification time offset defaults to five minutes and is applied to certificate and attestation time checks.
  • iOS attestation validity now uses the same attestationStatementValiditySeconds model as Android and rejects future‑dated statements.
  • iOS verification time offset is no longer auto‑compensated, but the new defaults take this into account; increase attestationStatementValiditySeconds if you relied on the old behavior.
  • Android leaf certificate validity is ignored by default; Android's attestationStatementValiditySeconds defaults to null (no statement time check). If configured, Android attestation creation time is verified.
  • Roboto’s Kotlin APIs use kotlin.time.Instant as the verification time; Java-friendly overloads accept java.util.Date and Java's Instant.
  • Patch level checks reject patch levels too far in the future (default leeway: one month).

Revocation, Trust Anchors, and RKP

  • Revocation checks are configurable and chainable (HTTP/file/in‑memory loaders) and return richer details.
  • Revocation errors are classified under certificate trust errors rather than content errors and include the revocation list entry.
  • Per‑app trust anchor overrides change the order of checks so app metadata is validated before certificate chain validation. See Android technical notes.
  • Remote Key Provisioning checks are supported and can be required; failure yields a dedicated value error. See Android technical notes.

See also the data model, Error Handling, and the authoritative configuration example in the Warden Supreme integration guide.

Externalising Configuration

List of Configuration Properties

See Externalising Configuration for an up-to-date list of all configuration properties.

Migrating code from WARDEN / WARDEN-roboto is rather smooth because the compiler and the IDE will scream at you if you don't adapt to the changes. Far more tricky is correct migration of externalised configuration.

Warden Supreme 1.0 introduces canonical serialised representations of Android- and iOS-specific attestation configurations. Previously, Spring Boot and Hoplite could be used to load configurations directly. However, the introduced flexibility of Warden Supreme with respect to Android revocation checks, in particular, means that verifying and sanity-checking externalised configuration is only possible through code paths that are part of Warden Supreme. Hence, loading configurations must only be done through one of the following functions (or via Hoplite with the decoder from config-hoplite, or via the experimental config-spring module):

  • fromJsonString()
  • fromYamlString()
  • fromJsonObject()
  • fromJsonFile(...) / fromYamlFile(...) (JVM convenience helpers)

As a consequence, any Spring Boot configurations should contain a string pointing to Warden Supreme configurations, with those configuration files being read and their contents being fed into fromYamlString(). Alternatively, Spring Boot users can use the experimental config-spring module to map an Environment into the same fromJsonObject() path, which avoids direct binding while still allowing native Spring configuration sources. For Hoplite, register hopliteDecoder() (from the config-hoplite module) and load from your chosen sources, which will delegate into fromJsonObject().

Configuration Differences

Aside from changes to config loading, the actual configuration parameters and some defaults have changed between the last stable WARDEN / WARDEN-roboto releases and Warden Supreme 1.0.0.

  • Android:
    • Trust anchors are now TrustedRoots and are split into hardwareTrustedRoots / softwareTrustedRoots. See Externalising Configuration and Android technical notes.
    • Per‑app trust anchor overrides moved to AppData.trustedRootOverrides.
    • signatureDigests is now signerFingerprints.
    • attestationStatementValiditySeconds uses Long and can be null.
  • iOS:

Need more migration depth?

If you require a step‑by‑step migration playbook or have edge cases not covered here, please file an issue or upvote an existing one in the tracker so we can prioritise expanding this guide.

If you need personalised support, see our  đź’Ž Services.