Skip to content

An extension for connecting to authzed instances from Quarkus applications

License

Notifications You must be signed in to change notification settings

quarkiverse/quarkus-authzed-client

Repository files navigation

Quarkus - Authzed Client

All Contributors

An early draft of quarkus extension for https://github.com/authzed/authzed-java

Usage

To use the client add the following dependency to the pom.xml

<dependency>
    <groupId>io.quarkiverse.authzed</groupId>
    <artifactId>quarkus-authzed-client</artifactId>
</dependency>

Injecting the client

To inject the client into your code:

@Inject
private AuthzedClient client;

Then the client can be used like this:

Uni<ReadSchemaResponse> response = client.v1().schemaService().readSchema(ReadSchemaRequest.newBuilder().build());
//To actually invoke the request you need to subscribe / wait on the Uni:
System.out.println(response.await().indefinitely().getSchemaText());

Note: The request will not be executed until you subscribe or wait on the Uni.

Unifies imperative and reactive

With Quarkus supporting both imperative and reactive styles it made sense to expose both the blocking and the reactive stubs. Given the Quarkus favor Mutiny for reactive programming it made sense to generate everyting from scratch using the quarkus-grpc extension. This means that https://github.com/authzed/authzed-java is not directly used in this project.

If you want to access the blocking aspect of the client instead of using Mutiny you can:

BlockingAuthzedClinet blockingClient = client.blocking();

Both client's have access to exactly the same rpc methods. The following doc will focus on the Mutiny apsect of the client. Worth's mentioning that this client provides a thin layer / dsl on top of what's generated by grpc, so most of the documentaion found on https://docs.authzed.com/ apply here too.

Writing the schema

Provided that the schema is stored in a String variable called schema:

Uni<WriteSchemaResponse> writeSchemaResponse = client.v1()
    .schemaService()
    .writeSchema(WriteSchemaRequest.newBuilder().setSchema(schema).build());

//Wait for the reponse
writeSchemaResponse.await().indefinitely();

An example schma:

definition user {}
definition document {
  relation view: user
  relation write: user
}

Reading the schema

Uni<ReadSchemaResponse> response = client.v1().schemaService().readSchema(ReadSchemaRequest.newBuilder().build());
response.subscribe().with(r -> System.out.println("schema:\n" +r.getSchemaText()));

Creating relationships

Uni<WriteRelationshipsResponse> writeRelationshipRespone = client.v1().permissionService()
    .writeRelationships(WriteRelationshipsRequest.newBuilder()
        .addUpdates(RelationshipUpdate.newBuilder()
            .setOperation(Operation.OPERATION_CREATE)
            .setRelationship(Tuples.parseRelationship("document:cv#view@user:somegal"))
        .build())
    .build());

Checking permissions

Consistency full = Consistency.newBuilder().setFullyConsistent(true).build();
Uni<CheckPermissionResponse> checkPermissionResponse = client.v1().permissionService()
    .checkPermission(CheckPermissionRequest.newBuilder()
        .setConsistency(full)
        .setSubject(Tuples.parseUser("user:somegal"))
        .setResource(Tuples.parseObject("document:cv"))
        .setPermission("view")
        .build());

response.map(r -> r.getPermissionship().getNumber()).subscribe().with(n -> {
    switch (n) {
       case Permissionship.PERMISSIONSHIP_HAS_PERMISSION_VALUE:
           System.out.println("Has permission.");
           break;
       default:
           System.out.println("No permission!");
    }
});

An alternative way to process the response in a less async way is to wait on the Uni:

Permissionship p = checkPermissionResponse().wait().indefinitely().getPermissionship();
p == Permissionship.PERMISSIONSHIP_HAS_PERMISSION 
    ? System.out.println("Has permission.");
    : System.out.println("No permission!");

Note: In this example we used full consistency to avoid getting back cached values. An alternative would be to use zed token as described: https://docs.authzed.com/guides/first-app#checking-permissions

Configuration Reference

See the configuration reference for the full list of supported configuration options.

Compatibility

The table below specifies the Authzed Client version that used for each Quarkus Authzed Client Extension. Note: The table only includes the versions that contained a change in the Authzed Client version.

Quarkus Authzed Client Extension Versions Authzed Client Version
0.0.1 v.12.0
0.1.0 v.15.0

Credits

Heavily influeced by Kevin Wotten's (kdubb) work on https://github.com/quarkiverse/quarkus-openfga-client

Contributors ✨

Thanks goes to these wonderful people (emoji key):

Kevin Wooten
Kevin Wooten

💻 🚧
Ioannis Canellos
Ioannis Canellos

💻 🚧

This project follows the all-contributors specification. Contributions of any kind welcome!