diff --git a/src/main/java/org/akhq/modules/BasicAuthAuthenticationProvider.java b/src/main/java/org/akhq/modules/BasicAuthAuthenticationProvider.java index aa6508614..af977b1c2 100644 --- a/src/main/java/org/akhq/modules/BasicAuthAuthenticationProvider.java +++ b/src/main/java/org/akhq/modules/BasicAuthAuthenticationProvider.java @@ -11,6 +11,7 @@ import javax.inject.Inject; import javax.inject.Singleton; +import java.util.Optional; @Singleton public class BasicAuthAuthenticationProvider implements AuthenticationProvider { @@ -22,29 +23,35 @@ public class BasicAuthAuthenticationProvider implements AuthenticationProvider { @Override public Publisher authenticate(@Nullable HttpRequest httpRequest, AuthenticationRequest authenticationRequest) { String username = String.valueOf(authenticationRequest.getIdentity()); - for (BasicAuth auth : securityProperties.getBasicAuth()) { - if (!username.equals(auth.getUsername())) { - continue; - } - if (!auth.isValidPassword((String) authenticationRequest.getSecret())) { - return Flowable.just(new AuthenticationFailed(AuthenticationFailureReason.CREDENTIALS_DO_NOT_MATCH)); - } - ClaimProvider.AKHQClaimRequest request = - ClaimProvider.AKHQClaimRequest.builder() - .providerType(ClaimProvider.ProviderType.BASIC_AUTH) - .providerName(null) - .username(auth.getUsername()) - .groups(auth.getGroups()) - .build(); + Optional optionalBasicAuth = securityProperties.getBasicAuth() + .stream() + .filter(basicAuth -> basicAuth.getUsername().equals(username)) + .findFirst(); - ClaimProvider.AKHQClaimResponse claim = claimProvider.generateClaim(request); - UserDetails userDetails = new UserDetails( - auth.getUsername(), - claim.getRoles(), - claim.getAttributes()); - return Flowable.just(userDetails); + // User not found + if(optionalBasicAuth.isEmpty()){ + return Flowable.just(new AuthenticationFailed(AuthenticationFailureReason.USER_NOT_FOUND)); + } + BasicAuth auth = optionalBasicAuth.get(); + + // Invalid password + if (!auth.isValidPassword((String) authenticationRequest.getSecret())) { + return Flowable.just(new AuthenticationFailed(AuthenticationFailureReason.CREDENTIALS_DO_NOT_MATCH)); } - return Flowable.just(new AuthenticationFailed(AuthenticationFailureReason.USER_NOT_FOUND)); + ClaimProvider.AKHQClaimRequest request = + ClaimProvider.AKHQClaimRequest.builder() + .providerType(ClaimProvider.ProviderType.BASIC_AUTH) + .providerName(null) + .username(auth.getUsername()) + .groups(auth.getGroups()) + .build(); + try { + ClaimProvider.AKHQClaimResponse claim = claimProvider.generateClaim(request); + return Flowable.just(new UserDetails(auth.getUsername(), claim.getRoles(), claim.getAttributes())); + } catch (Exception e) { + String claimProviderClass = claimProvider.getClass().getName(); + return Flowable.just(new AuthenticationFailed("Exception from ClaimProvider " + claimProviderClass + ": " + e.getMessage())); + } } } diff --git a/src/test/java/org/akhq/modules/BasicAuthAuthenticationProviderTest.java b/src/test/java/org/akhq/modules/BasicAuthAuthenticationProviderTest.java index 5fcf6e9d8..32433e322 100644 --- a/src/test/java/org/akhq/modules/BasicAuthAuthenticationProviderTest.java +++ b/src/test/java/org/akhq/modules/BasicAuthAuthenticationProviderTest.java @@ -1,8 +1,6 @@ package org.akhq.modules; -import io.micronaut.security.authentication.AuthenticationResponse; -import io.micronaut.security.authentication.UserDetails; -import io.micronaut.security.authentication.UsernamePasswordCredentials; +import io.micronaut.security.authentication.*; import io.reactivex.Flowable; import org.akhq.AbstractTest; import org.junit.jupiter.api.Test; @@ -44,7 +42,7 @@ public void success() { } @Test - public void failed() { + public void failed_UserNotFound() { AuthenticationResponse response = Flowable .fromPublisher(auth.authenticate(null, new UsernamePasswordCredentials( "user2", @@ -52,5 +50,19 @@ public void failed() { ))).blockingFirst(); assertFalse(response.isAuthenticated()); + AuthenticationFailed authenticationFailed = (AuthenticationFailed) response; + assertEquals(AuthenticationFailureReason.USER_NOT_FOUND, authenticationFailed.getReason()); + } + @Test + public void failed_PasswordInvalid() { + AuthenticationResponse response = Flowable + .fromPublisher(auth.authenticate(null, new UsernamePasswordCredentials( + "user", + "invalid-pass" + ))).blockingFirst(); + + assertFalse(response.isAuthenticated()); + AuthenticationFailed authenticationFailed = (AuthenticationFailed) response; + assertEquals(AuthenticationFailureReason.CREDENTIALS_DO_NOT_MATCH, authenticationFailed.getReason()); } }