Skip to content

Commit dcd516c

Browse files
committed
Add OpenID authentication support to HTTP call task
Signed-off-by: Dmitrii Tikhomirov <[email protected]>
1 parent 91d6b5e commit dcd516c

File tree

18 files changed

+220
-113
lines changed

18 files changed

+220
-113
lines changed

impl/http/src/main/java/io/serverlessworkflow/impl/executors/http/OAuth2AuthProvider.java

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,17 @@
2222
import io.serverlessworkflow.impl.WorkflowApplication;
2323
import io.serverlessworkflow.impl.WorkflowContext;
2424
import io.serverlessworkflow.impl.WorkflowModel;
25-
import io.serverlessworkflow.impl.executors.http.oauth.JWT;
26-
import io.serverlessworkflow.impl.executors.http.oauth.OAuthRequestBuilder;
25+
import io.serverlessworkflow.impl.executors.http.auth.jwt.JWT;
26+
import io.serverlessworkflow.impl.executors.http.auth.requestbuilder.AuthRequestBuilder;
27+
import io.serverlessworkflow.impl.executors.http.auth.requestbuilder.OAuthRequestBuilder;
2728
import jakarta.ws.rs.client.Invocation;
2829
import jakarta.ws.rs.client.Invocation.Builder;
2930

3031
public class OAuth2AuthProvider implements AuthProvider {
3132

32-
private OAuthRequestBuilder requestBuilder;
33+
private AuthRequestBuilder requestBuilder;
3334

34-
private static final String BEARER_TOKEN = "%s %s";
35+
private static final String BEARER_TOKEN = "Bearer %s";
3536

3637
public OAuth2AuthProvider(
3738
WorkflowApplication application, Workflow workflow, OAuth2AuthenticationPolicy authPolicy) {
@@ -53,9 +54,6 @@ public Builder build(
5354
public void preRequest(
5455
Invocation.Builder builder, WorkflowContext workflow, TaskContext task, WorkflowModel model) {
5556
JWT jwt = requestBuilder.build(workflow, task, model).validateAndGet();
56-
String type =
57-
jwt.type().orElseThrow(() -> new IllegalStateException("Token type is not present"));
58-
builder.header(
59-
AuthProviderFactory.AUTH_HEADER_NAME, String.format(BEARER_TOKEN, type, jwt.token()));
57+
builder.header(AuthProviderFactory.AUTH_HEADER_NAME, String.format(BEARER_TOKEN, jwt.token()));
6058
}
6159
}

impl/http/src/main/java/io/serverlessworkflow/impl/executors/http/OpenIdAuthProvider.java

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,24 +16,49 @@
1616
package io.serverlessworkflow.impl.executors.http;
1717

1818
import io.serverlessworkflow.api.types.OpenIdConnectAuthenticationPolicy;
19+
import io.serverlessworkflow.api.types.OpenIdConnectAuthenticationPolicyConfiguration;
1920
import io.serverlessworkflow.api.types.Workflow;
2021
import io.serverlessworkflow.impl.TaskContext;
2122
import io.serverlessworkflow.impl.WorkflowApplication;
2223
import io.serverlessworkflow.impl.WorkflowContext;
2324
import io.serverlessworkflow.impl.WorkflowModel;
25+
import io.serverlessworkflow.impl.executors.http.auth.jwt.JWT;
26+
import io.serverlessworkflow.impl.executors.http.auth.requestbuilder.AuthRequestBuilder;
27+
import io.serverlessworkflow.impl.executors.http.auth.requestbuilder.OpenIdRequestBuilder;
28+
import jakarta.ws.rs.client.Invocation;
2429
import jakarta.ws.rs.client.Invocation.Builder;
2530

2631
public class OpenIdAuthProvider implements AuthProvider {
2732

33+
private AuthRequestBuilder requestBuilder;
34+
35+
private static final String BEARER_TOKEN = "Bearer %s";
36+
2837
public OpenIdAuthProvider(
29-
WorkflowApplication app, Workflow workflow, OpenIdConnectAuthenticationPolicy authPolicy) {
30-
throw new UnsupportedOperationException("OpenId auth not supported yet");
38+
WorkflowApplication application,
39+
Workflow workflow,
40+
OpenIdConnectAuthenticationPolicy authPolicy) {
41+
OpenIdConnectAuthenticationPolicyConfiguration configuration = authPolicy.getOidc();
42+
43+
if (configuration.getOpenIdConnectAuthenticationProperties() != null) {
44+
this.requestBuilder =
45+
new OpenIdRequestBuilder(
46+
application, configuration.getOpenIdConnectAuthenticationProperties());
47+
} else if (configuration.getOpenIdConnectAuthenticationPolicySecret() != null) {
48+
throw new UnsupportedOperationException("Secrets are still not supported");
49+
}
3150
}
3251

3352
@Override
3453
public Builder build(
3554
Builder builder, WorkflowContext workflow, TaskContext task, WorkflowModel model) {
36-
// TODO Auto-generated method stub
3755
return builder;
3856
}
57+
58+
@Override
59+
public void preRequest(
60+
Invocation.Builder builder, WorkflowContext workflow, TaskContext task, WorkflowModel model) {
61+
JWT jwt = requestBuilder.build(workflow, task, model).validateAndGet();
62+
builder.header(AuthProviderFactory.AUTH_HEADER_NAME, String.format(BEARER_TOKEN, jwt.token()));
63+
}
3964
}

impl/http/src/main/java/io/serverlessworkflow/impl/executors/http/oauth/JWT.java renamed to impl/http/src/main/java/io/serverlessworkflow/impl/executors/http/auth/jwt/JWT.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16-
package io.serverlessworkflow.impl.executors.http.oauth;
16+
package io.serverlessworkflow.impl.executors.http.auth.jwt;
1717

1818
import java.time.Instant;
1919
import java.util.List;

impl/http/src/main/java/io/serverlessworkflow/impl/executors/http/oauth/JWTConverter.java renamed to impl/http/src/main/java/io/serverlessworkflow/impl/executors/http/auth/jwt/JWTConverter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16-
package io.serverlessworkflow.impl.executors.http.oauth;
16+
package io.serverlessworkflow.impl.executors.http.auth.jwt;
1717

1818
public interface JWTConverter {
1919

impl/http/src/main/java/io/serverlessworkflow/impl/executors/http/oauth/OAuthRequestBuilder.java renamed to impl/http/src/main/java/io/serverlessworkflow/impl/executors/http/auth/requestbuilder/AbstractAuthRequestBuilder.java

Lines changed: 36 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -13,63 +13,50 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16-
package io.serverlessworkflow.impl.executors.http.oauth;
16+
package io.serverlessworkflow.impl.executors.http.auth.requestbuilder;
1717

1818
import static io.serverlessworkflow.api.types.OAuth2AuthenticationDataClient.ClientAuthentication.CLIENT_SECRET_POST;
1919

2020
import io.serverlessworkflow.api.types.OAuth2AuthenticationData;
2121
import io.serverlessworkflow.api.types.OAuth2AuthenticationDataClient;
22-
import io.serverlessworkflow.api.types.OAuth2AuthenticationPropertiesEndpoints;
23-
import io.serverlessworkflow.api.types.Oauth2;
2422
import io.serverlessworkflow.impl.TaskContext;
2523
import io.serverlessworkflow.impl.WorkflowApplication;
2624
import io.serverlessworkflow.impl.WorkflowContext;
2725
import io.serverlessworkflow.impl.WorkflowModel;
28-
import java.net.URI;
2926
import java.util.Arrays;
3027
import java.util.List;
31-
import java.util.Map;
3228
import java.util.Objects;
29+
import java.util.function.Consumer;
3330
import java.util.stream.Collectors;
3431

35-
public class OAuthRequestBuilder {
32+
abstract class AbstractAuthRequestBuilder implements AuthRequestBuilder {
3633

37-
private final Oauth2 oauth2;
34+
protected final OAuth2AuthenticationData authenticationData;
3835

39-
private final OAuth2AuthenticationData authenticationData;
36+
protected final WorkflowApplication application;
4037

41-
private final WorkflowApplication application;
38+
private final List<Consumer<HttpRequestBuilder>> steps =
39+
List.of(
40+
this::requestEncoding,
41+
this::authenticationURI,
42+
this::audience,
43+
this::scope,
44+
this::authenticationMethod);
4245

43-
private List<String> issuers;
44-
45-
private final Map<String, String> defaults =
46-
Map.of(
47-
"endpoints.token", "oauth2/token",
48-
"endpoints.revocation", "oauth2/revoke",
49-
"endpoints.introspection", "oauth2/introspect");
50-
51-
public OAuthRequestBuilder(WorkflowApplication application, Oauth2 oauth2) {
52-
this.oauth2 = oauth2;
53-
this.authenticationData =
54-
oauth2.getOAuth2ConnectAuthenticationProperties().getOAuth2AuthenticationData();
46+
protected AbstractAuthRequestBuilder(
47+
OAuth2AuthenticationData authenticationData, WorkflowApplication application) {
48+
this.authenticationData = authenticationData;
5549
this.application = application;
5650
}
5751

58-
public AccessTokenProvider build(
59-
WorkflowContext workflow, TaskContext task, WorkflowModel model) {
60-
HttpRequestBuilder requestBuilder = new HttpRequestBuilder(application);
61-
62-
requestEncoding(requestBuilder);
63-
authenticationURI(requestBuilder);
64-
audience(requestBuilder);
65-
scope(requestBuilder);
66-
issuers();
67-
authenticationMethod(requestBuilder);
68-
69-
return new AccessTokenProvider(requestBuilder.build(workflow, task, model), task, issuers);
52+
protected void audience(HttpRequestBuilder requestBuilder) {
53+
if (authenticationData.getAudiences() != null && !authenticationData.getAudiences().isEmpty()) {
54+
String audiences = String.join(" ", authenticationData.getAudiences());
55+
requestBuilder.addQueryParam("audience", audiences);
56+
}
7057
}
7158

72-
private void authenticationMethod(HttpRequestBuilder requestBuilder) {
59+
protected void authenticationMethod(HttpRequestBuilder requestBuilder) {
7360
switch (getClientAuthentication()) {
7461
case CLIENT_SECRET_BASIC:
7562
clientSecretBasic(requestBuilder);
@@ -83,11 +70,11 @@ private void authenticationMethod(HttpRequestBuilder requestBuilder) {
8370
}
8471

8572
private void clientSecretBasic(HttpRequestBuilder requestBuilder) {
86-
new ClientSecretBasic(oauth2).execute(requestBuilder);
73+
new ClientSecretBasic(authenticationData).execute(requestBuilder);
8774
}
8875

8976
private void clientSecretPost(HttpRequestBuilder requestBuilder) {
90-
new ClientSecretPostStep(oauth2).execute(requestBuilder);
77+
new ClientSecretPost(authenticationData).execute(requestBuilder);
9178
}
9279

9380
private OAuth2AuthenticationDataClient.ClientAuthentication getClientAuthentication() {
@@ -98,23 +85,20 @@ private OAuth2AuthenticationDataClient.ClientAuthentication getClientAuthenticat
9885
return authenticationData.getClient().getAuthentication();
9986
}
10087

101-
private void issuers() {
102-
issuers =
103-
oauth2
104-
.getOAuth2ConnectAuthenticationProperties()
105-
.getOAuth2AuthenticationData()
106-
.getIssuers();
88+
@Override
89+
public AccessTokenProvider build(
90+
WorkflowContext workflow, TaskContext task, WorkflowModel model) {
91+
HttpRequestBuilder requestBuilder = new HttpRequestBuilder(application);
92+
steps.forEach(step -> step.accept(requestBuilder));
93+
return new AccessTokenProvider(
94+
requestBuilder.build(workflow, task, model), task, authenticationData.getIssuers());
10795
}
10896

109-
public void audience(HttpRequestBuilder requestBuilder) {
110-
if (authenticationData.getAudiences() != null && !authenticationData.getAudiences().isEmpty()) {
111-
String audiences = String.join(" ", authenticationData.getAudiences());
112-
requestBuilder.addQueryParam("audience", audiences);
113-
}
97+
protected void scope(HttpRequestBuilder requestBuilder) {
98+
scope(requestBuilder, authenticationData.getScopes());
11499
}
115100

116-
private void scope(HttpRequestBuilder requestBuilder) {
117-
List<String> scopesList = authenticationData.getScopes();
101+
protected void scope(HttpRequestBuilder requestBuilder, List<String> scopesList) {
118102
if (scopesList == null || scopesList.isEmpty()) {
119103
return;
120104
}
@@ -132,29 +116,7 @@ private void scope(HttpRequestBuilder requestBuilder) {
132116
}
133117
}
134118

135-
private void authenticationURI(HttpRequestBuilder requestBuilder) {
136-
OAuth2AuthenticationPropertiesEndpoints endpoints =
137-
oauth2
138-
.getOAuth2ConnectAuthenticationProperties()
139-
.getOAuth2ConnectAuthenticationProperties()
140-
.getEndpoints();
141-
142-
String baseUri =
143-
oauth2
144-
.getOAuth2ConnectAuthenticationProperties()
145-
.getOAuth2AuthenticationData()
146-
.getAuthority()
147-
.getLiteralUri()
148-
.toString()
149-
.replaceAll("/$", "");
150-
String tokenPath = defaults.get("endpoints.token");
151-
if (endpoints != null && endpoints.getToken() != null) {
152-
tokenPath = endpoints.getToken().replaceAll("^/", "");
153-
}
154-
requestBuilder.withUri(URI.create(baseUri + "/" + tokenPath));
155-
}
156-
157-
public void requestEncoding(HttpRequestBuilder requestBuilder) {
119+
void requestEncoding(HttpRequestBuilder requestBuilder) {
158120
if (authenticationData.getRequest() != null
159121
&& authenticationData.getRequest().getEncoding() != null) {
160122
requestBuilder.addHeader(
@@ -163,4 +125,6 @@ public void requestEncoding(HttpRequestBuilder requestBuilder) {
163125
requestBuilder.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
164126
}
165127
}
128+
129+
protected abstract void authenticationURI(HttpRequestBuilder requestBuilder);
166130
}

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,11 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16-
package io.serverlessworkflow.impl.executors.http.oauth;
16+
package io.serverlessworkflow.impl.executors.http.auth.requestbuilder;
1717

1818
import io.serverlessworkflow.impl.TaskContext;
19+
import io.serverlessworkflow.impl.executors.http.auth.jwt.JWT;
20+
import io.serverlessworkflow.impl.executors.http.auth.jwt.JWTConverter;
1921
import java.util.List;
2022
import java.util.Map;
2123
import java.util.ServiceLoader;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
* Copyright 2020-Present The Serverless Workflow Specification Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.serverlessworkflow.impl.executors.http.auth.requestbuilder;
17+
18+
import io.serverlessworkflow.impl.TaskContext;
19+
import io.serverlessworkflow.impl.WorkflowContext;
20+
import io.serverlessworkflow.impl.WorkflowModel;
21+
22+
public interface AuthRequestBuilder {
23+
24+
public AccessTokenProvider build(WorkflowContext workflow, TaskContext task, WorkflowModel model);
25+
}

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

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,26 +13,23 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16-
package io.serverlessworkflow.impl.executors.http.oauth;
16+
package io.serverlessworkflow.impl.executors.http.auth.requestbuilder;
1717

1818
import static io.serverlessworkflow.api.types.OAuth2AuthenticationData.OAuth2AuthenticationDataGrant.CLIENT_CREDENTIALS;
1919
import static io.serverlessworkflow.api.types.OAuth2AuthenticationData.OAuth2AuthenticationDataGrant.PASSWORD;
2020

2121
import io.serverlessworkflow.api.types.OAuth2AuthenticationData;
22-
import io.serverlessworkflow.api.types.Oauth2;
2322
import java.util.Base64;
2423

2524
class ClientSecretBasic {
2625

27-
private final Oauth2 oauth2;
26+
private final OAuth2AuthenticationData authenticationData;
2827

29-
public ClientSecretBasic(Oauth2 oauth2) {
30-
this.oauth2 = oauth2;
28+
ClientSecretBasic(OAuth2AuthenticationData authenticationData) {
29+
this.authenticationData = authenticationData;
3130
}
3231

33-
public void execute(HttpRequestBuilder requestBuilder) {
34-
OAuth2AuthenticationData authenticationData =
35-
oauth2.getOAuth2ConnectAuthenticationProperties().getOAuth2AuthenticationData();
32+
void execute(HttpRequestBuilder requestBuilder) {
3633
if (authenticationData.getGrant().equals(PASSWORD)) {
3734
password(requestBuilder, authenticationData);
3835
} else if (authenticationData.getGrant().equals(CLIENT_CREDENTIALS)) {

impl/http/src/main/java/io/serverlessworkflow/impl/executors/http/oauth/ClientSecretPostStep.java renamed to impl/http/src/main/java/io/serverlessworkflow/impl/executors/http/auth/requestbuilder/ClientSecretPost.java

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,25 +13,21 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16-
package io.serverlessworkflow.impl.executors.http.oauth;
16+
package io.serverlessworkflow.impl.executors.http.auth.requestbuilder;
1717

1818
import static io.serverlessworkflow.api.types.OAuth2AuthenticationData.OAuth2AuthenticationDataGrant.CLIENT_CREDENTIALS;
1919
import static io.serverlessworkflow.api.types.OAuth2AuthenticationData.OAuth2AuthenticationDataGrant.PASSWORD;
2020

2121
import io.serverlessworkflow.api.types.OAuth2AuthenticationData;
22-
import io.serverlessworkflow.api.types.Oauth2;
2322

24-
class ClientSecretPostStep {
25-
private final Oauth2 oauth2;
23+
class ClientSecretPost {
24+
private final OAuth2AuthenticationData authenticationData;
2625

27-
public ClientSecretPostStep(Oauth2 oauth2) {
28-
this.oauth2 = oauth2;
26+
ClientSecretPost(OAuth2AuthenticationData authenticationData) {
27+
this.authenticationData = authenticationData;
2928
}
3029

31-
public void execute(HttpRequestBuilder requestBuilder) {
32-
OAuth2AuthenticationData authenticationData =
33-
oauth2.getOAuth2ConnectAuthenticationProperties().getOAuth2AuthenticationData();
34-
30+
void execute(HttpRequestBuilder requestBuilder) {
3531
if (authenticationData.getGrant().equals(PASSWORD)) {
3632
password(requestBuilder, authenticationData);
3733
} else if (authenticationData.getGrant().equals(CLIENT_CREDENTIALS)) {

impl/http/src/main/java/io/serverlessworkflow/impl/executors/http/oauth/HttpRequestBuilder.java renamed to impl/http/src/main/java/io/serverlessworkflow/impl/executors/http/auth/requestbuilder/HttpRequestBuilder.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16-
package io.serverlessworkflow.impl.executors.http.oauth;
16+
package io.serverlessworkflow.impl.executors.http.auth.requestbuilder;
1717

1818
import static io.serverlessworkflow.api.types.OAuth2TokenRequest.Oauth2TokenRequestEncoding;
1919
import static io.serverlessworkflow.api.types.OAuth2TokenRequest.Oauth2TokenRequestEncoding.APPLICATION_X_WWW_FORM_URLENCODED;

0 commit comments

Comments
 (0)