Skip to content

Commit

Permalink
Add more configuration properties (#80)
Browse files Browse the repository at this point in the history
This pull request introduces several changes to the `README.md`
documentation and the Spring Boot auto-configuration for OpenFGA. The
major changes include:
- Extensive updates to the configuration properties.
- Addition of telemetry configuration.
- Improvements to the codebase structure.

## Description

### Documentation updates:
- `README.md`: Reformatted the text for better readability and added a
full example of the configuration in YAML format. Included detailed
descriptions for each configuration property.
- Reformatting and content updates for better readability and
completeness.
- Added a YAML configuration example and detailed property descriptions.

### Spring Boot auto-configuration improvements:
- `OpenFgaAutoConfiguration.java`: Refactored to use `PropertyMapper`
for mapping configuration properties to `ClientConfiguration`. Added
support for new properties such as `userAgent`, `readTimeout`,
`connectTimeout`, `maxRetries`, `minimumRetryDelay`, `defaultHeaders`,
and `telemetryConfiguration`.
  - Improved property mapping using `PropertyMapper`.
  - Added new configuration properties.

- `OpenFgaProperties.java`: Added new configuration properties for user
agent, timeouts, retries, default headers, and telemetry configuration.
  - Added new configuration properties.
  - Updated property handling logic.

### Telemetry configuration:
- `TelemetryAttribute.java`: Added an enum to represent telemetry
attributes.
  - New enum for telemetry attributes.

- `TelemetryMetric.java`: Added an enum to represent telemetry metrics.
  - New enum for telemetry metrics.

### Testing improvements:
- `OpenFgaTest.java`: Removed public modifiers from test methods to
adhere to JUnit 5 conventions.
- Adhered to JUnit 5 conventions by removing public modifiers from test
methods.

## References
- #70

## Review Checklist
- [x] I have clicked on ["allow edits by
maintainers"](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/allowing-changes-to-a-pull-request-branch-created-from-a-fork).
- [x] I have added documentation for new/changed functionality in this
PR or in a PR to [openfga.dev](https://github.com/openfga/openfga.dev)
[Provide a link to any relevant PRs in the references section above]
- [x] The correct base branch is being used, if not `main`
- [x] I have added tests to validate that the change in functionality is
working as expected
  • Loading branch information
jimmyjames authored Jan 2, 2025
2 parents 021acd2 + 792afa2 commit aea68f9
Show file tree
Hide file tree
Showing 17 changed files with 1,217 additions and 271 deletions.
225 changes: 206 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,15 @@ A Spring Boot Starter for OpenFGA.

## About

[OpenFGA](https://openfga.dev) is an open source Fine-Grained Authorization solution inspired by [Google's Zanzibar paper](https://research.google/pubs/pub48190/). It was created by the FGA team at [Auth0](https://auth0.com) based on [Auth0 Fine-Grained Authorization (FGA)](https://fga.dev), available under [a permissive license (Apache-2)](https://github.com/openfga/rfcs/blob/main/LICENSE) and welcomes community contributions.
[OpenFGA](https://openfga.dev) is an open source Fine-Grained Authorization solution inspired
by [Google's Zanzibar paper](https://research.google/pubs/pub48190/). It was created by the FGA team
at [Auth0](https://auth0.com) based on [Auth0 Fine-Grained Authorization (FGA)](https://fga.dev), available
under [a permissive license (Apache-2)](https://github.com/openfga/rfcs/blob/main/LICENSE) and welcomes community
contributions.

OpenFGA is designed to make it easy for application builders to model their permission layer, and to add and integrate fine-grained authorization into their applications. OpenFGA’s design is optimized for reliability and low latency at a high scale.
OpenFGA is designed to make it easy for application builders to model their permission layer, and to add and integrate
fine-grained authorization into their applications. OpenFGA’s design is optimized for reliability and low latency at a
high scale.

## Resources

Expand Down Expand Up @@ -43,6 +49,7 @@ implementation("dev.openfga:openfga-spring-boot-starter:0.0.1")
* Apache Maven

```xml

<dependency>
<groupId>dev.openfga</groupId>
<artifactId>openfga-spring-boot-starter</artifactId>
Expand All @@ -54,12 +61,20 @@ implementation("dev.openfga:openfga-spring-boot-starter:0.0.1")

### Requirements

Java 17 and Spring Boot 3
Java >= 17 and Spring Boot >= 3

### Configuring the starter

The OpenFGA Spring Boot Starter can be configured via standard [Spring configuration](https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.external-config).
The configuration properties are used to create an [OpenFgaClient](https://github.com/openfga/java-sdk/blob/main/src/main/java/dev/openfga/sdk/api/client/OpenFgaClient.java) instance.
The OpenFGA Spring Boot Starter can be configured via
standard [Spring configuration](https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.external-config).
The configuration properties are used to create
an [OpenFgaClient](https://github.com/openfga/java-sdk/blob/main/src/main/java/dev/openfga/sdk/api/client/OpenFgaClient.java)
instance.

To initialize the OpenFGA Spring Boot Starter, please provide the configuration property `openfga.api-url`. An
`OpenFgaClient` instance will then be created with the provided configuration.

The following examples demonstrate how to configure the OpenFGA Spring Boot Starter.

#### No Credentials

Expand Down Expand Up @@ -99,21 +114,169 @@ openfga:
credentials:
method: CLIENT_CONFIGURATION # constant
config:
client-id: YOUR_CLIENT_ID
client-secret: YOUR_CLIENT_SECRET
api-token-issuer: YOUR_API_TOKEN_ISSUER
api-audience: YOUR_API_AUDIENCE
scopes: YOUR_SPACE_SEPERATED_SCOPES
client-id: YOUR_CLIENT_ID
client-secret: YOUR_CLIENT_SECRET
api-token-issuer: YOUR_API_TOKEN_ISSUER
api-audience: YOUR_API_AUDIENCE
scopes: YOUR_SPACE_SEPERATED_SCOPES
```
#### Full Configuration Example
```yaml
# src/main/resources/application.yaml

openfga:
api-url: YOUR_FGA_API_URL
store-id: YOUR_FGA_STORE_ID
authorization-model-id: YOUR_FGA_AUTHORIZATION_MODEL_ID
user-agent: YOUR_USER_AGENT # default: openfga-sdk java/version
read-timeout: 1m # default: 10 seconds
connect-timeout: 15 # default: 10 seconds
max-retries: 3 # default: no retries
minimum-retry-delay: 1m
http-version: HTTP_2
default-headers:
X-SOME-HEADER: Some Header Value
telemetry-configuration:
fga_client_request_model_id: YOUR_FGA_CLIENT_REQUEST_MODEL_ID
credentials:
method: CLIENT_CONFIGURATION # constant
config:
client-id: YOUR_CLIENT_ID
client-secret: YOUR_CLIENT_SECRET
api-token-issuer: YOUR_API_TOKEN_ISSUER
api-audience: YOUR_API_AUDIENCE
scopes: YOUR_SPACE_SEPERATED_SCOPES
```
### Configuration Properties
The OpenFGA Spring Boot Starter can be configured using the following properties:
#### `openfga.api-url`

- **Description**: The base URL of the OpenFGA API endpoint.
- **Example**: `https://api.openfga.example.com`

#### `openfga.store-id`

- **Description**: The unique identifier for the store in OpenFGA.
- **Example**: `store-12345`

#### `openfga.authorization-model-id`

- **Description**: The unique identifier for the authorization model in OpenFGA.
- **Example**: `auth-model-67890`

#### `openfga.user-agent`

- **Description**: The user agent string to be included in the request headers.
- **Example**: `MyApp/1.0.0`
- **Default**: `openfga-sdk java/version`

#### `openfga.read-timeout`

- **Description**: The maximum duration to wait for a read operation to complete. Default unit is seconds. Must be positive or null.
- **Example**: `30s`
- **Default**: `10s`

#### `openfga.connect-timeout`

- **Description**: The maximum duration to wait for a connection to be established. Default unit is seconds. Must be positive or null.
- **Example**: `10s`
- **Default**: `10s`

#### `openfga.max-retries`

- **Description**: The maximum number of retry attempts for failed requests. Must be positive or null. If you set this to a positive value, ensure that you also set the `minimum-retry-delay` property.
- **Example**: `5`
- **Default**: No retries

#### `openfga.minimum-retry-delay`

- **Description**: The minimum delay between retry attempts. Default unit is seconds. Must be positive or null. Only used if `max-retries` is set.
- **Example**: `500ms`
- **Default**: `10s`

#### `openfga.http-version`

- **Description**: The HTTP version to use for requests.
- **Example**: `HTTP_1_1`
- **Default**: `HTTP_2`

#### `openfga.default-headers`

- **Description**: Default headers to be included in all requests.
- **Example**:

```yaml
default-headers:
X-Custom-Header: CustomHeaderValue
```

#### `openfga.telemetry-configuration`

- **Description**: Configuration settings for telemetry, which help in monitoring and logging the behavior of the
OpenFGA client.
- **Example**:

```yaml
telemetry-configuration:
fga_client_request_model_id: "example-model-id"
```

#### `openfga.credentials.method`

- **Description**: Specifies the authentication method to be used for connecting to the OpenFGA API.
- **Possible Values**:
- `NONE`: No authentication.
- `API_TOKEN`: Use an API token for authentication.
- `CLIENT_CREDENTIALS`: Use OAuth2 client credentials for authentication.

#### `openfga.credentials.config.api-token`

- **Description**: The API token used for authenticating requests when the `API_TOKEN` method is selected.
- **Example**: `your-api-token`

#### `openfga.credentials.config.client-id`

- **Description**: The client ID used for OAuth2 authentication when the `CLIENT_CREDENTIALS` method is selected.
- **Example**: `your-client-id`

#### `openfga.credentials.config.client-secret`

- **Description**: The client secret used for OAuth2 authentication when the `CLIENT_CREDENTIALS` method is selected.
- **Example**: `your-client-secret`

#### `openfga.credentials.config.api-token-issuer`

- **Description**: The issuer of the API token used for OAuth2 authentication when the `CLIENT_CREDENTIALS` method is
selected.
- **Example**: `https://issuer.example.com`

#### `openfga.credentials.config.api-audience`

- **Description**: The audience for the API token used for OAuth2 authentication when the `CLIENT_CREDENTIALS` method is
selected.
- **Example**: `https://api.example.com`

#### `openfga.credentials.config.scopes`

- **Description**: The scopes required for OAuth2 authentication when the `CLIENT_CREDENTIALS` method is selected.
Scopes are space-separated.
- **Example**: `read write`

### Using the `fgaClient` bean

Once configured, an `fgaClient` bean is available to be injected into your Spring components:

```java
@Service
public class MyService {
@Autowired
private OpenFgaClient fgaClient;
}
Expand All @@ -124,11 +287,10 @@ This can be used to interact with the FGA API, for example to write authorizatio
```java
public Document createDoc(String id) {
// ...
ClientWriteRequest writeRequest = new ClientWriteRequest()
.writes(List.of(new ClientTupleKey()
.user(String.format("user:%s", SecurityContextHolder.getContext().getAuthentication()))
.relation("owner")
._object(String.format("document:%s", id))));
ClientWriteRequest writeRequest = new ClientWriteRequest().writes(List.of(new ClientTupleKey()
.user(String.format("user:%s", SecurityContextHolder.getContext().getAuthentication()))
.relation("owner")
._object(String.format("document:%s", id))));
try {
fgaClient.write(writeRequest).get();
Expand Down Expand Up @@ -163,20 +325,45 @@ public Document getDocument(@PathVariable String docId) {
}
```

## Customize ApiClient and HttpClient Configuration

To customize the `ApiClient` configuration, create a `@Bean` method in your Spring Boot application:

```java
@Bean
public ApiClient apiClient(HttpClient.Builder builder, ObjectMapper mapper) {
return new ApiClient(httpClientBuilder, objectMapper);
}
```

Similarly, to customize the `HttpClient.Builder`:

```java
@Bean
public HttpClient.Builder httpClientBuilder() {
return HttpClient.newBuilder()
.version(Version.HTTP_2);
}
```

## Contributing

### Issues

If you have found a bug or if you have a feature request, please [create an issue](https://github.com/openfga/fga-spring-boot/issues). Please do not report security vulnerabilities on the public GitHub issue tracker.
If you have found a bug or if you have a feature request,
please [create an issue](https://github.com/openfga/fga-spring-boot/issues). Please do not report security
vulnerabilities on the public GitHub issue tracker.

### Pull Requests

Pull requests are welcome, however we do kindly ask that for non-trivial changes or feature additions, that you create an [issue]((https://github.com/openfga/fga-spring-boot/issues)) first.
Pull requests are welcome, however, we do kindly ask that for non-trivial changes or feature additions, that you create
an [issue]((https://github.com/openfga/fga-spring-boot/issues)) first.

## Author

[OpenFGA](https://github.com/openfga)

## License

This project is licensed under the Apache-2.0 license. See the [LICENSE](https://github.com/openfga/fga-spring-boot/blob/main/LICENSE) file for more info.
This project is licensed under the Apache-2.0 license. See
the [LICENSE](https://github.com/openfga/fga-spring-boot/blob/main/LICENSE) file for more info.
8 changes: 8 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ dependencies {

api 'dev.openfga:openfga-sdk:0.7.2'

compileOnly 'com.fasterxml.jackson.core:jackson-databind'
compileOnly 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310'
compileOnly 'org.openapitools:jackson-databind-nullable:0.2.6'

testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.security:spring-security-test'
testImplementation 'org.hamcrest:hamcrest:2.2'
Expand All @@ -69,6 +73,10 @@ spotless {
removeUnusedImports()
importOrder()
}
flexmark {
target "*.md"
flexmark()
}
}

test {
Expand Down
14 changes: 10 additions & 4 deletions examples/servlet/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,15 @@ To use a different FGA server, update `src/main/resources/application.yaml` acco

### Start the example application:

To run a local OpenFGA instance, you can use the provided `docker-compose.yml` file:

```shell
docker-compose up -d
```

In a terminal, start the application:

```bash
```shell
./gradlew bootRun
```

Expand Down Expand Up @@ -46,15 +52,15 @@ You should receive a 200 response with the document:

Execute a request for document 2, for which user `anne` does **not** have viewer access to:

```bash
```shell
curl http://localhost:8080/documents/2
```

You should receive a 403 response, as user `anne` does not have the required relation to document 2.

You can also create a document, for which user `anne` will be granted the owner relation for the document:

```bash
```shell
curl -d '{"id": "10", "content": "new document content"}' -H 'Content-Type: application/json' http://localhost:8080/documents
```

Expand All @@ -64,7 +70,7 @@ To run the example using a non-published version of the Okta FGA Spring Boot Sta

In the root directory of this repository, run:

```bash
```shell
./gradlew assemble publishToMavenLocal
```

Expand Down
7 changes: 7 additions & 0 deletions examples/servlet/docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
services:
openfga:
image: openfga/openfga:latest
command: run
ports:
- "4000:8080"

6 changes: 6 additions & 0 deletions examples/servlet/src/main/resources/application.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,9 @@ logging:
### NO AUTH - for example purposes only!! ###
openfga:
api-url: http://localhost:4000
user-agent: My Custom App 12.0
read-timeout: 30
connect-timeout: 5s
max-retries: 3
minimum-retry-delay: 5
http-version: HTTP_1_1
6 changes: 5 additions & 1 deletion src/main/java/dev/openfga/OpenFga.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,11 @@ public class OpenFga {

private final OpenFgaClient fgaClient;

// Inject OpenFga client
/**
* Create a new OpenFGA instance.
*
* @param fgaClient The OpenFGA client to use
*/
public OpenFga(OpenFgaClient fgaClient) {
this.fgaClient = fgaClient;
}
Expand Down
Loading

0 comments on commit aea68f9

Please sign in to comment.