Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Authentication is null on the SecurityContextHolder.getContext();

I am trying to add Facebook authorization using Spring Security in Spring Boot app. Currently, my problem is extracting data from Principal.

Here is my security config:

public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure (HttpSecurity http) throws Exception {
        http
            .csrf().disable()
            .antMatcher("/**")
            .authorizeRequests()
                .antMatchers("/", "/login**").permitAll()
                .anyRequest().authenticated()
                .and()
            .logout()
                .deleteCookies("JSESSIONID")
                .clearAuthentication(true)
                .logoutSuccessUrl("/").permitAll();
    }

    @Bean
    public PrincipalExtractor facebookPrincipalExtractor(){
        return new FacebookPrincipalExtractor();
    }
}

and principal extractor:

public class FacebookPrincipalExtractor implements PrincipalExtractor {

    @Autowired
    UserService userService;

    @Override
    public Object extractPrincipal(Map<String, Object> map) {
        String name = (String) map.get("name");
        String id = (String) map.get("id");
        User user = userService.findOne(id);
        if (user == null) {
            SecurityContext securityContext = SecurityContextHolder.getContext();
            Authentication authentication = securityContext.getAuthentication();
            String token = ((OAuth2AuthenticationDetails) authentication.getDetails()).getTokenValue();
            user = new User();

            FacebookClient facebookClient = new DefaultFacebookClient(token, Version.VERSION_2_10);

            JSONObject object = facebookClient.fetchObject("me", JSONObject.class);
//           userService.createUser(object);
        }
        return user;
    }
}

After login, the Map<String, Object> map contains only the name and id. Call to securityContext.getAuthentication() returns null.

Moreover, if I create something similar to the endpoint and pass the Principal there as a parameter, then this will work. Example:

@RequestMapping("/user")
public Principal user(Principal principal) {
    return principal;
}

The principal will contain all the necessary data.

In this regard, 2 questions:

  1. Why security context does not contain authentication?
  2. Where does the principal come from if it is passed as a parameter to a method?

This is what the debug looks like inside

enter image description here

like image 370
Pavel Grudina Avatar asked Feb 18 '20 20:02

Pavel Grudina


1 Answers

Although SecurityContextHolder.getContext() is never null the authentication it contains is cleared once a request is completed. What this means is that if you try to access it during a process which goes through the spring web security it will be there. But as soon as the request finishes the following gets logged

SecurityContextHolder now cleared, as request processing completed

and the authentication is set to null. Any attempts to access it directly through the SecurityContext outside of an http request will result in a null.

like image 163
InsertKnowledge Avatar answered Sep 28 '22 09:09

InsertKnowledge