diff --git a/security/keycloak-oidc-client-extended/src/main/java/io/quarkus/ts/security/keycloak/oidcclient/extended/restclient/ping/clients/TokenPropagationPongClient.java b/security/keycloak-oidc-client-extended/src/main/java/io/quarkus/ts/security/keycloak/oidcclient/extended/restclient/ping/clients/TokenPropagationPongClient.java
index 37e6576b7..9e734e6fb 100644
--- a/security/keycloak-oidc-client-extended/src/main/java/io/quarkus/ts/security/keycloak/oidcclient/extended/restclient/ping/clients/TokenPropagationPongClient.java
+++ b/security/keycloak-oidc-client-extended/src/main/java/io/quarkus/ts/security/keycloak/oidcclient/extended/restclient/ping/clients/TokenPropagationPongClient.java
@@ -10,13 +10,14 @@
 import jakarta.ws.rs.Produces;
 import jakarta.ws.rs.core.MediaType;
 
+import org.eclipse.microprofile.rest.client.annotation.RegisterProvider;
 import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
 
-import io.quarkus.oidc.token.propagation.AccessToken;
 import io.quarkus.ts.security.keycloak.oidcclient.extended.restclient.model.Score;
+import io.quarkus.ts.security.keycloak.oidcclient.extended.restclient.ping.filters.DefaultTokenRequestFilter;
 
 @RegisterRestClient
-@AccessToken
+@RegisterProvider(DefaultTokenRequestFilter.class)
 @Path("/rest-pong")
 public interface TokenPropagationPongClient {
 
diff --git a/security/keycloak-oidc-client-extended/src/main/java/io/quarkus/ts/security/keycloak/oidcclient/extended/restclient/ping/filters/CustomTokenRequestFilter.java b/security/keycloak-oidc-client-extended/src/main/java/io/quarkus/ts/security/keycloak/oidcclient/extended/restclient/ping/filters/CustomTokenRequestFilter.java
new file mode 100644
index 000000000..5334997ca
--- /dev/null
+++ b/security/keycloak-oidc-client-extended/src/main/java/io/quarkus/ts/security/keycloak/oidcclient/extended/restclient/ping/filters/CustomTokenRequestFilter.java
@@ -0,0 +1,15 @@
+package io.quarkus.ts.security.keycloak.oidcclient.extended.restclient.ping.filters;
+
+import io.quarkus.oidc.token.propagation.AccessTokenRequestFilter;
+
+public class CustomTokenRequestFilter extends AccessTokenRequestFilter {
+    @Override
+    protected String getClientName() {
+        return "exchange-token";
+    }
+
+    @Override
+    protected boolean isExchangeToken() {
+        return true;
+    }
+}
diff --git a/security/keycloak-oidc-client-extended/src/main/java/io/quarkus/ts/security/keycloak/oidcclient/extended/restclient/ping/filters/DefaultTokenRequestFilter.java b/security/keycloak-oidc-client-extended/src/main/java/io/quarkus/ts/security/keycloak/oidcclient/extended/restclient/ping/filters/DefaultTokenRequestFilter.java
new file mode 100644
index 000000000..d3ad622a8
--- /dev/null
+++ b/security/keycloak-oidc-client-extended/src/main/java/io/quarkus/ts/security/keycloak/oidcclient/extended/restclient/ping/filters/DefaultTokenRequestFilter.java
@@ -0,0 +1,14 @@
+package io.quarkus.ts.security.keycloak.oidcclient.extended.restclient.ping.filters;
+
+import io.quarkus.oidc.token.propagation.AccessTokenRequestFilter;
+
+/**
+ * This class is required for
+ * {@link io.quarkus.ts.security.keycloak.oidcclient.extended.restclient.ping.clients.TokenPropagationPongClient}
+ * It would not be required normally, but having {@link CustomTokenRequestFilter} causes AmbiguousResolutionException when
+ * getting a default filter.
+ * So this class is necessary to have unambiguous filter for TokenPropagatingPongClient.
+ * TODO: remove once issue is solved https://github.com/quarkusio/quarkus/issues/36994
+ */
+public class DefaultTokenRequestFilter extends AccessTokenRequestFilter {
+}
diff --git a/security/keycloak-oidc-client-extended/src/main/java/io/quarkus/ts/security/keycloak/oidcclient/extended/restclient/principal/FilteredTokenResource.java b/security/keycloak-oidc-client-extended/src/main/java/io/quarkus/ts/security/keycloak/oidcclient/extended/restclient/principal/FilteredTokenResource.java
new file mode 100644
index 000000000..b867bf85c
--- /dev/null
+++ b/security/keycloak-oidc-client-extended/src/main/java/io/quarkus/ts/security/keycloak/oidcclient/extended/restclient/principal/FilteredTokenResource.java
@@ -0,0 +1,22 @@
+package io.quarkus.ts.security.keycloak.oidcclient.extended.restclient.principal;
+
+import jakarta.inject.Inject;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+
+import org.eclipse.microprofile.rest.client.inject.RestClient;
+
+import io.quarkus.ts.security.keycloak.oidcclient.extended.restclient.principal.clients.TokenPropagationFilteredClient;
+
+@Path("/token-propagation-filter")
+public class FilteredTokenResource {
+
+    @Inject
+    @RestClient
+    TokenPropagationFilteredClient tokenPropagationFilterClient;
+
+    @GET
+    public String getUserName() {
+        return tokenPropagationFilterClient.getUserName();
+    }
+}
diff --git a/security/keycloak-oidc-client-extended/src/main/java/io/quarkus/ts/security/keycloak/oidcclient/extended/restclient/principal/PrincipalResource.java b/security/keycloak-oidc-client-extended/src/main/java/io/quarkus/ts/security/keycloak/oidcclient/extended/restclient/principal/PrincipalResource.java
new file mode 100644
index 000000000..196147e7d
--- /dev/null
+++ b/security/keycloak-oidc-client-extended/src/main/java/io/quarkus/ts/security/keycloak/oidcclient/extended/restclient/principal/PrincipalResource.java
@@ -0,0 +1,22 @@
+package io.quarkus.ts.security.keycloak.oidcclient.extended.restclient.principal;
+
+import java.security.Principal;
+
+import jakarta.inject.Inject;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+
+import io.quarkus.security.Authenticated;
+
+@Path("/principal")
+@Authenticated
+public class PrincipalResource {
+
+    @Inject
+    Principal principal;
+
+    @GET
+    public String principalName() {
+        return principal.getName();
+    }
+}
diff --git a/security/keycloak-oidc-client-extended/src/main/java/io/quarkus/ts/security/keycloak/oidcclient/extended/restclient/principal/clients/TokenPropagationFilteredClient.java b/security/keycloak-oidc-client-extended/src/main/java/io/quarkus/ts/security/keycloak/oidcclient/extended/restclient/principal/clients/TokenPropagationFilteredClient.java
new file mode 100644
index 000000000..e95cecd55
--- /dev/null
+++ b/security/keycloak-oidc-client-extended/src/main/java/io/quarkus/ts/security/keycloak/oidcclient/extended/restclient/principal/clients/TokenPropagationFilteredClient.java
@@ -0,0 +1,20 @@
+package io.quarkus.ts.security.keycloak.oidcclient.extended.restclient.principal.clients;
+
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+
+import org.eclipse.microprofile.rest.client.annotation.RegisterClientHeaders;
+import org.eclipse.microprofile.rest.client.annotation.RegisterProvider;
+import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
+
+import io.quarkus.ts.security.keycloak.oidcclient.extended.restclient.ping.filters.CustomTokenRequestFilter;
+
+@RegisterRestClient
+@RegisterClientHeaders
+@Path("/principal")
+@RegisterProvider(CustomTokenRequestFilter.class)
+public interface TokenPropagationFilteredClient {
+
+    @GET
+    String getUserName();
+}
diff --git a/security/keycloak-oidc-client-extended/src/main/resources/application.properties b/security/keycloak-oidc-client-extended/src/main/resources/application.properties
index cffc8f631..08a07d7d9 100644
--- a/security/keycloak-oidc-client-extended/src/main/resources/application.properties
+++ b/security/keycloak-oidc-client-extended/src/main/resources/application.properties
@@ -24,6 +24,13 @@ quarkus.oidc-client.test-user.grant.type=password
 quarkus.oidc-client.test-user.grant-options.password.username=test-user
 quarkus.oidc-client.test-user.grant-options.password.password=test-user
 
+
+## Exchange token client
+quarkus.oidc-client.exchange-token.auth-server-url=${quarkus.oidc.auth-server-url}
+quarkus.oidc-client.exchange-token.client-id=test-application-client
+quarkus.oidc-client.exchange-token.credentials.secret=test-application-client-secret
+quarkus.oidc-client.exchange-token.grant.type=exchange
+
 # RestClient
 io.quarkus.ts.security.keycloak.oidcclient.extended.restclient.ping.clients.PongClient/mp-rest/url=http://localhost:${quarkus.http.port}
 io.quarkus.ts.security.keycloak.oidcclient.extended.restclient.ping.clients.PongClient/mp-rest/scope=jakarta.inject.Singleton
@@ -38,5 +45,7 @@ io.quarkus.ts.security.keycloak.oidcclient.extended.restclient.ping.clients.Auto
 
 io.quarkus.ts.security.keycloak.oidcclient.extended.restclient.ping.clients.TokenPropagationPongClient/mp-rest/url=http://localhost:${quarkus.http.port}
 
+io.quarkus.ts.security.keycloak.oidcclient.extended.restclient.principal.clients.TokenPropagationFilteredClient/mp-rest/url=http://localhost:${quarkus.http.port}
+
 #OpenAPI
 quarkus.smallrye-openapi.store-schema-directory=target/generated/jakarta-rest/
diff --git a/security/keycloak-oidc-client-extended/src/test/java/io/quarkus/ts/security/keycloak/oidcclient/extended/restclient/TokenPropagationFilterIT.java b/security/keycloak-oidc-client-extended/src/test/java/io/quarkus/ts/security/keycloak/oidcclient/extended/restclient/TokenPropagationFilterIT.java
new file mode 100644
index 000000000..d3a751d7a
--- /dev/null
+++ b/security/keycloak-oidc-client-extended/src/test/java/io/quarkus/ts/security/keycloak/oidcclient/extended/restclient/TokenPropagationFilterIT.java
@@ -0,0 +1,22 @@
+package io.quarkus.ts.security.keycloak.oidcclient.extended.restclient;
+
+import static io.restassured.RestAssured.given;
+import static org.hamcrest.CoreMatchers.containsString;
+
+import org.apache.http.HttpStatus;
+import org.junit.jupiter.api.Test;
+
+import io.quarkus.test.scenarios.QuarkusScenario;
+
+@QuarkusScenario
+public class TokenPropagationFilterIT extends BaseOidcIT {
+
+    @Test
+    public void usernameTest() {
+        given()
+                .auth().oauth2(createToken())
+                .when().get("/token-propagation-filter")
+                .then().statusCode(HttpStatus.SC_OK)
+                .body(containsString(USER));
+    }
+}
diff --git a/security/keycloak-oidc-client-reactive-extended/src/main/java/io/quarkus/ts/security/keycloak/oidcclient/reactive/extended/ping/clients/TokenPropagationPongClient.java b/security/keycloak-oidc-client-reactive-extended/src/main/java/io/quarkus/ts/security/keycloak/oidcclient/reactive/extended/ping/clients/TokenPropagationPongClient.java
index 7856d0bd0..aac3cad1f 100644
--- a/security/keycloak-oidc-client-reactive-extended/src/main/java/io/quarkus/ts/security/keycloak/oidcclient/reactive/extended/ping/clients/TokenPropagationPongClient.java
+++ b/security/keycloak-oidc-client-reactive-extended/src/main/java/io/quarkus/ts/security/keycloak/oidcclient/reactive/extended/ping/clients/TokenPropagationPongClient.java
@@ -13,11 +13,11 @@
 import org.eclipse.microprofile.rest.client.annotation.RegisterProvider;
 import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
 
-import io.quarkus.oidc.token.propagation.reactive.AccessTokenRequestReactiveFilter;
 import io.quarkus.ts.security.keycloak.oidcclient.reactive.extended.model.Score;
+import io.quarkus.ts.security.keycloak.oidcclient.reactive.extended.ping.filters.DefaultTokenRequestFilter;
 
 @RegisterRestClient
-@RegisterProvider(AccessTokenRequestReactiveFilter.class)
+@RegisterProvider(DefaultTokenRequestFilter.class)
 @Path("/rest-pong")
 public interface TokenPropagationPongClient {
 
diff --git a/security/keycloak-oidc-client-reactive-extended/src/main/java/io/quarkus/ts/security/keycloak/oidcclient/reactive/extended/ping/filters/CustomTokenRequestFilter.java b/security/keycloak-oidc-client-reactive-extended/src/main/java/io/quarkus/ts/security/keycloak/oidcclient/reactive/extended/ping/filters/CustomTokenRequestFilter.java
new file mode 100644
index 000000000..10386027b
--- /dev/null
+++ b/security/keycloak-oidc-client-reactive-extended/src/main/java/io/quarkus/ts/security/keycloak/oidcclient/reactive/extended/ping/filters/CustomTokenRequestFilter.java
@@ -0,0 +1,15 @@
+package io.quarkus.ts.security.keycloak.oidcclient.reactive.extended.ping.filters;
+
+import io.quarkus.oidc.token.propagation.reactive.AccessTokenRequestReactiveFilter;
+
+public class CustomTokenRequestFilter extends AccessTokenRequestReactiveFilter {
+    @Override
+    protected String getClientName() {
+        return "exchange-token";
+    }
+
+    @Override
+    protected boolean isExchangeToken() {
+        return true;
+    }
+}
diff --git a/security/keycloak-oidc-client-reactive-extended/src/main/java/io/quarkus/ts/security/keycloak/oidcclient/reactive/extended/ping/filters/DefaultTokenRequestFilter.java b/security/keycloak-oidc-client-reactive-extended/src/main/java/io/quarkus/ts/security/keycloak/oidcclient/reactive/extended/ping/filters/DefaultTokenRequestFilter.java
new file mode 100644
index 000000000..b12d38b62
--- /dev/null
+++ b/security/keycloak-oidc-client-reactive-extended/src/main/java/io/quarkus/ts/security/keycloak/oidcclient/reactive/extended/ping/filters/DefaultTokenRequestFilter.java
@@ -0,0 +1,9 @@
+package io.quarkus.ts.security.keycloak.oidcclient.reactive.extended.ping.filters;
+
+import io.quarkus.oidc.token.propagation.reactive.AccessTokenRequestReactiveFilter;
+
+/**
+ * TODO: remove once issue is solved https://github.com/quarkusio/quarkus/issues/36994
+ */
+public class DefaultTokenRequestFilter extends AccessTokenRequestReactiveFilter {
+}
diff --git a/security/keycloak-oidc-client-reactive-extended/src/main/java/io/quarkus/ts/security/keycloak/oidcclient/reactive/extended/principal/FilteredTokenResource.java b/security/keycloak-oidc-client-reactive-extended/src/main/java/io/quarkus/ts/security/keycloak/oidcclient/reactive/extended/principal/FilteredTokenResource.java
new file mode 100644
index 000000000..ea1d9526d
--- /dev/null
+++ b/security/keycloak-oidc-client-reactive-extended/src/main/java/io/quarkus/ts/security/keycloak/oidcclient/reactive/extended/principal/FilteredTokenResource.java
@@ -0,0 +1,22 @@
+package io.quarkus.ts.security.keycloak.oidcclient.reactive.extended.principal;
+
+import jakarta.inject.Inject;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+
+import org.eclipse.microprofile.rest.client.inject.RestClient;
+
+import io.quarkus.ts.security.keycloak.oidcclient.reactive.extended.principal.clients.TokenPropagationFilteredClient;
+
+@Path("/token-propagation-filter")
+public class FilteredTokenResource {
+
+    @Inject
+    @RestClient
+    TokenPropagationFilteredClient tokenPropagationFilterClient;
+
+    @GET
+    public String getUserName() {
+        return tokenPropagationFilterClient.getUserName();
+    }
+}
diff --git a/security/keycloak-oidc-client-reactive-extended/src/main/java/io/quarkus/ts/security/keycloak/oidcclient/reactive/extended/principal/PrincipalResource.java b/security/keycloak-oidc-client-reactive-extended/src/main/java/io/quarkus/ts/security/keycloak/oidcclient/reactive/extended/principal/PrincipalResource.java
new file mode 100644
index 000000000..0734a9676
--- /dev/null
+++ b/security/keycloak-oidc-client-reactive-extended/src/main/java/io/quarkus/ts/security/keycloak/oidcclient/reactive/extended/principal/PrincipalResource.java
@@ -0,0 +1,22 @@
+package io.quarkus.ts.security.keycloak.oidcclient.reactive.extended.principal;
+
+import java.security.Principal;
+
+import jakarta.inject.Inject;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+
+import io.quarkus.security.Authenticated;
+
+@Path("/principal")
+@Authenticated
+public class PrincipalResource {
+
+    @Inject
+    Principal principal;
+
+    @GET
+    public String principalName() {
+        return principal.getName();
+    }
+}
diff --git a/security/keycloak-oidc-client-reactive-extended/src/main/java/io/quarkus/ts/security/keycloak/oidcclient/reactive/extended/principal/clients/TokenPropagationFilteredClient.java b/security/keycloak-oidc-client-reactive-extended/src/main/java/io/quarkus/ts/security/keycloak/oidcclient/reactive/extended/principal/clients/TokenPropagationFilteredClient.java
new file mode 100644
index 000000000..e7e1ddc4d
--- /dev/null
+++ b/security/keycloak-oidc-client-reactive-extended/src/main/java/io/quarkus/ts/security/keycloak/oidcclient/reactive/extended/principal/clients/TokenPropagationFilteredClient.java
@@ -0,0 +1,20 @@
+package io.quarkus.ts.security.keycloak.oidcclient.reactive.extended.principal.clients;
+
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+
+import org.eclipse.microprofile.rest.client.annotation.RegisterClientHeaders;
+import org.eclipse.microprofile.rest.client.annotation.RegisterProvider;
+import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
+
+import io.quarkus.ts.security.keycloak.oidcclient.reactive.extended.ping.filters.CustomTokenRequestFilter;
+
+@RegisterRestClient
+@RegisterClientHeaders
+@Path("/principal")
+@RegisterProvider(CustomTokenRequestFilter.class)
+public interface TokenPropagationFilteredClient {
+
+    @GET
+    String getUserName();
+}
diff --git a/security/keycloak-oidc-client-reactive-extended/src/main/resources/application.properties b/security/keycloak-oidc-client-reactive-extended/src/main/resources/application.properties
index 9066bef98..42fc152a0 100644
--- a/security/keycloak-oidc-client-reactive-extended/src/main/resources/application.properties
+++ b/security/keycloak-oidc-client-reactive-extended/src/main/resources/application.properties
@@ -24,6 +24,12 @@ quarkus.oidc-client.test-user.grant.type=password
 quarkus.oidc-client.test-user.grant-options.password.username=test-user
 quarkus.oidc-client.test-user.grant-options.password.password=test-user
 
+## Exchange token client
+quarkus.oidc-client.exchange-token.auth-server-url=${quarkus.oidc.auth-server-url}
+quarkus.oidc-client.exchange-token.client-id=test-application-client
+quarkus.oidc-client.exchange-token.credentials.secret=test-application-client-secret
+quarkus.oidc-client.exchange-token.grant.type=exchange
+
 # RestClient
 io.quarkus.ts.security.keycloak.oidcclient.reactive.extended.ping.clients.PongClient/mp-rest/url=http://localhost:${quarkus.http.port}
 io.quarkus.ts.security.keycloak.oidcclient.reactive.extended.ping.clients.PongClient/mp-rest/scope=jakarta.inject.Singleton
@@ -38,5 +44,7 @@ io.quarkus.ts.security.keycloak.oidcclient.reactive.extended.ping.clients.AutoAc
 
 io.quarkus.ts.security.keycloak.oidcclient.reactive.extended.ping.clients.TokenPropagationPongClient/mp-rest/url=http://localhost:${quarkus.http.port}
 
+io.quarkus.ts.security.keycloak.oidcclient.reactive.extended.principal.clients.TokenPropagationFilteredClient/mp-rest/url=http://localhost:${quarkus.http.port}
+
 #OpenAPI
 quarkus.smallrye-openapi.store-schema-directory=target/generated/jakarta-rest/
diff --git a/security/keycloak-oidc-client-reactive-extended/src/test/java/io/quarkus/ts/security/keycloak/oidcclient/reactive/extended/TokenPropagationFilterIT.java b/security/keycloak-oidc-client-reactive-extended/src/test/java/io/quarkus/ts/security/keycloak/oidcclient/reactive/extended/TokenPropagationFilterIT.java
new file mode 100644
index 000000000..6c7a2b980
--- /dev/null
+++ b/security/keycloak-oidc-client-reactive-extended/src/test/java/io/quarkus/ts/security/keycloak/oidcclient/reactive/extended/TokenPropagationFilterIT.java
@@ -0,0 +1,22 @@
+package io.quarkus.ts.security.keycloak.oidcclient.reactive.extended;
+
+import static io.restassured.RestAssured.given;
+import static org.hamcrest.CoreMatchers.containsString;
+
+import org.apache.http.HttpStatus;
+import org.junit.jupiter.api.Test;
+
+import io.quarkus.test.scenarios.QuarkusScenario;
+
+@QuarkusScenario
+public class TokenPropagationFilterIT extends BaseOidcIT {
+
+    @Test
+    public void usernameTest() {
+        given()
+                .auth().oauth2(createToken())
+                .when().get("/token-propagation-filter")
+                .then().statusCode(HttpStatus.SC_OK)
+                .body(containsString(USER));
+    }
+}