skip to Main Content

This is my : login.tsx

import { ViewConfig } from '@vaadin/hilla-file-router/types.js';
import { useSignal } from '@vaadin/hilla-react-signals';
import { LoginI18n, LoginOverlay, LoginOverlayElement } from '@vaadin/react-components/LoginOverlay.js';
import { useAuth } from 'Frontend/util/auth.js';

export const config: ViewConfig = {
  menu: { exclude: true },
};

const loginI18n: LoginI18n = {
  ...new LoginOverlayElement().i18n,
  header: { title: 'RiconTrans Login', description: '' },
};

export default function LoginView() {
  const { login } = useAuth();
  const loginError = useSignal(false);

  return (
    <LoginOverlay
      opened
      error={loginError.value}
      noForgotPassword
      i18n={loginI18n}
      onLogin={async ({ detail: { username, password } }) => {
        const { defaultUrl, error, redirectUrl } = await login(username, password);

        if (error) {
          loginError.value = true;
        } else {
          const url = redirectUrl ?? defaultUrl ?? '/Main';  // Ensure the path starts with '/'
          const path = new URL(url, document.baseURI).pathname;
          document.location.href = path;  
        }
      }}
    />
  );
}

);
}

serving as the view of logging in, and here is my security package:

AuthenticatedUser:

package com.ricontrans.application.security;

import com.ricontrans.application.data.User;
import com.ricontrans.application.data.UserRepository;
import com.ricontrans.application.services.UserService;
import com.vaadin.flow.spring.security.AuthenticationContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.Optional;

@Component
public class AuthenticatedUser {

    private static final Logger logger = LoggerFactory.getLogger(AuthenticatedUser.class);

    private final UserService userService;
    private final AuthenticationContext authenticationContext;
    public AuthenticatedUser(AuthenticationContext authenticationContext, UserService userService) {
        this.userService = userService;
        this.authenticationContext = authenticationContext;
    }

    @Transactional
    public Optional<Object> get() {
        logger.info("Attempting to get authenticated user.");
        Optional<Object> user = authenticationContext.getAuthenticatedUser(UserDetails.class)
                .map(userDetails -> {
                    logger.info("Authenticated user found: {}", userDetails.getUsername());
                    
                    // Call your custom findByUsername method from UserService
                    Optional<User> foundUser = UserService.findByUsername(userDetails.getUsername());

                    if (foundUser.isPresent()) {
                        return (Object) foundUser.get(); // Cast User to Object
                    } else {
                        return Optional.empty();
                    }
                });


        user.ifPresentOrElse(
                u -> logger.info("User retrieved from repository: {}", u),
                () -> logger.warn("No user found in repository.")
        );

        return user;
    }

    public Optional<UserDetails> getCurrentUserDetails() {
        logger.info("Attempting to get current user details from security context.");
        org.springframework.security.core.Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication != null && authentication.getPrincipal() instanceof UserDetails) {
            UserDetails userDetails = (UserDetails) authentication.getPrincipal();
            logger.info("Current user details found: {}", userDetails.getUsername());
            return Optional.of(userDetails);
        }
        logger.info("No user details found in security context.");
        return Optional.empty();
    }

    public void logout() {
        logger.info("Logging out user.");
        authenticationContext.logout();
    }
}

SecurityConfiguration:

package com.ricontrans.application.security;

import com.vaadin.flow.spring.security.VaadinWebSecurity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
@EnableWebSecurity
@Configuration
public class SecurityConfiguration extends VaadinWebSecurity {

    private static final Logger logger = LoggerFactory.getLogger(SecurityConfiguration.class);
    private static final String LOGIN_FAILURE_URL = "/login?error";
    private static final String SUCCESS_URL = "/Main";
    private static final String LOGIN_URL = "/login";
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        logger.debug("Configuring HTTP security.");

        http.authorizeHttpRequests(authorize -> {
            logger.debug("Permitting all requests to /images/*.png");
            authorize.requestMatchers(new AntPathRequestMatcher("/images/*.png")).permitAll();
        });

        // Icons from the line-awesome addon
        http.authorizeHttpRequests(authorize -> {
            logger.debug("Permitting all requests to /line-awesome/**/*.svg");
            authorize.requestMatchers(new AntPathRequestMatcher("/line-awesome/**/*.svg")).permitAll();
        });

        // Set custom success and failure handlers
        http.formLogin()
            .loginPage(LOGIN_URL)
            .successForwardUrl(SUCCESS_URL)
            .failureUrl(LOGIN_FAILURE_URL)
            .permitAll();

        super.configure(http);
        logger.debug("Setting login view to /login");
        setLoginView(http, LOGIN_URL);
    }
}


    // Set custom success and failure handlers
    http.formLogin()
        .loginPage(LOGIN_URL)
        .successForwardUrl(SUCCESS_URL)
        .failureUrl(LOGIN_FAILURE_URL)
        .permitAll();

    super.configure(http);
    logger.debug("Setting login view to /login");
    setLoginView(http, LOGIN_URL);
}

UserDetailsServiceImpl

package com.ricontrans.application.security;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.ricontrans.application.data.User;
import com.ricontrans.application.data.UserRepository;
import com.ricontrans.application.services.UserService;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import com.ricontrans.application.data.Role;

@Service
public class UserDetailsServiceImpl implements UserDetailsService {

    private static final Logger logger = LoggerFactory.getLogger(UserDetailsServiceImpl.class);
    private final UserRepository userRepository;
    private final PasswordEncoder passwordEncoder;

    @Autowired
    public UserDetailsServiceImpl(UserRepository userRepository, PasswordEncoder passwordEncoder) {
        this.userRepository = userRepository;
        this.passwordEncoder = passwordEncoder;
    }

    @Override
    @Transactional
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
          logger.info("Attempting to load user by username: {}", username);
          try {
              User user = UserService.findByUsername(username)
                      .orElseThrow(() -> new UsernameNotFoundException("No user present with username: " + username));

              logger.info("User found: {}", username);
              Set<Role> roles = UserService.findRolesByUserId(user.getId());
              List<GrantedAuthority> authorities = roles.stream()
                      .map(role -> new SimpleGrantedAuthority("ROLE_" + role.getRoleName()))
                      .collect(Collectors.toList());

              logger.info("Assigning roles to user: {}", authorities);
              logger.info("user.getUsername(): {}", user.getUsername());
              logger.info("user.getHashedPassword()", user.getHashedPassword());
              return new org.springframework.security.core.userdetails.User(user.getUsername(),
                      user.getHashedPassword(), authorities);
          } catch (Exception e) {
              logger.error("Error loading user by username: {}. Exception: {}", username, e.getMessage(), e);
              throw e;
          }
      }

    private static List<GrantedAuthority> getAuthorities(User user) {
        return user.getRoles().stream()
                .map(role -> new SimpleGrantedAuthority("ROLE_" + role))
                .collect(Collectors.toList());
    }
}

I also have a user service file for my database queyring .From the logging of my user named "qq"

2024-07-08 14:11:52 INFO  c.r.a.security.AuthenticatedUser - Authenticated user found: qq
2024-07-08 14:11:52 INFO  c.r.application.services.UserService - Attempting to find user by username: qq
2024-07-08 14:11:52 INFO  c.r.application.services.UserService - User found by username 'qq': com.ricontrans.application.data.User@11
2024-07-08 14:11:52 INFO  c.r.a.security.AuthenticatedUser - User retrieved from repository: com.ricontrans.application.data.User@11
2024-07-08 14:11:52 INFO  c.r.a.security.AuthenticatedUser - Attempting to get authenticated user.
2024-07-08 14:11:52 INFO  c.r.a.security.AuthenticatedUser - Authenticated user found: qq
2024-07-08 14:11:52 INFO  c.r.application.services.UserService - Attempting to find user by username: qq
2024-07-08 14:11:52 INFO  c.r.application.services.UserService - User found by username 'qq': com.ricontrans.application.data.User@11
2024-07-08 14:11:52 INFO  c.r.a.security.AuthenticatedUser - User retrieved from repository: com.ricontrans.application.data.User@11

everything seems correct but the problem is :
That the redirection to /Main never happens, it just redirects to the root route, where all the user is authenticated because he can visit all the views needing permission. Also everything i tried to show a notification after a successful login never happens.

2

Answers


  1. Chosen as BEST ANSWER

    Unfortunately,nothing changed!


  2. Try using defaultSuccessUrl instead of successForwardUrl in your SecurityConfiguration class.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search