0

I am trying to configure security for 2 end points /api and /admin. For /api i want to secure with jwt token based mechanism which is stateless and for /admin i want to have form based login.

following others already found on Spring security oauth2 and form login configuration i tried to configure it. which leads me to either my /admin is secured or /api is secure based on @Order i set for my config.

Some how the ordering has no effect with integer value. Had to set it with org.springframework.core.Ordered then only the resource server config get priority

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.context.annotation.Primary;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.security.authentication.AuthenticationManager;
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.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore;

@EnableWebSecurity
public class MultiHttpSecurityConfig {

    @Autowired
    private CustomUserDetailsService userDetailsService;

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

    @Autowired
    public void configAuthentication(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
    }

    @Configuration
    @EnableWebSecurity
    public static class ApiWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {

        Logger logger = LoggerFactory.getLogger(ApiWebSecurityConfigurationAdapter.class);

        @Override
        protected void configure(HttpSecurity http) throws Exception {

            logger.info("\n---------\n m here ApiWebSecurityConfigurationAdapter\n---------\n");
            http.authorizeRequests().antMatchers("/api/**").hasRole("USER").and().formLogin();
        }

        @Bean
        @Override
        public AuthenticationManager authenticationManagerBean() throws Exception {
            return super.authenticationManagerBean();
        }

    }

    @Configuration
    @Order(1)
    public static class FormLoginWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {

        Logger logger = LoggerFactory.getLogger(FormLoginWebSecurityConfigurerAdapter.class);

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            logger.info("\n---------\n m here FormLoginWebSecurityConfigurerAdapter\n---------\n");

            http.csrf().disable().authorizeRequests().antMatchers("/admin/**")
                    .hasAnyAuthority("admin", "ADMIN_USER").and().formLogin().permitAll().and().logout().permitAll();
        }
    }

    @Configuration
    @EnableResourceServer
    @Order(2)
    public class CustomResourceServerConfigurerAdapter extends ResourceServerConfigurerAdapter {

        Logger logger = LoggerFactory.getLogger(CustomResourceServerConfigurerAdapter.class);

        @Autowired
        private JdbcTemplate jdbcTemplate;

        @Bean
        public TokenStore tokenStore() {
            return new JdbcTokenStore(jdbcTemplate.getDataSource());
        }

        @Bean
        @Primary
        //Making this primary to avoid any accidental duplication with another token service instance of the same name
        public DefaultTokenServices tokenServices() {
            DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
            defaultTokenServices.setTokenStore(tokenStore());
            defaultTokenServices.setSupportRefreshToken(true);
            return defaultTokenServices;
        }

        @Override
        public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
            resources.tokenServices(tokenServices());
        }

        @Override
        public void configure(HttpSecurity http) throws Exception {

            logger.info("\n---------\n m here CustomResourceServerConfigurerAdapter\n---------\n");

            http.authorizeRequests()
                        .and()
                        .anonymous().disable()
                        .sessionManagement()
                        .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                        .and().httpBasic()
                        .and()
                        .authorizeRequests()
                        .antMatchers("/api/**").fullyAuthenticated();

        }
    }

}

and my OAuth2Configuration

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;

@Configuration
@EnableAuthorizationServer
public class OAuth2Configuration extends AuthorizationServerConfigurerAdapter {

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Autowired 
    private CustomUserDetailsService userDetailsService;

    @Autowired
    private TokenStore tokenStore;

    @Bean
    public JwtAccessTokenConverter accessTokenConverter() {
        return new JwtAccessTokenConverter();
    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
        oauthServer.tokenKeyAccess("hasAuthority('ROLE_TRUSTED_CLIENT')")
                .checkTokenAccess("hasAuthority('ROLE_TRUSTED_CLIENT')");
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints
                .tokenStore(tokenStore)
                .reuseRefreshTokens(false)
                .authenticationManager(authenticationManager)
                .accessTokenConverter(accessTokenConverter())
                .userDetailsService(userDetailsService);
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.jdbc(jdbcTemplate.getDataSource());
    }

}

I expect securing both endpoint i.e /api with jwt token and /admin with form based login. I don't want to implement 2 different project for Rest API and for UI

Edit

thanks @dur that was eye opening

i was able to secure my rest api with

@Override
public void configure(HttpSecurity http) throws Exception {

    logger.info("\n---------\n m here CustomResourceServerConfigurerAdapter\n---------\n");

    http
        .antMatcher("/api/**")
        .authorizeRequests()
            .antMatchers("/api/**" ).authenticated();

}

but i am unable to secure my /admin except with httpBasic

Would be very helpfull if anyone can tell me how to configure form login

@Override
protected void configure(HttpSecurity http) throws Exception {
    logger.info("\n---------\n m here FormLoginWebSecurityConfigurerAdapter\n---------\n");


            http
            .antMatcher("/admin/**")
            .authorizeRequests()
                .anyRequest().hasAnyAuthority("ADMIN_USER")
                .and()
            .httpBasic();
}

I tried

http.antMatcher("/admin/**").authorizeRequests()
    .antMatchers("/admin/**").hasAnyAuthority("ADMIN_USER")
    .and()
        .formLogin()
            .permitAll()
    .and()
        .logout()
            .permitAll();

But it didn't work

Edit 2

finally got it

http
    .antMatcher("/admin/**")
    .authorizeRequests()
        .anyRequest().hasAnyAuthority("ADMIN_USER")
    .and()
        .formLogin()
        .loginPage("/admin/login")
        .permitAll()
    .and()
        .logout()
            .logoutUrl("/admin/logout")
            .invalidateHttpSession(true)
            .permitAll();

http.csrf().disable();
sango
  • 151
  • 1
  • 10
  • All of your configurations are matching `/**` (defautl). You have to configurate, which configuration should be applied for wich URL. – dur Aug 07 '19 at 09:39
  • @dur "All of your configurations are matching `/**` (defautl)." i didnt get it – sango Aug 07 '19 at 11:13
  • What don't you get? You have three configurations all are matching `/**`, so the first is applied and all others are not applied. Look into the other question there is the part of the Spring Security Reference quoted. – dur Aug 07 '19 at 11:17

0 Answers0