I am currently working on a project in which we want the user to log in via Facebook and other OAuth2 providers. In addition, REST api must be stateless. Therefore, no cookies / jsessionids should be created / used. For authorization against api, JWT issues api after successful login via Facebook. The webapp, consuming the rest of the api, is built using AgularJS and satellite. I reduced my code to the smallest example available on github .
Workflow idea:
- The user enters the site, selects "login with facebook".
- A pop-up window opens in the web application that displays the facebook login page.
- User signs, accepts and forwards facebook to webapp
- Webapp receives a token from Facebook and uses it to enter the rest of the api (GET / login / facebook? Code = XXXXXXXXXXXXXXXXX)
- The rest of the api returns JWT.
- Webapp uses JWT to authenticate against the rest of the api for any further requests.
Works for now
- Webapp can handle steps 1 through 4
- The rest of the api can handle steps 5 and 6 if you use the redirect that you get from the OAuth2ClientContextFilter, which performs a GET for "/ login / facebook" without a code parameter. (This redirect is sent to facebook, you are logged in, you are redirected to api again.)
- The rest of the api has no status, jsessionid / cookies are not created / required (csrf is disabled and SessionCreationPolicy.STATELESS is used). Except for calling "login / facebook", this one still creates jsessionid.
Problem
The combination of webapp and the rest of the call "login / facebook? Code = XXX" does not work. I found out that when you do a GET "login / facebook", you will be redirected to facebook with an additional status parameter attached to the URL. In addition, this status parameter is also added when facebook redirects back to api. From what I found on the Internet, it seems to be some kind of CSRF protection, right? And I think this stuff also creates a jsessionid cookie?
Questions
- Is the workflow presented above a smart idea?
- Do I need this CSRF protection in my use case?
- How can I disable this behavior? I mean, I used SessionCreationPolicy.STATELESS, but spring is still creating a session with jsessionid. How can I create a truly stateless vacation api? (At least regarding cookies ...)
- Is this the right way to do this? Or am I missing something?
Code example
As already mentioned, I put the full working minimal example on GitHub. Here I will post (hopefully) the most important part of the WebSecurityConfigurerAdapter. full file is here.
@EnableOAuth2Client @Configuration public class OAuth2ClientConfigurer extends WebSecurityConfigurerAdapter { @Autowired private OAuth2ClientContext oAuth2ClientContext; @Override protected void configure(HttpSecurity httpSecurity) throws Exception { httpSecurity .csrf().disable() .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).enableSessionUrlRewriting(false).and() .antMatcher("/**").authorizeRequests() .antMatchers("/login/**").permitAll() .anyRequest().authenticated().and() .exceptionHandling().authenticationEntryPoint(new Http403ForbiddenEntryPoint()).and() .addFilterBefore(statelessJwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class) .addFilterBefore(createSsoFilter(facebook(), facebookSuccessHandler(), "/login/facebook"), BasicAuthenticationFilter.class); } private OAuth2ClientAuthenticationProcessingFilter createSsoFilter(ClientResourceDetails clientDetails, AuthenticationSuccessHandler successHandler, String path) { OAuth2ClientAuthenticationProcessingFilter ssoFilter = new OAuth2ClientAuthenticationProcessingFilter(path); ssoFilter.setAllowSessionCreation(false); OAuth2RestTemplate restTemplate = new OAuth2RestTemplate(clientDetails.getClient(), oAuth2ClientContext); ssoFilter.setRestTemplate(restTemplate); ssoFilter.setTokenServices(new UserInfoTokenServices(clientDetails.getResource().getUserInfoUri(), clientDetails.getClient().getClientId())); ssoFilter.setAuthenticationSuccessHandler(successHandler); return ssoFilter; } @Bean
Many thanks for your help!
source share