7

Spring Security OAuth2 の作業中の XML 構成を Java 構成に移行し、OAuth プロバイダーとして Google を使用しています。

これは私のJava構成がどのように見えるかです:

@Configuration
@EnableWebMvcSecurity
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    private static final List<String> scope;

    static {
        // Permissions to access email and profile
        scope = new ArrayList<>(3);
        scope.add("openid");
        scope.add("email");
        scope.add("profile");
    }

    @Autowired(required = true)
    private UserService userService;

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

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // @formatter:off
        http.
            authorizeRequests()
                .antMatchers(HttpMethod.GET, "/","/public/**", "/resources/**","/resources/public/**").permitAll()
                //.antMatchers("/google_oauth2_login").permitAll()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                    .loginPage("/")
                    .loginProcessingUrl("/login")
                    .defaultSuccessUrl("/home")
                    .and()
                    .csrf().disable()
                    .logout()
                        .logoutSuccessUrl("/")
                        .logoutUrl("/logout")
                .and()
                    .requiresChannel().anyRequest().requiresSecure()
                .and()
                    .addFilterAfter(oAuth2ClientContextFilter(),ExceptionTranslationFilter.class)
                    .addFilterAfter(googleOAuth2Filter(),OAuth2ClientContextFilter.class)
                .userDetailsService(userService);
        // @formatter:on
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth)
            throws Exception {
        // @formatter:off
        auth
            .authenticationProvider(googleOauth2AuthProvider())
            .userDetailsService(userService);
        // @formatter:on
    }

    @Bean
    public GoogleOAuth2Filter googleOAuth2Filter() throws Exception {
        GoogleOAuth2Filter filter = new GoogleOAuth2Filter(
                "/google_oauth2_login",
                "https://accounts.google.com/o/oauth2/auth",
                oAuth2RestTemplate(auth2ProtectedResourceDetails()));
        filter.setAuthenticationManager(authenticationManagerBean());
        return filter;
    }

    @Bean
    public GoogleOauth2AuthProvider googleOauth2AuthProvider() {
        GoogleOauth2AuthProvider authProvider = new GoogleOauth2AuthProvider();
        return authProvider;
    }

    @Bean
    public OAuth2ProtectedResourceDetails auth2ProtectedResourceDetails() {
        AuthorizationCodeResourceDetails auth2ProtectedResourceDetails = new AuthorizationCodeResourceDetails();
        auth2ProtectedResourceDetails
                .setClientAuthenticationScheme(AuthenticationScheme.form);
        auth2ProtectedResourceDetails
                .setAuthenticationScheme(AuthenticationScheme.form);
        auth2ProtectedResourceDetails.setGrantType("authorization_code");
        auth2ProtectedResourceDetails
                .setClientId("the-client-id");
        auth2ProtectedResourceDetails
                .setClientSecret("the-client-secret");
        auth2ProtectedResourceDetails
                .setAccessTokenUri("https://accounts.google.com/o/oauth2/token");
        auth2ProtectedResourceDetails.setScope(scope);
        auth2ProtectedResourceDetails
                .setUserAuthorizationUri("https://accounts.google.com/o/oauth2/auth");
        auth2ProtectedResourceDetails.setUseCurrentUri(false);
        auth2ProtectedResourceDetails
                .setPreEstablishedRedirectUri("https://localhost/google_oauth2_login");
        return auth2ProtectedResourceDetails;
    }

    @Bean
    public OAuth2RestTemplate oAuth2RestTemplate(
            OAuth2ProtectedResourceDetails resource) {
        OAuth2RestTemplate oAuth2RestTemplate = new OAuth2RestTemplate(resource);
        return oAuth2RestTemplate;
    }

    @Bean
    public OAuth2ClientContextFilter oAuth2ClientContextFilter() {
        OAuth2ClientContextFilter oAuth2ClientContextFilter = new OAuth2ClientContextFilter();
        return oAuth2ClientContextFilter;
    }

}

CSRF を無効にしたことに注意してください。私のログインページから、ユーザーはGoogleログインページにリダイレクトされます

問題:-

  1. Google 許可ページは「オフライン アクセスを許可する」だけを求めます。「メール/プロフィール」アクセス リクエストがありません。

同等の「スコープ」属性 XML 構成:-

<oauth2:resource id="googleOauth2Resource" type="authorization_code"
        client-id="the-client-id
        client-secret="the-client-secret"
        user-authorization-uri="https://accounts.google.com/o/oauth2/auth"
        scope="openid email profile" use-current-uri="false"
        client-authentication-scheme="form" pre-established-redirect-uri="https://localhost/google_oauth2_login" />

メールとプロファイルのアクセス許可を正しく要求します。なんで?

  1. とにかく「オフライン アクセスを使用する」を続行すると、次の例外が発生します:-
    org.springframework.web.client.HttpClientErrorException: 400 Bad Request
        at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:91)
        at org.springframework.security.oauth2.client.token.OAuth2AccessTokenSupport$AccessTokenErrorHandler.handleError(OAuth2AccessTokenSupport.java:243)
        at org.springframework.web.client.RestTemplate.handleResponseError(RestTemplate.java:592)
        at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:550)
        at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:514)
        at org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeAccessTokenProvider.obtainAuthorizationCode(AuthorizationCodeAccessTokenProvider.java:145)
        at org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeAccessTokenProvider.obtainAccessToken(AuthorizationCodeAccessTokenProvider.java:196)
        at org.springframework.security.oauth2.client.token.AccessTokenProviderChain.obtainNewAccessTokenInternal(AccessTokenProviderChain.java:142)
        at org.springframework.security.oauth2.client.token.AccessTokenProviderChain.obtainAccessToken(AccessTokenProviderChain.java:118)
        at org.springframework.security.oauth2.client.OAuth2RestTemplate.acquireAccessToken(OAuth2RestTemplate.java:221)
        at org.springframework.security.oauth2.client.OAuth2RestTemplate.getAccessToken(OAuth2RestTemplate.java:173)
        at org.springframework.security.oauth2.client.OAuth2RestTemplate.createRequest(OAuth2RestTemplate.java:105)

このコード ブロックを使用してユーザー プロファイルを取得しようとしているとき:

@Override
public Authentication attemptAuthentication(HttpServletRequest request,
        HttpServletResponse response) throws AuthenticationException,
        IOException, ServletException {
    logger.info("Google Oauth Filter Triggered!!");
    SecurityContext context = SecurityContextHolder.getContext();
    // auth null or not authenticated.
    String code = request.getParameter("code");
    Authentication dummyAuthentication = null;

    if (StringUtils.isEmpty(code)) {
        // Google authentication in progress. will return null.
        logger.debug("Will set dummy user in context ");
        dummyAuthentication = getDummyAuthenticationToken();
        context.setAuthentication(dummyAuthentication);
        // trigger google oauth2.
        oauth2RestTemplate.postForEntity(authURI, null, Object.class);
        return null;
    } else {
        // response from google received !!.
        // remove dummy authentication from context.
        //SecurityContextHolder.clearContext();
        logger.debug("Response from Google Recieved !!");
        // get user profile and prepare the authentication token object.
        ResponseEntity<Object> forEntity = oauth2RestTemplate.getForEntity(
                HTTPS_WWW_GOOGLEAPIS_COM_PLUS_V1_PEOPLE_ME_OPEN_ID_CONNECT,
                Object.class);

        @SuppressWarnings("unchecked")
        Map<String, String> profile = (Map<String, String>) forEntity
                .getBody();

        CustomOAuth2AuthenticationToken authenticationToken = getOAuth2Token(
                profile.get(EMAIL), profile.get(NAME));
        authenticationToken.setAuthenticated(false);
        return getAuthenticationManager().authenticate(authenticationToken);
    }
}

ログにこれを示すSpring RestTemplate:

o.s.web.client.RestTemplate              : POST request for "https://accounts.google.com/o/oauth2/auth" resulted in 400 (Bad Request); invoking error handler
2014-09-05 21:51:46.870  WARN 5836 --- [ qtp25546756-15] o.eclipse.jetty.servlet.ServletHandler   : /google_oauth2_login

この同じコードは、XML 構成を使用しているときに機能します。

更新 1

スコープを ' https://www.googleapis.com/auth/plus.profile.emails.read ' & ' https://www.googleapis.com/auth/に変更することで、「オフライン アクセス」の問題を修正できました。 plus.login '.

ユーザープロファイルを取得しようとしているときにまだ不正なリクエストエラーが発生しています

ここで問題のソース コードを見つけてください - git clone https://kumarsambhavjain@bitbucket.org/kumarsambhavjain/spring-oauth2-login.git

4

2 に答える 2