Cedar policy engine for Java via WebAssembly.
Evaluates Cedar authorization policies in pure Java by compiling the Cedar Rust crate to Wasm and running it through Endive. No JNI, no native binaries — runs everywhere the JVM runs.
<dependency>
<groupId>io.roastedroot</groupId>
<artifactId>cedar4j</artifactId>
<version>${cedar4j.version}</version>
</dependency>CedarEngine engine = CedarEngine.create();
AuthorizationRequest request = AuthorizationRequest.builder()
.principal("User", "alice")
.action("Action", "view")
.resource("Document", "doc1")
.build();
PolicySet policies = PolicySet.of(
Policy.of("permit(principal, action, resource);", "allow-all"));
AuthorizationResponse response = engine.isAuthorized(
request, policies, Collections.emptySet());
response.isAllowed(); // true
response.decision(); // Decision.ALLOW
response.reasons(); // ["allow-all"]EntityUID alice = EntityUID.of("User", "alice");
EntityUID admins = EntityUID.of("Group", "admins");
Set<Entity> entities = Set.of(
Entity.of(alice, Set.of(admins)),
Entity.of(admins));
Map<String, Object> context = Map.of("authenticated", true);
AuthorizationRequest request = AuthorizationRequest.builder()
.principal(alice)
.action("Action", "delete")
.resource("Document", "doc1")
.context(context)
.build();
PolicySet policies = PolicySet.of(Policy.of(
"permit(principal, action, resource) when { principal in Group::\"admins\" };",
"admin-access"));
AuthorizationResponse response = engine.isAuthorized(request, policies, entities);Schema schema = Schema.fromCedar(
"entity User;\n"
+ "entity Photo;\n"
+ "action viewPhoto appliesTo { principal: [User], resource: [Photo] };");
ValidationRequest request = ValidationRequest.builder()
.schema(schema)
.policies(policies)
.build();
ValidationResponse response = engine.validate(request);
response.isValid(); // true if no validation errors
response.validationErrors(); // list of ValidationErrorPre-parse policies for repeated evaluations:
engine.cachePolicySet("my-policies", policies);
AuthorizationResponse response = engine.isAuthorizedCached(
request, "my-policies", entities);Schemas can be pre-parsed the same way. On the cached path the schema must be
referenced by id — an inline request.schema() is rejected, because the
underlying call only accepts a pre-parsed schema name:
engine.cacheSchema("my-schema", schema);
AuthorizationResponse response = engine.isAuthorizedCached(
request, "my-policies", "my-schema", entities);The cache lives inside the Wasm instance, so it is scoped to a single
CedarEngine. To share it across a pool, cache on the pool rather than on a
borrowed engine — see below.
Evaluate with unknown principal, action, or resource:
PartialAuthorizationRequest partial = PartialAuthorizationRequest.builder()
.action("Action", "view")
.resource("Document", "doc1")
.build();
PartialAuthorizationResponse response = engine.isAuthorizedPartial(
partial, policies, entities);
response.decision(); // ALLOW or DENY
response.nontrivialResiduals(); // policies that couldn't be fully evaluatedWasm instances are not thread-safe. Use CedarEnginePool for concurrent access:
CedarEnginePool pool = CedarEnginePool.create(4);
try (CedarEnginePool.Loan loan = pool.borrow()) {
AuthorizationResponse response = loan.engine().isAuthorized(
request, policies, entities);
}Cache on the pool, not on a borrowed engine — each engine has its own Wasm instance and therefore its own cache. The pool replays cached entries onto every engine it hands out, including ones it creates later:
pool.cachePolicySet("my-policies", policies);
pool.cacheSchema("my-schema", schema);
try (CedarEnginePool.Loan loan = pool.borrow()) {
AuthorizationResponse response = loan.engine().isAuthorizedCached(
request, "my-policies", "my-schema", entities);
}CedarEngine engine = CedarEngine.builder()
.withObjectMapper(myCustomMapper)
.build();A low-level string-based API is available for advanced use cases via engine.raw():
String result = engine.raw().authorize(requestJson);
String parsed = engine.raw().parsePolicy(policyText);
String formatted = engine.raw().formatPolicies(policiesText);See CedarRawEngine for the full list of raw methods.
mvn clean verifyTo rebuild the Wasm binary (requires Rust):
cd wasm-build
make allApache-2.0