Skip to content

Commit c46fe9b

Browse files
committed
[Fix #952] More refactor
Signed-off-by: fjtirado <ftirados@redhat.com>
1 parent 35fdccf commit c46fe9b

13 files changed

+297
-334
lines changed

impl/http/src/main/java/io/serverlessworkflow/impl/executors/http/auth/requestbuilder/AbstractAuthRequestBuilder.java

Lines changed: 36 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -37,84 +37,85 @@
3737
abstract class AbstractAuthRequestBuilder<T extends OAuth2AuthenticationData>
3838
implements AuthRequestBuilder<T> {
3939

40-
private static final String DEFAULT_ENCODING = "application/x-www-form-urlencoded; charset=UTF-8";
41-
4240
protected final WorkflowApplication application;
41+
protected final HttpRequestInfoBuilder requestBuilder = new HttpRequestInfoBuilder();
4342

4443
public AbstractAuthRequestBuilder(WorkflowApplication application) {
4544
this.application = application;
4645
}
4746

48-
public void accept(HttpRequestBuilder requestBuilder, T authenticationData) {
49-
requestEncoding(requestBuilder, authenticationData);
50-
authenticationURI(requestBuilder, authenticationData);
51-
audience(requestBuilder, authenticationData);
52-
scope(requestBuilder, authenticationData);
53-
authenticationMethod(requestBuilder, authenticationData);
47+
@Override
48+
public HttpRequestInfo apply(T authenticationData) {
49+
requestEncoding(authenticationData);
50+
authenticationURI(authenticationData);
51+
audience(authenticationData);
52+
scope(authenticationData);
53+
authenticationMethod(authenticationData);
54+
return requestBuilder.build();
5455
}
5556

5657
@Override
57-
public void accept(HttpRequestBuilder requestBuilder, Map<String, Object> secret) {
58-
requestEncoding(requestBuilder, secret);
59-
authenticationURI(requestBuilder, secret);
60-
audience(requestBuilder, secret);
61-
scope(requestBuilder, secret);
62-
authenticationMethod(requestBuilder, secret);
58+
public HttpRequestInfo apply(Map<String, Object> secret) {
59+
requestEncoding(secret);
60+
authenticationURI(secret);
61+
audience(secret);
62+
scope(secret);
63+
authenticationMethod(secret);
64+
return requestBuilder.build();
6365
}
6466

65-
protected void audience(HttpRequestBuilder requestBuilder, T authenticationData) {
67+
protected void audience(T authenticationData) {
6668
if (authenticationData.getAudiences() != null && !authenticationData.getAudiences().isEmpty()) {
6769
String audiences = String.join(" ", authenticationData.getAudiences());
6870
requestBuilder.addQueryParam(
6971
"audience", WorkflowUtils.buildStringFilter(application, audiences));
7072
}
7173
}
7274

73-
protected void audience(HttpRequestBuilder requestBuilder, Map<String, Object> secret) {
75+
protected void audience(Map<String, Object> secret) {
7476
String audiences = (String) secret.get(AUDIENCES);
7577
if (isValid(audiences)) {
7678
requestBuilder.addQueryParam("audience", (w, t, m) -> audiences);
7779
}
7880
}
7981

80-
protected void authenticationMethod(HttpRequestBuilder requestBuilder, T authenticationData) {
82+
protected void authenticationMethod(T authenticationData) {
8183
ClientSecretHandler secretHandler;
8284
switch (getClientAuthentication(authenticationData)) {
8385
case CLIENT_SECRET_BASIC:
84-
secretHandler = new ClientSecretBasic(application);
86+
secretHandler = new ClientSecretBasic(application, requestBuilder);
8587
case CLIENT_SECRET_JWT:
8688
throw new UnsupportedOperationException("Client Secret JWT is not supported yet");
8789
case PRIVATE_KEY_JWT:
8890
throw new UnsupportedOperationException("Private Key JWT is not supported yet");
8991
default:
90-
secretHandler = new ClientSecretPost(application);
92+
secretHandler = new ClientSecretPost(application, requestBuilder);
9193
}
92-
secretHandler.accept(requestBuilder, authenticationData);
94+
secretHandler.accept(authenticationData);
9395
}
9496

95-
protected void authenticationMethod(
96-
HttpRequestBuilder requestBuilder, Map<String, Object> secret) {
97+
protected void authenticationMethod(Map<String, Object> secret) {
9798
Map<String, Object> client = (Map<String, Object>) secret.get(CLIENT);
9899
ClientSecretHandler secretHandler;
99100
String auth = (String) client.get(AUTHENTICATION);
100101
if (auth == null) {
101-
secretHandler = new ClientSecretPost(application);
102+
secretHandler = new ClientSecretPost(application, requestBuilder);
102103
} else {
103104
switch (auth) {
104105
case "client_secret_basic":
105-
secretHandler = new ClientSecretBasic(application);
106+
secretHandler = new ClientSecretBasic(application, requestBuilder);
106107
break;
107108
default:
108109
case "client_secret_post":
109-
secretHandler = new ClientSecretPost(application);
110+
secretHandler = new ClientSecretPost(application, requestBuilder);
110111
break;
111112
case "private_key_jwt":
112113
throw new UnsupportedOperationException("Private Key JWT is not supported yet");
113114
case "client_secret_jwt":
114115
throw new UnsupportedOperationException("Client Secret JWT is not supported yet");
115116
}
116117
}
117-
secretHandler.accept(requestBuilder, secret);
118+
secretHandler.accept(secret);
118119
}
119120

120121
private OAuth2AuthenticationDataClient.ClientAuthentication getClientAuthentication(
@@ -125,11 +126,11 @@ private OAuth2AuthenticationDataClient.ClientAuthentication getClientAuthenticat
125126
: authenticationData.getClient().getAuthentication();
126127
}
127128

128-
protected void scope(HttpRequestBuilder requestBuilder, T authenticationData) {
129-
scope(requestBuilder, authenticationData.getScopes());
129+
protected void scope(T authenticationData) {
130+
scope(authenticationData.getScopes());
130131
}
131132

132-
protected void scope(HttpRequestBuilder requestBuilder, List<String> scopesList) {
133+
protected void scope(List<String> scopesList) {
133134
if (scopesList == null || scopesList.isEmpty()) {
134135
return;
135136
}
@@ -147,28 +148,26 @@ protected void scope(HttpRequestBuilder requestBuilder, List<String> scopesList)
147148
}
148149
}
149150

150-
protected void scope(HttpRequestBuilder requestBuilder, Map<String, Object> secret) {
151+
protected void scope(Map<String, Object> secret) {
151152
String scopes = (String) secret.get(SCOPES);
152153
if (isValid(scopes)) {
153154
requestBuilder.addQueryParam("scope", (w, t, m) -> scopes);
154155
}
155156
}
156157

157-
void requestEncoding(HttpRequestBuilder requestBuilder, T authenticationData) {
158-
requestBuilder.withRequestContentType(authenticationData.getRequest());
158+
void requestEncoding(T authenticationData) {
159+
requestBuilder.withContentType(authenticationData.getRequest());
159160
}
160161

161-
void requestEncoding(HttpRequestBuilder requestBuilder, Map<String, Object> secret) {
162+
void requestEncoding(Map<String, Object> secret) {
162163
Map<String, Object> request = (Map<String, Object>) secret.get(REQUEST);
163164
String encoding = (String) request.get(ENCODING);
164165
if (isValid(encoding)) {
165166
requestBuilder.addHeader("Content-Type", (w, t, m) -> encoding);
166167
}
167168
}
168169

169-
protected abstract void authenticationURI(
170-
HttpRequestBuilder requestBuilder, T authenticationData);
170+
protected abstract void authenticationURI(T authenticationData);
171171

172-
protected abstract void authenticationURI(
173-
HttpRequestBuilder requestBuilder, Map<String, Object> secret);
172+
protected abstract void authenticationURI(Map<String, Object> secret);
174173
}

impl/http/src/main/java/io/serverlessworkflow/impl/executors/http/auth/requestbuilder/AccessTokenProvider.java

Lines changed: 94 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,36 +15,44 @@
1515
*/
1616
package io.serverlessworkflow.impl.executors.http.auth.requestbuilder;
1717

18+
import static io.serverlessworkflow.api.types.OAuth2TokenRequest.Oauth2TokenRequestEncoding.APPLICATION_X_WWW_FORM_URLENCODED;
19+
1820
import io.serverlessworkflow.impl.TaskContext;
1921
import io.serverlessworkflow.impl.WorkflowContext;
22+
import io.serverlessworkflow.impl.WorkflowError;
23+
import io.serverlessworkflow.impl.WorkflowException;
2024
import io.serverlessworkflow.impl.WorkflowModel;
25+
import io.serverlessworkflow.impl.executors.http.HttpClientResolver;
2126
import io.serverlessworkflow.impl.executors.http.auth.jwt.JWT;
2227
import io.serverlessworkflow.impl.executors.http.auth.jwt.JWTConverter;
28+
import jakarta.ws.rs.ProcessingException;
29+
import jakarta.ws.rs.client.Client;
30+
import jakarta.ws.rs.client.Entity;
31+
import jakarta.ws.rs.client.Invocation;
32+
import jakarta.ws.rs.client.ResponseProcessingException;
33+
import jakarta.ws.rs.client.WebTarget;
34+
import jakarta.ws.rs.core.Form;
35+
import jakarta.ws.rs.core.GenericType;
36+
import jakarta.ws.rs.core.MediaType;
37+
import jakarta.ws.rs.core.Response;
38+
import java.util.HashMap;
2339
import java.util.List;
2440
import java.util.Map;
25-
import java.util.ServiceLoader;
2641

2742
public class AccessTokenProvider {
2843

29-
private final TokenResponseHandler tokenResponseHandler = new TokenResponseHandler();
30-
3144
private final List<String> issuers;
32-
private final HttpRequestBuilder requestBuilder;
33-
45+
private final HttpRequestInfo requestInfo;
3446
private final JWTConverter jwtConverter;
3547

36-
AccessTokenProvider(HttpRequestBuilder requestBuilder, List<String> issuers) {
37-
this.requestBuilder = requestBuilder;
48+
AccessTokenProvider(HttpRequestInfo requestInfo, List<String> issuers, JWTConverter converter) {
49+
this.requestInfo = requestInfo;
3850
this.issuers = issuers;
39-
this.jwtConverter =
40-
ServiceLoader.load(JWTConverter.class)
41-
.findFirst()
42-
.orElseThrow(() -> new IllegalStateException("No JWTConverter implementation found"));
51+
this.jwtConverter = converter;
4352
}
4453

4554
public JWT validateAndGet(WorkflowContext workflow, TaskContext context, WorkflowModel model) {
46-
Map<String, Object> token =
47-
tokenResponseHandler.apply(requestBuilder.build(workflow, context, model), context);
55+
Map<String, Object> token = invoke(workflow, context, model);
4856
JWT jwt = jwtConverter.fromToken((String) token.get("access_token"));
4957
if (issuers != null && !issuers.isEmpty()) {
5058
jwt.issuer()
@@ -57,4 +65,77 @@ public JWT validateAndGet(WorkflowContext workflow, TaskContext context, Workflo
5765
}
5866
return jwt;
5967
}
68+
69+
private Map<String, Object> invoke(
70+
WorkflowContext workflowContext, TaskContext taskContext, WorkflowModel model) {
71+
try {
72+
Response response = executeRequest(workflowContext, taskContext, model);
73+
74+
if (response.getStatus() < 200 || response.getStatus() >= 300) {
75+
throw new WorkflowException(
76+
WorkflowError.communication(
77+
response.getStatus(),
78+
taskContext,
79+
"Failed to obtain token: HTTP "
80+
+ response.getStatus()
81+
+ " — "
82+
+ response.getEntity())
83+
.build());
84+
}
85+
return response.readEntity(new GenericType<>() {});
86+
} catch (ResponseProcessingException e) {
87+
throw new WorkflowException(
88+
WorkflowError.communication(
89+
e.getResponse().getStatus(),
90+
taskContext,
91+
"Failed to process response: " + e.getMessage())
92+
.build(),
93+
e);
94+
} catch (ProcessingException e) {
95+
throw new WorkflowException(
96+
WorkflowError.communication(
97+
-1, taskContext, "Failed to connect or process request: " + e.getMessage())
98+
.build(),
99+
e);
100+
}
101+
}
102+
103+
private Response executeRequest(WorkflowContext workflow, TaskContext task, WorkflowModel model) {
104+
105+
Client client = HttpClientResolver.client(workflow, task);
106+
WebTarget target = client.target(requestInfo.uri().apply(workflow, task, model));
107+
108+
Invocation.Builder builder = target.request(MediaType.APPLICATION_JSON);
109+
110+
builder.header("grant_type", requestInfo.grantType());
111+
builder.header("User-Agent", "OAuth2-Client-Credentials/1.0");
112+
builder.header("Accept", MediaType.APPLICATION_JSON);
113+
builder.header("Cache-Control", "no-cache");
114+
115+
for (var entry : requestInfo.headers().entrySet()) {
116+
String headerValue = entry.getValue().apply(workflow, task, model);
117+
if (headerValue != null) {
118+
builder.header(entry.getKey(), headerValue);
119+
}
120+
}
121+
122+
Entity<?> entity;
123+
if (requestInfo.contentType().equals(APPLICATION_X_WWW_FORM_URLENCODED.value())) {
124+
Form form = new Form();
125+
form.param("grant_type", requestInfo.grantType());
126+
requestInfo
127+
.queryParams()
128+
.forEach((key, value) -> form.param(key, value.apply(workflow, task, model)));
129+
entity = Entity.entity(form, MediaType.APPLICATION_FORM_URLENCODED);
130+
} else {
131+
Map<String, Object> jsonData = new HashMap<>();
132+
jsonData.put("grant_type", requestInfo.grantType());
133+
requestInfo
134+
.queryParams()
135+
.forEach((key, value) -> jsonData.put(key, value.apply(workflow, task, model)));
136+
entity = Entity.entity(jsonData, MediaType.APPLICATION_JSON);
137+
}
138+
139+
return builder.post(entity);
140+
}
60141
}

impl/http/src/main/java/io/serverlessworkflow/impl/executors/http/auth/requestbuilder/AccessTokenProviderFactory.java

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,31 +19,37 @@
1919

2020
import io.serverlessworkflow.api.types.OAuth2AuthenticationData;
2121
import io.serverlessworkflow.impl.WorkflowValueResolver;
22+
import io.serverlessworkflow.impl.executors.http.auth.jwt.JWTConverter;
2223
import java.util.Arrays;
2324
import java.util.Map;
25+
import java.util.ServiceLoader;
2426

2527
public class AccessTokenProviderFactory {
2628

2729
private AccessTokenProviderFactory() {}
2830

31+
private static JWTConverter jwtConverter =
32+
ServiceLoader.load(JWTConverter.class)
33+
.findFirst()
34+
.orElseThrow(() -> new IllegalStateException("No JWTConverter implementation found"));
35+
2936
public static WorkflowValueResolver<AccessTokenProvider> build(
3037
OAuth2AuthenticationData authenticationData, AuthRequestBuilder authBuilder) {
31-
HttpRequestBuilder httpBuilder = new HttpRequestBuilder();
32-
authBuilder.accept(httpBuilder, authenticationData);
3338
AccessTokenProvider tokenProvider =
34-
new AccessTokenProvider(httpBuilder, authenticationData.getIssuers());
39+
new AccessTokenProvider(
40+
authBuilder.apply(authenticationData), authenticationData.getIssuers(), jwtConverter);
3541
return (w, t, m) -> tokenProvider;
3642
}
3743

3844
public static WorkflowValueResolver<AccessTokenProvider> build(
3945
String secretName, AuthRequestBuilder authBuilder) {
40-
HttpRequestBuilder httpBuilder = new HttpRequestBuilder();
4146
return (w, t, m) -> {
4247
Map<String, Object> secret = secret(w, secretName);
43-
authBuilder.accept(httpBuilder, secret);
4448
String issuers = (String) secret.get("issuers");
4549
return new AccessTokenProvider(
46-
httpBuilder, issuers != null ? Arrays.asList(issuers.split(",")) : null);
50+
authBuilder.apply(secret),
51+
issuers != null ? Arrays.asList(issuers.split(",")) : null,
52+
jwtConverter);
4753
};
4854
}
4955
}

impl/http/src/main/java/io/serverlessworkflow/impl/executors/http/auth/requestbuilder/AuthRequestBuilder.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020

2121
public interface AuthRequestBuilder<T extends OAuth2AuthenticationData> {
2222

23-
void accept(HttpRequestBuilder requestBuilder, T authenticationData);
23+
HttpRequestInfo apply(T authenticationData);
2424

25-
void accept(HttpRequestBuilder requestBuilder, Map<String, Object> authenticationData);
25+
HttpRequestInfo apply(Map<String, Object> authenticationData);
2626
}

impl/http/src/main/java/io/serverlessworkflow/impl/executors/http/auth/requestbuilder/ClientSecretBasic.java

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,22 +30,21 @@
3030

3131
class ClientSecretBasic extends ClientSecretHandler {
3232

33-
protected ClientSecretBasic(WorkflowApplication application) {
34-
super(application);
33+
protected ClientSecretBasic(
34+
WorkflowApplication application, HttpRequestInfoBuilder requestBuilder) {
35+
super(application, requestBuilder);
3536
}
3637

3738
@Override
38-
protected void clientCredentials(
39-
HttpRequestBuilder requestBuilder, OAuth2AuthenticationData authenticationData) {
39+
protected void clientCredentials(OAuth2AuthenticationData authenticationData) {
4040
requestBuilder
4141
.addHeader("Authorization", "Basic " + encodedAuth(authenticationData))
4242
.withGrantType(authenticationData.getGrant().value());
4343
}
4444

4545
@Override
46-
protected void password(
47-
HttpRequestBuilder requestBuilder, OAuth2AuthenticationData authenticationData) {
48-
clientCredentials(requestBuilder, authenticationData);
46+
protected void password(OAuth2AuthenticationData authenticationData) {
47+
clientCredentials(authenticationData);
4948
requestBuilder
5049
.addQueryParam(
5150
"username",
@@ -56,15 +55,15 @@ protected void password(
5655
}
5756

5857
@Override
59-
protected void clientCredentials(HttpRequestBuilder requestBuilder, Map<String, Object> secret) {
58+
protected void clientCredentials(Map<String, Object> secret) {
6059
requestBuilder
6160
.withGrantType((String) secret.get(GRANT))
6261
.addHeader("Authorization", "Basic " + encodedAuth(secret));
6362
}
6463

6564
@Override
66-
protected void password(HttpRequestBuilder requestBuilder, Map<String, Object> secret) {
67-
clientCredentials(requestBuilder, secret);
65+
protected void password(Map<String, Object> secret) {
66+
clientCredentials(secret);
6867
requestBuilder
6968
.addQueryParam("username", (String) secret.get(USER))
7069
.addQueryParam("password", (String) secret.get(PASSWORD));

0 commit comments

Comments
 (0)