Skip to content

Commit ec993ef

Browse files
authored
Expose auth policy resolution utilities for framework integrations (#1512)
* Create a resolvePolicy to help downstream frameworks Signed-off-by: Matheus Cruz <matheuscruz.dev@gmail.com> * Introduce OAuthPolicyData Signed-off-by: Matheus Cruz <matheuscruz.dev@gmail.com> * Guard against null nested configuration in OAuthPolicyData.from Signed-off-by: Matheus Cruz <matheuscruz.dev@gmail.com> * Fail fast on null workflow in resolvePolicy Signed-off-by: Matheus Cruz <matheuscruz.dev@gmail.com> * Consolidate auth utilities into OAuthUtils Signed-off-by: Matheus Cruz <matheuscruz.dev@gmail.com> * Return Optional from resolvePolicy and extract OAuthScheme enum Replace null returns with Optional in OAuthUtils.resolvePolicy to align with the existing from() method style, and extract OAuthScheme to its own top-level file. Signed-off-by: Matheus Cruz <matheuscruz.dev@gmail.com> * Extract OAuthPolicyData to a top-level file with a from() factory method Move OAuthPolicyData out of OAuthUtils into its own file so integrations can reference it directly, and add a static from(AuthenticationPolicyUnion) convenience factory that delegates to OAuthUtils.from(). Signed-off-by: Matheus Cruz <matheuscruz.dev@gmail.com> --------- Signed-off-by: Matheus Cruz <matheuscruz.dev@gmail.com>
1 parent f375b6d commit ec993ef

8 files changed

Lines changed: 364 additions & 51 deletions

File tree

impl/core/src/main/java/io/serverlessworkflow/impl/auth/DefaultAuthProviderFactory.java

Lines changed: 10 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@
1818
import io.serverlessworkflow.api.types.AuthenticationPolicyUnion;
1919
import io.serverlessworkflow.api.types.EndpointConfiguration;
2020
import io.serverlessworkflow.api.types.ReferenceableAuthenticationPolicy;
21-
import io.serverlessworkflow.api.types.Use;
22-
import io.serverlessworkflow.api.types.UseAuthentications;
2321
import io.serverlessworkflow.api.types.Workflow;
2422
import io.serverlessworkflow.impl.WorkflowApplication;
2523
import io.serverlessworkflow.impl.WorkflowDefinition;
@@ -46,35 +44,10 @@ public Optional<AuthProvider> getAuth(
4644
@Override
4745
public Optional<AuthProvider> getAuth(
4846
WorkflowDefinition definition, ReferenceableAuthenticationPolicy auth, String method) {
49-
if (auth == null) {
50-
return Optional.empty();
51-
}
52-
if (auth.getAuthenticationPolicyReference() != null) {
53-
return buildFromReference(
54-
definition.application(),
55-
definition.workflow(),
56-
auth.getAuthenticationPolicyReference().getUse(),
57-
method);
58-
} else if (auth.getAuthenticationPolicy() != null) {
59-
return buildFromPolicy(
60-
definition.application(), definition.workflow(), auth.getAuthenticationPolicy(), method);
61-
}
62-
return Optional.empty();
63-
}
64-
65-
private Optional<AuthProvider> buildFromReference(
66-
WorkflowApplication app, Workflow workflow, String use, String method) {
67-
Use useInfo = workflow.getUse();
68-
if (useInfo == null) {
69-
return Optional.empty();
70-
}
71-
UseAuthentications authInfo = useInfo.getAuthentications();
72-
return authInfo == null
73-
? Optional.empty()
74-
: authInfo.getAdditionalProperties().entrySet().stream()
75-
.filter(s -> s.getKey().equals(use))
76-
.findAny()
77-
.flatMap(e -> buildFromPolicy(app, workflow, e.getValue(), method));
47+
return OAuthUtils.resolvePolicy(definition.workflow(), auth)
48+
.flatMap(
49+
policy ->
50+
buildFromPolicy(definition.application(), definition.workflow(), policy, method));
7851
}
7952

8053
private Optional<AuthProvider> buildFromPolicy(
@@ -94,16 +67,12 @@ private Optional<AuthProvider> buildFromPolicy(
9467
return Optional.of(
9568
new DigestAuthProvider(
9669
app, workflow, authenticationPolicy.getDigestAuthenticationPolicy(), method));
97-
} else if (authenticationPolicy.getOAuth2AuthenticationPolicy() != null) {
98-
return Optional.of(
99-
new OAuth2AuthProvider(
100-
app, workflow, authenticationPolicy.getOAuth2AuthenticationPolicy()));
101-
} else if (authenticationPolicy.getOpenIdConnectAuthenticationPolicy() != null) {
102-
return Optional.of(
103-
new OpenIdAuthProvider(
104-
app, workflow, authenticationPolicy.getOpenIdConnectAuthenticationPolicy()));
10570
}
106-
107-
return Optional.empty();
71+
return OAuthUtils.from(authenticationPolicy)
72+
.map(
73+
policyData ->
74+
policyData.scheme() == OAuthScheme.OPENID_CONNECT
75+
? new OpenIdAuthProvider(app, workflow, policyData)
76+
: new OAuth2AuthProvider(app, workflow, policyData));
10877
}
10978
}

impl/core/src/main/java/io/serverlessworkflow/impl/auth/OAuth2AuthProvider.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,18 @@
1515
*/
1616
package io.serverlessworkflow.impl.auth;
1717

18-
import io.serverlessworkflow.api.types.OAuth2AuthenticationPolicy;
1918
import io.serverlessworkflow.api.types.Workflow;
2019
import io.serverlessworkflow.impl.WorkflowApplication;
2120

2221
class OAuth2AuthProvider extends CommonOAuthProvider {
2322

2423
public OAuth2AuthProvider(
25-
WorkflowApplication application, Workflow workflow, OAuth2AuthenticationPolicy authPolicy) {
24+
WorkflowApplication application, Workflow workflow, OAuthPolicyData policyData) {
2625
super(
2726
accessToken(
2827
workflow,
29-
authPolicy.getOauth2().getOAuth2ConnectAuthenticationProperties(),
30-
authPolicy.getOauth2().getOAuth2AuthenticationPolicySecret(),
28+
policyData.data(),
29+
policyData.secret(),
3130
new OAuthRequestBuilder(application)));
3231
}
3332
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
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.auth;
17+
18+
import io.serverlessworkflow.api.types.AuthenticationPolicyUnion;
19+
import io.serverlessworkflow.api.types.OAuth2AuthenticationData;
20+
import io.serverlessworkflow.api.types.SecretBasedAuthenticationPolicy;
21+
import java.util.Optional;
22+
23+
public record OAuthPolicyData(
24+
OAuth2AuthenticationData data, SecretBasedAuthenticationPolicy secret, OAuthScheme scheme) {
25+
26+
public static Optional<OAuthPolicyData> from(AuthenticationPolicyUnion policy) {
27+
return OAuthUtils.from(policy);
28+
}
29+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
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.auth;
17+
18+
public enum OAuthScheme {
19+
OAUTH2,
20+
OPENID_CONNECT
21+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
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.auth;
17+
18+
import io.serverlessworkflow.api.types.AuthenticationPolicyUnion;
19+
import io.serverlessworkflow.api.types.OAuth2AuthenticationPolicy;
20+
import io.serverlessworkflow.api.types.OAuth2AuthenticationPolicyConfiguration;
21+
import io.serverlessworkflow.api.types.OpenIdConnectAuthenticationPolicy;
22+
import io.serverlessworkflow.api.types.OpenIdConnectAuthenticationPolicyConfiguration;
23+
import io.serverlessworkflow.api.types.ReferenceableAuthenticationPolicy;
24+
import io.serverlessworkflow.api.types.Use;
25+
import io.serverlessworkflow.api.types.Workflow;
26+
import java.util.Optional;
27+
28+
public class OAuthUtils {
29+
30+
private OAuthUtils() {}
31+
32+
public static Optional<OAuthPolicyData> from(AuthenticationPolicyUnion policy) {
33+
if (policy == null) {
34+
return Optional.empty();
35+
}
36+
OAuth2AuthenticationPolicy oauth2 = policy.getOAuth2AuthenticationPolicy();
37+
if (oauth2 != null) {
38+
OAuth2AuthenticationPolicyConfiguration config = oauth2.getOauth2();
39+
if (config != null) {
40+
return Optional.of(
41+
new OAuthPolicyData(
42+
config.getOAuth2ConnectAuthenticationProperties(),
43+
config.getOAuth2AuthenticationPolicySecret(),
44+
OAuthScheme.OAUTH2));
45+
}
46+
}
47+
OpenIdConnectAuthenticationPolicy oidc = policy.getOpenIdConnectAuthenticationPolicy();
48+
if (oidc != null) {
49+
OpenIdConnectAuthenticationPolicyConfiguration config = oidc.getOidc();
50+
if (config != null) {
51+
return Optional.of(
52+
new OAuthPolicyData(
53+
config.getOpenIdConnectAuthenticationProperties(),
54+
config.getOpenIdConnectAuthenticationPolicySecret(),
55+
OAuthScheme.OPENID_CONNECT));
56+
}
57+
}
58+
return Optional.empty();
59+
}
60+
61+
public static Optional<AuthenticationPolicyUnion> resolvePolicy(
62+
Workflow workflow, ReferenceableAuthenticationPolicy auth) {
63+
if (auth == null) {
64+
return Optional.empty();
65+
}
66+
if (auth.getAuthenticationPolicyReference() != null) {
67+
String use = auth.getAuthenticationPolicyReference().getUse();
68+
return Optional.ofNullable(workflow.getUse())
69+
.map(Use::getAuthentications)
70+
.map(a -> a.getAdditionalProperties().get(use));
71+
}
72+
return Optional.ofNullable(auth.getAuthenticationPolicy());
73+
}
74+
}

impl/core/src/main/java/io/serverlessworkflow/impl/auth/OpenIdAuthProvider.java

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,21 +15,18 @@
1515
*/
1616
package io.serverlessworkflow.impl.auth;
1717

18-
import io.serverlessworkflow.api.types.OpenIdConnectAuthenticationPolicy;
1918
import io.serverlessworkflow.api.types.Workflow;
2019
import io.serverlessworkflow.impl.WorkflowApplication;
2120

2221
class OpenIdAuthProvider extends CommonOAuthProvider {
2322

2423
public OpenIdAuthProvider(
25-
WorkflowApplication application,
26-
Workflow workflow,
27-
OpenIdConnectAuthenticationPolicy authPolicy) {
24+
WorkflowApplication application, Workflow workflow, OAuthPolicyData policyData) {
2825
super(
2926
accessToken(
3027
workflow,
31-
authPolicy.getOidc().getOpenIdConnectAuthenticationProperties(),
32-
authPolicy.getOidc().getOpenIdConnectAuthenticationPolicySecret(),
28+
policyData.data(),
29+
policyData.secret(),
3330
new OpenIdRequestBuilder(application)));
3431
}
3532
}
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
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.test;
17+
18+
import static org.junit.jupiter.api.Assertions.assertEquals;
19+
import static org.junit.jupiter.api.Assertions.assertNull;
20+
import static org.junit.jupiter.api.Assertions.assertTrue;
21+
22+
import io.serverlessworkflow.api.types.AuthenticationPolicyUnion;
23+
import io.serverlessworkflow.api.types.BasicAuthenticationPolicy;
24+
import io.serverlessworkflow.api.types.OAuth2AuthenticationData;
25+
import io.serverlessworkflow.api.types.OAuth2AuthenticationPolicy;
26+
import io.serverlessworkflow.api.types.OAuth2AuthenticationPolicyConfiguration;
27+
import io.serverlessworkflow.api.types.OAuth2ConnectAuthenticationProperties;
28+
import io.serverlessworkflow.api.types.OpenIdConnectAuthenticationPolicy;
29+
import io.serverlessworkflow.api.types.OpenIdConnectAuthenticationPolicyConfiguration;
30+
import io.serverlessworkflow.api.types.SecretBasedAuthenticationPolicy;
31+
import io.serverlessworkflow.impl.auth.OAuthPolicyData;
32+
import io.serverlessworkflow.impl.auth.OAuthScheme;
33+
import io.serverlessworkflow.impl.auth.OAuthUtils;
34+
import java.util.Optional;
35+
import org.junit.jupiter.api.Test;
36+
37+
public class OAuthUtilsTest {
38+
39+
@Test
40+
void fromNullReturnsEmpty() {
41+
assertEquals(Optional.empty(), OAuthUtils.from(null));
42+
}
43+
44+
@Test
45+
void fromNonOAuthPolicyReturnsEmpty() {
46+
AuthenticationPolicyUnion union =
47+
new AuthenticationPolicyUnion()
48+
.withBasicAuthenticationPolicy(new BasicAuthenticationPolicy());
49+
assertTrue(OAuthUtils.from(union).isEmpty());
50+
}
51+
52+
@Test
53+
void fromOAuth2InlineData() {
54+
OAuth2ConnectAuthenticationProperties props = new OAuth2ConnectAuthenticationProperties();
55+
AuthenticationPolicyUnion union =
56+
new AuthenticationPolicyUnion()
57+
.withOAuth2AuthenticationPolicy(
58+
new OAuth2AuthenticationPolicy()
59+
.withOauth2(
60+
new OAuth2AuthenticationPolicyConfiguration()
61+
.withOAuth2ConnectAuthenticationProperties(props)));
62+
Optional<OAuthPolicyData> result = OAuthUtils.from(union);
63+
assertTrue(result.isPresent());
64+
OAuthPolicyData data = result.get();
65+
assertEquals(OAuthScheme.OAUTH2, data.scheme());
66+
assertEquals(props, data.data());
67+
assertNull(data.secret());
68+
}
69+
70+
@Test
71+
void fromOAuth2Secret() {
72+
SecretBasedAuthenticationPolicy secret = new SecretBasedAuthenticationPolicy("mySecret");
73+
AuthenticationPolicyUnion union =
74+
new AuthenticationPolicyUnion()
75+
.withOAuth2AuthenticationPolicy(
76+
new OAuth2AuthenticationPolicy()
77+
.withOauth2(
78+
new OAuth2AuthenticationPolicyConfiguration()
79+
.withOAuth2AuthenticationPolicySecret(secret)));
80+
Optional<OAuthPolicyData> result = OAuthUtils.from(union);
81+
assertTrue(result.isPresent());
82+
OAuthPolicyData data = result.get();
83+
assertEquals(OAuthScheme.OAUTH2, data.scheme());
84+
assertNull(data.data());
85+
assertEquals(secret, data.secret());
86+
}
87+
88+
@Test
89+
void fromOidcInlineData() {
90+
OAuth2AuthenticationData oidcData = new OAuth2AuthenticationData();
91+
AuthenticationPolicyUnion union =
92+
new AuthenticationPolicyUnion()
93+
.withOpenIdConnectAuthenticationPolicy(
94+
new OpenIdConnectAuthenticationPolicy()
95+
.withOidc(
96+
new OpenIdConnectAuthenticationPolicyConfiguration()
97+
.withOpenIdConnectAuthenticationProperties(oidcData)));
98+
Optional<OAuthPolicyData> result = OAuthUtils.from(union);
99+
assertTrue(result.isPresent());
100+
OAuthPolicyData data = result.get();
101+
assertEquals(OAuthScheme.OPENID_CONNECT, data.scheme());
102+
assertEquals(oidcData, data.data());
103+
assertNull(data.secret());
104+
}
105+
106+
@Test
107+
void fromOidcSecret() {
108+
SecretBasedAuthenticationPolicy secret = new SecretBasedAuthenticationPolicy("oidcSecret");
109+
AuthenticationPolicyUnion union =
110+
new AuthenticationPolicyUnion()
111+
.withOpenIdConnectAuthenticationPolicy(
112+
new OpenIdConnectAuthenticationPolicy()
113+
.withOidc(
114+
new OpenIdConnectAuthenticationPolicyConfiguration()
115+
.withOpenIdConnectAuthenticationPolicySecret(secret)));
116+
Optional<OAuthPolicyData> result = OAuthUtils.from(union);
117+
assertTrue(result.isPresent());
118+
OAuthPolicyData data = result.get();
119+
assertEquals(OAuthScheme.OPENID_CONNECT, data.scheme());
120+
assertNull(data.data());
121+
assertEquals(secret, data.secret());
122+
}
123+
}

0 commit comments

Comments
 (0)