feat(actionsv2): Propagate request headers in actions v2 (#10632)

# Which Problems Are Solved

This PR adds functionality to propagate request headers in actions v2. 

# How the Problems Are Solved
The new functionality is added to the`ExecutionHandler` interceptors,
where the incoming request headers (from a list of allowed headers to be
forwarded) are set in the payload of the request before calling the
target.

# Additional Changes
This PR also contains minor fixes to the Actions V2 example docs. 

# Additional Context
- Closes #9941

---------

Co-authored-by: Marco A. <[email protected]>
This commit is contained in:
Gayathri Vijayan
2025-09-08 08:50:52 +00:00
committed by GitHub
co-authored by Marco A.
parent a06ae2c835
commit 51e12e224d
11 changed files with 363 additions and 138 deletions
@@ -114,17 +114,27 @@ Now that you have set up the target and execution, you can test it by creating a
by calling the ZITADEL API to create a human user.
```shell
curl -L -X PUT 'https://$CUSTOM-DOMAIN/v2/users/human' \
curl -L -X POST 'https://$CUSTOM-DOMAIN/v2/users/new' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer <TOKEN>' \
--data-raw '{
"userId": {
"givenName": "Test",
"familyName": "User"
},
"email": {
"email": "[email protected]"
"organizationId": "336392597046099971",
"human":
{
"profile":
{
"givenName": "Minnie",
"familyName": "Mouse",
"nickName": "Mini",
"displayName": "Minnie Mouse",
"preferredLanguage": "en",
"gender": "GENDER_FEMALE"
},
"email":
{
"email": "[email protected]"
}
}
}'
```
@@ -134,22 +144,25 @@ the [Sent information Event](./usage#sent-information-event) payload description
```json
{
"aggregateID": "313014806065971608",
"aggregateID": "336494809936035843",
"aggregateType": "user",
"resourceOwner": "312909075211944344",
"instanceID": "312909075211878808",
"resourceOwner": "336392597046099971",
"instanceID": "336392597046034435",
"version": "v2",
"sequence": 1,
"event_type": "user.human.added",
"created_at": "2025-03-27T10:22:43.262665+01:00",
"userID": "312909075212468632",
"event_payload": {
"userName":"[email protected]",
"firstName":"Test",
"lastName":"User",
"displayName":"Test User",
"preferredLanguage":"und",
"email":"example@test.com"
"created_at": "2025-09-05T08:55:36.156333Z",
"userID": "336392597046755331",
"event_payload":
{
"email": "[email protected]",
"gender": 1,
"lastName": "Mouse",
"nickName": "Mini",
"userName": "mini@mouse.com",
"firstName": "Minnie",
"displayName": "Minnie Mouse",
"preferredLanguage": "en"
}
}
```
@@ -158,12 +171,14 @@ The event_payload is base64 encoded and has the following content:
```json
{
"userName": "example@test.com",
"firstName": "Test",
"lastName": "User",
"displayName": "Test User",
"preferredLanguage": "und",
"email": "[email protected]"
"email": "mini@mouse.com",
"gender": 1,
"lastName": "Mouse",
"nickName": "Mini",
"userName": "[email protected]",
"firstName": "Minnie",
"displayName": "Minnie Mouse",
"preferredLanguage": "en"
}
```
@@ -150,7 +150,7 @@ curl -L -X PUT 'https://$CUSTOM-DOMAIN/v2beta/actions/executions' \
--data-raw '{
"condition": {
"request": {
"method": "/zitadel.user.v2.UserService/AddHumanUser"
"method": "/zitadel.user.v2.UserService/CreateUser"
}
},
"targets": [
@@ -165,17 +165,27 @@ Now that you have set up the target and execution, you can test it by creating a
by calling the ZITADEL API to create a human user.
```shell
curl -L -X PUT 'https://$CUSTOM-DOMAIN/v2/users/human' \
curl -L -X POST 'https://$CUSTOM-DOMAIN/v2/users/new' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer <TOKEN>' \
--data-raw '{
"profile": {
"givenName": "Example_given",
"familyName": "Example_family"
},
"email": {
"email": "[email protected]"
"organizationId": "336392597046099971",
"human":
{
"profile":
{
"givenName": "Minnie",
"familyName": "Mouse",
"nickName": "Mini",
"displayName": "Minnie Mouse",
"preferredLanguage": "en",
"gender": "GENDER_FEMALE"
},
"email":
{
"email": "[email protected]"
}
}
}'
```
@@ -184,17 +194,27 @@ Your server should now manipulate the request to something like the following. C
the [Sent information Request](./usage#sent-information-request) payload description.
```shell
curl -L -X PUT 'https://$CUSTOM-DOMAIN/v2/users/human' \
curl -L -X PUT 'https://$CUSTOM-DOMAIN/v2/users/new' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer <TOKEN>' \
--data-raw '{
"profile": {
"givenName": "Example_given",
"familyName": "Example_family"
},
"email": {
"email": "[email protected]"
"organizationId": "336392597046099971",
"human":
{
"profile":
{
"givenName": "Minnie",
"familyName": "Mouse",
"nickName": "Mini",
"displayName": "Minnie Mouse",
"preferredLanguage": "en",
"gender": "GENDER_FEMALE"
},
"email":
{
"email": "[email protected]"
}
}
"metadata": [
{"key": "organization", "value": "Y29tcGFueQ=="}
@@ -110,7 +110,7 @@ curl -L -X PUT 'https://$CUSTOM-DOMAIN/v2beta/actions/executions' \
--data-raw '{
"condition": {
"request": {
"method": "/zitadel.user.v2.UserService/AddHumanUser"
"method": "/zitadel.user.v2.UserService/CreateUser"
}
},
"targets": [
@@ -125,17 +125,27 @@ Now that you have set up the target and execution, you can test it by creating a
by calling the ZITADEL API to create a human user.
```shell
curl -L -X PUT 'https://$CUSTOM-DOMAIN/v2/users/human' \
curl -L -X PUT 'https://$CUSTOM-DOMAIN/v2/users/new' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer <TOKEN>' \
--data-raw '{
"profile": {
"givenName": "Example_given",
"familyName": "Example_family"
},
"email": {
"email": "[email protected]"
"organizationId": "336392597046099971",
"human":
{
"profile":
{
"givenName": "Minnie",
"familyName": "Mouse",
"nickName": "Mini",
"displayName": "Minnie Mouse",
"preferredLanguage": "en",
"gender": "GENDER_FEMALE"
},
"email":
{
"email": "[email protected]"
}
}
}'
```
@@ -143,22 +153,48 @@ curl -L -X PUT 'https://$CUSTOM-DOMAIN/v2/users/human' \
Your server should now print out something like the following. Check out
the [Sent information Request](./usage#sent-information-request) payload description.
```shell
```json
{
"fullMethod": "/zitadel.user.v2.UserService/AddHumanUser",
"instanceID": "262851882718855632",
"orgID": "262851882718921168",
"projectID": "262851882719052240",
"userID": "262851882718986704",
"request": {
"profile": {
"given_name": "Example_given",
"family_name": "Example_family"
"fullMethod": "/zitadel.user.v2.UserService/CreateUser",
"instanceID": "336392597046034435",
"orgID": "336392597046099971",
"projectID": "336392597046165507",
"userID": "336392597046755331",
"request":
{
"organizationId": "336392597046099971",
"human":
{
"profile":
{
"givenName": "Minnie",
"familyName": "Mouse",
"nickName": "Mini",
"displayName": "Minnie Mouse",
"preferredLanguage": "en",
"gender": "GENDER_FEMALE"
},
"email":
{
"email": "[email protected]"
}
}
},
"email": {
"email": "[email protected]"
"headers":
{
"Content-Type":
[
"application/grpc"
],
"Host":
[
"localhost:8080"
],
"X-Forwarded-Host":
[
"localhost:8080"
]
}
}
}
```
@@ -103,7 +103,7 @@ curl -L -X PUT 'https://$CUSTOM-DOMAIN/v2beta/actions/executions' \
--data-raw '{
"condition": {
"request": {
"method": "/zitadel.user.v2.UserService/AddHumanUser"
"method": "/zitadel.user.v2.UserService/CreateUser"
}
},
"targets": [
@@ -118,40 +118,77 @@ Now that you have set up the target and execution, you can test it by creating a
by calling the ZITADEL API to create a human user.
```shell
curl -L -X PUT 'https://$CUSTOM-DOMAIN/v2/users/human' \
curl -L -X POST 'https://$CUSTOM-DOMAIN/v2/users/new' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer <TOKEN>' \
--data-raw '{
"profile": {
"givenName": "Test",
"familyName": "User"
},
"email": {
"email": "[email protected]"
"organizationId": "336392597046099971",
"human":
{
"profile":
{
"givenName": "Minnie",
"familyName": "Mouse",
"nickName": "Mini",
"displayName": "Minnie Mouse",
"preferredLanguage": "en",
"gender": "GENDER_FEMALE"
},
"email":
{
"email": "[email protected]"
}
}
}'
```
Your server should now print out something like the following. Check out
the [Sent information Request](./usage#sent-information-request) payload description.
the [Sent information Request](./usage#sent-information-request) payload description.
The incoming request headers to the Execution are propagated via the request payload to the target.
```shell
```json
{
"fullMethod": "/zitadel.user.v2.UserService/AddHumanUser",
"instanceID": "262851882718855632",
"orgID": "262851882718921168",
"projectID": "262851882719052240",
"userID": "262851882718986704",
"request": {
"profile": {
"given_name": "Test",
"family_name": "User"
"fullMethod": "/zitadel.user.v2.UserService/CreateUser",
"instanceID": "336392597046034435",
"orgID": "336392597046099971",
"projectID": "336392597046165507",
"userID": "336392597046755331",
"request":
{
"organizationId": "336392597046099971",
"human":
{
"profile":
{
"givenName": "Minnie",
"familyName": "Mouse",
"nickName": "Mini",
"displayName": "Minnie Mouse",
"preferredLanguage": "en",
"gender": "GENDER_FEMALE"
},
"email":
{
"email": "[email protected]"
}
}
},
"email": {
"email": "[email protected]"
"headers":
{
"Content-Type":
[
"application/grpc"
],
"Host":
[
"localhost:8080"
],
"X-Forwarded-Host":
[
"localhost:8080"
]
}
}
}
```
@@ -103,7 +103,7 @@ curl -L -X PUT 'https://$CUSTOM-DOMAIN/v2beta/actions/executions' \
--data-raw '{
"condition": {
"response": {
"method": "/zitadel.user.v2.UserService/AddHumanUser"
"method": "/zitadel.user.v2.UserService/CreateUser"
}
},
"targets": [
@@ -118,47 +118,81 @@ Now that you have set up the target and execution, you can test it by creating a
by calling the ZITADEL API to create a human user.
```shell
curl -L -X PUT 'https://$CUSTOM-DOMAIN/v2/users/human' \
curl -L -X POST 'https://$CUSTOM-DOMAIN/v2/users/new' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer <TOKEN>' \
--data-raw '{
"userId": {
"givenName": "Example_given",
"familyName": "Example_family"
},
"email": {
"email": "[email protected]"
"organizationId": "336392597046099971",
"human":
{
"profile":
{
"givenName": "Minnie",
"familyName": "Mouse",
"nickName": "Mini",
"displayName": "Minnie Mouse",
"preferredLanguage": "en",
"gender": "GENDER_FEMALE"
},
"email":
{
"email": "[email protected]"
}
}
}'
```
Your server should now print out something like the following. Check out
the [Sent information Response](./usage#sent-information-response) payload description.
The incoming request headers to the Execution are propagated via the request payload to the target.
```json
{
"fullMethod": "/zitadel.user.v2.UserService/AddHumanUser",
"instanceID": "262851882718855632",
"orgID": "262851882718921168",
"projectID": "262851882719052240",
"userID": "262851882718986704",
"request": {
"profile": {
"given_name": "Example_given",
"family_name": "Example_family"
},
"email": {
"email": "[email protected]"
"fullMethod": "/zitadel.user.v2.UserService/CreateUser",
"instanceID": "336392597046034435",
"orgID": "336392597046099971",
"projectID": "336392597046165507",
"userID": "336392597046755331",
"request":
{
"organizationId": "336392597046099971",
"human":
{
"profile":
{
"givenName": "Minnie",
"familyName": "Mouse",
"nickName": "Mini",
"displayName": "Minnie Mouse",
"preferredLanguage": "en",
"gender": "GENDER_FEMALE"
},
"email":
{
"email": "[email protected]"
}
}
},
"response": {
"user_id": "312918757460672920",
"details": {
"sequence": "2",
"change_date": "2025-03-26T17:28:33.856436Z",
"resource_owner": "312909075211944344",
}
"response":
{
"id": "336494809936035843",
"creationDate": "2025-09-05T08:55:36.156333Z"
},
"headers":
{
"Content-Type":
[
"application/grpc"
],
"Host":
[
"localhost:8080"
],
"X-Forwarded-Host":
[
"localhost:8080"
]
}
}
```