I'm developing a spring boot application and I need to use spring social login for facebook. I tried different strategies and tutorials to achieve that, but every time after user is redirected from facebook to my application, I get the error saying 'state' parameter doesn't exist or not match
. I know this parameter is something like CSRF protection and I can see that spring is sending it when user is redirecting to facebook. But I almost get lost inside facebook response. I can see the parameter exists in the set-cookie
header from facebook, but not as a parameter.
I can see more people have faced this issue before, but none of the answers worked for me and they were quite old questions. There is also an open issue on github about this. Is it a bug? or cant it be fixed through some configuration?
I'm using spring security
and spring session redis
in this project too.
While I have tried many different configuration, here is the last one I have been working on:
SOCIAL CONFIG
@Configuration
@EnableSocial
public class SocialConfig
implements SocialConfigurer
{
private final Environment environment;
private final MongoOperations mongoOperations;
private final FacebookConnectionSignup facebookConnectionSignup;
@Autowired
public SocialConfig(Environment environment, MongoOperations mongoOperations, FacebookConnectionSignup facebookConnectionSignup) {
this.environment = environment;
this.mongoOperations = mongoOperations;
this.facebookConnectionSignup = facebookConnectionSignup;
}
@Bean
public TextEncryptor textEncryptor(){
return noOpText();
}
@Override
public void addConnectionFactories(ConnectionFactoryConfigurer connectionFactoryConfigurer, Environment environment) {
connectionFactoryConfigurer.addConnectionFactory(new FacebookConnectionFactory(
environment.getProperty("spring.social.facebook.appId"),
environment.getProperty("spring.social.facebook.appSecret")));
}
@Override
public UserIdSource getUserIdSource() {
return new AuthenticationNameUserIdSource();
}
@Override
public UsersConnectionRepository getUsersConnectionRepository(ConnectionFactoryLocator connectionFactoryLocator) {
MongoUsersConnectionRepository mongoUsersConnectionRepository = new MongoUsersConnectionRepository(
mongoOperations,
connectionFactoryLocator,
new MongoConnectionTransformers(
connectionFactoryLocator,
textEncryptor()
)
);
mongoUsersConnectionRepository.setConnectionSignUp(facebookConnectionSignup);
return mongoUsersConnectionRepository;
}
@Bean
public SocialUserDetailsService socialUserDetailsService(UserDetailsService customUserDetailsService){
return new SimpleSocialUserDetailsService(customUserDetailsService);
}
}
SECURITY CONFIG
@Configuration
@EnableGlobalMethodSecurity()
@EnableRedisHttpSession
@Order(-10)
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.httpBasic().disable()
.csrf().disable()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.ALWAYS)
// .sessionFixation().changeSessionId()
.and()
.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/admin/**").authenticated()
.antMatchers("/m/**").authenticated()
.and()
.headers().frameOptions().disable()
.and()
.requestCache()
.requestCache(new NullRequestCache())
.and()
.cors()
.and()
.rememberMe()
.and().logout().clearAuthentication(true).logoutSuccessHandler(customLogoutSuccessHandler)
.and().apply(new SpringSocialConfigurer()
.postLoginUrl("/")
.defaultFailureUrl("/#/login")
.alwaysUsePostLoginUrl(true));
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public static AuthenticationTrustResolver getAuthenticationTrustResolver() {
return new AuthenticationTrustResolverImpl();
}
@Bean("authenticationManager")
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(customUserDetailsService);
}
@Bean
public CookieSerializer cookieSerializer() {
DefaultCookieSerializer serializer = new DefaultCookieSerializer();
serializer.setCookieName(Setting.COOKIE_NAME);
serializer.setCookiePath("/");
serializer.setUseSecureCookie(false);
serializer.setDomainNamePattern("^.+?\\.(\\w+\\.[a-z]+)$");
return serializer;
}
@Bean
public ProviderSignInController providerSignInController() throws Exception {
((MongoUsersConnectionRepository) usersConnectionRepository)
.setConnectionSignUp(facebookConnectionSignup);
ProviderSignInController providerSignInController = new ProviderSignInController(
connectionFactoryLocator, usersConnectionRepository, facebookSignInAdapter);
List<ProviderSignInInterceptor<?>> list = new ArrayList<>();
list.add(new FacebookConnectionInterceptor());
providerSignInController.setSessionStrategy(new HttpSessionSessionStrategy());
providerSignInController.setSignInInterceptors(list);
providerSignInController.afterPropertiesSet();
return providerSignInController;
}
}
SIGNIN ADAPTER
@Component
public class FacebookSignInAdapter implements SignInAdapter {
private UserService userService;
private AuthenticationService authenticationService;
@Autowired
public FacebookSignInAdapter(UserService userService, AuthenticationService authenticationService) {
this.userService = userService;
this.authenticationService = authenticationService;
}
@Override
public String signIn(
String localUserId,
Connection<?> connection,
NativeWebRequest request) {
final String email = connection.getDisplayName();
final UserEntity userEntity = userService.getUserEntityFromUnknownIdentity(email);
authenticationService.authenticateWithoutPassword(userEntity.getUsername());
return email;
}
}
I'm running this on localhost:8080
. The exception:
2018-09-01 09:48:16.054 ERROR 7169 --- [nio-8080-exec-6] o.s.s.c.web.ProviderSignInController : Exception while completing OAuth 2 connection:
java.lang.IllegalStateException: The OAuth2 'state' parameter is missing or doesn't match.
at org.springframework.social.connect.web.ConnectSupport.verifyStateParameter(ConnectSupport.java:173) ~[spring-social-web-1.1.6.RELEASE.jar:1.1.6.RELEASE]
at org.springframework.social.connect.web.ConnectSupport.completeConnection(ConnectSupport.java:155) ~[spring-social-web-1.1.6.RELEASE.jar:1.1.6.RELEASE]
at org.springframework.social.connect.web.ProviderSignInController.oauth2Callback(ProviderSignInController.java:228) ~[spring-social-web-1.1.6.RELEASE.jar:1.1.6.RELEASE]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_181]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_181]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_181]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_181]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:209) [spring-web-5.0.8.RELEASE.jar:5.0.8.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136) [spring-web-5.0.8.RELEASE.jar:5.0.8.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102) [spring-webmvc-5.0.8.RELEASE.jar:5.0.8.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:877) [spring-webmvc-5.0.8.RELEASE.jar:5.0.8.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:783) [spring-webmvc-5.0.8.RELEASE.jar:5.0.8.RELEASE]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) [spring-webmvc-5.0.8.RELEASE.jar:5.0.8.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:991) [spring-webmvc-5.0.8.RELEASE.jar:5.0.8.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:925) [spring-webmvc-5.0.8.RELEASE.jar:5.0.8.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:974) [spring-webmvc-5.0.8.RELEASE.jar:5.0.8.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:866) [spring-webmvc-5.0.8.RELEASE.jar:5.0.8.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:635) [tomcat-embed-core-8.5.32.jar:8.5.32]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:851) [spring-webmvc-5.0.8.RELEASE.jar:5.0.8.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:742) [tomcat-embed-core-8.5.32.jar:8.5.32]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) [tomcat-embed-core-8.5.32.jar:8.5.32]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.32.jar:8.5.32]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) [tomcat-embed-websocket-8.5.32.jar:8.5.32]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.32.jar:8.5.32]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.32.jar:8.5.32]
at org.springframework.boot.actuate.web.trace.servlet.HttpTraceFilter.doFilterInternal(HttpTraceFilter.java:90) [spring-boot-actuator-2.0.4.RELEASE.jar:2.0.4.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-5.0.8.RELEASE.jar:5.0.8.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.32.jar:8.5.32]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.32.jar:8.5.32]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:320) [spring-security-web-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:127) [spring-security-web-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:91) [spring-security-web-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:119) [spring-security-web-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137) [spring-security-web-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111) [spring-security-web-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter.doFilter(RememberMeAuthenticationFilter.java:150) [spring-security-web-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:170) [spring-security-web-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63) [spring-security-web-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:200) [spring-security-web-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116) [spring-security-web-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:96) [spring-web-5.0.8.RELEASE.jar:5.0.8.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-5.0.8.RELEASE.jar:5.0.8.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:66) [spring-security-web-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-5.0.8.RELEASE.jar:5.0.8.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105) [spring-security-web-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56) [spring-security-web-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-5.0.8.RELEASE.jar:5.0.8.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215) [spring-security-web-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178) [spring-security-web-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:357) [spring-web-5.0.8.RELEASE.jar:5.0.8.RELEASE]
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:270) [spring-web-5.0.8.RELEASE.jar:5.0.8.RELEASE]
at ...
2018-09-01 10:05:50.679 INFO 7169 --- [io-8080-exec-10] o.apache.coyote.http11.Http11Processor : Error parsing HTTP request header
Note: further occurrences of HTTP header parsing errors will be logged at DEBUG level.
java.lang.IllegalArgumentException: Invalid character found in method name. HTTP method names must be tokens
at org.apache.coyote.http11.Http11InputBuffer.parseRequestLine(Http11InputBuffer.java:428) ~[tomcat-embed-core-8.5.32.jar:8.5.32]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:684) ~[tomcat-embed-core-8.5.32.jar:8.5.32]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-8.5.32.jar:8.5.32]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:800) [tomcat-embed-core-8.5.32.jar:8.5.32]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1471) [tomcat-embed-core-8.5.32.jar:8.5.32]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.32.jar:8.5.32]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_181]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_181]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.32.jar:8.5.32]
at java.lang.Thread.run(Thread.java:748) [na:1.8.0_181]
EXTRA INFO
Here is the request timeline provided by insomnia
where I am testing the login process.
> POST /signin/facebook HTTP/1.1
> Host: localhost:8080
> User-Agent: insomnia/6.0.2
> Content-Type: multipart/form-data; boundary=X-INSOMNIA-BOUNDARY
> Accept: */*
> Content-Length: 112
| --X-INSOMNIA-BOUNDARY
| Content-Disposition: form-data; name="scope"
| public_profile
| --X-INSOMNIA-BOUNDARY--
< HTTP/1.1 302
< X-Content-Type-Options: nosniff
< X-XSS-Protection: 1; mode=block
< Cache-Control: no-cache, no-store, max-age=0, must-revalidate
< Pragma: no-cache
< Expires: 0
< Set-Cookie: JSESSIONID=MzA4YjJiZGMtNmU1Yy00ODQ0LWFiNDYtYjkyZjg5NjVjYTc4; Path=/; HttpOnly
< Location: https://www.facebook.com/v1.0/dialog/oauth?client_id=*****************&response_type=code&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2Fsignin%2Ffacebook&scope=public_profile&state=d8a641c9-8748-4a95-b603-737c956a99a9
< Content-Language: en-US
< Content-Length: 0
< Date: Sat, 01 Sep 2018 05:18:07 GMT
> POST /v1.0/dialog/oauth?client_id=*****************&response_type=code&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2Fsignin%2Ffacebook&scope=public_profile&state=d8a641c9-8748-4a95-b603-737c956a99a9 HTTP/1.1
> Host: www.facebook.com
> User-Agent: insomnia/6.0.2
> Content-Type: multipart/form-data; boundary=X-INSOMNIA-BOUNDARY
> Accept: */*
> Content-Length: 112
| --X-INSOMNIA-BOUNDARY
| Content-Disposition: form-data; name="scope"
| public_profile
| --X-INSOMNIA-BOUNDARY--
< HTTP/1.1 302 Found
< X-XSS-Protection: 0
< Pragma: no-cache
< Location: https://m.facebook.com/v3.1/dialog/oauth?redirect_uri=http%3A%2F%2Flocalhost%3A8080%2Fsignin%2Ffacebook&state=d8a641c9-8748-4a95-b603-737c956a99a9&scope=public_profile&response_type=code&client_id=*****************
< Cache-Control: private, no-cache, no-store, must-revalidate
< X-Frame-Options: DENY
< Strict-Transport-Security: max-age=15552000; preload
< X-Content-Type-Options: nosniff
< Expires: Sat, 01 Jan 2000 00:00:00 GMT
< facebook-api-version: v3.1
< Content-Type: text/html; charset="utf-8"
< X-FB-Debug: IzMwWhuz/h6oL3pLb7+7KWm0ll5EAPKo3e2aJjVwLkGcGvkIKH2tDaWQM0P3LSSygnoxsBBkn343+xe0I+flRQ==
< Date: Sat, 01 Sep 2018 05:18:07 GMT
< Connection: keep-alive
< Content-Length: 0
> POST /v3.1/dialog/oauth?redirect_uri=http%3A%2F%2Flocalhost%3A8080%2Fsignin%2Ffacebook&state=d8a641c9-8748-4a95-b603-737c956a99a9&scope=public_profile&response_type=code&client_id=***************** HTTP/1.1
> Host: m.facebook.com
> User-Agent: insomnia/6.0.2
> Content-Type: multipart/form-data; boundary=X-INSOMNIA-BOUNDARY
> Accept: */*
> Content-Length: 112
| --X-INSOMNIA-BOUNDARY
| Content-Disposition: form-data; name="scope"
| public_profile
| --X-INSOMNIA-BOUNDARY--
* We are completely uploaded and fine
< HTTP/1.1 302 Found
< Location: https://m.facebook.com/login.php?skip_api_login=1&api_key=*****************&signed_next=1&next=https%3A%2F%2Fm.facebook.com%2Fv3.1%2Fdialog%2Foauth%3Fredirect_uri%3Dhttp%253A%252F%252Flocalhost%253A8080%252Fsignin%252Ffacebook%26state%3Dd8a641c9-8748-4a95-b603-737c956a99a9%26scope%3Dpublic_profile%26response_type%3Dcode%26client_id%3D*****************%26ret%3Dlogin%26logger_id%3Dfb742942-3c31-c425-5749-882c6c0ef46c&cancel_url=http%3A%2F%2Flocalhost%3A8080%2Fsignin%2Ffacebook%3Ferror%3Daccess_denied%26error_code%3D200%26error_description%3DPermissions%2Berror%26error_reason%3Duser_denied%26state%3Dd8a641c9-8748-4a95-b603-737c956a99a9%23_%3D_&display=touch&locale=en_GB&logger_id=fb742942-3c31-c425-5749-882c6c0ef46c&_rdr
< X-Frame-Options: DENY
< X-XSS-Protection: 0
< Cache-Control: private, no-cache, no-store, must-revalidate
< Expires: Sat, 01 Jan 2000 00:00:00 GMT
< Access-Control-Allow-Origin: https://m.facebook.com
< Access-Control-Expose-Headers: X-FB-Debug, X-Loader-Length
< Pragma: no-cache
< Vary: Origin
< Access-Control-Allow-Credentials: true
< Access-Control-Allow-Methods: OPTIONS
< Strict-Transport-Security: max-age=15552000; preload; includeSubDomains
< Content-Type: text/html; charset=utf-8
< X-Content-Type-Options: nosniff
< facebook-api-version: v3.1
< Set-Cookie: datr=DyGKW_ZKdOwz5HKz9nMlERCC; expires=Mon, 31-Aug-2020 05:18:07 GMT; Max-Age=63072000; path=/; domain=.facebook.com; secure; httponly
< Set-Cookie: reg_fb_ref=https%3A%2F%2Fm.facebook.com%2Fv3.1%2Fdialog%2Foauth%3Fredirect_uri%3Dhttp%253A%252F%252Flocalhost%253A8080%252Fsignin%252Ffacebook%26state%3Dd8a641c9-8748-4a95-b603-737c956a99a9%26scope%3Dpublic_profile%26response_type%3Dcode%26client_id%3D*****************; path=/; domain=.facebook.com; secure; httponly
< Set-Cookie: reg_fb_gate=https%3A%2F%2Fm.facebook.com%2Fv3.1%2Fdialog%2Foauth%3Fredirect_uri%3Dhttp%253A%252F%252Flocalhost%253A8080%252Fsignin%252Ffacebook%26state%3Dd8a641c9-8748-4a95-b603-737c956a99a9%26scope%3Dpublic_profile%26response_type%3Dcode%26client_id%3D*****************; path=/; domain=.facebook.com; secure; httponly
< X-FB-Debug: mTfLJKXvLxLJkSzdZfSkNjnljOEAKuIf+Wn7qnRU85Cd0FhFNebW5D6zCharUAZdfK89GRl886DDq3l2q1m6RQ==
< Date: Sat, 01 Sep 2018 05:18:07 GMT
< Connection: keep-alive
< Content-Length: 0
> POST /login.php?skip_api_login=1&api_key=*****************&signed_next=1&next=https%3A%2F%2Fm.facebook.com%2Fv3.1%2Fdialog%2Foauth%3Fredirect_uri%3Dhttp%253A%252F%252Flocalhost%253A8080%252Fsignin%252Ffacebook%26state%3Dd8a641c9-8748-4a95-b603-737c956a99a9%26scope%3Dpublic_profile%26response_type%3Dcode%26client_id%3D*****************%26ret%3Dlogin%26logger_id%3Dfb742942-3c31-c425-5749-882c6c0ef46c&cancel_url=http%3A%2F%2Flocalhost%3A8080%2Fsignin%2Ffacebook%3Ferror%3Daccess_denied%26error_code%3D200%26error_description%3DPermissions%2Berror%26error_reason%3Duser_denied%26state%3Dd8a641c9-8748-4a95-b603-737c956a99a9%23_%3D_&display=touch&locale=en_GB&logger_id=fb742942-3c31-c425-5749-882c6c0ef46c&_rdr HTTP/1.1
> Host: m.facebook.com
> User-Agent: insomnia/6.0.2
> Cookie: datr=DyGKW_ZKdOwz5HKz9nMlERCC; reg_fb_gate=https%3A%2F%2Fm.facebook.com%2Fv3.1%2Fdialog%2Foauth%3Fredirect_uri%3Dhttp%253A%252F%252Flocalhost%253A8080%252Fsignin%252Ffacebook%26state%3Dd8a641c9-8748-4a95-b603-737c956a99a9%26scope%3Dpublic_profile%26response_type%3Dcode%26client_id%3D*****************; reg_fb_ref=https%3A%2F%2Fm.facebook.com%2Fv3.1%2Fdialog%2Foauth%3Fredirect_uri%3Dhttp%253A%252F%252Flocalhost%253A8080%252Fsignin%252Ffacebook%26state%3Dd8a641c9-8748-4a95-b603-737c956a99a9%26scope%3Dpublic_profile%26response_type%3Dcode%26client_id%3D*****************
> Content-Type: multipart/form-data; boundary=X-INSOMNIA-BOUNDARY
> Accept: */*
> Content-Length: 112
| --X-INSOMNIA-BOUNDARY
| Content-Disposition: form-data; name="scope"
| public_profile
| --X-INSOMNIA-BOUNDARY--
< HTTP/1.1 200 OK
< X-Frame-Options: DENY
< X-XSS-Protection: 0
< Cache-Control: private, no-cache, no-store, must-revalidate
< Access-Control-Allow-Origin: https://m.facebook.com
< Access-Control-Expose-Headers: X-FB-Debug, X-Loader-Length
< Pragma: no-cache
< Vary: Origin
< Content-Type: text/html; charset=utf-8
< X-Content-Type-Options: nosniff
< Access-Control-Allow-Credentials: true
< Access-Control-Allow-Methods: OPTIONS
< Strict-Transport-Security: max-age=15552000; preload; includeSubDomains
< Expires: Sat, 01 Jan 2000 00:00:00 GMT
< Set-Cookie: datr=DyGKW_ZKdOwz5HKz9nMlERCC; expires=Mon, 31-Aug-2020 05:18:08 GMT; Max-Age=63072000; path=/; domain=.facebook.com; secure; httponly
< Set-Cookie: reg_fb_ref=https%3A%2F%2Fm.facebook.com%2Flogin.php%3Fskip_api_login%3D1%26api_key%3D*****************%26signed_next%3D1%26next%3Dhttps%253A%252F%252Fm.facebook.com%252Fv3.1%252Fdialog%252Foauth%253Fredirect_uri%253Dhttp%25253A%25252F%25252Flocalhost%25253A8080%25252Fsignin%25252Ffacebook%2526state%253Dd8a641c9-8748-4a95-b603-737c956a99a9%2526scope%253Dpublic_profile%2526response_type%253Dcode%2526client_id%253D*****************%2526ret%253Dlogin%2526logger_id%253Dfb742942-3c31-c425-5749-882c6c0ef46c%26cancel_url%3Dhttp%253A%252F%252Flocalhost%253A8080%252Fsignin%252Ffacebook%253Ferror%253Daccess_denied%2526error_code%253D200%2526error_description%253DPermissions%252Berror%2526error_reason%253Duser_denied%2526state%253Dd8a641c9-8748-4a95-b603-737c956a99a9%2523_%253D_%26display%3Dtouch%26locale%3Den_GB%26logger_id%3Dfb742942-3c31-c425-5749-882c6c0ef46c; path=/; domain=.facebook.com; secure; httponly
< Set-Cookie: sb=ECGKW6bOTMEfm2xndqZoMTNO; expires=Mon, 31-Aug-2020 05:18:08 GMT; Max-Age=63072000; path=/; domain=.facebook.com; secure; httponly
< Vary: Accept-Encoding
< X-FB-Debug: OnwhdsOlxvieobB7fQUJzvrM0ZsEsBT0GmQcjwly4PrW9W+LqTolqmH1tic3u2pfnvLrOHcG89yVOutAWdihVQ==
< Date: Sat, 01 Sep 2018 05:18:08 GMT
< Transfer-Encoding: chunked
< Connection: keep-alive
After around three days today I finally found the solution.
First of all, The problem I was facing was because of this exception:
2018-09-01 10:05:50.679 INFO 7169 --- [io-8080-exec-10] o.apache.coyote.http11.Http11Processor : Error parsing HTTP request header
Note: further occurrences of HTTP header parsing errors will be logged at DEBUG level.
java.lang.IllegalArgumentException: Invalid character found in method name. HTTP method names must be tokens
at org.apache.coyote.http11.Http11InputBuffer.parseRequestLine(Http11InputBuffer.java:428) ~[tomcat-embed-core-8.5.32.jar:8.5.32]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:684) ~[tomcat-embed-core-8.5.32.jar:8.5.32]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-8.5.32.jar:8.5.32]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:800) [tomcat-embed-core-8.5.32.jar:8.5.32]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1471) [tomcat-embed-core-8.5.32.jar:8.5.32]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.32.jar:8.5.32]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_181]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_181]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.32.jar:8.5.32]
at java.lang.Thread.run(Thread.java:748) [na:1.8.0_181]
with a little search I found out facebook has began forcing HTTPS in callback urls.
After that, I had to fix call back url. The callback url that is set in application must match valid ones in facebook setting.
So I made this change:
@Bean
public ProviderSignInController providerSignInController(UsersConnectionRepository usersConnectionRepository, ConnectionFactoryLocator connectionFactoryLocator, FacebookSignInAdapter facebookSignInAdapter) throws Exception {
((MongoUsersConnectionRepository) usersConnectionRepository)
.setConnectionSignUp(facebookConnectionSignup);
ProviderSignInController providerSignInController = new ProviderSignInController(
connectionFactoryLocator, usersConnectionRepository, facebookSignInAdapter);
List<ProviderSignInInterceptor<?>> list = new ArrayList<>();
list.add(new FacebookConnectionInterceptor());
providerSignInController.setSessionStrategy(new HttpSessionSessionStrategy());
providerSignInController.setSignInInterceptors(list);
// **IMPORTANT PART** >>
providerSignInController.setApplicationUrl("https://test.dropinmessenger.com");
providerSignInController.afterPropertiesSet();
return providerSignInController;
}
after fixing the url (I could not use https on localhost, not sure even if this works on localhost), I had to provide valid callback_uri in facebook too:
The next error I faced was because I was not providing secret_proof
or something close to that. The quickest fix was to turn it off from App Setting > Advanced > Require App Secret
which does not seem to be safest solution.
ATTENTION
Also make sure you are using latest spring-social-facebook
dependency. these didn't work in version 1.1.1RELEASE, I used 2.0.3RELEASE.