Spring Boot 3 与 Spring Security 6 - Twitter OAuth2 配置不起作用

问题描述 投票:0回答:1

我一直在尝试在 Spring Boot Security 中为 Twitter Oauth2 配置找到合适的配置,但没有任何效果。

单击“登录 Twitter”按钮后,启动流程,显示授权对话框,单击“授权”后,抛出以下错误: “[invalid_token_response] 尝试检索 OAuth 2.0 访问令牌时发生错误响应:401 未经授权:[无正文]”.

application.properties
文件中的配置如下所示:

spring.security.oauth2.client.registration.twitter.client-id=[my-client-id]
spring.security.oauth2.client.registration.twitter.client-secret=[my-secret]
spring.security.oauth2.client.registration.twitter.scope=users.read
spring.security.oauth2.client.registration.twitter.redirect-uri={baseUrl}/oauth2/callback/{registrationId}
spring.security.oauth2.client.registration.twitter.client-authentication-method=client_secret_post
spring.security.oauth2.client.provider.twitter.authorization-uri=https://twitter.com/i/oauth2/authorize?code_challenge=challenge&code_challenge_method=plain
spring.security.oauth2.client.provider.twitter.token-uri=https://api.twitter.com/2/oauth2/token
spring.security.oauth2.client.registration.twitter.authorization-grant-type=authorization_code

这是我在应用程序中的

SecurityConfig

@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig {

    private final CustomOAuth2UserService customOAuth2UserService;
    private final OAuth2AuthenticationSuccessHandler oAuthAuthenticationSuccessHandler;
    private final OAuth2AuthenticationFailureHandler oAuth2AuthenticationFailureHandler;
    private final HttpCookieOAuth2AuthorizationRequestRepository httpCookieOAuth2AuthorizationRequestRepository;
    private final TokenAuthenticationFilter tokenAuthenticationFilter;
    private final ClientRegistrationRepository clientRegistrationRepository;

    @Bean
    public HttpCookieOAuth2AuthorizationRequestRepository cookieAuthorizationRequestRepository() {
        return new HttpCookieOAuth2AuthorizationRequestRepository();
    }

    @Bean
    protected SecurityFilterChain configure(HttpSecurity http) throws Exception {
        http.csrf(AbstractHttpConfigurer::disable);
        http.cors(Customizer.withDefaults());
        http.sessionManagement(sessionManagement -> sessionManagement.sessionCreationPolicy(STATELESS));
        http.formLogin(AbstractHttpConfigurer::disable);
        http.httpBasic(AbstractHttpConfigurer::disable);

        http.authorizeHttpRequests(
                auth -> auth
                        .requestMatchers("/token/refresh/**").permitAll()
                        .requestMatchers(
                                "/",
                                "/error"
                        ).permitAll()
                        .requestMatchers("/auth/**", "/oauth2/**").permitAll()
                        .anyRequest().authenticated()
        );

        http.oauth2Login(oauth2 -> oauth2
                .authorizationEndpoint(authorizationEndpointConfigurer -> authorizationEndpointConfigurer
                        .baseUri("/oauth2/authorize")
                        .authorizationRequestRepository(httpCookieOAuth2AuthorizationRequestRepository)
                        .authorizationRequestResolver(new CustomAuthorizationRequestResolver(
                                clientRegistrationRepository, "/oauth2/authorize"
                        ))
                )
                .redirectionEndpoint(redirectionEndpointConfigurer -> redirectionEndpointConfigurer
                        .baseUri("/oauth2/callback/*")
                )
                .userInfoEndpoint(userInfoEndpointConfigurer -> userInfoEndpointConfigurer
                        .userService(customOAuth2UserService)
                )
                .tokenEndpoint(token -> token.accessTokenResponseClient(authorizationCodeTokenResponseClient()))
                .successHandler(oAuthAuthenticationSuccessHandler)
                .failureHandler(oAuth2AuthenticationFailureHandler)
        );

        http.addFilterBefore(tokenAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);

        return http.build();
    }

    private OAuth2AccessTokenResponseClient<OAuth2AuthorizationCodeGrantRequest> authorizationCodeTokenResponseClient() {
        OAuth2AccessTokenResponseHttpMessageConverter tokenResponseHttpMessageConverter =
                new OAuth2AccessTokenResponseHttpMessageConverter();
        tokenResponseHttpMessageConverter.setAccessTokenResponseConverter(new CustomAccessTokenResponseConverter());

        RestTemplate restTemplate = new RestTemplate(Arrays.asList(
                new FormHttpMessageConverter(), tokenResponseHttpMessageConverter));
        restTemplate.setErrorHandler(new OAuth2ErrorResponseErrorHandler());

        DefaultAuthorizationCodeTokenResponseClient tokenResponseClient = new DefaultAuthorizationCodeTokenResponseClient();
        tokenResponseClient.setRestOperations(restTemplate);

        return tokenResponseClient;
    }

    @Bean
    public AuthenticationManager authenticationManagerBean(AuthenticationConfiguration authenticationConfiguration) throws Exception {
        return authenticationConfiguration.getAuthenticationManager();
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

}

这是我在 Twitter 开发者门户上的配置:

Click to see the configuration

这里有人处理过这种情况吗?

PS。我在 LinkedIn 配置中收到相同的错误:

spring.security.oauth2.client.registration.linkedin.client-id=[client-id]
spring.security.oauth2.client.registration.linkedin.client-secret=[client-secret]
spring.security.oauth2.client.registration.linkedin.scope=profile,email,openid
spring.security.oauth2.client.registration.linkedin.redirect-uri={baseUrl}/oauth2/callback/{registrationId}
spring.security.oauth2.client.registration.linkedin.authorization-grant-type=authorization_code
spring.security.oauth2.client.registration.linkedin.client-authentication-method=client_secret_post
spring.security.oauth2.client.provider.linkedin.authorization-uri=https://www.linkedin.com/oauth/v2/authorization
spring.security.oauth2.client.provider.linkedin.token-uri=https://www.linkedin.com/oauth/v2/accessToken
spring.security.oauth2.client.provider.linkedin.user-info-uri=https://api.linkedin.com/v2/me?projection=(id,firstName,lastName,profilePicture(displayImage~:playableStreams))
spring.security.oauth2.client.provider.linkedin.user-name-attribute=localizedFirstName
spring.security.oauth2.client.provider.linkedin.jwk-set-uri=https://www.linkedin.com/oauth/openid/jwks

我已经检查了凭据(客户端 ID、客户端密钥),它们以及重定向 uri 都是正确的。

spring-boot twitter oauth-2.0 spring-boot-security
1个回答
0
投票

您遇到的错误很可能发生在您的应用程序点击

token-uri
端点以交换访问令牌的代码时。我在使用 Twitter API 时也遇到了类似的问题。

经过一番研究,我找到了这个文档。尽管提到的 API URL 不同,但 v2 的要求似乎是相同的。端点要求请求具有带有基本身份验证的标头

base64(clientId:clientSercret)

对我来说,

解决方案是在 Spring Security 配置中使用

client-authentication-method: client_secret_basic
。因此,Spring 将添加 Basic auth 标头,并且交换应该成功。

© www.soinside.com 2019 - 2024. All rights reserved.