From 6e6358a58362f7ddd377f5b64ca803100aa881aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9rald=20Quintana?= Date: Thu, 13 May 2021 21:22:46 +0200 Subject: [PATCH] feat(auth): log login failures --- .../BasicAuthAuthenticationProvider.java | 22 +++++++------- .../akhq/utils/LoginFailedEventListener.java | 30 +++++++++++++++++++ 2 files changed, 42 insertions(+), 10 deletions(-) create mode 100644 src/main/java/org/akhq/utils/LoginFailedEventListener.java diff --git a/src/main/java/org/akhq/modules/BasicAuthAuthenticationProvider.java b/src/main/java/org/akhq/modules/BasicAuthAuthenticationProvider.java index f030123fc..a3de6e6e1 100644 --- a/src/main/java/org/akhq/modules/BasicAuthAuthenticationProvider.java +++ b/src/main/java/org/akhq/modules/BasicAuthAuthenticationProvider.java @@ -28,18 +28,20 @@ public class BasicAuthAuthenticationProvider implements AuthenticationProvider { @Override public Publisher authenticate(@Nullable HttpRequest httpRequest, AuthenticationRequest authenticationRequest) { - for(BasicAuth auth : securityProperties.getBasicAuth()) { - if (authenticationRequest.getIdentity().equals(auth.getUsername()) && - auth.isValidPassword((String) authenticationRequest.getSecret())) { - - UserDetails userDetails = new UserDetails(auth.getUsername(), - userGroupUtils.getUserRoles(auth.getGroups()), - userGroupUtils.getUserAttributes(auth.getGroups())); - - return Flowable.just(userDetails); + 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)); } + UserDetails userDetails = new UserDetails(username, + userGroupUtils.getUserRoles(auth.getGroups()), + userGroupUtils.getUserAttributes(auth.getGroups())); + return Flowable.just(userDetails); } - return Flowable.just(new AuthenticationFailed()); + return Flowable.just(new AuthenticationFailed(AuthenticationFailureReason.USER_NOT_FOUND)); } } diff --git a/src/main/java/org/akhq/utils/LoginFailedEventListener.java b/src/main/java/org/akhq/utils/LoginFailedEventListener.java new file mode 100644 index 000000000..0ec4ef051 --- /dev/null +++ b/src/main/java/org/akhq/utils/LoginFailedEventListener.java @@ -0,0 +1,30 @@ +package org.akhq.utils; + +import io.micronaut.context.event.ApplicationEventListener; +import io.micronaut.security.authentication.AuthenticationFailed; +import io.micronaut.security.authentication.UserDetails; +import io.micronaut.security.event.LoginFailedEvent; +import lombok.extern.slf4j.Slf4j; + +import javax.inject.Singleton; + +@Singleton +@Slf4j +public class LoginFailedEventListener implements ApplicationEventListener { + @Override + public void onApplicationEvent(LoginFailedEvent event) { + if (event.getSource() instanceof AuthenticationFailed) { + AuthenticationFailed authenticationFailed = (AuthenticationFailed) event.getSource(); + log.warn("Login failed reason {}, username {}, message {}", + authenticationFailed.getReason(), + authenticationFailed.getUserDetails().map(UserDetails::getUsername).orElse("unknown"), + authenticationFailed.getMessage().orElse("none") + ); + } + } + + @Override + public boolean supports(LoginFailedEvent event) { + return true; + } +}