Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion .openapi-generator-ignore
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
# Used but at a different location
**/client/Configuration.java
**/client/Pair.java
**/client/ApiException.java

# Unused
**/ServerConfiguration.java
**/ServerVariable.java
**/JSON.java
**/client/Configuration.java
**/RFC3339DateFormat.java
src/main/AndroidManifest.xml
build.sbt
pom.xml
Expand Down
23 changes: 14 additions & 9 deletions .openapi-generator/FILES
Original file line numberDiff line numberDiff line change
Expand Up@@ -75,17 +75,19 @@ gradlew
gradlew.bat
settings.gradle
src/main/java/dev/openfga/sdk/api/OpenFgaApi.java
src/main/java/dev/openfga/sdk/api/client/ApiBearerToken.java
src/main/java/dev/openfga/sdk/api/auth/AccessToken.java
src/main/java/dev/openfga/sdk/api/auth/CredentialsFlowRequest.java
src/main/java/dev/openfga/sdk/api/auth/CredentialsFlowResponse.java
src/main/java/dev/openfga/sdk/api/auth/OAuth2Client.java
src/main/java/dev/openfga/sdk/api/client/ApiClient.java
src/main/java/dev/openfga/sdk/api/client/ApiException.java
src/main/java/dev/openfga/sdk/api/client/ApiResponse.java
src/main/java/dev/openfga/sdk/api/client/ClientCredentials.java
src/main/java/dev/openfga/sdk/api/client/CredentialsMethod.java
src/main/java/dev/openfga/sdk/api/client/Pair.java
src/main/java/dev/openfga/sdk/api/client/RFC3339DateFormat.java
src/main/java/dev/openfga/sdk/api/configuration/ApiToken.java
src/main/java/dev/openfga/sdk/api/configuration/BaseConfiguration.java
src/main/java/dev/openfga/sdk/api/configuration/ClientCredentials.java
src/main/java/dev/openfga/sdk/api/configuration/Configuration.java
src/main/java/dev/openfga/sdk/api/configuration/ConfigurationOverride.java
src/main/java/dev/openfga/sdk/api/configuration/Credentials.java
src/main/java/dev/openfga/sdk/api/configuration/CredentialsMethod.java
src/main/java/dev/openfga/sdk/api/model/AbstractOpenApiSchema.java
src/main/java/dev/openfga/sdk/api/model/Any.java
src/main/java/dev/openfga/sdk/api/model/Assertion.java
Expand DownExpand Up@@ -141,12 +143,15 @@ src/main/java/dev/openfga/sdk/api/model/WriteAssertionsRequest.java
src/main/java/dev/openfga/sdk/api/model/WriteAuthorizationModelRequest.java
src/main/java/dev/openfga/sdk/api/model/WriteAuthorizationModelResponse.java
src/main/java/dev/openfga/sdk/api/model/WriteRequest.java
src/main/java/dev/openfga/sdk/errors/ApiException.java
src/main/java/dev/openfga/sdk/errors/FgaInvalidParameterException.java
src/main/java/dev/openfga/util/StringUtil.java
src/main/java/dev/openfga/sdk/util/Pair.java
src/main/java/dev/openfga/sdk/util/StringUtil.java
src/test-integration/java/dev/openfga/sdk/api/OpenFgaApiIntegrationTest.java
src/test/java/dev/openfga/sdk/api/OpenFgaApiTest.java
src/test/java/dev/openfga/sdk/api/OpenFgaApiTest.java
src/test/java/dev/openfga/sdk/api/client/ClientCredentialsTest.java
src/test/java/dev/openfga/sdk/api/auth/OAuth2ClientTest.java
src/test/java/dev/openfga/sdk/api/configuration/ClientCredentialsTest.java
src/test/java/dev/openfga/sdk/api/configuration/ConfigurationTest.java
src/test/java/dev/openfga/sdk/api/model/AnyTest.java
src/test/java/dev/openfga/sdk/api/model/AssertionTest.java
Expand DownExpand Up@@ -202,4 +207,4 @@ src/test/java/dev/openfga/sdk/api/model/WriteAssertionsRequestTest.java
src/test/java/dev/openfga/sdk/api/model/WriteAuthorizationModelRequestTest.java
src/test/java/dev/openfga/sdk/api/model/WriteAuthorizationModelResponseTest.java
src/test/java/dev/openfga/sdk/api/model/WriteRequestTest.java
src/test/java/dev/openfga/util/StringUtilTest.java
src/test/java/dev/openfga/sdk/util/StringUtilTest.java
193 changes: 145 additions & 48 deletions src/main/java/dev/openfga/sdk/api/OpenFgaApi.java

Large diffs are not rendered by default.

49 changes: 49 additions & 0 deletions src/main/java/dev/openfga/sdk/api/auth/AccessToken.java
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
/*
* OpenFGA
* A high performance and flexible authorization/permission engine built for developers and inspired by Google Zanzibar.
*
* The version of the OpenAPI document: 0.1
* Contact: community@openfga.dev
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/

package dev.openfga.sdk.api.auth;

import static dev.openfga.sdk.util.StringUtil.isNullOrWhitespace;

import java.time.Instant;
import java.util.Random;

class AccessToken {
private static final int TOKEN_EXPIRY_BUFFER_THRESHOLD_IN_SEC = 300;
private static final int TOKEN_EXPIRY_JITTER_IN_SEC =
300; // We add some jitter so that token refreshes are less likely to collide

private final Random random = new Random();
private Instant expiresAt;

private String token;

public boolean isValid() {
return !isNullOrWhitespace(token)
&& (expiresAt == null
|| expiresAt.isBefore(Instant.now()
.plusSeconds(TOKEN_EXPIRY_BUFFER_THRESHOLD_IN_SEC)
.plusSeconds(random.nextLong() % TOKEN_EXPIRY_JITTER_IN_SEC)));
}

public String getToken() {
return token;
}

public void setExpiresAt(Instant expiresAt) {
this.expiresAt = expiresAt;
}

public void setToken(String token) {
this.token = token;
}
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
/*
* OpenFGA
* A high performance and flexible authorization/permission engine built for developers and inspired by Google Zanzibar.
*
* The version of the OpenAPI document: 0.1
* Contact: community@openfga.dev
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/

package dev.openfga.sdk.api.auth;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;

/**
* A credentials flow request. It contains a Client ID and Secret that can be exchanged for an access token.
* <p>
* {@see "https://auth0.com/docs/get-started/authentication-and-authorization-flow/client-credentials-flow"}
*/
@JsonPropertyOrder({
CredentialsFlowRequest.JSON_PROPERTY_CLIENT_ID,
CredentialsFlowRequest.JSON_PROPERTY_CLIENT_SECRET,
CredentialsFlowRequest.JSON_PROPERTY_AUDIENCE,
CredentialsFlowRequest.JSON_PROPERTY_GRANT_TYPE
})
class CredentialsFlowRequest {
public static final String JSON_PROPERTY_CLIENT_ID = "client_id";
private String clientId;

public static final String JSON_PROPERTY_CLIENT_SECRET = "client_secret";
private String clientSecret;

public static final String JSON_PROPERTY_AUDIENCE = "audience";
private String audience;

public static final String JSON_PROPERTY_GRANT_TYPE = "grant_type";
private String grantType;

@JsonCreator
public CredentialsFlowRequest() {}

@JsonProperty(JSON_PROPERTY_CLIENT_ID)
public String getClientId() {
return clientId;
}

@JsonProperty(JSON_PROPERTY_CLIENT_ID)
public void setClientId(String clientId) {
this.clientId = clientId;
}

@JsonProperty(JSON_PROPERTY_CLIENT_SECRET)
public String getClientSecret() {
return clientSecret;
}

@JsonProperty(JSON_PROPERTY_CLIENT_SECRET)
public void setClientSecret(String clientSecret) {
this.clientSecret = clientSecret;
}

@JsonProperty(JSON_PROPERTY_AUDIENCE)
public String getAudience() {
return audience;
}

@JsonProperty(JSON_PROPERTY_AUDIENCE)
public void setAudience(String audience) {
this.audience = audience;
}

@JsonProperty(JSON_PROPERTY_GRANT_TYPE)
public String getGrantType() {
return grantType;
}

@JsonProperty(JSON_PROPERTY_GRANT_TYPE)
public void setGrantType(String grantType) {
this.grantType = grantType;
}
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
/*
* OpenFGA
* A high performance and flexible authorization/permission engine built for developers and inspired by Google Zanzibar.
*
* The version of the OpenAPI document: 0.1
* Contact: community@openfga.dev
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/

package dev.openfga.sdk.api.auth;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;

/**
* A credentials flow response. Contains an access token that can be used to authenticate
* <p>
* {@see "https://auth0.com/docs/get-started/authentication-and-authorization-flow/client-credentials-flow"}
*/
@JsonPropertyOrder({
CredentialsFlowResponse.JSON_PROPERTY_ACCESS_TOKEN,
CredentialsFlowResponse.JSON_PROPERTY_SCOPE,
CredentialsFlowResponse.JSON_PROPERTY_EXPIRES_IN,
CredentialsFlowResponse.JSON_PROPERTY_TOKEN_TYPE
})
class CredentialsFlowResponse {
public static final String JSON_PROPERTY_ACCESS_TOKEN = "access_token";
private String accessToken;

public static final String JSON_PROPERTY_SCOPE = "scope";
private String scope;

public static final String JSON_PROPERTY_EXPIRES_IN = "expires_in";
private long expiresInSeconds;

public static final String JSON_PROPERTY_TOKEN_TYPE = "token_type";
private String tokenType;

@JsonProperty(JSON_PROPERTY_ACCESS_TOKEN)
public String getAccessToken() {
return accessToken;
}

@JsonProperty(JSON_PROPERTY_ACCESS_TOKEN)
public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}

@JsonProperty(JSON_PROPERTY_SCOPE)
public String getScope() {
return scope;
}

@JsonProperty(JSON_PROPERTY_SCOPE)
public void setScope(String scope) {
this.scope = scope;
}

/**
* The expiration time, in seconds.
* <p>
* By the convention of RFC 6749 section 5.1, an expires_in value from a response will be understood
* as a value in seconds. {@see https://datatracker.ietf.org/doc/html/rfc6749#autoid-55}
* @return The expiration time, from now, in seconds
*/
@JsonProperty(JSON_PROPERTY_EXPIRES_IN)
public long getExpiresInSeconds() {
return expiresInSeconds;
}

@JsonProperty(JSON_PROPERTY_EXPIRES_IN)
public void setExpiresInSeconds(long expiresInSeconds) {
this.expiresInSeconds = expiresInSeconds;
}

@JsonProperty(JSON_PROPERTY_TOKEN_TYPE)
public String getTokenType() {
return tokenType;
}

@JsonProperty(JSON_PROPERTY_TOKEN_TYPE)
public void setTokenType(String tokenType) {
this.tokenType = tokenType;
}
}
106 changes: 106 additions & 0 deletions src/main/java/dev/openfga/sdk/api/auth/OAuth2Client.java
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
/*
* OpenFGA
* A high performance and flexible authorization/permission engine built for developers and inspired by Google Zanzibar.
*
* The version of the OpenAPI document: 0.1
* Contact: community@openfga.dev
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/

package dev.openfga.sdk.api.auth;

import com.fasterxml.jackson.databind.ObjectMapper;
import dev.openfga.sdk.api.client.ApiClient;
import dev.openfga.sdk.api.configuration.*;
import dev.openfga.sdk.errors.ApiException;
import dev.openfga.sdk.errors.FgaInvalidParameterException;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Instant;
import java.util.concurrent.CompletableFuture;

public class OAuth2Client {
private final HttpClient httpClient;
private final Credentials credentials;
private final ObjectMapper mapper;
private final AccessToken token = new AccessToken();
private final CredentialsFlowRequest authRequest;
private final String apiTokenIssuer;

/**
* Initializes a new instance of the {@link OAuth2Client} class
*
* @param configuration Configuration, including credentials, that can be used to retrieve an access tokens
* @param httpClient Http client
*/
public OAuth2Client(Configuration configuration, HttpClient httpClient, ObjectMapper mapper)
throws FgaInvalidParameterException {
this.credentials = configuration.getCredentials();

this.httpClient = httpClient;
this.mapper = mapper;
this.apiTokenIssuer = credentials.getClientCredentials().getApiTokenIssuer();
this.authRequest = new CredentialsFlowRequest();
this.authRequest.setClientId(credentials.getClientCredentials().getClientId());
this.authRequest.setClientSecret(credentials.getClientCredentials().getClientSecret());
this.authRequest.setAudience(credentials.getClientCredentials().getApiAudience());
this.authRequest.setGrantType("client_credentials");
}

/**
* Gets an access token, handling exchange when necessary. The access token is naively cached in memory until it
* expires.
*
* @return An access token in a {@link CompletableFuture}
*/
public CompletableFuture<String> getAccessToken() throws FgaInvalidParameterException, ApiException {
if (!token.isValid()) {
return exchangeToken().thenCompose(response -> {
token.setToken(response.getAccessToken());
token.setExpiresAt(Instant.now().plusSeconds(response.getExpiresInSeconds()));
return CompletableFuture.completedFuture(token.getToken());
});
}

return CompletableFuture.completedFuture(token.getToken());
}

/**
* Exchange a client id and client secret for an access token.
* @return The credentials flow response
*/
private CompletableFuture<CredentialsFlowResponse> exchangeToken()
throws ApiException, FgaInvalidParameterException {
try {
byte[] body = mapper.writeValueAsBytes(authRequest);

Configuration config = new Configuration().apiUrl("https://" + apiTokenIssuer);

HttpRequest request = ApiClient.requestBuilder("POST", "/oauth/token", body, config)
.build();

return httpClient
.sendAsync(request, HttpResponse.BodyHandlers.ofString())
.thenCompose(httpResponse -> {
if (httpResponse.statusCode() != HttpURLConnection.HTTP_OK) {
return CompletableFuture.failedFuture(new ApiException("exchangeToken", httpResponse));
}
try {
CredentialsFlowResponse response =
mapper.readValue(httpResponse.body(), CredentialsFlowResponse.class);
return CompletableFuture.completedFuture(response);
} catch (Exception e) {
return CompletableFuture.failedFuture(e);
}
});
} catch (IOException e) {
throw new ApiException(e);
}
}
}
Loading