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-hoplitemodule and register the providedhopliteDecoder(); 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 theRobotoentry point. - If you used WARDEN: use Warden makoto (
at.asitplus.warden:makoto) and theMakotoentry 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→MakotoAndroidAttestationChecker→Roboto.
Robotois now the primary Android verifier. It can validate hardware and/or software attestations depending on configuration (disableHardwareAttestation,enableSoftwareAttestation).- Legacy
HardwareAttestationVerifier/SoftwareAttestationVerifierremain as deprecated compatibility factories that return aRobotoinstance.
- Legacy
- 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) orverifyBlocking(...)(blocking) and optioanlly chain it withgetOrThrow(). The legacyverifyAttestation(...)API (returningParsedAttestationRecord) 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!!!
- use
- The parameters
iosAttestationConfigurationJandandroidAttestationConfigurationJinMakoto'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.
AttestationResultgains aVerifiedmarker; NOOP results are distinct.AttestationResult.Erroralways carries acause.AttestationValueException.Reason.TIMEis renamed toSTATEMENT_TIME.- Non-configured platforms return
AttestationResult.Errorwith a configuration cause. See Error Handling. - Roboto verification now returns the verified certificate chain (
List<X509Certificate>) wrapped inKmmResult. Downstream code should parse the extension from the resulting chain viaandroidAttestationExtension(preferred).- Be sure to deal with the result. This function does not throw!!!
ParsedAttestationRecordis considered legacy: it is still accessible via deprecated helpers (e.g.AttestationResult.Android.attestationRecord), but new code should useAttestationResult.Android.attestationExtension/androidAttestationExtension.- The
supremeParserflag 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
attestationStatementValiditySecondsmodel 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
attestationStatementValiditySecondsif you relied on the old behavior. - Android leaf certificate validity is ignored by default; Android's
attestationStatementValiditySecondsdefaults tonull(no statement time check). If configured, Android attestation creation time is verified. - Roboto’s Kotlin APIs use
kotlin.time.Instantas the verification time; Java-friendly overloads acceptjava.util.Dateand Java'sInstant. - 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 intohardwareTrustedRoots/softwareTrustedRoots. See Externalising Configuration and Android technical notes. - Per‑app trust anchor overrides moved to
AppData.trustedRootOverrides. signatureDigestsis nowsignerFingerprints.attestationStatementValiditySecondsusesLongand can benull.
- Trust anchors are now
- iOS:
- iOS versions now require both SemVer and build number (
OsVersions). See Externalising Configuration and iOS technical notes. - Per‑app trust anchor overrides use
TrustedRootPair.
- iOS versions now require both SemVer and build number (
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.