Giter Site home page Giter Site logo

openfga / java-sdk Goto Github PK

View Code? Open in Web Editor NEW
28.0 15.0 5.0 992 KB

OpenFGA SDK for Java - https://central.sonatype.com/artifact/dev.openfga/openfga-sdk

Home Page: https://openfga.dev

License: Apache License 2.0

Java 99.18% Makefile 0.04% Kotlin 0.79%
access-control authorization fga fine-grained-authorization openfga security zanzibar java

java-sdk's Introduction

OpenFGA

Go Reference GitHub release (latest SemVer) Docker Pulls Codecov Go Report CII Best Practices Join our community Twitter FOSSA Status Artifact HUB OpenSSF Scorecard SLSA 3

A high-performance and flexible authorization/permission engine built for developers and inspired by Google Zanzibar.

OpenFGA is designed to make it easy for developers to model their application permissions and add and integrate fine-grained authorization into their applications.

It allows in-memory data storage for quick development, as well as pluggable database modules. It currently supports PostgreSQL 14 and MySQL 8.

It offers an HTTP API and a gRPC API. It has SDKs for Java, Node.js/JavaScript, GoLang, Python and .NET. Look in our Community section for third-party SDKs and tools. It can also be used as a library (see example).

Getting Started

The following section aims to help you get started quickly. Please look at our official documentation for in-depth information.

Setup and Installation

ℹī¸ The following sections setup an OpenFGA server using the default configuration values. These are for rapid development and not for a production environment. Data written to an OpenFGA instance using the default configuration with the memory storage engine will not persist after the service is stopped.

For more information on how to configure the OpenFGA server, please take a look at our official documentation on Running in Production.

Docker

OpenFGA is available on Dockerhub, so you can quickly start it using the in-memory datastore by running the following commands:

docker pull openfga/openfga
docker run -p 8080:8080 -p 3000:3000 openfga/openfga run

Tip

The OPENFGA_HTTP_ADDR environment variable can used to configure the address at which the playground expects the OpenFGA server to be. For example, docker run -e OPENFGA_PLAYGROUND_ENABLED=true -e OPENFGA_HTTP_ADDR=0.0.0.0:4000 -p 4000:4000 -p 3000:3000 openfga/openfga run will start the OpenFGA server on port 4000, and configure the playground too.

Docker Compose

docker-compose.yaml provides an example of how to launch OpenFGA with Postgres using docker compose.

  1. First, either clone this repo or curl the docker-compose.yaml file with the following command:

    curl -LO https://openfga.dev/docker-compose.yaml
  2. Then, run the following command:

    docker compose up

Package Managers

If you are a Homebrew user, you can install OpenFGA with the following command:

brew install openfga

Pre-compiled Binaries

Download your platform's latest release and extract it. Then run the binary with the command:

./openfga run

Building from Source

There are two recommended options for building OpenFGA from source code:

Building from source with go install

Make sure you have Go 1.20 or later installed. See the Go downloads page.

You can install from source using Go modules:

  1. First, make sure $GOBIN is on your shell $PATH:

    export PATH=$PATH:$(go env GOBIN)
  2. Then use the install command:

    go install github.com/openfga/openfga/cmd/openfga
  3. Run the server with:

    ./openfga run

Building from source with go build

Alternatively you can build OpenFGA by cloning the project from this Github repo, and then building it with the go build command:

  1. Clone the repo to a local directory, and navigate to that directory:

    git clone https://github.com/openfga/openfga.git && cd openfga
  2. Then use the build command:

    go build -o ./openfga ./cmd/openfga
  3. Run the server with:

    ./openfga run

Verifying the Installation

Now that you have Set up and Installed OpenFGA, you can test your installation by creating an OpenFGA Store.

curl -X POST 'localhost:8080/stores' \
--header 'Content-Type: application/json' \
--data-raw '{
    "name": "openfga-demo"
}'

If everything is running correctly, you should get a response with information about the newly created store, for example:

{
  "id": "01G3EMTKQRKJ93PFVDA1SJHWD2",
  "name": "openfga-demo",
  "created_at": "2022-05-19T17:11:12.888680Z",
  "updated_at": "2022-05-19T17:11:12.888680Z"
}

Playground

The Playground facilitates rapid development by allowing you to visualize and model your application's authorization model(s) and manage relationship tuples with a locally running OpenFGA instance.

To run OpenFGA with the Playground disabled, provide the --playground-enabled=false flag.

./openfga run --playground-enabled=false

Once OpenFGA is running, by default, the Playground can be accessed at http://localhost:3000/playground.

In the event that a port other than the default port is required, the --playground-port flag can be set to change it. For example,

./openfga run --playground-enabled --playground-port 3001

Profiler (pprof)

Profiling through pprof can be enabled on the OpenFGA server by providing the --profiler-enabled flag.

./openfga run --profiler-enabled

This will start serving profiling data on port 3001. You can see that data by visiting http://localhost:3001/debug/pprof.

If you need to serve the profiler on a different address, you can do so by specifying the --profiler-addr flag. For example,

./openfga run --profiler-enabled --profiler-addr :3002

Once the OpenFGA server is running, in another window you can run the following command to generate a compressed CPU profile:

go tool pprof -proto -seconds 60 http://localhost:3001/debug/pprof/profile
# will collect data for 60 seconds and generate a file like pprof.samples.cpu.001.pb.gz

That file can be analyzed visually by running the following command and then visiting http://localhost:8084:

go tool pprof -http=localhost:8084 pprof.samples.cpu.001.pb.gz

Next Steps

Take a look at examples of how to:

Don't hesitate to browse the official Documentation, API Reference.

Limitations

MySQL Storage engine

The MySQL storage engine has a lower length limit for some properties of a tuple compared with other storage backends. For more information see the docs.

OpenFGA's MySQL Storage Adapter was contributed to OpenFGA by @twintag. Thanks!

Production Readiness

The core OpenFGA service has been in use by Okta FGA in production since December 2021.

OpenFGA's Memory Storage Adapter was built for development purposes only and is not recommended for a production environment, because it is not designed for scalable queries and has no support for persistence.

You can learn about more organizations using OpenFGA in production here. If your organization is using OpenFGA in production please consider adding it to the list.

The OpenFGA team will do its best to address all production issues with high priority.

Contributing

See CONTRIBUTING.

Community Meetings

We hold a monthly meeting to interact with the community, collaborate and receive/provide feedback. You can find more details, including the time, our agenda, and the meeting minutes here.

java-sdk's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

java-sdk's Issues

OAuth2 client credentials are sent with wrong Content-Type

Description

When an OAuth2 access token is requested from an OAuth2 Authorization server's token endpoint, the credentials are sent using the application/json Content-Type, but client credentials should be sent using the application/x-www-form-urlencoded according to the OAuth 2.0 RFC

Version of SDK

v0.3.1

Reproduction

  1. Configure the openfga client using the OAuth2 Credentials example in the README
  2. Observe that the content-type is set to application/json

Expected behavior

When an OAuth2 token is requested from an OAuth2 Authorization server, the credentials are sent using the application/x-www-form-urlencoded content-type as specified in the OAuth 2.0 RFC

Unable to retrieve all tuples

Description

Unable to retrieve list of tuples using empty ClientReadRequest. The read method always creates a TupleKey whether you pass in null or and empty ClientReadRequest. This triggers a validation error when calling the api

I am attempting to simulate this request
curl --location --request POST 'http://localhost:8080/stores//read'

Version of SDK

v0.2.1

Version of OpenFGA (if known)

v1.3.4

OpenFGA Flags/Custom Configuration Applicable

environment:
- OPENFGA_DATASTORE_ENGINE=mysql
- OPENFGA_DATASTORE_URI=:@tcp(mysql:3306)/fga?parseTime=true
- OPENFGA_LOG_FORMAT=json

Reproduction

The error occurs every time when attempting to read all tuples. When you create an empty ClientReadRequest with "new ClientReadRequest()" and call the read method, you will recieve the following error:
{
"code": "validation_error",
"message": "the 'tuple_key' field was provided but the object type field is required and both the object id and user cannot be empty"
}

Sample Code the Produces Issues

ClientReadRequest request = new ClientReadRequest();
ClientReadOptions options = (new ClientReadOptions()).pageSize(10);
CompletableFuture future = client.read(request, options);

Expected behavior

You should recieve a response listing the tuples on the server
The exact same behavior as "curl --location --request POST 'http://localhost:8080/stores//read'"

Additional context

This issue is caused by the read method in the API. It always creates a TupleKey and adds it to the body of the request even if the ClientReadRequest is empty. It should leave the body empty and not create a TupleKey

example application does not work with local SDK as documented

Checklist

  • I have looked into the README and have not found a suitable solution or answer.
  • I have looked into the documentation and have not found a suitable solution or answer.
  • I have searched the issues and have not found a suitable solution or answer.
  • I have upgraded to the latest version of OpenFGA and the issue still persists.
  • I have searched the Slack community and have not found a suitable solution or answer.
  • I agree to the terms within the OpenFGA Code of Conduct.

Description

When following the documentation to run the example with a local version of the SDK, an error occurs when running make.

Expectation

It should be possible to run the example with a local unpublished version of the SDK

Reproduction

Update the example build.gradle as shown in the example README:

dependencies {
    // implementation("dev.openfga:openfga-sdk:0.4.+")
    implementation project(path: ':')

    // ...etc
}

Run make, and observe the error:

FAILURE: Build failed with an exception.

* What went wrong:
Circular dependency between the following tasks:
:classes
\--- :compileJava
     +--- :compileKotlin
     |    \--- :jar
     |         +--- :classes (*)
     |         +--- :compileJava (*)
     |         \--- :compileKotlin (*)
     \--- :jar (*)

I don't know that trying to reference the SDK project is possible given that the repository is not organized as a gradle multi-project. I suspect the error is that the implementation project(path: ':') is adding a dependency to itself (: path is the project root). Even a hard-coded path will fail because the example project is not associated with the SDK project.

It may be easiest to update the documentation to publish the SDK to the local maven repository, and then use the mavenLocal repository.

OpenFGA SDK version

0.4.1

OpenFGA version

latest

SDK Configuration

n/a

Logs

n/a

References

No response

Allow specifying OAuth Token URL in ClientCredentials

Describe the problem you'd like to have solved

You can specify apiTokenIssuer in ClientCredentials but the token path always defaults to "/oauth/token". That may not always be true as for me it's /oauth2/token.

I need to create a separate OAuth client and manage token manually.

Describe the ideal solution

Replace or add a new field in ClientCredentials to accept apiTokenURL (the entire path) or optionally add a field to allow overriding DEFAULT_API_TOKEN_ISSUER_PATH in OAuth2Client.

Alternatives and current workarounds

Create a separate OAuth client and manage token manually.

Additional context

None.

PHP SDK client

Checklist

Describe the problem you'd like to have solved

The lack of a PHP SDK client for this project limits integration options for PHP-based applications

Describe the ideal solution

Hello,

I'm currently working with your project and find it very useful. I was wondering if there are any plans to develop a PHP SDK client in the near future.

A PHP SDK would greatly benefit developers who primarily work with PHP-based applications, making it easier to integrate your project into their existing systems.

If there are no current plans for a PHP SDK, would you be open to community contributions in this area? I'd be interested in knowing your thoughts on this and any potential roadmap for SDK development.

Thank you for your time and consideration.

Alternatives and current workarounds

No response

References

No response

Additional context

No response

A new thread is being created for every OpenFgaClient call

Description

A new HttpClient is being created for each request, leading to an increasing number of threads. Specifying a thread pool alleviates the problem, but not completely. The issue happens because here a new HttpClient is built everytime.

Version of SDK

v0.3.1

Reproduction

Below is an example of how to reproduce the issue.

  1. Initialize OpenFgaClient with any set of configs;
  2. Invoke method OpenFgaClient#write(ClientWriteRequest request) multiple times;
  3. Notice that for every write call, a new thread is created. If you have 300k write calls, 300k threads are created, eventually running out of memory.

Expected behavior

It should not create a new thread for every request.

At Present the error messages does not contain any details.

Please do not report security vulnerabilities here. See the Responsible Disclosure Program.

Thank you in advance for helping us to improve this library! Please read through the template below and answer all relevant questions. Your additional work here is greatly appreciated and will help us respond as quickly as possible.

By submitting an issue to this repository, you agree to the terms within the OpenFGA Code of Conduct.

Description

The OpenFGA java sdk at present does not return any error messages with proper types. It's only returning FgaApiValidationError. java sdk default error log has so little information. It just prints method which is not very helpful to find error.
Caused by: dev.openfga.sdk.errors.FgaApiValidationError: check

At present there is no way to identify such errors. It would be really helpful if these error codes are returned in the response from SDK.

Version of SDK

v0.4.2

Version of OpenFGA (if known)

v1.1.0

OpenFGA Flags/Custom Configuration Applicable

environment:
- OPENFGA_DATASTORE_ENGINE=postgres
- OPENFGA_DATASTORE_URI=postgres://postgres:password@postgres:5432/postgres?sslmode=disable
- OPENFGA_TRACE_ENABLED=true
- OPENFGA_TRACE_SAMPLE_RATIO=1
- OPENFGA_TRACE_OTLP_ENDPOINT=otel-collector:4317
- OPENFGA_METRICS_ENABLE_RPC_HISTOGRAMS=true

Reproduction

Detail the steps taken to reproduce this error, what was expected, and whether this issue can be reproduced consistently or if it is intermittent.

  1. Initialize OpenFgaClient with openfga_sdk.ClientConfiguration parameter api_host=127.0.0.1, credentials method client_credentials
  2. Invoke method read_authorization_models
  3. See exception thrown

Sample Code the Produces Issues

<code snippet>

Backtrace (if applicable)

<backtrace>

Expected behavior

A clear and concise description of what you expected to happen.

Additional context

Add any other context about the problem here.

Intermittent FgaApiAuthenticationError when using Oauth2 Client Credentials

Checklist

  • I have looked into the README and have not found a suitable solution or answer.
  • I have looked into the documentation and have not found a suitable solution or answer.
  • I have searched the issues and have not found a suitable solution or answer.
  • I have upgraded to the latest version of OpenFGA and the issue still persists.
  • I have searched the Slack community and have not found a suitable solution or answer.
  • I agree to the terms within the OpenFGA Code of Conduct.

Description

I have observed FgaApiAuthenticationError is thrown intermittently when using OAuth2 client credentials. This occurs most frequently after a period of inactivity where the OpenFgaClient is not used for a long period of time, or at an intervals roughly equal to the OAuth2 access token's expires_in value. I think there may be an issue with the way that OAuth2 tokens are refreshed before expiry.

Expectation

I expect for OAuth2 access tokens to be refreshed automatically before being sent to the openfga api. An expired token should never be sent to the openfga api and the openFgaClient does not intermittently throw FgaApiAuthenticationError

Reproduction

Given:

Given I set up an OpenFgaClient using the Oauth2 Credentials example in the README

        var config = new ClientConfiguration()
                .apiUrl(System.getenv("FGA_API_URL")) // If not specified, will default to "http://localhost:8080"
                .storeId(System.getenv("FGA_STORE_ID")) // Not required when calling createStore() or listStores()
                .authorizationModelId(System.getenv("FGA_AUTHORIZATION_MODEL_ID")) // Optional, can be overridden per request
                .credentials(new Credentials(
                    new ClientCredentials()
                            .apiTokenIssuer(System.getenv("FGA_API_TOKEN_ISSUER"))
                            .scopes(System.getenv("FGA_API_SCOPES")) // optional space separated scopes
                            .clientId(System.getenv("FGA_CLIENT_ID"))
                            .clientSecret(System.getenv("FGA_CLIENT_SECRET"))
                ));

        var openFgaClient = new OpenFgaClient(config);

When:
When I make an openfga check request using the openfgaClient set up using clientCredentials

openFgaClient.check(checkRequest)

Then:

  • The openFgaClient always sends a fresh OAuth2 access token to the openfga server.
  • The openFgaClient ensures that the OAuth2 access token is refreshed before being sent if it is expired
  • The openFgaClient does not intermittently throw FgaApiAuthenticationError

OpenFGA SDK version

0.4.1

OpenFGA version

1.3.3

SDK Configuration

OAuth2 Client Credentials

Logs

dev.openfga.sdk.errors.FgaApiAuthenticationError: check
  at dev.openfga.sdk.errors.FgaError.getError(FgaError.java:49)
  at dev.openfga.sdk.api.client.HttpRequestAttempt.lambda$attemptHttpRequest$2(HttpRequestAttempt.java:56)
  at java.util.concurrent.CompletableFuture$UniCompose.tryFire(CompletableFuture.java:1150)
  at java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:510)
  at java.util.concurrent.CompletableFuture.postFire(CompletableFuture.java:614)
  at java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:844)
  at java.util.concurrent.CompletableFuture$Completion.run(CompletableFuture.java:482)
  at java.lang.Thread.run(Thread.java:833)

References

No response

In the client, the transaction modes are flipped

Please do not report security vulnerabilities here. See the Responsible Disclosure Program.

Thank you in advance for helping us to improve this library! Please read through the template below and answer all relevant questions. Your additional work here is greatly appreciated and will help us respond as quickly as possible.

By submitting an issue to this repository, you agree to the terms within the OpenFGA Code of Conduct.

Description

The OpenFgaClient in the Java SDK has a flipped implementation of non transactional writes.

Implementation is flipped: https://github.com/openfga/java-sdk/blob/main/src/main/java/dev/openfga/sdk/api/client/OpenFgaClient.java#L366-L431
Tests are flipped: https://github.com/openfga/java-sdk/blob/main/src/test/java/dev/openfga/sdk/api/client/OpenFgaClientTest.java#L1109-L1328

Discord Thread

Version of SDK

v0.3.2

Version of OpenFGA (if known)

All versions

OpenFGA Flags/Custom Configuration Applicable

N/A

Reproduction

Sample Code the Produces Issues

Backtrace (if applicable)

Expected behavior

A clear and concise description of what you expected to happen.

Setting disableTransaction to true should send multiple requests, setting it to false (default), should send everything in the same request

Additional context

`AccessToken#isValid()` incorrectly returns false

Description

The isValid() check of AccessToken incorrectly returns false for a valid token, causing an unnecessary fetch of a new token.

Expected behavior

AccessToken#isValid() should not return false for a valid non-expired token, and a new token should not be fetched.

Version of SDK

v0.3.1

Reproduction

  1. Initialize the OpenFgaClient with ClientCredentials
  2. Invoke any API call at least twice
  3. Observe that AccessToken#isValid() returns false, even though the token expiry is in the future, causing a new token to be retrieved.

Sample code to reproduce

// Create a new configuration with ClientCredentials
var config = new ClientConfiguration()
        .apiUrl(FGA_API_URL)
        .storeId(FGA_STORE_ID)
        .credentials(new Credentials(
                new ClientCredentials()
                        .apiTokenIssuer(FGA_API_TOKEN_ISSUER)
                        .apiAudience(FGA_API_AUDIENCE)
                        .clientId(FGA_CLIENT_ID)
                        .clientSecret(FGA_CLIENT_SECRET)
        )
);

var fgaClient = new OpenFgaClient(config);

var checkRequest = new ClientCheckRequest()
    .user("user")
    .relation("relation")
    ._object("obj");
    
var r1 = client.check(checkRequest).get();
// make another request, observe that AccessToken#isValid() returns false even though the expiry is in the future
var r2 = client.check(checkRequest).get();

Expected behavior

AccessToken#isValid() should not return false for a non-expired token, and a new token should not be unnecessarily fetched.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤ī¸ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.