Skip to main content

Signed definitions

For stronger integrity guarantees, Toggly can return signed feature definitions.

When enabled, the SDK:

  • fetches signed definitions from GET https://definitions.toggly.io/definitions-signed/{appKey}/{environment}
  • fetches JWKS from GET https://definitions.toggly.io/.well-known/jwks
  • verifies the signature using ES256 (double SHA-256 over <raw defs json>|<timestamp>, ECDSA P-256)
  • only then applies definitions locally
  • stores signedDefsJson on snapshots for cache re-verification

Enable signed definitions​

TogglyConfig config = TogglyConfig.builder()
.appKey("YOUR_APP_KEY")
.environment("Production")
.useSignedDefinitions(true)
.build();

try (TogglyClient client = new TogglyClient(config)) {
client.refresh(); // Attempt verification before application evaluations.
// Keep the client open for the application's lifetime.
}

Pin accepted key IDs (KIDs) with allowedKeyIds. Empty / null allows all kids:

TogglyConfig config = TogglyConfig.builder()
.appKey("YOUR_APP_KEY")
.environment("Production")
.useSignedDefinitions(true)
.allowedKeyIds(Set.of("ABCDEF...ES256"))
.onError((message, cause) -> {
// surface signature / refresh failures
System.err.println(message);
})
.build();

How verification works (high level)​

  • payload: <raw defs json>|<timestamp>
  • hash: SHA-256 (double)
  • signature: ES256 (ECDSA P-256), IEEE P1363 or DER

Never re-serialize typed feature models to verify — the SDK keeps the exact server defs JSON. See Server-side reliability and Caching.

Spring Boot​

toggly-spring-boot-starter properties currently bind app key, environment, base URL, refresh interval, and defaults — not useSignedDefinitions. Provide a custom TogglyConfig bean when you need signed definitions:

@Configuration
public class TogglySignedConfig {

@Bean
public TogglyConfig togglyConfig() {
return TogglyConfig.builder()
.appKey(System.getenv("TOGGLY_APP_KEY"))
.environment("Production")
.useSignedDefinitions(true)
.allowedKeyIds(Set.of("ABCDEF...ES256"))
.build();
}
}

Use the explicit HTTP provider bean with this config. Spring owns the supplied provider's shutdown. Configure onError to observe failed verification; refresh() returning or refreshAsync() completing only reports completion of the attempt. A failed initial download uses defaults; later failures retain the last good snapshot.