Spring-security: @AuthenticationPrincipal return empty User

Created on 10 Dec 2016  路  1Comment  路  Source: spring-projects/spring-security

Summary

I have a Spring MVC controller where I save the post information associated with the currently authenticated user. This current user is obtained by using the @AuthenticationPrincipal annotation in the method next to the User class that implements the UserDetails interface. The problem is that this user has all the empty fields, however if I get the user through SecurityContextHolder this does not happen.

Actual Behavior

When the controller is executed the user obtained by @AuthenticationPrincipal is empty and the one obtained by SecurityContextHoldercontains all the information:

2016-12-10 19:37:52 INFO  PostController:62 - Informaci贸n del usuario mediate @CurrentUser: User{id=null, username=null, passwordClear=null, confirmPassword=null, password=null, email=null, enabled=true, fullName=null, posts=[]}
2016-12-10 19:37:52 INFO  PostController:63 - Informaci贸n del usuario mediate SecurityContextHolder: User{id=1, username=sergio11, passwordClear=null, confirmPassword=null, password=$2a$10$LJvYTNacIvqZWDQWjF7xaeheK1MrF.FkXxovb2QgcF2CMudA1mM/., [email protected], enabled=true, fullName=Sergio S脙隆nchez S脙隆nchez, posts=[]}

Expected Behavior

As I understand using @EnableWebSecurity already enable in the context the resolver argument for the @AuthenticationPrincipal.

So I could use this to get the current user managed:
@AuthenticationPrincipal(expression = "@jpaEntityManager.merge(#this)")

And to be able to persist the Post associated with the current user

Configuration

package config.security;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.DefaultAuthenticationEventPublisher;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import services.security.CustomUserDetailsService;
/**
 *
 * @author sergio
 */
@Configuration
@EnableWebSecurity
@ComponentScan(basePackageClasses = CustomUserDetailsService.class)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsService userDetailsService;
    @Autowired
    private DefaultAuthenticationEventPublisher defaultAuthenticationEventPublisher;

    @Bean
    public PasswordEncoder passwordEncoder() {
        PasswordEncoder encoder = new BCryptPasswordEncoder();
        return encoder;
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
         auth
            .authenticationEventPublisher(defaultAuthenticationEventPublisher)
            .userDetailsService(userDetailsService)
            .passwordEncoder(passwordEncoder());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/admin/signup").anonymous()
                .antMatchers("/admin/**").authenticated()
                .anyRequest().permitAll()
                .and()
                .formLogin().loginPage("/admin/login").permitAll()
                .usernameParameter("username").passwordParameter("password")
                .and()
                .logout()
                    .logoutRequestMatcher(new AntPathRequestMatcher("/admin/logout"))
                    .logoutSuccessUrl("/admin/login?logout")
                .and()
                .exceptionHandling().accessDeniedPage("/403")
                .and()
                .csrf();
    }

    @Bean
    public DefaultAuthenticationEventPublisher authenticationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        return new DefaultAuthenticationEventPublisher(applicationEventPublisher);
    }
}
package config;

import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;

/**
 *
 * @author sergio
 */
public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer {

}

Version

Spring Security 4.2.0.RELEASE

Sample

Github Repository

Stack Overflow

invalid

>All comments

Summary

This issue is because DelegatingFlashMessagesConfiguration eagerly initializes the handlerExceptionResolver which prevents the AuthenticationPrincipalArgumentResolver from being registered until after Spring MVC has constructed the DispatcherServlets custom argument resolvers.

# Details

DelegatingWebMvcConfiguration the container finds all the WebMvcConfigurer. Then DelegatingFlashMessagesConfiguration is created but it requires the handlerExceptionResolver which adds all the argument resolvers before WebMvcSecurityConfiguration is added as a WebMvcConfigurer.

If you comment out the @EnableFlashMessages it resolves this problem.

Was this page helpful?
0 / 5 - 0 ratings