This is an automated email from the ASF dual-hosted git repository.
pefernan pushed a commit to branch main
in repository
https://gitbox.apache.org/repos/asf/incubator-kie-kogito-runtimes.git
The following commit(s) were added to refs/heads/main by this push:
new 34dfa56204 [incubator-kie-issues#2309] REST-WorkItemHandler
implementation in kogito-rest-workitems (#4213)
34dfa56204 is described below
commit 34dfa56204299afd501d61583b114c6166ba82d1
Author: Christine-Jose <[email protected]>
AuthorDate: Wed May 13 21:34:07 2026 +0530
[incubator-kie-issues#2309] REST-WorkItemHandler implementation in
kogito-rest-workitems (#4213)
* Changes for REST WorkItemHandler
* WIH changes
* WIH token propagation changes
* Registering quarkus
* - code changes
* Changes for REST WorkItemHandler
* Review and testing changes
* Adding License Header
* Review comments
* Review comments and issue fixes
* Review comments addressed
* Bug fix
* Review Comments
* Review Comments
* Review Comments
* Review comments
* Review Comments
* Review Comment
* Review comments
---------
Co-authored-by: Pere Fernández <[email protected]>
---
.../org/kie/kogito/auth/AuthTokenProvider.java | 18 +-
.../kogito/auth/impl/NoOpAuthTokenProvider.java | 23 +-
.../java/org/kie/kogito/process/ProcessConfig.java | 3 +
.../compiler/canonical/WorkItemNodeVisitor.java | 18 +-
.../canonical/descriptors/RestTaskDescriptor.java | 15 +-
.../canonical/descriptors/TaskDescriptor.java | 8 +
.../descriptors/TaskDescriptorBuilder.java | 3 +-
.../RestWorkItemHandlerTemplate.java | 3 +
.../kogito/process/impl/AbstractProcessConfig.java | 10 +
.../kogito/process/impl/StaticProcessConfig.java | 22 ++
.../process/impl/AbstractProcessConfigTest.java | 2 +-
.../calendar/BusinessCalendarTimerProcessTest.java | 2 +-
.../process/workitems/impl/ConfigResolver.java} | 19 +-
.../workitems/impl/ConfigResolverHolder.java} | 24 +-
.../workitems/impl/ConfigWorkItemResolver.java | 56 +++++
.../impl/SystemPropertiesConfigResolver.java | 21 +-
.../config/ProcessConfigQuarkusTemplate.java | 4 +-
.../config/ProcessConfigSpringTemplate.java | 3 +
kogito-workitems/kogito-rest-workitem/pom.xml | 8 +
.../kogito/workitem/rest/RestWorkItemHandler.java | 12 +-
.../rest/decorators/TokenPropagationDecorator.java | 141 ++++++++++++
...ogito.workitem.rest.decorators.RequestDecorator | 1 +
.../rest/decorators/ParamsDecoratorTest.java | 3 +
.../decorators/TokenPropagationDecoratorTest.java | 255 +++++++++++++++++++++
.../quarkus/auth/QuarkusAuthTokenProvider.java | 62 +++++
.../deployment/ProcessesAssetsProcessor.java | 4 +-
.../processes/workitems/QuarkusConfigResolver.java | 58 +++++
springboot/addons/common/pom.xml | 2 +-
.../kogito-processes-spring-boot-starter/pom.xml | 10 +
.../kogito/process/SpringBootConfigResolver.java | 48 ++++
.../spring}/auth/SecurityContextInitializer.java | 4 +-
.../spring/auth/SpringAuthTokenProvider.java | 57 +++++
.../kogito/spring/auth/token/AuthTokenReader.java | 21 +-
.../auth/token/impl/JwtAuthTokenReader.java} | 21 +-
.../auth/token/impl/OIDCAuthTokenReader.java} | 21 +-
.../SpringBootAuthTokenProvider.java | 56 +++++
36 files changed, 928 insertions(+), 110 deletions(-)
diff --git
a/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/descriptors/TaskDescriptor.java
b/api/kogito-api/src/main/java/org/kie/kogito/auth/AuthTokenProvider.java
similarity index 63%
copy from
jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/descriptors/TaskDescriptor.java
copy to api/kogito-api/src/main/java/org/kie/kogito/auth/AuthTokenProvider.java
index 7e9e2c737c..d17218ac1d 100644
---
a/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/descriptors/TaskDescriptor.java
+++ b/api/kogito-api/src/main/java/org/kie/kogito/auth/AuthTokenProvider.java
@@ -16,22 +16,12 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.jbpm.compiler.canonical.descriptors;
+package org.kie.kogito.auth;
-import com.github.javaparser.ast.CompilationUnit;
+import java.util.Optional;
-public interface TaskDescriptor {
+public interface AuthTokenProvider {
- String KEY_WORKITEM_TYPE = "Type";
- String KEY_WORKITEM_INTERFACE = "Interface";
- String KEY_WORKITEM_OPERATION = "Operation";
- String KEY_SERVICE_IMPL = "implementation";
- String DEFAULT_SERVICE_IMPL = "Java";
-
- String getName();
-
- String getType();
-
- CompilationUnit generateHandlerClassForService();
+ Optional<String> getAuthToken();
}
diff --git
a/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/descriptors/TaskDescriptor.java
b/api/kogito-api/src/main/java/org/kie/kogito/auth/impl/NoOpAuthTokenProvider.java
similarity index 63%
copy from
jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/descriptors/TaskDescriptor.java
copy to
api/kogito-api/src/main/java/org/kie/kogito/auth/impl/NoOpAuthTokenProvider.java
index 7e9e2c737c..8487c4b03f 100644
---
a/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/descriptors/TaskDescriptor.java
+++
b/api/kogito-api/src/main/java/org/kie/kogito/auth/impl/NoOpAuthTokenProvider.java
@@ -16,22 +16,15 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.jbpm.compiler.canonical.descriptors;
+package org.kie.kogito.auth.impl;
-import com.github.javaparser.ast.CompilationUnit;
+import java.util.Optional;
-public interface TaskDescriptor {
-
- String KEY_WORKITEM_TYPE = "Type";
- String KEY_WORKITEM_INTERFACE = "Interface";
- String KEY_WORKITEM_OPERATION = "Operation";
- String KEY_SERVICE_IMPL = "implementation";
- String DEFAULT_SERVICE_IMPL = "Java";
-
- String getName();
-
- String getType();
-
- CompilationUnit generateHandlerClassForService();
+import org.kie.kogito.auth.AuthTokenProvider;
+public class NoOpAuthTokenProvider implements AuthTokenProvider {
+ @Override
+ public Optional<String> getAuthToken() {
+ return Optional.empty();
+ }
}
diff --git
a/api/kogito-api/src/main/java/org/kie/kogito/process/ProcessConfig.java
b/api/kogito-api/src/main/java/org/kie/kogito/process/ProcessConfig.java
index 794d859aba..dd271cf579 100644
--- a/api/kogito-api/src/main/java/org/kie/kogito/process/ProcessConfig.java
+++ b/api/kogito-api/src/main/java/org/kie/kogito/process/ProcessConfig.java
@@ -19,6 +19,7 @@
package org.kie.kogito.process;
import org.kie.kogito.KogitoConfig;
+import org.kie.kogito.auth.AuthTokenProvider;
import org.kie.kogito.auth.IdentityProvider;
import org.kie.kogito.calendar.BusinessCalendar;
import org.kie.kogito.jobs.JobsService;
@@ -41,5 +42,7 @@ public interface ProcessConfig extends KogitoConfig {
IdentityProvider identityProvider();
+ AuthTokenProvider authTokenProvider();
+
BusinessCalendar getBusinessCalendar();
}
diff --git
a/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/WorkItemNodeVisitor.java
b/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/WorkItemNodeVisitor.java
index 4441f9d616..b344fdf4b2 100644
---
a/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/WorkItemNodeVisitor.java
+++
b/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/WorkItemNodeVisitor.java
@@ -18,7 +18,10 @@
*/
package org.jbpm.compiler.canonical;
+import java.util.Collections;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
@@ -86,6 +89,7 @@ public class WorkItemNodeVisitor<T extends WorkItemNode>
extends AbstractNodeVis
String workName = node.getWork().getName();
final String nodeId = getNodeId(node);
+ Map<String, Expression> customParams = new HashMap<>();
if (TaskDescriptorBuilder.isBuilderSupported(workName)) {
final TaskDescriptor taskDescriptor = new
TaskDescriptorBuilder(workName)
.withProcessMetadata(metadata)
@@ -94,6 +98,7 @@ public class WorkItemNodeVisitor<T extends WorkItemNode>
extends AbstractNodeVis
.build();
workName = taskDescriptor.getName();
metadata.getGeneratedHandlers().put(workName,
taskDescriptor.generateHandlerClassForService());
+ customParams.putAll(taskDescriptor.getCustomParams());
}
body.addStatement(getAssignedFactoryMethod(factoryField,
WorkItemNodeFactory.class, getNodeId(node), getNodeKey(),
getWorkflowElementConstructor(node.getId())))
@@ -104,7 +109,7 @@ public class WorkItemNodeVisitor<T extends WorkItemNode>
extends AbstractNodeVis
body.addStatement(getFactoryMethod(nodeId,
METHOD_WORK_PARAMETER_FACTORY,
ExpressionUtils.getLiteralExpr(work.getWorkParametersFactory())));
}
- addWorkItemParameters(work, body, nodeId);
+ addWorkItemParameters(work, body, nodeId, customParams);
addNodeMappings(node, body, nodeId);
body.addStatement(getDoneMethod(nodeId));
@@ -116,10 +121,19 @@ public class WorkItemNodeVisitor<T extends WorkItemNode>
extends AbstractNodeVis
protected void addWorkItemParameters(Work work, BlockStmt body, String
variableName) {
// This is to ensure that each run of the generator produces the same
code.
+ addWorkItemParameters(work, body, variableName,
Collections.emptyMap());
+ }
+
+ private void addWorkItemParameters(Work work, BlockStmt body, String
variableName, Map<String, Expression> customParams) {
+ for (Map.Entry<String, Expression> entry : customParams.entrySet()) {
+ body.addStatement(getFactoryMethod(variableName,
METHOD_WORK_PARAMETER,
+ new StringLiteralExpr(entry.getKey()), entry.getValue()));
+ }
+
final List<Entry<String, Object>> sortedParameters =
work.getParameters().entrySet().stream().sorted(Entry.comparingByKey()).toList();
for (Entry<String, Object> entry : sortedParameters) {
if (entry.getValue() == null) {
- continue; // interfaceImplementationRef ?
+ continue;// interfaceImplementationRef ?
}
String paramType = null;
if (work.getParameterDefinition(entry.getKey()) != null) {
diff --git
a/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/descriptors/RestTaskDescriptor.java
b/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/descriptors/RestTaskDescriptor.java
index 2045307a33..d2461be5c4 100644
---
a/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/descriptors/RestTaskDescriptor.java
+++
b/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/descriptors/RestTaskDescriptor.java
@@ -18,7 +18,11 @@
*/
package org.jbpm.compiler.canonical.descriptors;
+import java.util.Collections;
+import java.util.Map;
+
import org.jbpm.compiler.canonical.ProcessMetaData;
+import org.jbpm.workflow.core.node.WorkItemNode;
import org.kie.kogito.internal.utils.ConversionUtils;
import com.github.javaparser.ast.CompilationUnit;
@@ -26,6 +30,7 @@ import com.github.javaparser.ast.NodeList;
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
import com.github.javaparser.ast.body.ConstructorDeclaration;
import com.github.javaparser.ast.body.MethodDeclaration;
+import com.github.javaparser.ast.expr.Expression;
import com.github.javaparser.ast.expr.StringLiteralExpr;
import com.github.javaparser.ast.stmt.BlockStmt;
import com.github.javaparser.ast.stmt.ReturnStmt;
@@ -37,9 +42,11 @@ public class RestTaskDescriptor implements TaskDescriptor {
public static final String TYPE = "Rest";
private final ProcessMetaData processMetadata;
+ private final WorkItemNode workItemNode;
- protected RestTaskDescriptor(final ProcessMetaData processMetadata) {
+ protected RestTaskDescriptor(final ProcessMetaData processMetadata, final
WorkItemNode workItemNode) {
this.processMetadata = processMetadata;
+ this.workItemNode = workItemNode;
}
@Override
@@ -64,4 +71,10 @@ public class RestTaskDescriptor implements TaskDescriptor {
.forEach(m -> m.setBody(new BlockStmt(NodeList.nodeList(new
ReturnStmt(new StringLiteralExpr(className))))));
return compilationUnit;
}
+
+ @Override
+ public Map<String, Expression> getCustomParams() {
+ return Collections.emptyMap();
+ }
+
}
diff --git
a/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/descriptors/TaskDescriptor.java
b/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/descriptors/TaskDescriptor.java
index 7e9e2c737c..60c1bc1f7a 100644
---
a/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/descriptors/TaskDescriptor.java
+++
b/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/descriptors/TaskDescriptor.java
@@ -18,7 +18,11 @@
*/
package org.jbpm.compiler.canonical.descriptors;
+import java.util.Collections;
+import java.util.Map;
+
import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.expr.Expression;
public interface TaskDescriptor {
@@ -34,4 +38,8 @@ public interface TaskDescriptor {
CompilationUnit generateHandlerClassForService();
+ default Map<String, Expression> getCustomParams() {
+ return Collections.emptyMap();
+ }
+
}
diff --git
a/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/descriptors/TaskDescriptorBuilder.java
b/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/descriptors/TaskDescriptorBuilder.java
index b8651bef4f..91a868740b 100644
---
a/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/descriptors/TaskDescriptorBuilder.java
+++
b/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/descriptors/TaskDescriptorBuilder.java
@@ -71,7 +71,8 @@ public final class TaskDescriptorBuilder {
switch (this.descriptorName) {
case (RestTaskDescriptor.TYPE):
requireNonNull(this.metadata, "Error creating descriptor " +
RestTaskDescriptor.TYPE + " ProcessMetadata can't be null");
- return new RestTaskDescriptor(this.metadata);
+ requireNonNull(this.workItemNode, "Error creating descriptor "
+ RestTaskDescriptor.TYPE + " WorkItemNode can't be null");
+ return new RestTaskDescriptor(this.metadata,
this.workItemNode);
case (ServiceTaskDescriptor.TYPE):
requireNonNull(this.workItemNode, "Error creating descriptor "
+ ServiceTaskDescriptor.TYPE + " WorkItemNode can't be null");
requireNonNull(this.classLoader, "Error creating descriptor "
+ ServiceTaskDescriptor.TYPE + " Classloader can't be null");
diff --git
a/jbpm/jbpm-flow-builder/src/main/resources/class-templates/RestWorkItemHandlerTemplate.java
b/jbpm/jbpm-flow-builder/src/main/resources/class-templates/RestWorkItemHandlerTemplate.java
index 513bf0be93..396a07a7f7 100644
---
a/jbpm/jbpm-flow-builder/src/main/resources/class-templates/RestWorkItemHandlerTemplate.java
+++
b/jbpm/jbpm-flow-builder/src/main/resources/class-templates/RestWorkItemHandlerTemplate.java
@@ -24,12 +24,15 @@ import io.vertx.mutiny.core.Vertx;
import org.kogito.workitem.rest.RestWorkItemHandler;
import static
org.kogito.workitem.rest.RestWorkItemHandlerUtils.sslWebClientOptions;
+
public class xxxRestWorkItemHandler extends RestWorkItemHandler {
+
public xxxRestWorkItemHandler() {
this(Vertx.vertx(), sslWebClientOptions());
}
+
public xxxRestWorkItemHandler(Vertx vertx, WebClientOptions sslOptions) {
super(WebClient.create(vertx), WebClient.create(vertx, sslOptions));
}
diff --git
a/jbpm/jbpm-flow/src/main/java/org/kie/kogito/process/impl/AbstractProcessConfig.java
b/jbpm/jbpm-flow/src/main/java/org/kie/kogito/process/impl/AbstractProcessConfig.java
index 826efc66d4..8e9c446340 100644
---
a/jbpm/jbpm-flow/src/main/java/org/kie/kogito/process/impl/AbstractProcessConfig.java
+++
b/jbpm/jbpm-flow/src/main/java/org/kie/kogito/process/impl/AbstractProcessConfig.java
@@ -27,7 +27,9 @@ import java.util.stream.StreamSupport;
import org.kie.api.event.process.ProcessEventListener;
import org.kie.kogito.Addons;
+import org.kie.kogito.auth.AuthTokenProvider;
import org.kie.kogito.auth.IdentityProvider;
+import org.kie.kogito.auth.impl.NoOpAuthTokenProvider;
import org.kie.kogito.calendar.BusinessCalendar;
import org.kie.kogito.event.EventPublisher;
import org.kie.kogito.jobs.JobsService;
@@ -53,6 +55,7 @@ public abstract class AbstractProcessConfig implements
ProcessConfig {
private final JobsService jobsService;
private final ProcessVersionResolver versionResolver;
private final IdentityProvider identityProvider;
+ private final AuthTokenProvider authTokenProvider;
private final BusinessCalendar businessCalendar;
protected AbstractProcessConfig(
@@ -66,6 +69,7 @@ public abstract class AbstractProcessConfig implements
ProcessConfig {
Iterable<UnitOfWorkEventListener> unitOfWorkListeners,
Iterable<ProcessVersionResolver> versionResolver,
Iterable<IdentityProvider> identityProvider,
+ Iterable<AuthTokenProvider> authTokenProvider,
Iterable<BusinessCalendar> businessCalendar) {
this.workItemHandlerConfig =
mergeWorkItemHandler(workItemHandlerConfig, DefaultWorkItemHandlerConfig::new);
@@ -74,6 +78,7 @@ public abstract class AbstractProcessConfig implements
ProcessConfig {
this.jobsService = orDefault(jobsService,
StaticJobService::staticJobService);
this.versionResolver = orDefault(versionResolver, () -> null);
this.identityProvider = orDefault(identityProvider,
NoOpIdentityProvider::new);
+ this.authTokenProvider = orDefault(authTokenProvider,
NoOpAuthTokenProvider::new);
this.businessCalendar = orDefault(businessCalendar, () -> null);
eventPublishers.forEach(publisher ->
unitOfWorkManager().eventManager().addPublisher(publisher));
@@ -127,6 +132,11 @@ public abstract class AbstractProcessConfig implements
ProcessConfig {
return identityProvider;
}
+ @Override
+ public AuthTokenProvider authTokenProvider() {
+ return authTokenProvider;
+ }
+
@Override
public BusinessCalendar getBusinessCalendar() {
return this.businessCalendar;
diff --git
a/jbpm/jbpm-flow/src/main/java/org/kie/kogito/process/impl/StaticProcessConfig.java
b/jbpm/jbpm-flow/src/main/java/org/kie/kogito/process/impl/StaticProcessConfig.java
index 456248960a..6dbbe61a5d 100644
---
a/jbpm/jbpm-flow/src/main/java/org/kie/kogito/process/impl/StaticProcessConfig.java
+++
b/jbpm/jbpm-flow/src/main/java/org/kie/kogito/process/impl/StaticProcessConfig.java
@@ -18,7 +18,9 @@
*/
package org.kie.kogito.process.impl;
+import org.kie.kogito.auth.AuthTokenProvider;
import org.kie.kogito.auth.IdentityProvider;
+import org.kie.kogito.auth.impl.NoOpAuthTokenProvider;
import org.kie.kogito.calendar.BusinessCalendar;
import org.kie.kogito.internal.process.event.KogitoProcessEventListener;
import org.kie.kogito.internal.process.workitem.KogitoWorkItemHandler;
@@ -45,6 +47,7 @@ public class StaticProcessConfig implements ProcessConfig {
private ProcessVersionResolver versionResolver;
private IdentityProvider identityProvider;
+ private AuthTokenProvider authTokenProvider;
private BusinessCalendar businessCalendar;
public StaticProcessConfig(JobsService jobService) {
@@ -80,6 +83,18 @@ public class StaticProcessConfig implements ProcessConfig {
ProcessVersionResolver versionResolver,
IdentityProvider identityProvider,
BusinessCalendar calendar) {
+ this(workItemHandlerConfig, processEventListenerConfig,
unitOfWorkManager, jobsService, versionResolver, identityProvider, null,
calendar);
+ }
+
+ public StaticProcessConfig(
+ WorkItemHandlerConfig workItemHandlerConfig,
+ ProcessEventListenerConfig processEventListenerConfig,
+ UnitOfWorkManager unitOfWorkManager,
+ JobsService jobsService,
+ ProcessVersionResolver versionResolver,
+ IdentityProvider identityProvider,
+ AuthTokenProvider authTokenProvider,
+ BusinessCalendar calendar) {
this.unitOfWorkManager = unitOfWorkManager;
this.workItemHandlerConfig = workItemHandlerConfig;
this.processEventListenerConfig = processEventListenerConfig;
@@ -87,6 +102,7 @@ public class StaticProcessConfig implements ProcessConfig {
this.jobsService = jobsService;
this.versionResolver = versionResolver;
this.identityProvider = identityProvider;
+ this.authTokenProvider = authTokenProvider;
this.businessCalendar = calendar;
}
@@ -135,6 +151,11 @@ public class StaticProcessConfig implements ProcessConfig {
return identityProvider;
}
+ @Override
+ public AuthTokenProvider authTokenProvider() {
+ return authTokenProvider;
+ }
+
@Override
public BusinessCalendar getBusinessCalendar() {
return this.businessCalendar;
@@ -153,6 +174,7 @@ public class StaticProcessConfig implements ProcessConfig {
StaticProcessConfig.this.jobsService = staticJobService();
StaticProcessConfig.this.versionResolver = process ->
process.version();
StaticProcessConfig.this.identityProvider = new
NoOpIdentityProvider();
+ StaticProcessConfig.this.authTokenProvider = new
NoOpAuthTokenProvider();
StaticProcessConfig.this.businessCalendar = null;
}
diff --git
a/jbpm/jbpm-flow/src/test/java/org/kie/kogito/process/impl/AbstractProcessConfigTest.java
b/jbpm/jbpm-flow/src/test/java/org/kie/kogito/process/impl/AbstractProcessConfigTest.java
index 6a3f26da38..82fe96b9db 100644
---
a/jbpm/jbpm-flow/src/test/java/org/kie/kogito/process/impl/AbstractProcessConfigTest.java
+++
b/jbpm/jbpm-flow/src/test/java/org/kie/kogito/process/impl/AbstractProcessConfigTest.java
@@ -34,7 +34,7 @@ public class AbstractProcessConfigTest {
private static class MockProcessConfig extends AbstractProcessConfig {
protected MockProcessConfig(Iterable<WorkItemHandlerConfig>
workItemHandlerConfig) {
super(workItemHandlerConfig, Collections.emptyList(),
Collections.emptyList(), Collections.emptyList(), Collections.emptyList(),
- Collections.emptyList(), null, Collections.emptyList(),
Collections.emptyList(), Collections.emptyList(), Collections.emptyList());
+ Collections.emptyList(), null, Collections.emptyList(),
Collections.emptyList(), Collections.emptyList(), Collections.emptyList(),
Collections.emptyList());
}
}
diff --git
a/jbpm/jbpm-tests/src/test/java/org/jbpm/bpmn2/calendar/BusinessCalendarTimerProcessTest.java
b/jbpm/jbpm-tests/src/test/java/org/jbpm/bpmn2/calendar/BusinessCalendarTimerProcessTest.java
index 7fa82242ad..838fec0d6e 100644
---
a/jbpm/jbpm-tests/src/test/java/org/jbpm/bpmn2/calendar/BusinessCalendarTimerProcessTest.java
+++
b/jbpm/jbpm-tests/src/test/java/org/jbpm/bpmn2/calendar/BusinessCalendarTimerProcessTest.java
@@ -114,7 +114,7 @@ public class BusinessCalendarTimerProcessTest {
private static class MockProcessConfig extends AbstractProcessConfig {
private MockProcessConfig(BusinessCalendar businessCalendar) {
super(Collections.emptyList(), Collections.emptyList(),
Collections.emptyList(), Collections.emptyList(), Collections.emptyList(),
- Collections.emptyList(), null, Collections.emptyList(),
Collections.emptyList(), Collections.emptyList(), List.of(businessCalendar));
+ Collections.emptyList(), null, Collections.emptyList(),
Collections.emptyList(), Collections.emptyList(), Collections.emptyList(),
List.of(businessCalendar));
}
}
}
diff --git
a/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/descriptors/TaskDescriptor.java
b/jbpm/process-workitems/src/main/java/org/kie/kogito/process/workitems/impl/ConfigResolver.java
similarity index 63%
copy from
jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/descriptors/TaskDescriptor.java
copy to
jbpm/process-workitems/src/main/java/org/kie/kogito/process/workitems/impl/ConfigResolver.java
index 7e9e2c737c..45fc80074c 100644
---
a/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/descriptors/TaskDescriptor.java
+++
b/jbpm/process-workitems/src/main/java/org/kie/kogito/process/workitems/impl/ConfigResolver.java
@@ -16,22 +16,11 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.jbpm.compiler.canonical.descriptors;
+package org.kie.kogito.process.workitems.impl;
-import com.github.javaparser.ast.CompilationUnit;
+import java.util.Optional;
-public interface TaskDescriptor {
-
- String KEY_WORKITEM_TYPE = "Type";
- String KEY_WORKITEM_INTERFACE = "Interface";
- String KEY_WORKITEM_OPERATION = "Operation";
- String KEY_SERVICE_IMPL = "implementation";
- String DEFAULT_SERVICE_IMPL = "Java";
-
- String getName();
-
- String getType();
-
- CompilationUnit generateHandlerClassForService();
+public interface ConfigResolver {
+ <T> Optional<T> getConfigProperty(String name, Class<T> clazz);
}
diff --git
a/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/descriptors/TaskDescriptor.java
b/jbpm/process-workitems/src/main/java/org/kie/kogito/process/workitems/impl/ConfigResolverHolder.java
similarity index 63%
copy from
jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/descriptors/TaskDescriptor.java
copy to
jbpm/process-workitems/src/main/java/org/kie/kogito/process/workitems/impl/ConfigResolverHolder.java
index 7e9e2c737c..bd7d7276b2 100644
---
a/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/descriptors/TaskDescriptor.java
+++
b/jbpm/process-workitems/src/main/java/org/kie/kogito/process/workitems/impl/ConfigResolverHolder.java
@@ -16,22 +16,20 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.jbpm.compiler.canonical.descriptors;
+package org.kie.kogito.process.workitems.impl;
-import com.github.javaparser.ast.CompilationUnit;
+public class ConfigResolverHolder {
-public interface TaskDescriptor {
+ private static ConfigResolver configResolver = new
SystemPropertiesConfigResolver();
- String KEY_WORKITEM_TYPE = "Type";
- String KEY_WORKITEM_INTERFACE = "Interface";
- String KEY_WORKITEM_OPERATION = "Operation";
- String KEY_SERVICE_IMPL = "implementation";
- String DEFAULT_SERVICE_IMPL = "Java";
+ public static void setConfigResolver(ConfigResolver resolver) {
+ ConfigResolverHolder.configResolver = resolver;
+ }
- String getName();
-
- String getType();
-
- CompilationUnit generateHandlerClassForService();
+ public static ConfigResolver getConfigResolver() {
+ return configResolver;
+ }
+ private ConfigResolverHolder() {
+ }
}
diff --git
a/jbpm/process-workitems/src/main/java/org/kie/kogito/process/workitems/impl/ConfigWorkItemResolver.java
b/jbpm/process-workitems/src/main/java/org/kie/kogito/process/workitems/impl/ConfigWorkItemResolver.java
new file mode 100644
index 0000000000..55ea91dd4f
--- /dev/null
+++
b/jbpm/process-workitems/src/main/java/org/kie/kogito/process/workitems/impl/ConfigWorkItemResolver.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.kie.kogito.process.workitems.impl;
+
+import org.kie.kogito.internal.process.workitem.KogitoWorkItem;
+
+public class ConfigWorkItemResolver<T> implements WorkItemParamResolver<T> {
+
+ private final String key;
+ private final Class<T> clazz;
+ private final T defaultValue;
+
+ @SuppressWarnings("unchecked")
+ public ConfigWorkItemResolver(String key) {
+ this(key, (Class<T>) String.class, null);
+ }
+
+ public ConfigWorkItemResolver(String key, Class<T> clazz, T defaultValue) {
+ this.key = key;
+ this.clazz = clazz;
+ this.defaultValue = defaultValue;
+ }
+
+ @Override
+ public T apply(KogitoWorkItem workitem) {
+ return ConfigResolverHolder.getConfigResolver().getConfigProperty(key,
clazz).orElse(defaultValue);
+ }
+
+ public String getKey() {
+ return key;
+ }
+
+ public Class<T> getClazz() {
+ return clazz;
+ }
+
+ public T getDefaultValue() {
+ return defaultValue;
+ }
+}
diff --git
a/springboot/addons/common/common-auth/src/main/java/org/kie/addons/springboot/auth/SecurityContextInitializer.java
b/jbpm/process-workitems/src/main/java/org/kie/kogito/process/workitems/impl/SystemPropertiesConfigResolver.java
similarity index 60%
copy from
springboot/addons/common/common-auth/src/main/java/org/kie/addons/springboot/auth/SecurityContextInitializer.java
copy to
jbpm/process-workitems/src/main/java/org/kie/kogito/process/workitems/impl/SystemPropertiesConfigResolver.java
index fa3327e6fc..73ed894987 100644
---
a/springboot/addons/common/common-auth/src/main/java/org/kie/addons/springboot/auth/SecurityContextInitializer.java
+++
b/jbpm/process-workitems/src/main/java/org/kie/kogito/process/workitems/impl/SystemPropertiesConfigResolver.java
@@ -16,19 +16,20 @@
* specific language governing permissions and limitations
* under the License.
*/
+package org.kie.kogito.process.workitems.impl;
-package org.kie.addons.springboot.auth;
+import java.util.Optional;
-import org.springframework.beans.factory.InitializingBean;
-import org.springframework.security.core.context.SecurityContextHolder;
-import org.springframework.stereotype.Component;
-
-@Component
-public class SecurityContextInitializer implements InitializingBean {
+public class SystemPropertiesConfigResolver implements ConfigResolver {
@Override
- public void afterPropertiesSet() throws Exception {
- // ensure the security context is inherited to child threads
-
SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL);
+ public <T> Optional<T> getConfigProperty(String name, Class<T> clazz) {
+ Object value = null;
+ if (Integer.class.isAssignableFrom(clazz)) {
+ value = Integer.getInteger(name);
+ } else if (String.class.isAssignableFrom(clazz) ||
Object.class.equals(clazz)) {
+ value = System.getProperty(name);
+ }
+ return Optional.ofNullable(clazz.cast(value));
}
}
diff --git
a/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/config/ProcessConfigQuarkusTemplate.java
b/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/config/ProcessConfigQuarkusTemplate.java
index 98daf8fbdc..a80ce02012 100644
---
a/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/config/ProcessConfigQuarkusTemplate.java
+++
b/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/config/ProcessConfigQuarkusTemplate.java
@@ -19,6 +19,7 @@
package $Package$;
import org.kie.api.event.process.ProcessEventListener;
+import org.kie.kogito.auth.AuthTokenProvider;
import org.kie.kogito.auth.IdentityProvider;
import org.kie.kogito.calendar.BusinessCalendar;
import org.kie.kogito.event.EventPublisher;
@@ -46,6 +47,7 @@ public class ProcessConfig extends
org.kie.kogito.process.impl.AbstractProcessCo
Instance<UnitOfWorkEventListener> unitOfWorkEventListeners,
Instance<ProcessVersionResolver> versionResolver,
Instance<IdentityProvider> identityProvider,
+ Instance<AuthTokenProvider> authTokenProvider,
Instance<BusinessCalendar> businessCalendar) {
super(workItemHandlerConfig,
@@ -58,7 +60,7 @@ public class ProcessConfig extends
org.kie.kogito.process.impl.AbstractProcessCo
unitOfWorkEventListeners,
versionResolver,
identityProvider,
+ authTokenProvider,
businessCalendar);
}
-
}
diff --git
a/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/config/ProcessConfigSpringTemplate.java
b/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/config/ProcessConfigSpringTemplate.java
index 8152091578..adbdb31856 100644
---
a/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/config/ProcessConfigSpringTemplate.java
+++
b/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/config/ProcessConfigSpringTemplate.java
@@ -21,6 +21,7 @@ package $Package$;
import java.util.List;
import org.kie.api.event.process.ProcessEventListener;
+import org.kie.kogito.auth.AuthTokenProvider;
import org.kie.kogito.auth.IdentityProvider;
import org.kie.kogito.calendar.BusinessCalendar;
import org.kie.kogito.event.EventPublisher;
@@ -46,6 +47,7 @@ public class ProcessConfig extends
org.kie.kogito.process.impl.AbstractProcessCo
List<UnitOfWorkEventListener> unitOfWorkEventListeners,
List<ProcessVersionResolver> versionResolver,
List<IdentityProvider> identityProvider,
+ List<AuthTokenProvider> authTokenProvider,
List<BusinessCalendar> businessCalendar) {
super(workItemHandlerConfig,
@@ -58,6 +60,7 @@ public class ProcessConfig extends
org.kie.kogito.process.impl.AbstractProcessCo
unitOfWorkEventListeners,
versionResolver,
identityProvider,
+ authTokenProvider,
businessCalendar);
}
}
diff --git a/kogito-workitems/kogito-rest-workitem/pom.xml
b/kogito-workitems/kogito-rest-workitem/pom.xml
index 75ebc13e8a..b7a3a27066 100644
--- a/kogito-workitems/kogito-rest-workitem/pom.xml
+++ b/kogito-workitems/kogito-rest-workitem/pom.xml
@@ -44,6 +44,14 @@
<artifactId>jbpm-deps-group-engine</artifactId>
<type>pom</type>
</dependency>
+ <dependency>
+ <groupId>org.kie.kogito</groupId>
+ <artifactId>process-workitems</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.kie.kogito</groupId>
+ <artifactId>kogito-api</artifactId>
+ </dependency>
<dependency>
<groupId>org.kie.kogito</groupId>
<artifactId>kogito-rest-utils</artifactId>
diff --git
a/kogito-workitems/kogito-rest-workitem/src/main/java/org/kogito/workitem/rest/RestWorkItemHandler.java
b/kogito-workitems/kogito-rest-workitem/src/main/java/org/kogito/workitem/rest/RestWorkItemHandler.java
index 5111a44715..9ed83ca868 100644
---
a/kogito-workitems/kogito-rest-workitem/src/main/java/org/kogito/workitem/rest/RestWorkItemHandler.java
+++
b/kogito-workitems/kogito-rest-workitem/src/main/java/org/kogito/workitem/rest/RestWorkItemHandler.java
@@ -54,6 +54,7 @@ import
org.kogito.workitem.rest.bodybuilders.RestWorkItemHandlerBodyBuilder;
import org.kogito.workitem.rest.decorators.ParamsDecorator;
import org.kogito.workitem.rest.decorators.PrefixParamsDecorator;
import org.kogito.workitem.rest.decorators.RequestDecorator;
+import org.kogito.workitem.rest.decorators.TokenPropagationDecorator;
import org.kogito.workitem.rest.pathresolvers.DefaultPathParamResolver;
import org.kogito.workitem.rest.pathresolvers.PathParamResolver;
import
org.kogito.workitem.rest.resulthandlers.DefaultRestWorkItemHandlerResult;
@@ -110,8 +111,11 @@ public class RestWorkItemHandler extends
DefaultKogitoWorkItemHandler {
private static final Map<String, ParamsDecorator> paramsDecorators = new
ConcurrentHashMap<>();
private static final Map<String, PathParamResolver> pathParamsResolvers =
new ConcurrentHashMap<>();
private static final Map<String, AuthDecorator> authDecoratorsMap = new
ConcurrentHashMap<>();
- private static final Collection<AuthDecorator> DEFAULT_AUTH_DECORATORS =
Arrays.asList(new ApiKeyAuthDecorator(), new BasicAuthDecorator(), new
BearerTokenAuthDecorator());
-
+ private static final Collection<AuthDecorator> DEFAULT_AUTH_DECORATORS =
Arrays.asList(
+ new ApiKeyAuthDecorator(),
+ new BasicAuthDecorator(),
+ new BearerTokenAuthDecorator(),
+ new TokenPropagationDecorator());
protected final WebClient httpClient;
protected final WebClient httpsClient;
private Collection<RequestDecorator> requestDecorators;
@@ -127,8 +131,10 @@ public class RestWorkItemHandler extends
DefaultKogitoWorkItemHandler {
//retrieving parameters
Map<String, Object> parameters = new
HashMap<>(workItem.getParameters());
+
//removing unnecessary parameter
parameters.remove("TaskName");
+
Class<?> targetInfo = getParamSupply(parameters, TARGET_TYPE,
Class.class, () -> getTargetInfo(workItem));
logger.debug("Using target {}", targetInfo);
@@ -190,7 +196,7 @@ public class RestWorkItemHandler extends
DefaultKogitoWorkItemHandler {
authDecorators.forEach(d -> d.decorate(workItem, parameters, request));
paramsDecorator.decorate(workItem, parameters, request);
Duration requestTimeout = getRequestTimeout(parameters);
- HttpResponse<Buffer> response = method.equals(HttpMethod.POST) ||
method.equals(HttpMethod.PUT)
+ HttpResponse<Buffer> response = method.equals(HttpMethod.POST) ||
method.equals(HttpMethod.PUT) || method.equals(HttpMethod.PATCH)
? sendBody(request, bodyBuilder.apply(parameters),
requestTimeout)
: send(request, requestTimeout);
Object outputParams = resultHandler.apply(response, targetInfo,
ContextFactory.fromItem(workItem));
diff --git
a/kogito-workitems/kogito-rest-workitem/src/main/java/org/kogito/workitem/rest/decorators/TokenPropagationDecorator.java
b/kogito-workitems/kogito-rest-workitem/src/main/java/org/kogito/workitem/rest/decorators/TokenPropagationDecorator.java
new file mode 100644
index 0000000000..3c3aca53f9
--- /dev/null
+++
b/kogito-workitems/kogito-rest-workitem/src/main/java/org/kogito/workitem/rest/decorators/TokenPropagationDecorator.java
@@ -0,0 +1,141 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.kogito.workitem.rest.decorators;
+
+import java.util.Arrays;
+import java.util.Map;
+import java.util.Optional;
+
+import org.kie.kogito.auth.AuthTokenProvider;
+import org.kie.kogito.internal.process.workitem.KogitoWorkItem;
+import org.kie.kogito.process.ProcessConfig;
+import org.kie.kogito.process.workitems.impl.ConfigResolverHolder;
+import org.kogito.workitem.rest.auth.AuthDecorator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import io.vertx.mutiny.ext.web.client.HttpRequest;
+
+enum AccessTokenAcquisitionStrategy {
+ NONE("none"),
+ CONFIGURED("configured"),
+ PROPAGATED("propagated");
+
+ private String name;
+
+ AccessTokenAcquisitionStrategy(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public static AccessTokenAcquisitionStrategy fromName(String strategyName)
{
+ return Arrays.stream(AccessTokenAcquisitionStrategy.values())
+ .filter(strategy -> strategy.getName().equals(strategyName))
+ .findFirst()
+ .orElse(NONE);
+ }
+}
+
+public class TokenPropagationDecorator implements AuthDecorator {
+
+ private static final Logger logger =
LoggerFactory.getLogger(TokenPropagationDecorator.class);
+
+ public static final String ACCESS_TOKEN_ACQUISITION_STRATEGY =
"AccessTokenAcquisitionStrategy";
+
+ private static final String REST_SERVICE_CALL_TASK_ID =
"RestServiceCallTaskId";
+
+ @Override
+ public void decorate(KogitoWorkItem item, Map<String, Object> parameters,
HttpRequest<?> request) {
+ Optional<String> bearerToken = getBearerToken(item, parameters);
+
+ bearerToken.ifPresentOrElse(
+ token -> {
+ logger.debug("Rest workItem `{}`: Bearer token available,
request will be sent with authentication", item.getNodeInstance().getId());
+ request.bearerTokenAuthentication(token);
+ },
+ () -> logger.debug("Rest workItem `{}`: No Bearer Token
available, request will be sent without authentication",
item.getNodeInstance().getId()));
+ }
+
+ Optional<String> getBearerToken(KogitoWorkItem item, Map<String, Object>
parameters) {
+ Object strategyParam =
parameters.get(ACCESS_TOKEN_ACQUISITION_STRATEGY);
+
+ if (!(strategyParam instanceof String)) {
+ logger.debug("No token acquisition strategy specified, skipping
authentication");
+ return Optional.empty();
+ }
+
+ String strategyName = (String) strategyParam;
+ AccessTokenAcquisitionStrategy strategy =
AccessTokenAcquisitionStrategy.fromName(strategyName);
+
+ return switch (strategy) {
+ case PROPAGATED -> getPropagatedTokenFromHeaders(item);
+ case CONFIGURED -> getConfiguredToken(item, parameters);
+ default -> {
+ logger.debug("Strategy {} is NONE or unknown, skipping",
strategyName);
+ yield Optional.empty();
+ }
+ };
+ }
+
+ private Optional<String> getPropagatedTokenFromHeaders(KogitoWorkItem
item) {
+ org.jbpm.process.instance.ProcessInstance jbpmProcessInstance =
+ (org.jbpm.process.instance.ProcessInstance)
item.getProcessInstance();
+
+ org.kie.kogito.internal.process.runtime.KogitoProcessRuntime
processRuntime =
+ ((org.jbpm.process.instance.InternalProcessRuntime)
jbpmProcessInstance.getKnowledgeRuntime().getProcessRuntime())
+ .getKogitoProcessRuntime();
+
+ ProcessConfig processConfig =
processRuntime.getApplication().config().get(ProcessConfig.class);
+ AuthTokenProvider authTokenProvider =
processConfig.authTokenProvider();
+
+ Optional<String> token = authTokenProvider.getAuthToken();
+ if (token.isPresent()) {
+ logger.debug("Using propagated token from AuthTokenProvider");
+ } else {
+ logger.debug("No token available from AuthTokenProvider");
+ }
+ return token;
+ }
+
+ private Optional<String> getConfiguredToken(KogitoWorkItem item,
Map<String, Object> parameters) {
+ String processId = item.getProcessInstance().getProcessId();
+ String taskName = (String)
parameters.getOrDefault(REST_SERVICE_CALL_TASK_ID, item.getName());
+
+ if (processId == null || taskName == null) {
+ logger.debug("Process ID or task name is null, cannot build
configuration key");
+ return Optional.empty();
+ }
+
+ String configKey =
String.format("kogito.processes.%s.%s.access_token", processId, taskName);
+
+ Optional<String> configToken = ConfigResolverHolder.getConfigResolver()
+ .getConfigProperty(configKey, String.class);
+
+ if (configToken.isPresent()) {
+ logger.debug("Using configured token from ConfigResolver with key:
{}", configKey);
+ return configToken;
+ } else {
+ logger.debug("No token found in ConfigResolver for key: {}",
configKey);
+ return Optional.empty();
+ }
+ }
+}
diff --git
a/kogito-workitems/kogito-rest-workitem/src/main/resources/META-INF/services/org.kogito.workitem.rest.decorators.RequestDecorator
b/kogito-workitems/kogito-rest-workitem/src/main/resources/META-INF/services/org.kogito.workitem.rest.decorators.RequestDecorator
index 5da309146b..ebe674c363 100644
---
a/kogito-workitems/kogito-rest-workitem/src/main/resources/META-INF/services/org.kogito.workitem.rest.decorators.RequestDecorator
+++
b/kogito-workitems/kogito-rest-workitem/src/main/resources/META-INF/services/org.kogito.workitem.rest.decorators.RequestDecorator
@@ -18,3 +18,4 @@
#
org.kogito.workitem.rest.decorators.HeaderMetadataDecorator
+org.kogito.workitem.rest.decorators.TokenPropagationDecorator
diff --git
a/kogito-workitems/kogito-rest-workitem/src/test/java/org/kogito/workitem/rest/decorators/ParamsDecoratorTest.java
b/kogito-workitems/kogito-rest-workitem/src/test/java/org/kogito/workitem/rest/decorators/ParamsDecoratorTest.java
index 0b9a6d7392..0a272cd4c9 100644
---
a/kogito-workitems/kogito-rest-workitem/src/test/java/org/kogito/workitem/rest/decorators/ParamsDecoratorTest.java
+++
b/kogito-workitems/kogito-rest-workitem/src/test/java/org/kogito/workitem/rest/decorators/ParamsDecoratorTest.java
@@ -23,13 +23,16 @@ import java.util.HashMap;
import java.util.Map;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
import org.kie.kogito.internal.process.workitem.KogitoWorkItem;
+import org.mockito.junit.jupiter.MockitoExtension;
import io.vertx.mutiny.ext.web.client.HttpRequest;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
+@ExtendWith(MockitoExtension.class)
class ParamsDecoratorTest {
@Test
diff --git
a/kogito-workitems/kogito-rest-workitem/src/test/java/org/kogito/workitem/rest/decorators/TokenPropagationDecoratorTest.java
b/kogito-workitems/kogito-rest-workitem/src/test/java/org/kogito/workitem/rest/decorators/TokenPropagationDecoratorTest.java
new file mode 100644
index 0000000000..8b12799e05
--- /dev/null
+++
b/kogito-workitems/kogito-rest-workitem/src/test/java/org/kogito/workitem/rest/decorators/TokenPropagationDecoratorTest.java
@@ -0,0 +1,255 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.kogito.workitem.rest.decorators;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+
+import org.drools.core.common.InternalKnowledgeRuntime;
+import org.jbpm.process.instance.InternalProcessRuntime;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.kie.kogito.Application;
+import org.kie.kogito.Config;
+import org.kie.kogito.auth.AuthTokenProvider;
+import org.kie.kogito.internal.process.runtime.KogitoNodeInstance;
+import org.kie.kogito.internal.process.runtime.KogitoProcessInstance;
+import org.kie.kogito.internal.process.runtime.KogitoProcessRuntime;
+import org.kie.kogito.internal.process.workitem.KogitoWorkItem;
+import org.kie.kogito.process.ProcessConfig;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import io.vertx.mutiny.ext.web.client.HttpRequest;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.mockito.Mockito.lenient;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@ExtendWith(MockitoExtension.class)
+public class TokenPropagationDecoratorTest {
+
+ private static final String CONFIGURED_TOKEN = "configured-token-12345";
+ private static final String PROPAGATED_TOKEN = "propagated-token-67890";
+
+ @Mock
+ private KogitoWorkItem workItem;
+
+ @Mock
+ private KogitoNodeInstance nodeInstance;
+
+ @Mock
+ private HttpRequest<?> httpRequest;
+
+ @Mock
+ private KogitoProcessInstance processInstance;
+
+ @Mock
+ private org.jbpm.process.instance.ProcessInstance jbpmProcessInstance;
+
+ @Mock
+ private InternalKnowledgeRuntime knowledgeRuntime;
+
+ @Mock
+ private InternalProcessRuntime internalProcessRuntime;
+
+ @Mock
+ private KogitoProcessRuntime kogitoProcessRuntime;
+
+ @Mock
+ private Application application;
+
+ @Mock
+ private Config config;
+
+ @Mock
+ private ProcessConfig processConfig;
+
+ @Mock
+ private AuthTokenProvider authTokenProvider;
+
+ private TokenPropagationDecorator decorator;
+ private Map<String, Object> parameters;
+
+ @BeforeEach
+ void setUp() {
+ decorator = new TokenPropagationDecorator();
+ parameters = new HashMap<>();
+
+ lenient().when(workItem.getNodeInstance()).thenReturn(nodeInstance);
+ lenient().when(nodeInstance.getId()).thenReturn("test-node-123");
+ lenient().when(workItem.getName()).thenReturn("TestTask");
+
lenient().when(workItem.getProcessInstance()).thenReturn(processInstance);
+
lenient().when(processInstance.getProcessId()).thenReturn("testProcess");
+
+ // Setup the chain to access AuthTokenProvider
+
lenient().when(jbpmProcessInstance.getKnowledgeRuntime()).thenReturn(knowledgeRuntime);
+
lenient().when(knowledgeRuntime.getProcessRuntime()).thenReturn(internalProcessRuntime);
+
lenient().when(internalProcessRuntime.getKogitoProcessRuntime()).thenReturn(kogitoProcessRuntime);
+
lenient().when(kogitoProcessRuntime.getApplication()).thenReturn(application);
+ lenient().when(application.config()).thenReturn(config);
+
lenient().when(config.get(ProcessConfig.class)).thenReturn(processConfig);
+
lenient().when(processConfig.authTokenProvider()).thenReturn(authTokenProvider);
+ }
+
+ @Test
+ void testGetBearerToken_ConfiguredStrategy_WithToken() {
+
System.setProperty("kogito.processes.testProcess.TestTask.access_token",
CONFIGURED_TOKEN);
+ try {
+
parameters.put(TokenPropagationDecorator.ACCESS_TOKEN_ACQUISITION_STRATEGY,
"configured");
+
+ Optional<String> result = decorator.getBearerToken(workItem,
parameters);
+
+ assertThat(result).isPresent().contains(CONFIGURED_TOKEN);
+ } finally {
+
System.clearProperty("kogito.processes.testProcess.TestTask.access_token");
+ }
+ }
+
+ @Test
+ void testGetBearerToken_ConfiguredStrategy_WithoutToken() {
+
parameters.put(TokenPropagationDecorator.ACCESS_TOKEN_ACQUISITION_STRATEGY,
"configured");
+
+ Optional<String> result = decorator.getBearerToken(workItem,
parameters);
+
+ assertThat(result).isEmpty();
+ }
+
+ @Test
+ void testGetBearerToken_PropagateStrategy_WithPropagatedTokenFromHeaders()
{
+
parameters.put(TokenPropagationDecorator.ACCESS_TOKEN_ACQUISITION_STRATEGY,
"propagated");
+ when(workItem.getProcessInstance()).thenReturn((KogitoProcessInstance)
jbpmProcessInstance);
+
when(authTokenProvider.getAuthToken()).thenReturn(Optional.of(PROPAGATED_TOKEN));
+
+ Optional<String> result = decorator.getBearerToken(workItem,
parameters);
+
+ assertThat(result).isPresent().contains(PROPAGATED_TOKEN);
+ }
+
+ @Test
+ void testGetBearerToken_PropagateStrategy_NoTokensAvailable() {
+
parameters.put(TokenPropagationDecorator.ACCESS_TOKEN_ACQUISITION_STRATEGY,
"propagated");
+
+ assertThatThrownBy(() -> decorator.getBearerToken(workItem,
parameters))
+ .isInstanceOf(ClassCastException.class);
+ }
+
+ @Test
+ void testGetBearerToken_PropagateStrategy_NoProcessInstance() {
+
parameters.put(TokenPropagationDecorator.ACCESS_TOKEN_ACQUISITION_STRATEGY,
"propagated");
+ when(workItem.getProcessInstance()).thenReturn(null);
+
+ assertThatThrownBy(() -> decorator.getBearerToken(workItem,
parameters))
+ .isInstanceOf(NullPointerException.class);
+ }
+
+ @Test
+ void testGetBearerToken_PropagateStrategy_EmptyToken() {
+
parameters.put(TokenPropagationDecorator.ACCESS_TOKEN_ACQUISITION_STRATEGY,
"propagated");
+ when(workItem.getProcessInstance()).thenReturn((KogitoProcessInstance)
jbpmProcessInstance);
+ when(authTokenProvider.getAuthToken()).thenReturn(Optional.empty());
+
+ Optional<String> result = decorator.getBearerToken(workItem,
parameters);
+
+ assertThat(result).isEmpty();
+ }
+
+ @Test
+ void testGetBearerToken_PropagateStrategy_AuthTokenProviderNotAvailable() {
+
parameters.put(TokenPropagationDecorator.ACCESS_TOKEN_ACQUISITION_STRATEGY,
"propagated");
+ when(workItem.getProcessInstance()).thenReturn((KogitoProcessInstance)
jbpmProcessInstance);
+ when(processConfig.authTokenProvider()).thenReturn(null);
+
+ assertThatThrownBy(() -> decorator.getBearerToken(workItem,
parameters))
+ .isInstanceOf(NullPointerException.class);
+ }
+
+ @Test
+ void testGetBearerToken_NoneStrategy() {
+
parameters.put(TokenPropagationDecorator.ACCESS_TOKEN_ACQUISITION_STRATEGY,
"none");
+
+ Optional<String> result = decorator.getBearerToken(workItem,
parameters);
+
+ assertThat(result).isEmpty();
+ }
+
+ @Test
+ void testGetBearerToken_UnknownStrategy_DefaultsToNone() {
+
parameters.put(TokenPropagationDecorator.ACCESS_TOKEN_ACQUISITION_STRATEGY,
"unknown-strategy");
+
+ Optional<String> result = decorator.getBearerToken(workItem,
parameters);
+
+ assertThat(result).isEmpty();
+ }
+
+ @Test
+ void testGetBearerToken_NoStrategySpecified_DefaultsToNone() {
+ Optional<String> result = decorator.getBearerToken(workItem,
parameters);
+
+ assertThat(result).isEmpty();
+ }
+
+ @Test
+ void testDecorate_WithToken_AddsAuthenticationHeader() {
+
System.setProperty("kogito.processes.testProcess.TestTask.access_token",
CONFIGURED_TOKEN);
+ try {
+
parameters.put(TokenPropagationDecorator.ACCESS_TOKEN_ACQUISITION_STRATEGY,
"configured");
+
+ decorator.decorate(workItem, parameters, httpRequest);
+
+ verify(httpRequest).bearerTokenAuthentication(CONFIGURED_TOKEN);
+ } finally {
+
System.clearProperty("kogito.processes.testProcess.TestTask.access_token");
+ }
+ }
+
+ @Test
+ void testDecorate_WithoutToken_DoesNotAddAuthenticationHeader() {
+
parameters.put(TokenPropagationDecorator.ACCESS_TOKEN_ACQUISITION_STRATEGY,
"none");
+
+ decorator.decorate(workItem, parameters, httpRequest);
+
+ verify(httpRequest,
never()).bearerTokenAuthentication(org.mockito.ArgumentMatchers.anyString());
+ }
+
+ @Test
+ void testDecorate_PropagateStrategy_UsesPropagatedTokenFromHeaders() {
+
parameters.put(TokenPropagationDecorator.ACCESS_TOKEN_ACQUISITION_STRATEGY,
"propagated");
+ when(workItem.getProcessInstance()).thenReturn((KogitoProcessInstance)
jbpmProcessInstance);
+
when(authTokenProvider.getAuthToken()).thenReturn(Optional.of(PROPAGATED_TOKEN));
+
+ decorator.decorate(workItem, parameters, httpRequest);
+
+ verify(httpRequest).bearerTokenAuthentication(PROPAGATED_TOKEN);
+ }
+
+ @Test
+ void testAccessTokenAcquisitionStrategy_FromName() {
+
assertThat(AccessTokenAcquisitionStrategy.fromName("none")).isEqualTo(AccessTokenAcquisitionStrategy.NONE);
+
assertThat(AccessTokenAcquisitionStrategy.fromName("configured")).isEqualTo(AccessTokenAcquisitionStrategy.CONFIGURED);
+
assertThat(AccessTokenAcquisitionStrategy.fromName("propagated")).isEqualTo(AccessTokenAcquisitionStrategy.PROPAGATED);
+
assertThat(AccessTokenAcquisitionStrategy.fromName("invalid")).isEqualTo(AccessTokenAcquisitionStrategy.NONE);
+
assertThat(AccessTokenAcquisitionStrategy.fromName(null)).isEqualTo(AccessTokenAcquisitionStrategy.NONE);
+ }
+}
diff --git
a/quarkus/extensions/kogito-quarkus-extension-common/kogito-quarkus-common/src/main/java/org/kie/kogito/quarkus/auth/QuarkusAuthTokenProvider.java
b/quarkus/extensions/kogito-quarkus-extension-common/kogito-quarkus-common/src/main/java/org/kie/kogito/quarkus/auth/QuarkusAuthTokenProvider.java
new file mode 100644
index 0000000000..93dc95998b
--- /dev/null
+++
b/quarkus/extensions/kogito-quarkus-extension-common/kogito-quarkus-common/src/main/java/org/kie/kogito/quarkus/auth/QuarkusAuthTokenProvider.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.kie.kogito.quarkus.auth;
+
+import java.util.Objects;
+import java.util.Optional;
+
+import org.kie.kogito.auth.AuthTokenProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import io.quarkus.security.credential.TokenCredential;
+import io.quarkus.security.identity.SecurityIdentity;
+
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.enterprise.inject.Instance;
+import jakarta.inject.Inject;
+
+@ApplicationScoped
+public class QuarkusAuthTokenProvider implements AuthTokenProvider {
+
+ private static final Logger logger =
LoggerFactory.getLogger(QuarkusAuthTokenProvider.class);
+
+ @Inject
+ Instance<SecurityIdentity> identity;
+
+ private Optional<SecurityIdentity> getIdentity() {
+ return identity.isResolvable() ? Optional.of(identity.get()) :
Optional.empty();
+ }
+
+ @Override
+ public Optional<String> getAuthToken() {
+ return getIdentity()
+ .filter(securityIdentity -> !securityIdentity.isAnonymous())
+ .map(securityIdentity ->
securityIdentity.getCredential(TokenCredential.class))
+ .filter(Objects::nonNull)
+ .map(tokenCredential -> {
+ logger.debug("Token retrieved from Quarkus
SecurityIdentity");
+ return tokenCredential.getToken();
+ })
+ .or(() -> {
+ logger.debug("No token available from SecurityIdentity");
+ return Optional.empty();
+ });
+ }
+}
diff --git
a/quarkus/extensions/kogito-quarkus-processes-extension/kogito-quarkus-processes-deployment/src/main/java/org/kie/kogito/quarkus/processes/deployment/ProcessesAssetsProcessor.java
b/quarkus/extensions/kogito-quarkus-processes-extension/kogito-quarkus-processes-deployment/src/main/java/org/kie/kogito/quarkus/processes/deployment/ProcessesAssetsProcessor.java
index 14819353e8..90bb8abc64 100644
---
a/quarkus/extensions/kogito-quarkus-processes-extension/kogito-quarkus-processes-deployment/src/main/java/org/kie/kogito/quarkus/processes/deployment/ProcessesAssetsProcessor.java
+++
b/quarkus/extensions/kogito-quarkus-processes-extension/kogito-quarkus-processes-deployment/src/main/java/org/kie/kogito/quarkus/processes/deployment/ProcessesAssetsProcessor.java
@@ -45,6 +45,7 @@ import
org.kie.kogito.event.usertask.UserTaskInstanceStateDataEvent;
import org.kie.kogito.event.usertask.UserTaskInstanceStateEventBody;
import org.kie.kogito.event.usertask.UserTaskInstanceVariableDataEvent;
import org.kie.kogito.event.usertask.UserTaskInstanceVariableEventBody;
+import org.kie.kogito.quarkus.processes.workitems.QuarkusConfigResolver;
import org.kie.kogito.quarkus.workflow.KogitoBeanProducer;
import org.kie.kogito.quarkus.workflow.deployment.WorkflowProcessor;
@@ -102,7 +103,8 @@ public class ProcessesAssetsProcessor extends
WorkflowProcessor {
QuarkusStatefulProcessService.class,
QuarkusHumanTaskService.class,
QuarkusProcessIdFactory.class,
- KogitoBeanProducer.class)
+ KogitoBeanProducer.class,
+ QuarkusConfigResolver.class)
.build();
}
diff --git
a/quarkus/extensions/kogito-quarkus-processes-extension/kogito-quarkus-processes/src/main/java/org/kie/kogito/quarkus/processes/workitems/QuarkusConfigResolver.java
b/quarkus/extensions/kogito-quarkus-processes-extension/kogito-quarkus-processes/src/main/java/org/kie/kogito/quarkus/processes/workitems/QuarkusConfigResolver.java
new file mode 100644
index 0000000000..006b94e113
--- /dev/null
+++
b/quarkus/extensions/kogito-quarkus-processes-extension/kogito-quarkus-processes/src/main/java/org/kie/kogito/quarkus/processes/workitems/QuarkusConfigResolver.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.kie.kogito.quarkus.processes.workitems;
+
+import java.util.Optional;
+
+import org.eclipse.microprofile.config.Config;
+import org.eclipse.microprofile.config.ConfigProvider;
+import org.kie.kogito.process.workitems.impl.ConfigResolver;
+import org.kie.kogito.process.workitems.impl.ConfigResolverHolder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import io.quarkus.runtime.StartupEvent;
+
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.enterprise.event.Observes;
+
+@ApplicationScoped
+public class QuarkusConfigResolver implements ConfigResolver {
+
+ private static final Logger logger =
LoggerFactory.getLogger(QuarkusConfigResolver.class);
+
+ private final Config config;
+
+ public QuarkusConfigResolver() {
+ this.config = ConfigProvider.getConfig();
+ logger.info("QuarkusConfigResolver instantiated");
+ }
+
+ void onStart(@Observes StartupEvent ev) {
+ ConfigResolverHolder.setConfigResolver(this);
+ logger.info("QuarkusConfigResolver registered with
ConfigResolverHolder");
+ }
+
+ @Override
+ public <T> Optional<T> getConfigProperty(String name, Class<T> clazz) {
+ Optional<T> value = config.getOptionalValue(name, clazz);
+ logger.debug("ConfigResolver lookup: key='{}', found={}", name,
value.isPresent());
+ return value;
+ }
+}
diff --git a/springboot/addons/common/pom.xml b/springboot/addons/common/pom.xml
index 65f45fe5d0..f5bac05da2 100644
--- a/springboot/addons/common/pom.xml
+++ b/springboot/addons/common/pom.xml
@@ -38,4 +38,4 @@
<modules>
<module>common-auth</module>
</modules>
-</project>
\ No newline at end of file
+</project>
diff --git a/springboot/starters/kogito-processes-spring-boot-starter/pom.xml
b/springboot/starters/kogito-processes-spring-boot-starter/pom.xml
index 996d79e487..33ac657e28 100644
--- a/springboot/starters/kogito-processes-spring-boot-starter/pom.xml
+++ b/springboot/starters/kogito-processes-spring-boot-starter/pom.xml
@@ -68,6 +68,16 @@
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-spring-boot3</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-security</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-oauth2-client</artifactId>
+ <scope>provided</scope>
+ </dependency>
</dependencies>
</project>
\ No newline at end of file
diff --git
a/springboot/starters/kogito-processes-spring-boot-starter/src/main/java/org/kie/kogito/process/SpringBootConfigResolver.java
b/springboot/starters/kogito-processes-spring-boot-starter/src/main/java/org/kie/kogito/process/SpringBootConfigResolver.java
new file mode 100644
index 0000000000..8e5b3f2c56
--- /dev/null
+++
b/springboot/starters/kogito-processes-spring-boot-starter/src/main/java/org/kie/kogito/process/SpringBootConfigResolver.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.kie.kogito.process;
+
+import java.util.Optional;
+
+import org.kie.kogito.process.workitems.impl.ConfigResolver;
+import org.kie.kogito.process.workitems.impl.ConfigResolverHolder;
+import org.springframework.boot.context.event.ApplicationStartedEvent;
+import org.springframework.context.ApplicationListener;
+import org.springframework.core.env.Environment;
+import org.springframework.stereotype.Component;
+
+@Component
+public class SpringBootConfigResolver implements ConfigResolver,
ApplicationListener<ApplicationStartedEvent> {
+
+ private final Environment environment;
+
+ public SpringBootConfigResolver(Environment environment) {
+ this.environment = environment;
+ }
+
+ @Override
+ public void onApplicationEvent(ApplicationStartedEvent event) {
+ ConfigResolverHolder.setConfigResolver(this);
+ }
+
+ @Override
+ public <T> Optional<T> getConfigProperty(String name, Class<T> clazz) {
+ return Optional.ofNullable(environment.getProperty(name, clazz));
+ }
+}
diff --git
a/springboot/addons/common/common-auth/src/main/java/org/kie/addons/springboot/auth/SecurityContextInitializer.java
b/springboot/starters/kogito-processes-spring-boot-starter/src/main/java/org/kie/kogito/spring/auth/SecurityContextInitializer.java
similarity index 88%
copy from
springboot/addons/common/common-auth/src/main/java/org/kie/addons/springboot/auth/SecurityContextInitializer.java
copy to
springboot/starters/kogito-processes-spring-boot-starter/src/main/java/org/kie/kogito/spring/auth/SecurityContextInitializer.java
index fa3327e6fc..6440651325 100644
---
a/springboot/addons/common/common-auth/src/main/java/org/kie/addons/springboot/auth/SecurityContextInitializer.java
+++
b/springboot/starters/kogito-processes-spring-boot-starter/src/main/java/org/kie/kogito/spring/auth/SecurityContextInitializer.java
@@ -17,13 +17,15 @@
* under the License.
*/
-package org.kie.addons.springboot.auth;
+package org.kie.kogito.spring.auth;
import org.springframework.beans.factory.InitializingBean;
+import
org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
@Component
+@ConditionalOnMissingBean(SecurityContextHolder.class)
public class SecurityContextInitializer implements InitializingBean {
@Override
diff --git
a/springboot/starters/kogito-processes-spring-boot-starter/src/main/java/org/kie/kogito/spring/auth/SpringAuthTokenProvider.java
b/springboot/starters/kogito-processes-spring-boot-starter/src/main/java/org/kie/kogito/spring/auth/SpringAuthTokenProvider.java
new file mode 100644
index 0000000000..d637c1189c
--- /dev/null
+++
b/springboot/starters/kogito-processes-spring-boot-starter/src/main/java/org/kie/kogito/spring/auth/SpringAuthTokenProvider.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.kie.kogito.spring.auth;
+
+import java.util.List;
+import java.util.Optional;
+
+import org.kie.kogito.auth.AuthTokenProvider;
+import org.kie.kogito.spring.auth.token.AuthTokenReader;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.security.core.context.SecurityContext;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.stereotype.Component;
+
+@Component
+@ConditionalOnClass({ SecurityContextHolder.class })
+@SuppressWarnings({ "unchecked", "rawtypes" })
+public class SpringAuthTokenProvider implements AuthTokenProvider {
+
+ private final List<AuthTokenReader> authTokenReaders;
+
+ public SpringAuthTokenProvider(@Autowired List<AuthTokenReader>
authTokenReaders) {
+ this.authTokenReaders = authTokenReaders;
+ }
+
+ @Override
+ public Optional<String> getAuthToken() {
+ SecurityContext securityContext = SecurityContextHolder.getContext();
+
+ if (securityContext == null || securityContext.getAuthentication() ==
null) {
+ return Optional.empty();
+ }
+
+ Object principal = securityContext.getAuthentication().getPrincipal();
+
+ return this.authTokenReaders.stream()
+ .filter(reader ->
reader.acceptsPrincipal(principal)).findFirst()
+ .map(reader -> reader.readToken(principal));
+ }
+}
diff --git
a/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/descriptors/TaskDescriptor.java
b/springboot/starters/kogito-processes-spring-boot-starter/src/main/java/org/kie/kogito/spring/auth/token/AuthTokenReader.java
similarity index 63%
copy from
jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/descriptors/TaskDescriptor.java
copy to
springboot/starters/kogito-processes-spring-boot-starter/src/main/java/org/kie/kogito/spring/auth/token/AuthTokenReader.java
index 7e9e2c737c..ce3f5c0311 100644
---
a/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/descriptors/TaskDescriptor.java
+++
b/springboot/starters/kogito-processes-spring-boot-starter/src/main/java/org/kie/kogito/spring/auth/token/AuthTokenReader.java
@@ -16,22 +16,15 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.jbpm.compiler.canonical.descriptors;
+package org.kie.kogito.spring.auth.token;
-import com.github.javaparser.ast.CompilationUnit;
+public interface AuthTokenReader<T> {
-public interface TaskDescriptor {
+ Class<T> getPrincipalType();
- String KEY_WORKITEM_TYPE = "Type";
- String KEY_WORKITEM_INTERFACE = "Interface";
- String KEY_WORKITEM_OPERATION = "Operation";
- String KEY_SERVICE_IMPL = "implementation";
- String DEFAULT_SERVICE_IMPL = "Java";
-
- String getName();
-
- String getType();
-
- CompilationUnit generateHandlerClassForService();
+ String readToken(T principal);
+ default boolean acceptsPrincipal(Object principal) {
+ return getPrincipalType().isAssignableFrom(principal.getClass());
+ }
}
diff --git
a/springboot/addons/common/common-auth/src/main/java/org/kie/addons/springboot/auth/SecurityContextInitializer.java
b/springboot/starters/kogito-processes-spring-boot-starter/src/main/java/org/kie/kogito/spring/auth/token/impl/JwtAuthTokenReader.java
similarity index 63%
copy from
springboot/addons/common/common-auth/src/main/java/org/kie/addons/springboot/auth/SecurityContextInitializer.java
copy to
springboot/starters/kogito-processes-spring-boot-starter/src/main/java/org/kie/kogito/spring/auth/token/impl/JwtAuthTokenReader.java
index fa3327e6fc..3ab6cebfd3 100644
---
a/springboot/addons/common/common-auth/src/main/java/org/kie/addons/springboot/auth/SecurityContextInitializer.java
+++
b/springboot/starters/kogito-processes-spring-boot-starter/src/main/java/org/kie/kogito/spring/auth/token/impl/JwtAuthTokenReader.java
@@ -16,19 +16,24 @@
* specific language governing permissions and limitations
* under the License.
*/
+package org.kie.kogito.spring.auth.token.impl;
-package org.kie.addons.springboot.auth;
-
-import org.springframework.beans.factory.InitializingBean;
-import org.springframework.security.core.context.SecurityContextHolder;
+import org.kie.kogito.spring.auth.token.AuthTokenReader;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.stereotype.Component;
@Component
-public class SecurityContextInitializer implements InitializingBean {
+@ConditionalOnClass(Jwt.class)
+public class JwtAuthTokenReader implements AuthTokenReader<Jwt> {
+
+ @Override
+ public Class<Jwt> getPrincipalType() {
+ return Jwt.class;
+ }
@Override
- public void afterPropertiesSet() throws Exception {
- // ensure the security context is inherited to child threads
-
SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL);
+ public String readToken(Jwt principal) {
+ return principal.getTokenValue();
}
}
diff --git
a/springboot/addons/common/common-auth/src/main/java/org/kie/addons/springboot/auth/SecurityContextInitializer.java
b/springboot/starters/kogito-processes-spring-boot-starter/src/main/java/org/kie/kogito/spring/auth/token/impl/OIDCAuthTokenReader.java
similarity index 61%
rename from
springboot/addons/common/common-auth/src/main/java/org/kie/addons/springboot/auth/SecurityContextInitializer.java
rename to
springboot/starters/kogito-processes-spring-boot-starter/src/main/java/org/kie/kogito/spring/auth/token/impl/OIDCAuthTokenReader.java
index fa3327e6fc..100580210d 100644
---
a/springboot/addons/common/common-auth/src/main/java/org/kie/addons/springboot/auth/SecurityContextInitializer.java
+++
b/springboot/starters/kogito-processes-spring-boot-starter/src/main/java/org/kie/kogito/spring/auth/token/impl/OIDCAuthTokenReader.java
@@ -16,19 +16,24 @@
* specific language governing permissions and limitations
* under the License.
*/
+package org.kie.kogito.spring.auth.token.impl;
-package org.kie.addons.springboot.auth;
-
-import org.springframework.beans.factory.InitializingBean;
-import org.springframework.security.core.context.SecurityContextHolder;
+import org.kie.kogito.spring.auth.token.AuthTokenReader;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.security.oauth2.core.oidc.user.OidcUser;
import org.springframework.stereotype.Component;
@Component
-public class SecurityContextInitializer implements InitializingBean {
+@ConditionalOnClass({ OidcUser.class })
+public class OIDCAuthTokenReader implements AuthTokenReader<OidcUser> {
+
+ @Override
+ public Class<OidcUser> getPrincipalType() {
+ return OidcUser.class;
+ }
@Override
- public void afterPropertiesSet() throws Exception {
- // ensure the security context is inherited to child threads
-
SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL);
+ public String readToken(OidcUser principal) {
+ return principal.getIdToken().getTokenValue();
}
}
diff --git
a/springboot/starters/kogito-spring-boot-starter/SpringBootAuthTokenProvider.java
b/springboot/starters/kogito-spring-boot-starter/SpringBootAuthTokenProvider.java
new file mode 100644
index 0000000000..3db0c33ed4
--- /dev/null
+++
b/springboot/starters/kogito-spring-boot-starter/SpringBootAuthTokenProvider.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.kogito.addons.springboot.common.rest.workitem;
+
+import java.util.Optional;
+
+import org.kie.addons.springboot.auth.SpringBootAuthTokenHelper;
+import org.kie.kogito.auth.AuthTokenProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.stereotype.Component;
+
+@Component
+@ConditionalOnClass({ SecurityContextHolder.class })
+public class SpringBootAuthTokenProvider implements AuthTokenProvider {
+
+ private static final Logger logger =
LoggerFactory.getLogger(SpringBootAuthTokenProvider.class);
+
+ private final SpringBootAuthTokenHelper authTokenHelper;
+
+ @Autowired
+ public SpringBootAuthTokenProvider(SpringBootAuthTokenHelper
authTokenHelper) {
+ this.authTokenHelper = authTokenHelper;
+ }
+
+ @Override
+ public Optional<String> getAuthToken() {
+ Optional<String> token = authTokenHelper.getAuthToken();
+ if (token.isPresent()) {
+ logger.debug("Token retrieved from Spring Boot SecurityContext via
SpringBootAuthTokenHelper");
+ } else {
+ logger.debug("No token available from Spring Boot
SecurityContext");
+ }
+ return token;
+ }
+}
+
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]