diff --git a/extensions/security-jpa-reactive/deployment/src/test/java/io/quarkus/security/jpa/reactive/PanacheEntitiesConfigurationTest.java b/extensions/security-jpa-reactive/deployment/src/test/java/io/quarkus/security/jpa/reactive/PanacheEntitiesConfigurationTest.java index e393f804d4bd3..d06c6c138dc2b 100644 --- a/extensions/security-jpa-reactive/deployment/src/test/java/io/quarkus/security/jpa/reactive/PanacheEntitiesConfigurationTest.java +++ b/extensions/security-jpa-reactive/deployment/src/test/java/io/quarkus/security/jpa/reactive/PanacheEntitiesConfigurationTest.java @@ -1,10 +1,22 @@ package io.quarkus.security.jpa.reactive; import static org.hamcrest.Matchers.is; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import jakarta.enterprise.event.Observes; +import jakarta.inject.Inject; +import jakarta.inject.Singleton; +import jakarta.persistence.NonUniqueResultException; + +import org.awaitility.Awaitility; +import org.hamcrest.Matchers; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; +import io.quarkus.security.AuthenticationFailedException; +import io.quarkus.security.spi.runtime.AuthenticationFailureEvent; import io.quarkus.test.QuarkusUnitTest; import io.restassured.RestAssured; import io.restassured.response.ValidatableResponse; @@ -20,9 +32,13 @@ public class PanacheEntitiesConfigurationTest extends JpaSecurityRealmTest { .addClass(PanacheUserEntity.class) .addClass(PanacheRoleEntity.class) .addClass(UserResource.class) + .addClass(AuthenticationFailureObserver.class) .addAsResource("multiple-entities/import.sql", "import.sql") .addAsResource("multiple-entities/application.properties", "application.properties")); + @Inject + AuthenticationFailureObserver authenticationFailureObserver; + @Test void duplicateUsernameTest() { // duplicate username must lead to 401 @@ -34,8 +50,17 @@ void duplicateUsernameTest() { // one user getUsername().statusCode(200).body(is(DUPLICATE_USERNAME)); createUser(); + // two users -> NonUniqueResultException -> 401 - getUsername().statusCode(401); + authenticationFailureObserver.recordEvents(true); + getUsername().statusCode(401).body(Matchers.emptyOrNullString()); + Awaitility.await().untilAsserted(() -> assertNotNull(authenticationFailureObserver.getEvent())); + var authFailureEvent = authenticationFailureObserver.getEvent(); + assertInstanceOf(AuthenticationFailedException.class, authFailureEvent.getAuthenticationFailure()); + var cause = authFailureEvent.getAuthenticationFailure().getCause(); + assertInstanceOf(NonUniqueResultException.class, cause); + assertTrue(cause.getMessage().contains("Query did not return a unique result")); + authenticationFailureObserver.recordEvents(false); } private static void createUser() { @@ -57,4 +82,27 @@ private static ValidatableResponse getUsername() { .then(); } + @Singleton + public static class AuthenticationFailureObserver { + + private volatile boolean record = false; + private volatile AuthenticationFailureEvent event; + + void observerAuthFailure(@Observes AuthenticationFailureEvent event) { + if (record) { + this.event = event; + } + } + + void recordEvents(boolean record) { + this.record = record; + if (!record) { + this.event = null; + } + } + + AuthenticationFailureEvent getEvent() { + return event; + } + } } diff --git a/extensions/security-jpa-reactive/runtime/src/main/java/io/quarkus/security/jpa/reactive/runtime/JpaReactiveIdentityProvider.java b/extensions/security-jpa-reactive/runtime/src/main/java/io/quarkus/security/jpa/reactive/runtime/JpaReactiveIdentityProvider.java index 96da9cb2970a7..8e8d4c67f85ab 100644 --- a/extensions/security-jpa-reactive/runtime/src/main/java/io/quarkus/security/jpa/reactive/runtime/JpaReactiveIdentityProvider.java +++ b/extensions/security-jpa-reactive/runtime/src/main/java/io/quarkus/security/jpa/reactive/runtime/JpaReactiveIdentityProvider.java @@ -48,7 +48,7 @@ public boolean test(Throwable throwable) { @Override public Throwable apply(Throwable throwable) { LOG.debug("Authentication failed", throwable); - return new AuthenticationFailedException(); + return new AuthenticationFailedException(throwable); } }); } diff --git a/extensions/security-jpa-reactive/runtime/src/main/java/io/quarkus/security/jpa/reactive/runtime/JpaReactiveTrustedIdentityProvider.java b/extensions/security-jpa-reactive/runtime/src/main/java/io/quarkus/security/jpa/reactive/runtime/JpaReactiveTrustedIdentityProvider.java index 54bfef704f49b..e326222e67da7 100644 --- a/extensions/security-jpa-reactive/runtime/src/main/java/io/quarkus/security/jpa/reactive/runtime/JpaReactiveTrustedIdentityProvider.java +++ b/extensions/security-jpa-reactive/runtime/src/main/java/io/quarkus/security/jpa/reactive/runtime/JpaReactiveTrustedIdentityProvider.java @@ -48,7 +48,7 @@ public boolean test(Throwable throwable) { @Override public Throwable apply(Throwable throwable) { LOG.debug("Authentication failed", throwable); - return new AuthenticationFailedException(); + return new AuthenticationFailedException(throwable); } }); } diff --git a/extensions/security-jpa/runtime/src/main/java/io/quarkus/security/jpa/runtime/JpaIdentityProvider.java b/extensions/security-jpa/runtime/src/main/java/io/quarkus/security/jpa/runtime/JpaIdentityProvider.java index 15583f19b7bdb..fe0c6e88a3250 100644 --- a/extensions/security-jpa/runtime/src/main/java/io/quarkus/security/jpa/runtime/JpaIdentityProvider.java +++ b/extensions/security-jpa/runtime/src/main/java/io/quarkus/security/jpa/runtime/JpaIdentityProvider.java @@ -60,7 +60,7 @@ private SecurityIdentity authenticate(UsernamePasswordAuthenticationRequest requ return authenticate(session, request); } catch (SecurityException e) { log.debug("Authentication failed", e); - throw new AuthenticationFailedException(); + throw new AuthenticationFailedException(e); } } diff --git a/extensions/security-jpa/runtime/src/main/java/io/quarkus/security/jpa/runtime/JpaTrustedIdentityProvider.java b/extensions/security-jpa/runtime/src/main/java/io/quarkus/security/jpa/runtime/JpaTrustedIdentityProvider.java index 00de38dda2989..28fae7b27a5dc 100644 --- a/extensions/security-jpa/runtime/src/main/java/io/quarkus/security/jpa/runtime/JpaTrustedIdentityProvider.java +++ b/extensions/security-jpa/runtime/src/main/java/io/quarkus/security/jpa/runtime/JpaTrustedIdentityProvider.java @@ -60,7 +60,7 @@ private SecurityIdentity authenticate(TrustedAuthenticationRequest request) { return authenticate(session, request); } catch (SecurityException e) { log.debug("Authentication failed", e); - throw new AuthenticationFailedException(); + throw new AuthenticationFailedException(e); } }