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 37e6576b7e..9e734e6fb2 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 0000000000..5334997ca9 --- /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 0000000000..d3ad622a8e --- /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 0000000000..b867bf85c5 --- /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 0000000000..196147e7df --- /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 0000000000..e95cecd550 --- /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 cffc8f6314..08a07d7d9d 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 0000000000..d3a751d7a8 --- /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 7856d0bd07..aac3cad1fe 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 0000000000..10386027b0 --- /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 0000000000..b12d38b629 --- /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 0000000000..ea1d9526d3 --- /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 0000000000..0734a9676b --- /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 0000000000..e7e1ddc4d8 --- /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 9066bef989..42fc152a0e 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 0000000000..6c7a2b9806 --- /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)); + } +}