Ninoslol Ninoslol
Ninoslol Ninoslol

Reputation: 1

Redirection after a successful login in vaadin application

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.

Upvotes: 0

Views: 147

Answers (1)

Kumin
Kumin

Reputation: 140

Try using defaultSuccessUrl instead of successForwardUrl in your SecurityConfiguration class.

Upvotes: 0

Related Questions