Skip to content

Commit

Permalink
Use enum for credentials method
Browse files Browse the repository at this point in the history
  • Loading branch information
jimmyjames committed Mar 6, 2024
1 parent 4803373 commit 407676f
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 18 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package dev.openfga.autoconfigure;

import dev.openfga.sdk.api.client.OpenFgaClient;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;

import java.lang.annotation.ElementType;
Expand All @@ -10,4 +12,5 @@
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
@ConditionalOnProperty(name = {"openfga.api-url"})
@ConditionalOnClass(OpenFgaClient.class)
public @interface ConditionalOnFgaProperties {}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
* Configures an {@code openFgaClient} bean based on configuration values.
* The bean will only be created if the {@link OpenFgaClient} is present on
* the classpath, and the {@code openfga.api-url} is specified.
*/
@Configuration
@ConditionalOnFgaProperties
@EnableConfigurationProperties(OpenFgaProperties.class)
Expand All @@ -28,10 +33,10 @@ public ClientConfiguration openFgaConfig() {
var credentialsProperties = openFgaProperties.getCredentials();

if (credentialsProperties != null) {
if ("API_TOKEN".equalsIgnoreCase(credentialsProperties.getMethod())) {
if (OpenFgaProperties.CredentialsMethod.API_TOKEN.equals(credentialsProperties.getMethod())) {
credentials.setCredentialsMethod(CredentialsMethod.API_TOKEN);
credentials.setApiToken(new ApiToken(credentialsProperties.getConfig().getApiToken()));
} else if ("CLIENT_CREDENTIALS".equalsIgnoreCase(credentialsProperties.getMethod())) {
} else if (OpenFgaProperties.CredentialsMethod.CLIENT_CREDENTIALS.equals(credentialsProperties.getMethod())) {
ClientCredentials clientCredentials = new ClientCredentials()
.clientId(credentialsProperties.getConfig().getClientId())
.clientSecret(credentialsProperties.getConfig().getClientSecret())
Expand Down
63 changes: 48 additions & 15 deletions src/main/java/dev/openfga/autoconfigure/OpenFgaProperties.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@

import java.util.Set;

/**
* Properties used to configure an {@link dev.openfga.sdk.api.client.OpenFgaClient}
*/
@ConfigurationProperties(prefix="openfga")
public class OpenFgaProperties implements InitializingBean {

Expand Down Expand Up @@ -54,38 +57,41 @@ public void afterPropertiesSet() throws Exception {
public void validate() {
Credentials credentialsProperty = getCredentials();
if (credentialsProperty != null) {
String credentialsMethod = getCredentials().getMethod();
CredentialsMethod credentialsMethod = getCredentials().getMethod();
if (credentialsMethod == null) {
throw new IllegalStateException("credentials method must not be null");
}
if (!Set.of("NONE", "API_TOKEN", "CLIENT_CREDENTIALS").contains(credentialsMethod.toUpperCase())) {
throw new IllegalStateException("credentials method must be either 'NONE', 'API_TOKEN', or 'CLIENT_CREDENTIALS'");
}

CredentialsConfiguration credentialsConfig = credentialsProperty.getConfig();
if ("API_TOKEN".equalsIgnoreCase(credentialsMethod)) {
if (credentialsConfig == null || credentialsConfig.getApiToken() == null) {
throw new IllegalStateException("'API_TOKEN' credentials method specified, but no token specified");
switch (credentialsMethod) {
case NONE -> {}
case API_TOKEN -> {
if (credentialsConfig == null || credentialsConfig.getApiToken() == null) {
throw new IllegalStateException("'API_TOKEN' credentials method specified, but no token specified");
}
}
}
if ("CLIENT_CREDENTIALS".equalsIgnoreCase(credentialsMethod)) {
if (credentialsConfig == null || credentialsConfig.getApiTokenIssuer() == null || credentialsConfig.getClientId() == null || credentialsConfig.getClientSecret() == null) {
throw new IllegalStateException("'CLIENT_CREDENTIALS' configuration must contain 'client-id', 'client-secret', and 'api-token-issuer'");
case CLIENT_CREDENTIALS -> {
if (credentialsConfig == null || credentialsConfig.getApiTokenIssuer() == null || credentialsConfig.getClientId() == null || credentialsConfig.getClientSecret() == null) {
throw new IllegalStateException("'CLIENT_CREDENTIALS' configuration must contain 'client-id', 'client-secret', and 'api-token-issuer'");
}
}
default -> throw new IllegalStateException("credentials method must be either 'NONE', 'API_TOKEN', or 'CLIENT_CREDENTIALS'");
}
}
}

/**
* {@link dev.openfga.sdk.api.client.OpenFgaClient} credentials properties
*/
public static class Credentials {

private String method;
private CredentialsMethod method;
private CredentialsConfiguration config;

public String getMethod() {
public CredentialsMethod getMethod() {
return method;
}

public void setMethod(String method) {
public void setMethod(CredentialsMethod method) {
this.method = method;
}

Expand All @@ -98,6 +104,33 @@ public void setConfig(CredentialsConfiguration config) {
}
}

/**
* OpenFgaClient credentials methods
*/
public enum CredentialsMethod {

/**
* No authentication
*/
NONE,

/**
* A static API token. In OAuth2 terms, this indicates an "access token"
* that will be used to make a request. When used, an {@code api-token} must
* also be configured.
*/
API_TOKEN,

/**
* OAuth2 client credentials that can be used to acquire an OAuth2 access
* token. When used, you must also configure {@link CredentialsConfiguration}.
*/
CLIENT_CREDENTIALS
}

/**
* {@link dev.openfga.sdk.api.client.OpenFgaClient} credentials configuration properties
*/
public static class CredentialsConfiguration {
private String apiToken;
private String apiTokenIssuer;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ public void beanConfiguredForApiToken() {
"openfga.authorization-model-id=authorization model ID",
"openfga.store-id=store ID",
"openfga.credentials.method=API_TOKEN",
"openfga.credentials.config.api-token=XYZ"//,
"openfga.credentials.config.api-token=XYZ"
)
.withConfiguration(AutoConfigurations.of(OpenFgaAutoConfiguration.class))
.run((context) -> {
Expand Down Expand Up @@ -168,4 +168,19 @@ public void failsIfCredentialsWithNoMethod() {

assertThat(exception.getCause().getMessage(), containsString("credentials method must not be null"));
}

@Test
public void failsIfCredentialsWithInvalidMethod() {
assertThrows(IllegalStateException.class, () -> {
this.contextRunner
.withPropertyValues("openfga.api-url=https://api.fga.example",
"openfga.authorization-model-id=authorization model ID",
"openfga.store-id=store ID",
"openfga.credentials.method=INVALID",
"openfga.credentials.config.api-token=API_TOKEN"
)
.withConfiguration(AutoConfigurations.of(OpenFgaAutoConfiguration.class))
.run((context) -> context.getBean("openFgaConfig"));
});
}
}

0 comments on commit 407676f

Please sign in to comment.