From 3bbbcb91261d011ab480d58f07f0173624daa6cf Mon Sep 17 00:00:00 2001 From: Sergey Beryozkin Date: Fri, 7 Apr 2023 22:56:54 +0100 Subject: [PATCH] Throw the exception if OIDC client fails to acquire the token --- .../AbstractOidcClientRequestFilter.java | 8 +++---- ...stractOidcClientRequestReactiveFilter.java | 9 +++----- .../quarkus/it/keycloak/FrontendResource.java | 21 +++++++++++++++++++ .../keycloak/MisconfiguredClientFilter.java | 21 +++++++++++++++++++ .../src/main/resources/application.properties | 8 +++++++ .../quarkus/it/keycloak/OidcClientTest.java | 10 +++++++++ .../quarkus/it/keycloak/FrontendResource.java | 16 ++++++++++++++ .../keycloak/MisconfiguredClientFilter.java | 17 +++++++++++++++ .../src/main/resources/application.properties | 9 ++++++++ .../quarkus/it/keycloak/OidcClientTest.java | 10 +++++++++ 10 files changed, 119 insertions(+), 10 deletions(-) create mode 100644 integration-tests/oidc-client-reactive/src/main/java/io/quarkus/it/keycloak/MisconfiguredClientFilter.java create mode 100644 integration-tests/oidc-client/src/main/java/io/quarkus/it/keycloak/MisconfiguredClientFilter.java diff --git a/extensions/oidc-client-filter/runtime/src/main/java/io/quarkus/oidc/client/filter/runtime/AbstractOidcClientRequestFilter.java b/extensions/oidc-client-filter/runtime/src/main/java/io/quarkus/oidc/client/filter/runtime/AbstractOidcClientRequestFilter.java index 37657d832698c..5b2a0f25f67ac 100644 --- a/extensions/oidc-client-filter/runtime/src/main/java/io/quarkus/oidc/client/filter/runtime/AbstractOidcClientRequestFilter.java +++ b/extensions/oidc-client-filter/runtime/src/main/java/io/quarkus/oidc/client/filter/runtime/AbstractOidcClientRequestFilter.java @@ -5,7 +5,6 @@ import jakarta.ws.rs.client.ClientRequestContext; import jakarta.ws.rs.client.ClientRequestFilter; import jakarta.ws.rs.core.HttpHeaders; -import jakarta.ws.rs.core.Response; import org.jboss.logging.Logger; @@ -26,10 +25,11 @@ public void filter(ClientRequestContext requestContext) throws IOException { final String accessToken = getAccessToken(); requestContext.getHeaders().add(HttpHeaders.AUTHORIZATION, BEARER_SCHEME_WITH_SPACE + accessToken); } catch (DisabledOidcClientException ex) { - requestContext.abortWith(Response.status(500).build()); + LOG.debug("Client is disabled, aborting the request"); + throw ex; } catch (Exception ex) { - LOG.debugf("Access token is not available, aborting the request with HTTP 401 error: %s", ex.getMessage()); - requestContext.abortWith(Response.status(401).build()); + LOG.debugf("Access token is not available, cause: %s, aborting the request", ex.getMessage()); + throw (ex instanceof RuntimeException) ? (RuntimeException) ex : new RuntimeException(ex); } } diff --git a/extensions/oidc-client-reactive-filter/runtime/src/main/java/io/quarkus/oidc/client/reactive/filter/runtime/AbstractOidcClientRequestReactiveFilter.java b/extensions/oidc-client-reactive-filter/runtime/src/main/java/io/quarkus/oidc/client/reactive/filter/runtime/AbstractOidcClientRequestReactiveFilter.java index 777a10ee31142..9c266fb892baf 100644 --- a/extensions/oidc-client-reactive-filter/runtime/src/main/java/io/quarkus/oidc/client/reactive/filter/runtime/AbstractOidcClientRequestReactiveFilter.java +++ b/extensions/oidc-client-reactive-filter/runtime/src/main/java/io/quarkus/oidc/client/reactive/filter/runtime/AbstractOidcClientRequestReactiveFilter.java @@ -3,7 +3,6 @@ import java.util.function.Consumer; import jakarta.ws.rs.core.HttpHeaders; -import jakarta.ws.rs.core.Response; import org.jboss.logging.Logger; import org.jboss.resteasy.reactive.client.spi.ResteasyReactiveClientRequestContext; @@ -40,13 +39,11 @@ public void accept(Tokens tokens) { @Override public void accept(Throwable t) { if (t instanceof DisabledOidcClientException) { - LOG.debug("Client is disabled"); - requestContext.abortWith(Response.status(Response.Status.INTERNAL_SERVER_ERROR).build()); + LOG.debug("Client is disabled, aborting the request"); } else { - LOG.debugf("Access token is not available, aborting the request with HTTP 401 error: %s", t.getMessage()); - requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED).build()); + LOG.debugf("Access token is not available, cause: %s, aborting the request", t.getMessage()); } - requestContext.resume(); + requestContext.resume((t instanceof RuntimeException) ? t : new RuntimeException(t)); } }); } diff --git a/integration-tests/oidc-client-reactive/src/main/java/io/quarkus/it/keycloak/FrontendResource.java b/integration-tests/oidc-client-reactive/src/main/java/io/quarkus/it/keycloak/FrontendResource.java index 0726cbbe8cffa..9e3b2a559fc0c 100644 --- a/integration-tests/oidc-client-reactive/src/main/java/io/quarkus/it/keycloak/FrontendResource.java +++ b/integration-tests/oidc-client-reactive/src/main/java/io/quarkus/it/keycloak/FrontendResource.java @@ -1,5 +1,7 @@ package io.quarkus.it.keycloak; +import java.util.function.Function; + import jakarta.inject.Inject; import jakarta.ws.rs.GET; import jakarta.ws.rs.Path; @@ -23,6 +25,10 @@ public class FrontendResource { @RestClient ProtectedResourceServiceNamedFilter protectedResourceServiceNamedFilter; + @Inject + @RestClient + MisconfiguredClientFilter misconfiguredClientFilter; + @GET @Path("userNameCustomFilter") @Produces("text/plain") @@ -43,4 +49,19 @@ public Uni userNameReactive() { public Uni userNameNamedFilter() { return protectedResourceServiceNamedFilter.getUserName(); } + + @GET + @Path("userNameMisconfiguredClientFilter") + @Produces("text/plain") + public Uni userNameMisconfiguredClientFilter() { + return misconfiguredClientFilter.getUserName().onFailure(Throwable.class) + .recoverWithItem(new Function() { + + @Override + public String apply(Throwable t) { + return t.getMessage(); + } + + }); + } } diff --git a/integration-tests/oidc-client-reactive/src/main/java/io/quarkus/it/keycloak/MisconfiguredClientFilter.java b/integration-tests/oidc-client-reactive/src/main/java/io/quarkus/it/keycloak/MisconfiguredClientFilter.java new file mode 100644 index 0000000000000..fe92acce99e35 --- /dev/null +++ b/integration-tests/oidc-client-reactive/src/main/java/io/quarkus/it/keycloak/MisconfiguredClientFilter.java @@ -0,0 +1,21 @@ +package io.quarkus.it.keycloak; + +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; + +import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; + +import io.quarkus.oidc.client.filter.OidcClientFilter; +import io.smallrye.mutiny.Uni; + +@RegisterRestClient +@OidcClientFilter("misconfigured-client") +@Path("/") +public interface MisconfiguredClientFilter { + + @GET + @Produces("text/plain") + @Path("userNameReactive") + Uni getUserName(); +} diff --git a/integration-tests/oidc-client-reactive/src/main/resources/application.properties b/integration-tests/oidc-client-reactive/src/main/resources/application.properties index 26e2d60ffb0e4..3b9c72d07700c 100644 --- a/integration-tests/oidc-client-reactive/src/main/resources/application.properties +++ b/integration-tests/oidc-client-reactive/src/main/resources/application.properties @@ -17,9 +17,17 @@ quarkus.oidc-client.named-client.grant.type=password quarkus.oidc-client.named-client.grant-options.password.username=jdoe quarkus.oidc-client.named-client.grant-options.password.password=jdoe +quarkus.oidc-client.misconfigured-client.auth-server-url=${quarkus.oidc.auth-server-url} +quarkus.oidc-client.misconfigured-client.client-id=${quarkus.oidc.client-id} +quarkus.oidc-client.misconfigured-client.credentials.secret=${quarkus.oidc.credentials.secret} +quarkus.oidc-client.misconfigured-client.grant.type=password +quarkus.oidc-client.misconfigured-client.grant-options.password.username=jdoe +quarkus.oidc-client.misconfigured-client.grant-options.password.password=bob + io.quarkus.it.keycloak.ProtectedResourceServiceCustomFilter/mp-rest/url=http://localhost:8081/protected io.quarkus.it.keycloak.ProtectedResourceServiceReactiveFilter/mp-rest/url=http://localhost:8081/protected io.quarkus.it.keycloak.ProtectedResourceServiceNamedFilter/mp-rest/url=http://localhost:8081/protected +io.quarkus.it.keycloak.MisconfiguredClientFilter/mp-rest/url=http://localhost:8081/protected quarkus.log.category."io.quarkus.oidc.client.runtime.OidcClientImpl".min-level=TRACE quarkus.log.category."io.quarkus.oidc.client.runtime.OidcClientImpl".level=TRACE diff --git a/integration-tests/oidc-client-reactive/src/test/java/io/quarkus/it/keycloak/OidcClientTest.java b/integration-tests/oidc-client-reactive/src/test/java/io/quarkus/it/keycloak/OidcClientTest.java index ab999b6a55d01..70d3dea446bbb 100644 --- a/integration-tests/oidc-client-reactive/src/test/java/io/quarkus/it/keycloak/OidcClientTest.java +++ b/integration-tests/oidc-client-reactive/src/test/java/io/quarkus/it/keycloak/OidcClientTest.java @@ -2,6 +2,7 @@ import static org.awaitility.Awaitility.await; import static org.awaitility.Awaitility.given; +import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.equalTo; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -44,6 +45,15 @@ public void testGetUserNameNamedFilter() { .body(equalTo("jdoe")); } + @Test + public void testGetUserNameMisconfiguredClientFilter() { + RestAssured.given().header("Accept", "text/plain") + .when().get("/frontend/userNameMisconfiguredClientFilter") + .then() + .statusCode(200) + .body(containsString("invalid_grant")); + } + @Test public void testGetUserNameReactive() { RestAssured.given().header("Accept", "text/plain") diff --git a/integration-tests/oidc-client/src/main/java/io/quarkus/it/keycloak/FrontendResource.java b/integration-tests/oidc-client/src/main/java/io/quarkus/it/keycloak/FrontendResource.java index 59fc418d5e1a3..7af569e9a1d63 100644 --- a/integration-tests/oidc-client/src/main/java/io/quarkus/it/keycloak/FrontendResource.java +++ b/integration-tests/oidc-client/src/main/java/io/quarkus/it/keycloak/FrontendResource.java @@ -3,6 +3,7 @@ import jakarta.inject.Inject; import jakarta.ws.rs.GET; import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; import org.eclipse.microprofile.context.ManagedExecutor; import org.eclipse.microprofile.rest.client.inject.RestClient; @@ -29,6 +30,10 @@ public class FrontendResource { @RestClient ProtectedResourceServiceNonDefaultOidcClient protectedResourceServiceNonDefaultOidcClient; + @Inject + @RestClient + MisconfiguredClientFilter misconfiguredClientFilter; + @Inject ManagedExecutor managedExecutor; @@ -47,6 +52,17 @@ public String userNameNonDefaultOidcClient() { return protectedResourceServiceNonDefaultOidcClient.getUserName(); } + @GET + @Path("userNameMisconfiguredClientFilter") + @Produces("text/plain") + public String userNameMisconfiguredClientFilter() { + try { + return misconfiguredClientFilter.getUserName(); + } catch (Throwable t) { + return t.getMessage(); + } + } + @GET @Path("userOidcClientManagedExecutor") public String userNameOidcClientManagedExecutor() throws Exception { diff --git a/integration-tests/oidc-client/src/main/java/io/quarkus/it/keycloak/MisconfiguredClientFilter.java b/integration-tests/oidc-client/src/main/java/io/quarkus/it/keycloak/MisconfiguredClientFilter.java new file mode 100644 index 0000000000000..718644f3fc5fe --- /dev/null +++ b/integration-tests/oidc-client/src/main/java/io/quarkus/it/keycloak/MisconfiguredClientFilter.java @@ -0,0 +1,17 @@ +package io.quarkus.it.keycloak; + +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; + +import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; + +import io.quarkus.oidc.client.filter.OidcClientFilter; + +@RegisterRestClient +@OidcClientFilter("misconfigured-client") +@Path("/") +public interface MisconfiguredClientFilter { + + @GET + String getUserName(); +} diff --git a/integration-tests/oidc-client/src/main/resources/application.properties b/integration-tests/oidc-client/src/main/resources/application.properties index d020d5631dc32..e3a0bded82296 100644 --- a/integration-tests/oidc-client/src/main/resources/application.properties +++ b/integration-tests/oidc-client/src/main/resources/application.properties @@ -16,6 +16,14 @@ quarkus.oidc-client.named.grant.type=password quarkus.oidc-client.named.grant-options.password.username=alice quarkus.oidc-client.named.grant-options.password.password=alice +quarkus.oidc-client.misconfigured-client.auth-server-url=${quarkus.oidc.auth-server-url} +quarkus.oidc-client.misconfigured-client.client-id=${quarkus.oidc.client-id} +quarkus.oidc-client.misconfigured-client.credentials.secret=${quarkus.oidc.credentials.secret} +quarkus.oidc-client.misconfigured-client.grant.type=password +quarkus.oidc-client.misconfigured-client.grant-options.password.username=jdoe +quarkus.oidc-client.misconfigured-client.grant-options.password.password=bob +quarkus.oidc-client.misconfigured-client.early-tokens-acquisition=false + quarkus.oidc-client.non-default-client.auth-server-url=${quarkus.oidc.auth-server-url} quarkus.oidc-client.non-default-client.client-id=${quarkus.oidc.client-id} quarkus.oidc-client.non-default-client.credentials.secret=${quarkus.oidc.credentials.secret} @@ -28,6 +36,7 @@ io.quarkus.it.keycloak.ProtectedResourceServiceOidcClient/mp-rest/url=http://loc io.quarkus.it.keycloak.ProtectedResourceServiceNamedOidcClient/mp-rest/url=http://localhost:8081/protected io.quarkus.it.keycloak.ProtectedResourceServiceNoOidcClient/mp-rest/url=http://localhost:8081/protected io.quarkus.it.keycloak.ProtectedResourceServiceNonDefaultOidcClient/mp-rest/url=http://localhost:8081/protected +io.quarkus.it.keycloak.MisconfiguredClientFilter/mp-rest/url=http://localhost:8081/protected quarkus.tls.trust-all=true quarkus.log.category."io.quarkus.oidc.client.runtime.OidcClientImpl".min-level=TRACE diff --git a/integration-tests/oidc-client/src/test/java/io/quarkus/it/keycloak/OidcClientTest.java b/integration-tests/oidc-client/src/test/java/io/quarkus/it/keycloak/OidcClientTest.java index 94c1747f1fc1f..c6d8aca5b9bf9 100644 --- a/integration-tests/oidc-client/src/test/java/io/quarkus/it/keycloak/OidcClientTest.java +++ b/integration-tests/oidc-client/src/test/java/io/quarkus/it/keycloak/OidcClientTest.java @@ -2,6 +2,7 @@ import static org.awaitility.Awaitility.await; import static org.awaitility.Awaitility.given; +import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.equalTo; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -36,6 +37,15 @@ public void testGetUserNameOidcClient() { .body(equalTo("alice")); } + @Test + public void testGetUserNameMisconfiguredClientFilter() { + RestAssured.given().header("Accept", "text/plain") + .when().get("/frontend/userNameMisconfiguredClientFilter") + .then() + .statusCode(200) + .body(containsString("invalid_grant")); + } + @Test public void testGetUserNameNonDefaultOidcClient() { RestAssured.when().get("/frontend/userNonDefaultOidcClient")