# Class AppShield

java.lang.Object
com.codename1.security.shield.AppShield

public final class AppShield extends Object

API shielding: proves to your own backend that a request came from a genuine, unmodified build of your app running on a device that has not been tampered with.

##### How it differs from `DeviceIntegrity`

`DeviceIntegrity` is the raw platform primitive -- it hands you a Play Integrity or App Attest blob and leaves verification, policy and enforcement to you. `AppShield` is the managed layer on top: the attestation is verified server side against Apple and Google, evaluated against a policy you control, and turned into a short-lived signed token your backend can check with a few lines of middleware. Both remain available and `DeviceIntegrity` keeps working unchanged; an app that only needs the raw blob should keep using it.

##### The shape of the thing

    AppShield.init(new ShieldConfig()
        .protect("api.mybank.example", HostPolicy.PROTECTED));

    // ...then just make requests. Protected hosts get the header and the pin check.
    ConnectionRequest r = new ConnectionRequest("https://api.mybank.example/transfer", true);
    NetworkManager.getInstance().addToQueueAndWait(r);

Your backend rejects any request whose token is missing, expired or unsigned. That check is where the security actually lives -- not in this class. A device the attacker fully controls can always strip a header; what it cannot do is mint a token, because the token is signed by a service the attacker does not control, on the strength of a statement from Apple or Google.

##### When the engine is absent

Builds without the enterprise attestation engine -- open-source builds, and any project not entitled to it -- get a working, inert implementation. `isProtected()` returns false, `fetchToken()` completes with `ShieldStatus.UNPROTECTED` rather than hanging, `attach(ConnectionRequest)` does nothing, and no request is ever blocked. The API is safe to call unconditionally; there is no need to guard call sites.

##### Threading

`fetchToken()` is asynchronous. `attach(ConnectionRequest)` blocks and must not be called on the EDT -- in normal use you never call it yourself, because a protected host is handled automatically on the network thread.

- ## Field Summary

  Fields
  Modifier and Type
  Field
  Description
  `static final String`
  `REJECT_HEADER`
  Response header a backend sets to say it rejected the attestation token, as opposed to the user's own credentials.

- ## Method Summary

  Modifier and Type
  Method
  Description
  `static void`
  `addListener(ShieldListener l)`
  Registers a listener for status and signal changes.
  `static void`
  `addProtectedHost(String host)`
  Registers a host with the default policy, honouring `ShieldConfig.defaultFailureMode(FailureMode)`.
  `static void`
  `addProtectedHost(String host, HostPolicy policy)`
  Registers a protected host after `init(ShieldConfig)`, for a backend discovered at runtime.
  `static void`
  `attach(ConnectionRequest request)`
  Attaches the attestation header to a request.
  `static AsyncResource<ShieldToken>`
  `fetchToken()`
  Fetches a time-limited token, reusing the cached one when it is still good.
  `static AsyncResource<ShieldToken>`
  `fetchToken(String bindingData)`
  Fetches a token bound to specific request data.
  `static ShieldToken`
  `getCachedToken()`
  The cached token without triggering a fetch.
  `static ShieldConfig`
  `getConfig()`
  The configuration passed to `init(ShieldConfig)`, or defaults if it has not been called.
  `static String`
  `getEngineName()`
  The active engine's name, for diagnostics and support logs.
  `static NetworkGuard`
  `getNetworkGuard()`
  The shield's own `NetworkGuard`, for an app that has to install a guard of its own.
  `static PinSet`
  `getPinSet()`
  The pin set currently in force.
  `static ShieldSignal[]`
  `getSignals()`
  The runtime self-protection observations recorded so far, combining what the engine detected with anything the app or a library reported to `ShieldSignals`.
  `static ShieldStatus`
  `getStatus()`
  The most recent token status.
  `static Hashtable`
  `headersFor(String url)`
  The headers a protected URL should carry, for network paths that do not go through `ConnectionRequest` -- notably `BrowserComponent.setURL(url, headers)`.
  `static void`
  `init(ShieldConfig cfg)`
  Initializes the shield.
  `static void`
  `invalidateToken()`
  Discards any cached token.
  `static boolean`
  `isProtected()`
  True when a real attestation engine is present and available.
  `static HostPolicy`
  `policyFor(String host)`
  The policy in force for a host.
  `static Enumeration`
  `protectedHosts()`
  Every host currently protected: the ones `ShieldConfig` carried into `init(ShieldConfig)`, plus anything registered since through `addProtectedHost(String, HostPolicy)`.
  `static void`
  `removeListener(ShieldListener l)`

  ### Methods inherited from class Object

  `clone, equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- ## Field Details

  - ### REJECT_HEADER

    public static final String REJECT_HEADER

    Response header a backend sets to say it rejected the attestation token, as opposed to the user's own credentials.

    Without it a 401 or 403 is ambiguous: protected APIs normally carry ordinary user authorization too, and treating every such response as an attestation rejection would make a client re-attest through an entire login failure. Emit it only when the token itself was the problem; the value is ignored.

    See Also:
      - Constant Field Values

- ## Method Details

  - ### init

    public static void init(ShieldConfig cfg)

    Initializes the shield. Call once during app startup, after `Display.init`.

    Safe to call in a build with no attestation engine: it logs one line and leaves the shield inert. Calling it twice is a no-op.

  - ### getNetworkGuard

    public static NetworkGuard getNetworkGuard()

    The shield's own `NetworkGuard`, for an app that has to install a guard of its own.

    `NetworkManager` holds a single guard and seals the slot on first install, so an app with its own guard leaves no room for the shield's. Delegating to this one is the supported way to have both. Delegate every method, not only `NetworkGuard.beforeRequest(ConnectionRequest)`: attaching the token is the visible half of the shield, and the certificate callbacks are the half that enforces `HostPolicy.isEnforcePins()`. An app that forwards only `beforeRequest` gets tokens and no pinning, and nothing about its behaviour says so.

        final NetworkGuard shield = AppShield.getNetworkGuard();
        NetworkManager.setNetworkGuard(new NetworkGuard() {
            public void beforeRequest(ConnectionRequest r) throws IOException {
                myOwnHeaders(r);
                shield.beforeRequest(r);
            }
            public boolean isCertificateCheckRequired(String url) {
                return myOwnCheckNeeded(url) || shield.isCertificateCheckRequired(url);
            }
            public void checkCertificates(ConnectionRequest r,
                    ConnectionRequest.SSLCertificate[] c) throws IOException {
                myOwnCheck(r, c);
                shield.checkCertificates(r, c);
            }
            public String[] interestingResponseHeaders() {
                return concat(myOwnHeaderNames(), shield.interestingResponseHeaders());
            }
            public void afterResponse(ConnectionRequest r, int code, String[] headers) {
                shield.afterResponse(r, code, headers);
            }
        });
        AppShield.init(cfg);

    Note that `interestingResponseHeaders()` has to be the union of both guards' names, and that the `headers` array handed to `afterResponse` is positional against it -- so a composing guard must pass the shield the slice that corresponds to the shield's own names, in that order. Installing the shield's guard directly, by calling `init(ShieldConfig)` before installing anything of your own, avoids the bookkeeping entirely and is what most apps should do.

    Safe to call before `init(ShieldConfig)`; the returned guard reads the configuration live rather than capturing it.

  - ### isProtected

    public static boolean isProtected()
    True when a real attestation engine is present and available. False in an open-source or unentitled build, and in the simulator unless simulation is switched on.

  - ### getEngineName

    public static String getEngineName()
    The active engine's name, for diagnostics and support logs.

  - ### getConfig

    public static ShieldConfig getConfig()
    The configuration passed to `init(ShieldConfig)`, or defaults if it has not been called.

  - ### fetchToken

    public static AsyncResource<ShieldToken> fetchToken()
    Fetches a time-limited token, reusing the cached one when it is still good.

  - ### fetchToken

    public static AsyncResource<ShieldToken> fetchToken(String bindingData)

    Fetches a token bound to specific request data.

    Binding ties the token to one request, so a token lifted off a captured request cannot be replayed against a different one. Worth the extra round trip on the calls that matter -- a transfer, a password change -- and not worth it on the rest, which should use the plain `fetchToken()`.

    Parameters:
      `bindingData` - the data to bind to, typically a digest of the request body

  - ### invalidateToken

    public static void invalidateToken()
    Discards any cached token. Call this when your backend rejects a token, so the next request re-attests rather than replaying the token that was just refused.

  - ### attach

    public static void attach(ConnectionRequest request) throws ShieldException

    Attaches the attestation header to a request.

    Blocks while a token is fetched, so it must be called on a network thread. Requests to hosts registered via `ShieldConfig.protect(String, HostPolicy)` are handled automatically and do not need this; use it for a request built outside the normal path.

    Honours the host's `FailureMode`: under `FailureMode.OPEN` a token failure leaves the request untouched, under `FailureMode.CLOSED` it propagates.

    Throws:
      `ShieldException`

  - ### headersFor

    public static Hashtable headersFor(String url)

    The headers a protected URL should carry, for network paths that do not go through `ConnectionRequest` -- notably `BrowserComponent.setURL(url, headers)`.

    Returns an empty table when the host is unprotected or no token is available. Never blocks: it uses the cached token only, because the callers are typically on the EDT.

    Note this covers only the initial navigation. Requests the loaded page makes itself are not visible to the framework and cannot be given a token or pinned.

  - ### getCachedToken

    public static ShieldToken getCachedToken()
    The cached token without triggering a fetch. May be null or lapsed. Never blocks.

  - ### addProtectedHost

    public static void addProtectedHost(String host, HostPolicy policy)

    Registers a protected host after `init(ShieldConfig)`, for a backend discovered at runtime.

    Takes the same patterns as `ShieldConfig.protect(String, HostPolicy)` -- an exact host or a leading `*.` wildcard covering its subdomains -- and resolves them the same way, most specific first. A registration made here wins over a configured one for the same pattern, being the later statement of intent, but does not override a more specific configured host.

  - ### addProtectedHost

    public static void addProtectedHost(String host)
    Registers a host with the default policy, honouring `ShieldConfig.defaultFailureMode(FailureMode)`.

  - ### protectedHosts

    public static Enumeration protectedHosts()

    Every host currently protected: the ones `ShieldConfig` carried into `init(ShieldConfig)`, plus anything registered since through `addProtectedHost(String, HostPolicy)`.

    The config alone is not the answer to "what is protected", and treating it as such is a quiet way to lose the runtime registrations. An engine building a pin set from the config would leave a backend discovered at runtime with no pins, so `PinSet.isEnforcedFor(String)` returns false for it and the certificate check is skipped entirely -- the host the app went out of its way to register is the one host not pinned.

  - ### policyFor

    public static HostPolicy policyFor(String host)
    The policy in force for a host. Returns `HostPolicy.UNPROTECTED` for anything not registered, which is the great majority of hosts an app talks to.

  - ### getPinSet

    public static PinSet getPinSet()
    The pin set currently in force. Never null; may be `PinSet.EMPTY`.

  - ### getSignals

    public static ShieldSignal[] getSignals()

    The runtime self-protection observations recorded so far, combining what the engine detected with anything the app or a library reported to `ShieldSignals`.

    Informational. The attestation service applies the policy, and it may reach a different conclusion than a naive reading of this array -- an emulator signal, for instance, is normal on a developer's machine.

  - ### getStatus

    public static ShieldStatus getStatus()
    The most recent token status. `ShieldStatus.NOT_INITIALIZED` before `init(ShieldConfig)`.

  - ### addListener

    public static void addListener(ShieldListener l)
    Registers a listener for status and signal changes. Callbacks arrive on the EDT.

  - ### removeListener

    public static void removeListener(ShieldListener l)