Skip to content
Draft
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
10 changes: 10 additions & 0 deletions bom/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,16 @@
<artifactId>quarkus-flow-messaging-deployment</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.quarkiverse.flow</groupId>
<artifactId>quarkus-flow-oidc</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.quarkiverse.flow</groupId>
<artifactId>quarkus-flow-oidc-deployment</artifactId>
<version>${project.version}</version>
</dependency>

<dependency>
<groupId>io.quarkiverse.flow</groupId>
Expand Down
6 changes: 6 additions & 0 deletions core/deployment/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,12 @@
<version>${project.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>io.quarkiverse.flow</groupId>
<artifactId>quarkus-flow-oidc-deployment</artifactId>
<version>${project.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.github.zafarkhaja</groupId>
<artifactId>java-semver</artifactId>
Expand Down
8 changes: 8 additions & 0 deletions core/runtime/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,12 @@
<version>${project.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>io.quarkiverse.flow</groupId>
<artifactId>quarkus-flow-oidc</artifactId>
<version>${project.version}</version>
<optional>true</optional>
</dependency>

<!-- Required by serverlessworkflow-core-http HttpExecutor service module -->
<dependency>
Expand Down Expand Up @@ -150,6 +156,8 @@
<conditionalDependencies>
<dependency>${project.groupId}:${project.artifactId}-messaging:${project.version}
</dependency>
<dependency>${project.groupId}:${project.artifactId}-oidc:${project.version}
</dependency>
</conditionalDependencies>
<deployment>${project.groupId}:${project.artifactId}-deployment:${project.version}
</deployment>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,9 @@ public void decorate(Invocation.Builder requestBuilder, WorkflowContext workflow
.header(X_FLOW_TASK_ID, taskContext.position().jsonPointer());
}
}

@Override
public int priority() {
return 50;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import io.serverlessworkflow.api.types.CallHTTP;
import io.serverlessworkflow.api.types.CallOpenAPI;
import io.serverlessworkflow.api.types.TaskBase;
import io.serverlessworkflow.impl.ContextPropagator;
import io.serverlessworkflow.impl.WorkflowApplication;
import io.serverlessworkflow.impl.WorkflowApplication.Builder;
import io.serverlessworkflow.impl.WorkflowModel;
Expand All @@ -54,6 +55,10 @@ public class WorkflowApplicationCreator {
@Inject
QuarkusManagedExecutorServiceFactory executorServiceFactory;

@Inject
@Any
Instance<ContextPropagator> contextPropagators;

@Inject
JQScopeSupplier jqScopeSupplier;

Expand Down Expand Up @@ -118,6 +123,7 @@ public WorkflowApplication create(boolean isMicrometerSupported) {

injectAppId(builder);
injectExecutorServiceFactory(builder);
injectContextPropagator(builder);
injectJQExpressionFactory(builder);
injectEventConsumers(builder);
injectEventPublishers(builder);
Expand All @@ -142,6 +148,19 @@ private void injectExecutorServiceFactory(Builder builder) {
LOG.debug("Flow: Bound ExecutorServiceFactory bean: {}", executorServiceFactory.getClass().getName());
}

private void injectContextPropagator(Builder builder) {
if (contextPropagators.isResolvable()) {
ContextPropagator contextPropagator = contextPropagators.get();
builder.withContextPropagator(contextPropagator);
LOG.debug("Flow: Bound ContextPropagator bean: {}", contextPropagator.getClass().getName());
} else if (contextPropagators.isAmbiguous()) {
throw new IllegalStateException(
"Multiple ContextPropagator beans found. Provide exactly one.");
} else {
LOG.debug("Flow: No ContextPropagator bean found; caller context propagation disabled (NOOP).");
}
}

private void injectCustomListeners(Builder builder) {
final Set<Class<?>> internalListeners = Set.of(
TraceLoggerExecutionListener.class,
Expand Down
1 change: 1 addition & 0 deletions docs/modules/ROOT/nav.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
** External Integrations
*** xref:http-openapi-tasks.adoc[Call HTTP and OpenAPI services]
*** xref:http-client.adoc[Configure the HTTP client]
*** xref:oidc.adoc[Authenticate downstream calls with OIDC]
*** xref:grpc.adoc[Call gRPC services with Quarkus channels]
*** xref:fault-tolerance.adoc[Fault tolerance and resilience]
*** xref:messaging.adoc[Use messaging and events]
Expand Down
219 changes: 219 additions & 0 deletions docs/modules/ROOT/pages/includes/quarkus-flow-oidc.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
[.configuration-legend]
icon:lock[title=Fixed at build time] Configuration property fixed at build time - All other configuration properties are overridable at runtime
[.configuration-reference.searchable, cols="80,.^10,.^10"]
|===

h|[.header-title]##Configuration property##
h|Type
h|Default

a| [[quarkus-flow-oidc_quarkus-flow-oidc-token-exchange-enabled]] [.property-path]##link:#quarkus-flow-oidc_quarkus-flow-oidc-token-exchange-enabled[`+++quarkus.flow.oidc.token-exchange.enabled+++`]##
ifdef::add-copy-button-to-config-props[]
config_property_copy_button:+++quarkus.flow.oidc.token-exchange.enabled+++[]
endif::add-copy-button-to-config-props[]


[.description]
--
Whether token exchange is enabled globally. When `false`, schemes fall back to client-credentials unless they explicitly enable exchange or propagation.


ifdef::add-copy-button-to-env-var[]
Environment variable: env_var_with_copy_button:+++QUARKUS_FLOW_OIDC_TOKEN_EXCHANGE_ENABLED+++[]
endif::add-copy-button-to-env-var[]
ifndef::add-copy-button-to-env-var[]
Environment variable: `+++QUARKUS_FLOW_OIDC_TOKEN_EXCHANGE_ENABLED+++`
endif::add-copy-button-to-env-var[]
--
|boolean
|`+++true+++`

a| [[quarkus-flow-oidc_quarkus-flow-oidc-token-exchange-proactive-refresh-seconds]] [.property-path]##link:#quarkus-flow-oidc_quarkus-flow-oidc-token-exchange-proactive-refresh-seconds[`+++quarkus.flow.oidc.token-exchange.proactive-refresh-seconds+++`]##
ifdef::add-copy-button-to-config-props[]
config_property_copy_button:+++quarkus.flow.oidc.token-exchange.proactive-refresh-seconds+++[]
endif::add-copy-button-to-config-props[]


[.description]
--
How many seconds before expiry a cached token is proactively refreshed.


ifdef::add-copy-button-to-env-var[]
Environment variable: env_var_with_copy_button:+++QUARKUS_FLOW_OIDC_TOKEN_EXCHANGE_PROACTIVE_REFRESH_SECONDS+++[]
endif::add-copy-button-to-env-var[]
ifndef::add-copy-button-to-env-var[]
Environment variable: `+++QUARKUS_FLOW_OIDC_TOKEN_EXCHANGE_PROACTIVE_REFRESH_SECONDS+++`
endif::add-copy-button-to-env-var[]
--
|link:https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/time/Duration.html[Duration] link:#duration-note-anchor-quarkus-flow-oidc_quarkus-flow[icon:question-circle[title=More information about the Duration format]]
|`+++PT300S+++`

a| [[quarkus-flow-oidc_quarkus-flow-oidc-token-exchange-monitor-rate-seconds]] [.property-path]##link:#quarkus-flow-oidc_quarkus-flow-oidc-token-exchange-monitor-rate-seconds[`+++quarkus.flow.oidc.token-exchange.monitor-rate-seconds+++`]##
ifdef::add-copy-button-to-config-props[]
config_property_copy_button:+++quarkus.flow.oidc.token-exchange.monitor-rate-seconds+++[]
endif::add-copy-button-to-config-props[]


[.description]
--
How often (seconds) the proactive-refresh monitor runs.


ifdef::add-copy-button-to-env-var[]
Environment variable: env_var_with_copy_button:+++QUARKUS_FLOW_OIDC_TOKEN_EXCHANGE_MONITOR_RATE_SECONDS+++[]
endif::add-copy-button-to-env-var[]
ifndef::add-copy-button-to-env-var[]
Environment variable: `+++QUARKUS_FLOW_OIDC_TOKEN_EXCHANGE_MONITOR_RATE_SECONDS+++`
endif::add-copy-button-to-env-var[]
--
|link:https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/time/Duration.html[Duration] link:#duration-note-anchor-quarkus-flow-oidc_quarkus-flow[icon:question-circle[title=More information about the Duration format]]
|`+++PT60S+++`

a| [[quarkus-flow-oidc_quarkus-flow-oidc-subject-token-input-key]] [.property-path]##link:#quarkus-flow-oidc_quarkus-flow-oidc-subject-token-input-key[`+++quarkus.flow.oidc.subject-token.input-key+++`]##
ifdef::add-copy-button-to-config-props[]
config_property_copy_button:+++quarkus.flow.oidc.subject-token.input-key+++[]
endif::add-copy-button-to-config-props[]


[.description]
--
Workflow input key holding the subject token (for programmatic / non-HTTP triggers).


ifdef::add-copy-button-to-env-var[]
Environment variable: env_var_with_copy_button:+++QUARKUS_FLOW_OIDC_SUBJECT_TOKEN_INPUT_KEY+++[]
endif::add-copy-button-to-env-var[]
ifndef::add-copy-button-to-env-var[]
Environment variable: `+++QUARKUS_FLOW_OIDC_SUBJECT_TOKEN_INPUT_KEY+++`
endif::add-copy-button-to-env-var[]
--
|string
|`+++subjectToken+++`

a| [[quarkus-flow-oidc_quarkus-flow-oidc-subject-token-security-identity-attribute]] [.property-path]##link:#quarkus-flow-oidc_quarkus-flow-oidc-subject-token-security-identity-attribute[`+++quarkus.flow.oidc.subject-token.security-identity-attribute+++`]##
ifdef::add-copy-button-to-config-props[]
config_property_copy_button:+++quarkus.flow.oidc.subject-token.security-identity-attribute+++[]
endif::add-copy-button-to-config-props[]


[.description]
--
`SecurityIdentity` attribute holding the subject token (for HTTP-triggered workflows).


ifdef::add-copy-button-to-env-var[]
Environment variable: env_var_with_copy_button:+++QUARKUS_FLOW_OIDC_SUBJECT_TOKEN_SECURITY_IDENTITY_ATTRIBUTE+++[]
endif::add-copy-button-to-env-var[]
ifndef::add-copy-button-to-env-var[]
Environment variable: `+++QUARKUS_FLOW_OIDC_SUBJECT_TOKEN_SECURITY_IDENTITY_ATTRIBUTE+++`
endif::add-copy-button-to-env-var[]
--
|string
|`+++access_token+++`

a| [[quarkus-flow-oidc_quarkus-flow-oidc-auth-auth-oidc-client-name]] [.property-path]##link:#quarkus-flow-oidc_quarkus-flow-oidc-auth-auth-oidc-client-name[`+++quarkus.flow.oidc.auth."auth".oidc-client-name+++`]##
ifdef::add-copy-button-to-config-props[]
config_property_copy_button:+++quarkus.flow.oidc.auth."auth".oidc-client-name+++[]
endif::add-copy-button-to-config-props[]


[.description]
--
Name of the `quarkus.oidc-client.<name>` to use for exchange and client-credentials. Defaults to the scheme name.


ifdef::add-copy-button-to-env-var[]
Environment variable: env_var_with_copy_button:+++QUARKUS_FLOW_OIDC_AUTH__AUTH__OIDC_CLIENT_NAME+++[]
endif::add-copy-button-to-env-var[]
ifndef::add-copy-button-to-env-var[]
Environment variable: `+++QUARKUS_FLOW_OIDC_AUTH__AUTH__OIDC_CLIENT_NAME+++`
endif::add-copy-button-to-env-var[]
--
|string
|

a| [[quarkus-flow-oidc_quarkus-flow-oidc-auth-auth-token-exchange-enabled]] [.property-path]##link:#quarkus-flow-oidc_quarkus-flow-oidc-auth-auth-token-exchange-enabled[`+++quarkus.flow.oidc.auth."auth".token-exchange-enabled+++`]##
ifdef::add-copy-button-to-config-props[]
config_property_copy_button:+++quarkus.flow.oidc.auth."auth".token-exchange-enabled+++[]
endif::add-copy-button-to-config-props[]


[.description]
--
Force token exchange on/off for this scheme, overriding the global setting and smart default.


ifdef::add-copy-button-to-env-var[]
Environment variable: env_var_with_copy_button:+++QUARKUS_FLOW_OIDC_AUTH__AUTH__TOKEN_EXCHANGE_ENABLED+++[]
endif::add-copy-button-to-env-var[]
ifndef::add-copy-button-to-env-var[]
Environment variable: `+++QUARKUS_FLOW_OIDC_AUTH__AUTH__TOKEN_EXCHANGE_ENABLED+++`
endif::add-copy-button-to-env-var[]
--
|boolean
|

a| [[quarkus-flow-oidc_quarkus-flow-oidc-auth-auth-proactive-refresh-seconds]] [.property-path]##link:#quarkus-flow-oidc_quarkus-flow-oidc-auth-auth-proactive-refresh-seconds[`+++quarkus.flow.oidc.auth."auth".proactive-refresh-seconds+++`]##
ifdef::add-copy-button-to-config-props[]
config_property_copy_button:+++quarkus.flow.oidc.auth."auth".proactive-refresh-seconds+++[]
endif::add-copy-button-to-config-props[]


[.description]
--
Per-scheme proactive-refresh threshold (seconds), overriding the global value.


ifdef::add-copy-button-to-env-var[]
Environment variable: env_var_with_copy_button:+++QUARKUS_FLOW_OIDC_AUTH__AUTH__PROACTIVE_REFRESH_SECONDS+++[]
endif::add-copy-button-to-env-var[]
ifndef::add-copy-button-to-env-var[]
Environment variable: `+++QUARKUS_FLOW_OIDC_AUTH__AUTH__PROACTIVE_REFRESH_SECONDS+++`
endif::add-copy-button-to-env-var[]
--
|int
|

a| [[quarkus-flow-oidc_quarkus-flow-oidc-auth-auth-token-propagation-enabled]] [.property-path]##link:#quarkus-flow-oidc_quarkus-flow-oidc-auth-auth-token-propagation-enabled[`+++quarkus.flow.oidc.auth."auth".token-propagation-enabled+++`]##
ifdef::add-copy-button-to-config-props[]
config_property_copy_button:+++quarkus.flow.oidc.auth."auth".token-propagation-enabled+++[]
endif::add-copy-button-to-config-props[]


[.description]
--
Forward the caller's subject token unchanged. Takes precedence over exchange when enabled.


ifdef::add-copy-button-to-env-var[]
Environment variable: env_var_with_copy_button:+++QUARKUS_FLOW_OIDC_AUTH__AUTH__TOKEN_PROPAGATION_ENABLED+++[]
endif::add-copy-button-to-env-var[]
ifndef::add-copy-button-to-env-var[]
Environment variable: `+++QUARKUS_FLOW_OIDC_AUTH__AUTH__TOKEN_PROPAGATION_ENABLED+++`
endif::add-copy-button-to-env-var[]
--
|boolean
|

|===

ifndef::no-duration-note[]
[NOTE]
[id=duration-note-anchor-quarkus-flow-oidc_quarkus-flow]
.About the Duration format
====
To write duration values, use the standard `java.time.Duration` format.
See the link:https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/time/Duration.html#parse(java.lang.CharSequence)[Duration#parse() Java API documentation] for more information.

You can also use a simplified format, starting with a number:

* If the value is only a number, it represents time in seconds.
* If the value is a number followed by `ms`, it represents time in milliseconds.

In other cases, the simplified format is translated to the `java.time.Duration` format for parsing:

* If the value is a number followed by `h`, `m`, or `s`, it is prefixed with `PT`.
* If the value is a number followed by `d`, it is prefixed with `P`.
====
endif::no-duration-note[]
Loading
Loading