-
Notifications
You must be signed in to change notification settings - Fork 25
Expand file tree
/
Copy pathOAuth2Client.java
More file actions
107 lines (90 loc) · 4.33 KB
/
Copy pathOAuth2Client.java
File metadata and controls
107 lines (90 loc) · 4.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
package dev.openfga.sdk.api.auth;
import dev.openfga.sdk.api.client.*;
import dev.openfga.sdk.api.configuration.*;
import dev.openfga.sdk.errors.ApiException;
import dev.openfga.sdk.errors.FgaInvalidParameterException;
import dev.openfga.sdk.telemetry.Attribute;
import dev.openfga.sdk.telemetry.Telemetry;
import java.net.URI;
import java.net.http.HttpRequest;
import java.time.Instant;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
public class OAuth2Client {
private static final String DEFAULT_API_TOKEN_ISSUER_PATH = "/oauth/token";
private final ApiClient apiClient;
private final AccessToken token = new AccessToken();
private final CredentialsFlowRequest authRequest;
private final Configuration config;
private final Telemetry telemetry;
/**
* Initializes a new instance of the {@link OAuth2Client} class
*
* @param configuration Configuration, including credentials, that can be used to retrieve an access tokens
*/
public OAuth2Client(Configuration configuration, ApiClient apiClient) throws FgaInvalidParameterException {
var clientCredentials = configuration.getCredentials().getClientCredentials();
this.apiClient = apiClient;
this.authRequest =
new CredentialsFlowRequest(clientCredentials.getClientId(), clientCredentials.getClientSecret());
this.authRequest.setAudience(clientCredentials.getApiAudience());
this.authRequest.setScope(clientCredentials.getScopes());
this.config = new Configuration()
.apiUrl(buildApiTokenIssuer(clientCredentials.getApiTokenIssuer()))
.connectTimeout(configuration.getConnectTimeout())
.maxRetries(configuration.getMaxRetries())
.minimumRetryDelay(configuration.getMinimumRetryDelay())
.telemetryConfiguration(configuration.getTelemetryConfiguration());
this.telemetry = new Telemetry(this.config);
}
/**
* 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()));
Map<Attribute, String> attributesMap = new HashMap<>();
telemetry.metrics().credentialsRequest(1L, attributesMap);
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 {
HttpRequest.Builder requestBuilder =
ApiClient.formRequestBuilder("POST", "", this.authRequest.buildFormRequestBody(), config);
HttpRequest request = requestBuilder.build();
return new HttpRequestAttempt<>(request, "exchangeToken", CredentialsFlowResponse.class, apiClient, config)
.attemptHttpRequest()
.thenApply(ApiResponse::getData);
}
private static String buildApiTokenIssuer(String issuer) throws FgaInvalidParameterException {
URI uri;
try {
uri = URI.create(issuer);
} catch (IllegalArgumentException cause) {
throw new FgaInvalidParameterException("apiTokenIssuer", "ClientCredentials", cause);
}
var scheme = uri.getScheme();
if (scheme == null) {
uri = URI.create("https://" + issuer);
} else if (!"https".equals(scheme) && !"http".equals(scheme)) {
throw new FgaInvalidParameterException("scheme", "apiTokenIssuer");
}
if (uri.getPath().isEmpty() || uri.getPath().equals("/")) {
uri = URI.create(uri.getScheme() + "://" + uri.getAuthority() + DEFAULT_API_TOKEN_ISSUER_PATH);
}
return uri.toString();
}
}