openfga / spring-boot-starter

A Spring Boot Starter for OpenFGA
Apache License 2.0
28 stars 6 forks source link

feature: support contextual tuples and context params #43

Open jimmyjames opened 7 months ago

jimmyjames commented 7 months ago

When making an FGA check, contextual tuples and/or a context parameter can be passed for more advanced authorization scenarios.

Contextual tuples

Contextual tuples can be sent in a check request and will be part of the authorization evaluation as if they exist they in the store.

For example, user:123 is a member of the marketing group, and the marketing group has been granted the viewer relationship for document:roadmap.

We can send conditional tuples on the request to inform the groups to which user:123 belongs (e.g., from a groups claim):

var body = new ClientCheckRequest()
      .user("user:123")
      .relation("viewer")
      ._object("document:1")
      .contextualTuples(
          List.of(
              new ClientTupleKey()
                  .user("user:123")
                  .relation("member")
                  ._object("group:marketing"),
              new ClientTupleKey()
                  .user("user:123")
                  .relation("member")
                  ._object("group:everyone")
          ));

var allowed = fga.check(body).get().getAllowed();

Conext with conditions

An authorization model may define a condition, and a context parameter can be supplied to the check request as part of the authorization criteria. For example, a condition could exist that specifies that user:anne has viewer relationship to document:roadmap only if the current time is within 10 minutes of the time access was granted.

Example model:

model
  schema 1.1

type user

type document
  relations
    define viewer: [user with non_expired_grant]

condition non_expired_grant(current_time: timestamp, grant_time: timestamp, grant_duration: duration) {
  current_time < grant_time + grant_duration
}

Write a tuple with a condition:

var body = new ClientWriteRequest()
        .writes(List.of(
                new ClientTupleKey()
                        .user("user:123")
                        .relation("viewer")
                        ._object("document:roadmap")
                        .condition(new ClientRelationshipCondition()
                                .name("non_expired_grant")
                                .context(Map.of("grant_time", "2023-01-01T00:00:00Z","grant_duration", "10m"))
                        )

        ));

var response = fgaClient.write(body, options).get();

Send a check request including the context parameter:

var body = new ClientCheckRequest()
      .user("user:123")
      .relation("viewer")
      ._object("document:1")
      .context(Map.of("current_time", "2023-01-01T00:10:01Z"));

var response = fga.check(body).get();

References