Question

I am developing an API using Spring 3. I want all my users to be logged in when performing a request and so I tried to implement Basic HTTP Auth. I don't want to use XML (most of the doc uses XML).

The server currently replies 401 to every requests and my web-browser does not ask me for authentication. Where am I going wrong?

I searched many websites and here's what I've got so far:

Application class:

@Configuration
@EnableJpaRepositories
@EnableAutoConfiguration
@ComponentScan
public class Application
{
@Bean
    public BasicAuthenticationFilter basicAuthenticationFilter(BasicAuthenticationEntryPoint basicAuthenticationEntryPoint,
                                                                AuthenticationManager authenticationManager)
    {
        BasicAuthenticationFilter basicAuthenticationFilter = new BasicAuthenticationFilter(authenticationManager, basicAuthenticationEntryPoint);
        return basicAuthenticationFilter;
    }

    @Bean
    public UserDetailsService userDetailsService()
    {
        return new PersonService();
    }

    @Bean
    public AuthenticationManager authenticationManager()
    {
        return new AuthenticationManagerImpl();
    }

    @Bean
    public AuthenticationProvider authenticationProvider()
    {
        return new CustomAuthenticationProvider();
    }

    @Bean
    public BasicAuthenticationEntryPoint basicAuthenticationEntryPoint()
    {
        BasicAuthenticationEntryPoint basicAuthenticationEntryPoint = new BasicAuthenticationEntryPoint();
        basicAuthenticationEntryPoint.setRealmName("Doccto");
        return basicAuthenticationEntryPoint;
    }
}

My custom AuthenticationManager

@Component
public class AuthenticationManagerImpl implements AuthenticationManager
{
    @Autowired
    protected AuthenticationProvider authenticationProvider;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException
    {
        return this.authenticationProvider.authenticate(authentication);
    }
}

PersonService.class :

@Service
public class PersonService implements UserDetailsService
{
    @Autowired
    protected PersonRepository personRepository;

    @Override
    public Person loadUserByUsername(String s) throws UsernameNotFoundException
    {
        return this.personRepository.getUserByEmail(s);
    }
}

CustomAuthenticationProvider

@Component
public class CustomAuthenticationProvider implements AuthenticationProvider
{
    @Autowired
    protected PersonService personService;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException
    {
        String username = authentication.getName();
        String password = (String) authentication.getCredentials();

        Person person = this.personService.loadUserByUsername(username);

        if (person == null)
            {
                throw new BadCredentialsException("Username not found.");
            }

        if (!password.equals(person.getPassword()))
            {
                throw new BadCredentialsException("Wrong password.");
            }

        Collection<? extends GrantedAuthority> authorities = person.getAuthorities();

        return new UsernamePasswordAuthenticationToken(username, password, authorities);
    }

    @Override
    public boolean supports(Class<?> aClass)
    {
        return true;
    }
}

SecurityConfig.class

@EnableWebSecurity
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter
{
    @Override
    protected void configure(HttpSecurity http) throws Exception
    {
        http
            .authorizeRequests()
            .antMatchers("/api/**").hasRole("USER")
            .anyRequest().authenticated();
    }

I think that's it.

Was it helpful?

Solution

I finally found the solution. I had to bind all my pieces of code together in SecurityConfig like

@EnableWebSecurity
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter
{
    @Autowired
    protected BasicAuthenticationFilter filter;
    @Autowired
    protected AuthenticationProvider    authenticationProvider;

    @Override
    protected void configure(HttpSecurity http) throws Exception
    {
        http
            .addFilter(filter)
            .authenticationProvider(authenticationProvider)
            .httpBasic()
            .and()
            .authorizeRequests()
            .antMatchers("/api/**").hasRole("USER")
            .anyRequest().authenticated();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception
    {
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top