Spring Social Google, используемый в качестве провайдера входа, завершается с ошибкой 403 после успешного входа в Oauth2

Мне нужно использовать Facebook и Google в качестве OpenId Sing в провайдерах. Я интегрировал их с Spring Security с помощью SocialAuthenticationFilter, как описано в документации и ознакомился с примером приложения.

Я успешно настроил Facebook.

Проблема в том, когда я пытаюсь пройти аутентификацию в Google:

В OAuth2AuthenticationService.getAuthToken():

...
AccessGrant accessGrant = getConnectionFactory().getOAuthOperations().exchangeForAccess(code, returnToUrl, null);

На данный момент я вижу, что accessGrant содержит accessToken, так что, похоже, он пока правильный. Сбой в следующем вызове:

// TODO avoid API call if possible (auth using token would be fine)
Connection<S> connection = getConnectionFactory().createConnection(accessGrant);

createConnection() в итоге звонит GoogleConnectionFactory.extractProviderUserId(AccessGrant accessGrant):

Google api = ((GoogleServiceProvider)getServiceProvider()).getApi(accessGrant.getAccessToken());
UserProfile userProfile = getApiAdapter().fetchUserProfile(api);
...

а также getApiAdapter().fetchUserProfile(Google) -> google.plusOperations().getGoogleProfile(); выдает исключение 403:

org.springframework.web.client.HttpClientErrorException: 403 Forbidden

Почему он не может получить GoogleProfile? Видимо, сфера, которую я установил, и то, что пользователю предлагается, верна...

Полный проект доступен здесь: https://github.com/codependent/spring-boot-social-signin

Выдержки из конфига:

SecurityConfig:

@EnableWebSecurity
class SecurityConfig extends WebSecurityConfigurerAdapter{

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/secure*").authenticated()
                .and()
            .formLogin()
                .loginPage("/login").permitAll()
                //.loginProcessingUrl("/secure-home")
                .failureUrl("/login?param.error=bad_credentials")
                .and()
            .logout()
                .logoutUrl("/logout")
                .deleteCookies("JSESSIONID")
                .and()
            /*.rememberMe()
                .and()*/
            .apply(new SpringSocialConfigurer());
    }

    @Bean
    public SocialUserDetailsService socialUserDetailsService(){
        return new SocialUserDetailsService(){
            @Override
            public SocialUserDetails loadUserByUserId(String userId) throws UsernameNotFoundException{
                return new SimpleSocialUserDetails(userId);
            }
        }
    }

}

SocialConfig:

@Configuration
@EnableSocial
class SocialConfig extends SocialConfigurerAdapter{

    @Override
    void addConnectionFactories(ConnectionFactoryConfigurer cfConfig, Environment env) {
        FacebookConnectionFactory fcf = new FacebookConnectionFactory(env.getProperty("facebook.clientId"), env.getProperty("facebook.clientSecret"))
        fcf.setScope("public_profile,email")
        cfConfig.addConnectionFactory(fcf)

        GoogleConnectionFactory gcf = new GoogleConnectionFactory(env.getProperty("google.clientId"), env.getProperty("google.clientSecret"))
        gcf.setScope("openid https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo#email https://www.googleapis.com/auth/plus.me https://www.googleapis.com/auth/tasks https://www-opensocial.googleusercontent.com/api/people https://www.googleapis.com/auth/plus.login");
        cfConfig.addConnectionFactory(gcf);
    }

    @Bean
    @Scope(value="request", proxyMode=ScopedProxyMode.INTERFACES)
    Facebook facebook(ConnectionRepository repository) {
        Connection<Facebook> connection = repository.findPrimaryConnection(Facebook.class);
        return connection != null ? connection.getApi() : null;
    }

    @Bean
    @Scope(value="request", proxyMode=ScopedProxyMode.INTERFACES)
    Google google(ConnectionRepository repository) {
        Connection<Google> connection = repository.findPrimaryConnection(Google.class);
        return connection != null ? connection.getApi() : null;
    }

    @Override
    UsersConnectionRepository getUsersConnectionRepository(ConnectionFactoryLocator connectionFactoryLocator) {
        //return new JdbcUsersConnectionRepository(dataSource, connectionFactoryLocator, Encryptors.noOpText());
        InMemoryUsersConnectionRepository rep = new InMemoryUsersConnectionRepository(connectionFactoryLocator)
        rep.setConnectionSignUp(new ConnectionSignUp(){
            public String execute(Connection<?> connection){
                Facebook facebook = (Facebook)connection.getApi();
                String [] fields = [ "id", "email",  "first_name", "last_name", "about" , "gender" ];
                User userProfile = facebook.fetchObject(connection.getKey().getProviderUserId(), User.class, fields);
                return userProfile.getEmail();
            }
        })
        return rep;
    }

    @Override
    UserIdSource getUserIdSource() {
        return new AuthenticationNameUserIdSource()
    }

}

1 ответ

Решение

Исправлено, мне пришлось включить API Google+ на консоли разработчика Google.

Другие вопросы по тегам