Skip to content

Spring Boot starter

ihawu-spring-boot-starter is the Spring Boot adapter. Add it to the classpath and Ihawu configures itself into your application — no manual ObjectMapper or interceptor wiring. It pulls the ihawu-jackson backend (and ihawu-core) transitively, so it is the only dependency you add.

implementation("org.ihawu:ihawu-spring-boot-starter:0.4.1")
  • Auto-configuration — registers the IhawuModule (from ihawu-jackson, pulled transitively) onto your Jackson ObjectMapper and backs off entirely when ihawu.enabled=false.
  • Identity bridge — maps the authenticated Spring Security Authentication to an IhawuPrincipal per request, so masking has a caller to resolve policies for.
  • Request-scoped caching — resolves each (principal, resource) at most once per request.
  • Static rules from config — bind masking policies straight from ihawu.policies, or supply your own ResourcePolicyProvider / ResourcePolicyResolver bean to override the default.

Every contributed bean is guarded with @ConditionalOnMissingBean, so defining your own wins.

Ihawu checks your masking policies against your resources when the application starts, and fails the context on a policy it cannot honour — surfacing the mistake in development rather than as a silently mis-masked response in production. A policy fails startup when it:

  • REDACTs a non-nullable non-String field (no contract-safe masked value exists),
  • HIDEs a non-nullable field (omitting it breaks the schema), or
  • targets a field the resource does not have (it would mask nothing).

The error names the offending resource.field. Two properties tune the check:

  • ihawu.validate-resource-contract (default true) — set false to skip the check and rely on the runtime fail-closed behaviour instead.
  • ihawu.resource-base-packages — packages to scan for @IhawuResource types, if they live outside your application’s auto-configuration packages.

Only statically-known policies (from ihawu.policies or a ResourcePolicyProvider) are checked; a fully dynamic ResourcePolicyResolver is validated at request time by the fail-closed backstop.

A fail-closed {} (HTTP 200) is ambiguous — fully masked for this caller or policy resolution failed — so a policy-store outage can go unnoticed. Two opt-in knobs make it visible (requires 0.4.1+):

Failure metrics. With Micrometer on the classpath and a MeterRegistry bean present (e.g. Spring Boot Actuator), the starter counts every fail-closed drop as ihawu.masking.failures{resource,reason} — never the protected value. Alert on reason=RESOLVER_ERROR. Logging still happens either way; define your own MaskingFailureSink bean to replace both.

Fail the request instead of masking. By default a resolver outage masks to {} behind a 200. Set:

ihawu:
on-policy-failure: fail-request

and it surfaces as a 5xx instead, so the outage is not silent (only the resolver-error path — a missing principal still masks fail-closed). Best-effort: a resource nested past the point the response is already committed can’t become a clean 5xx.

Getting Started adds the starter to an app and masks a field end to end. For a working reference, the runnable sample shows it against a live endpoint with three roles and a test that pins each role’s masked JSON.

Full API on the Dokka reference for ihawu-spring-boot-starter.