Search code examples
javaspring-securityspring-security-oauth2spring-cloud-security

Spring Cloud OAuth2Authentication returns NullPointerException


I'm slowly moving into understanding Spring Cloud Security. I've created an authorization service and it works when authorizing and returning a token, but doesn't return any current user details when using that token, when getting these from OAuth2Authentication. This two lines return an NPE:

userInfo.put("user", user.getUserAuthentication().getPrincipal());
            userInfo.put("authorities", AuthorityUtils.authorityListToSet(user.getUserAuthentication().getAuthorities()));

OAuth2Authentication user isn't instantiated and is null, while I understood that it should be by default instantiated by Spring Security. Maybe I am missing some configuration beans? Thanks in advance!

Application.class

@SpringBootApplication
@RestController
@EnableResourceServer
@EnableAuthorizationServer
public class AuthorizationServiceApplication {

    @RequestMapping(value = {"/user"}, produces = "application/json")
    public Map <String, Object> user (OAuth2Authentication user) {
        Map <String, Object> userInfo = new HashMap <>();
        userInfo.put("user", user.getUserAuthentication().getPrincipal());
        userInfo.put("authorities", AuthorityUtils.authorityListToSet(user.getUserAuthentication().getAuthorities()));
        return userInfo;
    }

    public static void main (String[] args) {
        SpringApplication.run(AuthorizationServiceApplication.class, args);
    }
}

OAuth2Config.class

@Configuration
public class OAuth2Config extends AuthorizationServerConfigurerAdapter {

    @Value("${token.secret}")
    private String secret;
    private AuthenticationManager authenticationManager;
    private UserDetailsService userDetailsService;

    public OAuth2Config (AuthenticationManager authenticationManager, UserDetailsService userDetailsService) {
        this.authenticationManager = authenticationManager;
        this.userDetailsService = userDetailsService;
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()
                .withClient("eagleeye")
                .secret(secret)
                .authorizedGrantTypes("refresh_token", "password", "client_credentials")
                .scopes("webclient", "mobileclient");
    }

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

WebSecurityConfigurer.class

@Configuration
public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter {

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

    @Override
    @Bean
    public UserDetailsService userDetailsServiceBean() throws Exception {
        return super.userDetailsServiceBean();
    }

    // TODO: implemented DB stuff
    @Override
    protected void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
        authenticationManagerBuilder
                .inMemoryAuthentication()
                .withUser("deniss").password("deniss1").roles("USER")
                .and()
                .withUser("oksana").password("oksana").roles("USER, ADMIN");
    }

    private CsrfTokenRepository csrfTokenRepository() {
        HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
        repository.setSessionAttributeName("_csrf");
        return repository;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().csrfTokenRepository(csrfTokenRepository());
    }
}

Solution

  • In the end I got it working like this:

    Application.class

    @SpringBootApplication
    @RestController
    @EnableResourceServer
    public class AuthorizationServiceApplication {
    
        private final Logger log = LoggerFactory.getLogger(this.getClass());
    
        @RequestMapping("/user")
        public Principal user(Principal user) {
            log.info("User information display for User: " + user.getName());
            return user;
        }
    
        @Bean
        UserDetailsService userDetailsService() {
            InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
            manager.createUser(User.withUsername("deniss").password("deniss").roles("USER").build());
            return manager;
        }
    
        public static void main (String[] args) {
            SpringApplication.run(AuthorizationServiceApplication.class, args);
        }
    }
    

    OAuth2Config.java

    @Configuration
    @EnableAuthorizationServer
    public class OAuth2Config extends AuthorizationServerConfigurerAdapter {
    
        //TODO: refactor to recieve this info from config server
        @Value("${token.secret}")
        private String secret;
    
        @Autowired
        private AuthenticationManager authenticationManager;
    
        @Override
        public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
            endpoints.authenticationManager(authenticationManager);
        }
    
        @Override
        public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
            clients.inMemory()
                    .withClient("eagleeye")
                    .secret(secret)
                    .authorizedGrantTypes("refresh_token", "password", "client_credentials")
                    .scopes("webclient", "mobileclient");
        }
    }
    

    SecurityConfigurer.class

    @Configuration
    @EnableGlobalAuthentication
    public class SecurityConfigurer extends GlobalAuthenticationConfigurerAdapter {
    
        @Autowired
        private UserDetailsService userDetailsService;
    
        // TODO: implemented DB stuff
        @Override
        public void init(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
            authenticationManagerBuilder.userDetailsService(this.userDetailsService);
        }
    }