From 2f2f0d68e1183e07ddfa242d99a0c3631ec8b9eb Mon Sep 17 00:00:00 2001 From: Stanislav Trailov Date: Wed, 17 Sep 2025 16:11:00 +0300 Subject: [PATCH] Fix Simple UI Login (#2674) Signed-off-by: strailov --- .../hawkbit/ui/simple/SimpleUIApp.java | 29 ++++++++++++++++++- .../security/SecurityConfiguration.java | 16 ++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/hawkbit-simple-ui/src/main/java/org/eclipse/hawkbit/ui/simple/SimpleUIApp.java b/hawkbit-simple-ui/src/main/java/org/eclipse/hawkbit/ui/simple/SimpleUIApp.java index 7bc3dd56a..afae3943a 100644 --- a/hawkbit-simple-ui/src/main/java/org/eclipse/hawkbit/ui/simple/SimpleUIApp.java +++ b/hawkbit-simple-ui/src/main/java/org/eclipse/hawkbit/ui/simple/SimpleUIApp.java @@ -17,6 +17,7 @@ import feign.RequestInterceptor; import feign.codec.Decoder; import feign.codec.Encoder; import feign.codec.ErrorDecoder; +import lombok.extern.slf4j.Slf4j; import org.eclipse.hawkbit.sdk.HawkbitClient; import org.eclipse.hawkbit.sdk.HawkbitServer; import org.eclipse.hawkbit.sdk.Tenant; @@ -29,6 +30,7 @@ import org.springframework.cloud.openfeign.FeignClientsConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Import; import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.authority.SimpleGrantedAuthority; @@ -41,6 +43,8 @@ import org.springframework.security.oauth2.client.userinfo.OAuth2UserService; import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser; import org.springframework.security.oauth2.core.oidc.user.OidcUser; +import java.net.HttpURLConnection; +import java.net.URL; import java.util.Base64; import java.util.LinkedList; import java.util.List; @@ -50,6 +54,7 @@ import java.util.function.Function; import static feign.Util.ISO_8859_1; import static java.util.Collections.emptyList; +@Slf4j @Theme("hawkbit") @PWA(name = "hawkBit UI", shortName = "hawkBit UI") @SpringBootApplication @@ -126,11 +131,16 @@ public class SimpleUIApp implements AppShellConfigurator { // accepts all user / pass, just delegating them to the feign client @Bean - AuthenticationManager authenticationManager(final HawkbitMgmtClient hawkbitClient) { + AuthenticationManager authenticationManager(final HawkbitMgmtClient hawkbitClient, final HawkbitServer server) { return authentication -> { final String username = authentication.getName(); final String password = authentication.getCredentials().toString(); + // make simple check in order not to be logged in as not real user. + if (!isAuthenticated(username, password, server.getMgmtUrl())) { + throw new BadCredentialsException("Incorrect username or password!"); + } + final List grantedAuthorities = getGrantedAuthorities( hawkbitClient, new UsernamePasswordAuthenticationToken(username, password)); return new UsernamePasswordAuthenticationToken(username, password, grantedAuthorities) { @@ -172,4 +182,21 @@ public class SimpleUIApp implements AppShellConfigurator { } return roles.stream().map(role -> new SimpleGrantedAuthority("ROLE_" + role)).toList(); } + + public static boolean isAuthenticated(String username, String password, String mgmtUrl) { + try { + final URL url = new URL(mgmtUrl + "/rest/v1/rollouts"); + final HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setRequestMethod("GET"); + + final String auth = username + ":" + password; + final String encodedAuth = Base64.getEncoder().encodeToString(auth.getBytes()); + conn.setRequestProperty("Authorization", "Basic " + encodedAuth); + + return conn.getResponseCode() != 401; + } catch (final Exception ex) { + log.error("Failed to authenticate user {} .Reason : ", username, ex); + return false; + } + } } diff --git a/hawkbit-simple-ui/src/main/java/org/eclipse/hawkbit/ui/simple/security/SecurityConfiguration.java b/hawkbit-simple-ui/src/main/java/org/eclipse/hawkbit/ui/simple/security/SecurityConfiguration.java index 94413e6ba..2621a8bdc 100644 --- a/hawkbit-simple-ui/src/main/java/org/eclipse/hawkbit/ui/simple/security/SecurityConfiguration.java +++ b/hawkbit-simple-ui/src/main/java/org/eclipse/hawkbit/ui/simple/security/SecurityConfiguration.java @@ -22,6 +22,10 @@ import org.springframework.security.config.annotation.web.configuration.EnableWe import org.springframework.security.config.annotation.web.configurers.oauth2.client.OAuth2LoginConfigurer; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.web.authentication.AuthenticationFailureHandler; + +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; @EnableWebSecurity @Configuration @@ -41,6 +45,14 @@ public class SecurityConfiguration extends VaadinWebSecurity { return new BCryptPasswordEncoder(); } + @Bean + public AuthenticationFailureHandler customFailureHandler() { + return (request, response, exception) -> { + // Redirect back to login with your message + response.sendRedirect("/login?error=" + URLEncoder.encode(exception.getMessage(), StandardCharsets.UTF_8)); + }; + } + @Override protected void configure(final HttpSecurity http) throws Exception { http.authorizeHttpRequests(authorize -> authorize.requestMatchers("/images/*.png").permitAll()); @@ -50,6 +62,10 @@ public class SecurityConfiguration extends VaadinWebSecurity { if (oAuth2LoginConfigurerCustomizer != null) { http.oauth2Login(oAuth2LoginConfigurerCustomizer); } else { + http.formLogin(form -> form + .loginPage("/login") + .failureHandler(customFailureHandler()) + ); setLoginView(http, LoginView.class); } }