Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,17 @@
import io.serverlessworkflow.impl.WorkflowApplication;
import io.serverlessworkflow.impl.WorkflowContext;
import io.serverlessworkflow.impl.WorkflowModel;
import io.serverlessworkflow.impl.executors.http.oauth.JWT;
import io.serverlessworkflow.impl.executors.http.oauth.OAuthRequestBuilder;
import io.serverlessworkflow.impl.executors.http.auth.jwt.JWT;
import io.serverlessworkflow.impl.executors.http.auth.requestbuilder.AuthRequestBuilder;
import io.serverlessworkflow.impl.executors.http.auth.requestbuilder.OAuthRequestBuilder;
import jakarta.ws.rs.client.Invocation;
import jakarta.ws.rs.client.Invocation.Builder;

public class OAuth2AuthProvider implements AuthProvider {

private OAuthRequestBuilder requestBuilder;
private AuthRequestBuilder requestBuilder;

private static final String BEARER_TOKEN = "%s %s";
private static final String BEARER_TOKEN = "Bearer %s";

public OAuth2AuthProvider(
WorkflowApplication application, Workflow workflow, OAuth2AuthenticationPolicy authPolicy) {
Expand All @@ -53,9 +54,6 @@ public Builder build(
public void preRequest(
Invocation.Builder builder, WorkflowContext workflow, TaskContext task, WorkflowModel model) {
JWT jwt = requestBuilder.build(workflow, task, model).validateAndGet();
String type =
jwt.type().orElseThrow(() -> new IllegalStateException("Token type is not present"));
builder.header(
AuthProviderFactory.AUTH_HEADER_NAME, String.format(BEARER_TOKEN, type, jwt.token()));
builder.header(AuthProviderFactory.AUTH_HEADER_NAME, String.format(BEARER_TOKEN, jwt.token()));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,49 @@
package io.serverlessworkflow.impl.executors.http;

import io.serverlessworkflow.api.types.OpenIdConnectAuthenticationPolicy;
import io.serverlessworkflow.api.types.OpenIdConnectAuthenticationPolicyConfiguration;
import io.serverlessworkflow.api.types.Workflow;
import io.serverlessworkflow.impl.TaskContext;
import io.serverlessworkflow.impl.WorkflowApplication;
import io.serverlessworkflow.impl.WorkflowContext;
import io.serverlessworkflow.impl.WorkflowModel;
import io.serverlessworkflow.impl.executors.http.auth.jwt.JWT;
import io.serverlessworkflow.impl.executors.http.auth.requestbuilder.AuthRequestBuilder;
import io.serverlessworkflow.impl.executors.http.auth.requestbuilder.OpenIdRequestBuilder;
import jakarta.ws.rs.client.Invocation;
import jakarta.ws.rs.client.Invocation.Builder;

public class OpenIdAuthProvider implements AuthProvider {

private AuthRequestBuilder requestBuilder;

private static final String BEARER_TOKEN = "Bearer %s";

public OpenIdAuthProvider(
WorkflowApplication app, Workflow workflow, OpenIdConnectAuthenticationPolicy authPolicy) {
throw new UnsupportedOperationException("OpenId auth not supported yet");
WorkflowApplication application,
Workflow workflow,
OpenIdConnectAuthenticationPolicy authPolicy) {
OpenIdConnectAuthenticationPolicyConfiguration configuration = authPolicy.getOidc();

if (configuration.getOpenIdConnectAuthenticationProperties() != null) {
this.requestBuilder =
new OpenIdRequestBuilder(
application, configuration.getOpenIdConnectAuthenticationProperties());
} else if (configuration.getOpenIdConnectAuthenticationPolicySecret() != null) {
throw new UnsupportedOperationException("Secrets are still not supported");
}
}

@Override
public Builder build(
Builder builder, WorkflowContext workflow, TaskContext task, WorkflowModel model) {
// TODO Auto-generated method stub
return builder;
}

@Override
public void preRequest(
Invocation.Builder builder, WorkflowContext workflow, TaskContext task, WorkflowModel model) {
JWT jwt = requestBuilder.build(workflow, task, model).validateAndGet();
builder.header(AuthProviderFactory.AUTH_HEADER_NAME, String.format(BEARER_TOKEN, jwt.token()));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.serverlessworkflow.impl.executors.http.oauth;
package io.serverlessworkflow.impl.executors.http.auth.jwt;

import java.time.Instant;
import java.util.List;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.serverlessworkflow.impl.executors.http.oauth;
package io.serverlessworkflow.impl.executors.http.auth.jwt;

public interface JWTConverter {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,63 +13,50 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.serverlessworkflow.impl.executors.http.oauth;
package io.serverlessworkflow.impl.executors.http.auth.requestbuilder;

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

import io.serverlessworkflow.api.types.OAuth2AuthenticationData;
import io.serverlessworkflow.api.types.OAuth2AuthenticationDataClient;
import io.serverlessworkflow.api.types.OAuth2AuthenticationPropertiesEndpoints;
import io.serverlessworkflow.api.types.Oauth2;
import io.serverlessworkflow.impl.TaskContext;
import io.serverlessworkflow.impl.WorkflowApplication;
import io.serverlessworkflow.impl.WorkflowContext;
import io.serverlessworkflow.impl.WorkflowModel;
import java.net.URI;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.stream.Collectors;

public class OAuthRequestBuilder {
abstract class AbstractAuthRequestBuilder implements AuthRequestBuilder {

private final Oauth2 oauth2;
protected final OAuth2AuthenticationData authenticationData;

private final OAuth2AuthenticationData authenticationData;
protected final WorkflowApplication application;

private final WorkflowApplication application;
private final List<Consumer<HttpRequestBuilder>> steps =
List.of(
this::requestEncoding,
this::authenticationURI,
this::audience,
this::scope,
this::authenticationMethod);

private List<String> issuers;

private final Map<String, String> defaults =
Map.of(
"endpoints.token", "oauth2/token",
"endpoints.revocation", "oauth2/revoke",
"endpoints.introspection", "oauth2/introspect");

public OAuthRequestBuilder(WorkflowApplication application, Oauth2 oauth2) {
this.oauth2 = oauth2;
this.authenticationData =
oauth2.getOAuth2ConnectAuthenticationProperties().getOAuth2AuthenticationData();
protected AbstractAuthRequestBuilder(
OAuth2AuthenticationData authenticationData, WorkflowApplication application) {
this.authenticationData = authenticationData;
this.application = application;
}

public AccessTokenProvider build(
WorkflowContext workflow, TaskContext task, WorkflowModel model) {
HttpRequestBuilder requestBuilder = new HttpRequestBuilder(application);

requestEncoding(requestBuilder);
authenticationURI(requestBuilder);
audience(requestBuilder);
scope(requestBuilder);
issuers();
authenticationMethod(requestBuilder);

return new AccessTokenProvider(requestBuilder.build(workflow, task, model), task, issuers);
protected void audience(HttpRequestBuilder requestBuilder) {
if (authenticationData.getAudiences() != null && !authenticationData.getAudiences().isEmpty()) {
String audiences = String.join(" ", authenticationData.getAudiences());
requestBuilder.addQueryParam("audience", audiences);
}
}

private void authenticationMethod(HttpRequestBuilder requestBuilder) {
protected void authenticationMethod(HttpRequestBuilder requestBuilder) {
switch (getClientAuthentication()) {
case CLIENT_SECRET_BASIC:
clientSecretBasic(requestBuilder);
Expand All @@ -83,11 +70,11 @@ private void authenticationMethod(HttpRequestBuilder requestBuilder) {
}

private void clientSecretBasic(HttpRequestBuilder requestBuilder) {
new ClientSecretBasic(oauth2).execute(requestBuilder);
new ClientSecretBasic(authenticationData).execute(requestBuilder);
}

private void clientSecretPost(HttpRequestBuilder requestBuilder) {
new ClientSecretPostStep(oauth2).execute(requestBuilder);
new ClientSecretPost(authenticationData).execute(requestBuilder);
}

private OAuth2AuthenticationDataClient.ClientAuthentication getClientAuthentication() {
Expand All @@ -98,23 +85,20 @@ private OAuth2AuthenticationDataClient.ClientAuthentication getClientAuthenticat
return authenticationData.getClient().getAuthentication();
}

private void issuers() {
issuers =
oauth2
.getOAuth2ConnectAuthenticationProperties()
.getOAuth2AuthenticationData()
.getIssuers();
@Override
public AccessTokenProvider build(
WorkflowContext workflow, TaskContext task, WorkflowModel model) {
HttpRequestBuilder requestBuilder = new HttpRequestBuilder(application);
steps.forEach(step -> step.accept(requestBuilder));
return new AccessTokenProvider(
requestBuilder.build(workflow, task, model), task, authenticationData.getIssuers());
}

public void audience(HttpRequestBuilder requestBuilder) {
if (authenticationData.getAudiences() != null && !authenticationData.getAudiences().isEmpty()) {
String audiences = String.join(" ", authenticationData.getAudiences());
requestBuilder.addQueryParam("audience", audiences);
}
protected void scope(HttpRequestBuilder requestBuilder) {
scope(requestBuilder, authenticationData.getScopes());
}

private void scope(HttpRequestBuilder requestBuilder) {
List<String> scopesList = authenticationData.getScopes();
protected void scope(HttpRequestBuilder requestBuilder, List<String> scopesList) {
if (scopesList == null || scopesList.isEmpty()) {
return;
}
Expand All @@ -132,29 +116,7 @@ private void scope(HttpRequestBuilder requestBuilder) {
}
}

private void authenticationURI(HttpRequestBuilder requestBuilder) {
OAuth2AuthenticationPropertiesEndpoints endpoints =
oauth2
.getOAuth2ConnectAuthenticationProperties()
.getOAuth2ConnectAuthenticationProperties()
.getEndpoints();

String baseUri =
oauth2
.getOAuth2ConnectAuthenticationProperties()
.getOAuth2AuthenticationData()
.getAuthority()
.getLiteralUri()
.toString()
.replaceAll("/$", "");
String tokenPath = defaults.get("endpoints.token");
if (endpoints != null && endpoints.getToken() != null) {
tokenPath = endpoints.getToken().replaceAll("^/", "");
}
requestBuilder.withUri(URI.create(baseUri + "/" + tokenPath));
}

public void requestEncoding(HttpRequestBuilder requestBuilder) {
void requestEncoding(HttpRequestBuilder requestBuilder) {
if (authenticationData.getRequest() != null
&& authenticationData.getRequest().getEncoding() != null) {
requestBuilder.addHeader(
Expand All @@ -163,4 +125,6 @@ public void requestEncoding(HttpRequestBuilder requestBuilder) {
requestBuilder.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
}
}

protected abstract void authenticationURI(HttpRequestBuilder requestBuilder);
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.serverlessworkflow.impl.executors.http.oauth;
package io.serverlessworkflow.impl.executors.http.auth.requestbuilder;

import io.serverlessworkflow.impl.TaskContext;
import io.serverlessworkflow.impl.executors.http.auth.jwt.JWT;
import io.serverlessworkflow.impl.executors.http.auth.jwt.JWTConverter;
import java.util.List;
import java.util.Map;
import java.util.ServiceLoader;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Copyright 2020-Present The Serverless Workflow Specification Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.serverlessworkflow.impl.executors.http.auth.requestbuilder;

import io.serverlessworkflow.impl.TaskContext;
import io.serverlessworkflow.impl.WorkflowContext;
import io.serverlessworkflow.impl.WorkflowModel;

public interface AuthRequestBuilder {

public AccessTokenProvider build(WorkflowContext workflow, TaskContext task, WorkflowModel model);
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,26 +13,23 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.serverlessworkflow.impl.executors.http.oauth;
package io.serverlessworkflow.impl.executors.http.auth.requestbuilder;

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

import io.serverlessworkflow.api.types.OAuth2AuthenticationData;
import io.serverlessworkflow.api.types.Oauth2;
import java.util.Base64;

class ClientSecretBasic {

private final Oauth2 oauth2;
private final OAuth2AuthenticationData authenticationData;

public ClientSecretBasic(Oauth2 oauth2) {
this.oauth2 = oauth2;
ClientSecretBasic(OAuth2AuthenticationData authenticationData) {
this.authenticationData = authenticationData;
}

public void execute(HttpRequestBuilder requestBuilder) {
OAuth2AuthenticationData authenticationData =
oauth2.getOAuth2ConnectAuthenticationProperties().getOAuth2AuthenticationData();
void execute(HttpRequestBuilder requestBuilder) {
if (authenticationData.getGrant().equals(PASSWORD)) {
password(requestBuilder, authenticationData);
} else if (authenticationData.getGrant().equals(CLIENT_CREDENTIALS)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,25 +13,21 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.serverlessworkflow.impl.executors.http.oauth;
package io.serverlessworkflow.impl.executors.http.auth.requestbuilder;

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

import io.serverlessworkflow.api.types.OAuth2AuthenticationData;
import io.serverlessworkflow.api.types.Oauth2;

class ClientSecretPostStep {
private final Oauth2 oauth2;
class ClientSecretPost {
private final OAuth2AuthenticationData authenticationData;

public ClientSecretPostStep(Oauth2 oauth2) {
this.oauth2 = oauth2;
ClientSecretPost(OAuth2AuthenticationData authenticationData) {
this.authenticationData = authenticationData;
}

public void execute(HttpRequestBuilder requestBuilder) {
OAuth2AuthenticationData authenticationData =
oauth2.getOAuth2ConnectAuthenticationProperties().getOAuth2AuthenticationData();

void execute(HttpRequestBuilder requestBuilder) {
if (authenticationData.getGrant().equals(PASSWORD)) {
password(requestBuilder, authenticationData);
} else if (authenticationData.getGrant().equals(CLIENT_CREDENTIALS)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.serverlessworkflow.impl.executors.http.oauth;
package io.serverlessworkflow.impl.executors.http.auth.requestbuilder;

import static io.serverlessworkflow.api.types.OAuth2TokenRequest.Oauth2TokenRequestEncoding;
import static io.serverlessworkflow.api.types.OAuth2TokenRequest.Oauth2TokenRequestEncoding.APPLICATION_X_WWW_FORM_URLENCODED;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.serverlessworkflow.impl.executors.http.oauth;
package io.serverlessworkflow.impl.executors.http.auth.requestbuilder;

import jakarta.ws.rs.client.Client;
import jakarta.ws.rs.core.Response;
Expand Down
Loading