spring-security Spring授权服务器|/userinfo终结点返回401未授权错误

jaxagkaj  于 2022-11-11  发布在  Spring
关注(0)|答案(1)|浏览(445)

I'm trying to use Spring Authorization Server for authorizing users, but I have a problem with /userinfo endpoint, it's always returning 401 Unauthorized Error.

My /userinfo request looks like:

GET /userinfo HTTP/1.1Host: localhost:8080Authorization: Bearer eyJraWQiOiIyMTIxNjAzNC1kYTc4LTRlMTQtODI3Ni1lNzlmM2NlZDM3NzYiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJhZG1pbiIsImF1ZCI6ImN5cHJlc3MtY2xpZW50LWlkIiwibmJmIjoxNjQ2MzI2Mzc2LCJzY29wZSI6WyJvcGVuaWQiXSwiaXNzIjoiaHR0cDpcL1wvbG9jYWxob3N0OjgwODAiLCJleHAiOjE2NDYzMjgxNzYsImlhdCI6MTY0NjMyNjM3Nn0.aJsCVLoszgi2uCq6Jd9ov83QZFsqN1HK7-sE7Lbs11APRP1cHRYV2hlnrt7i7znMMquWsIfutiVlwOlPzX-lDJpNgthHkqVlIplrIFQdvCT6FTXO7V8dnyyHFhPbnPdYtWHnFoES3gpEazKD8IHnxuvYz75D98EcU9pOFH7zwqxh7t3uhvDXzijjdM59C_94zng2ufCCRmWf0NZd9uj1M9Y8iz1SI_fNjBbkwhe8ZecN6GGX9BPkuaWc_WB4OP8nANIkGgEpf-NlEoitrRPBDVwB-yAXKr8DV6c6Nb-AnGj-ogyjmdLBRE0tFG2mH6mHyplJYnQPzJjfOx_mqV9U0A

My Spring Authorization Server configuration:

@EnableWebSecurity
public class SpringSecurityConfiguration {
    @Bean
    public UserDetailsService users() {
    // @formatter:off
    UserDetails user = User.withUsername("admin").password("password").roles("ADMIN").build();
return new InMemoryUserDetailsManager(user);
    }

    @Bean
    SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
    // defining security for other endpoints of your application including the

    // @formatter:off
        http.authorizeRequests(authorizeRequest -> authorizeRequest.anyRequest().authenticated())
        .formLogin(Customizer.withDefaults());
    // @formatter:on

    return http.build();
    }

}
@Configuration
public class AuthorizationServerConfiguration {
    @Bean
    public OAuth2AuthorizationConsentService authorizationConsentService() {
    return new InMemoryOAuth2AuthorizationConsentService();
    }

    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
    // Defining security for the default endpoints of an Authorization Server

    applyDefaultSecurity(http);

    return http.cors().configurationSource(corsConfigurationSource()).and().formLogin(Customizer.withDefaults())
        .build();
    }

    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration config = new CorsConfiguration();
        config.addAllowedOrigin("http://localhost:3000");
        config.addAllowedHeader("*");
        config.addAllowedHeader("authorization");
        config.addAllowedMethod("GET");
        config.addAllowedMethod("POST");
        config.addAllowedMethod("OPTIONS");
        config.addAllowedMethod("HEAD");
        config.addAllowedMethod("DELETE");
        config.addAllowedMethod("PUT");
        config.addAllowedMethod("TRACE");

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/.well-known/openid-configuration", config);
        source.registerCorsConfiguration("/oauth2/token", config);
        source.registerCorsConfiguration("/userinfo", config);
        source.registerCorsConfiguration("userinfo", config);

        source.registerCorsConfiguration("/oauth2/authorize", config);
        source.registerCorsConfiguration("/oauth2/jwks", config);

        return source;
    }

    @Bean
    public RegisteredClientRepository registeredClientRepository() {
        RegisteredClient registeredClient = RegisteredClient.withId(UUID.randomUUID().toString())
                .clientId("cypress-client-id").clientAuthenticationMethod(ClientAuthenticationMethod.NONE)
                .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE).tokenSettings(tokenSettings())
                .redirectUri("http://localhost:3000/signin/callback")
                .redirectUri("http://localhost:3000/silent/callback").scope(OPENID).scope("offline_access")
                .clientSettings(ClientSettings.builder().requireProofKey(true).build()).build();

        return new InMemoryRegisteredClientRepository(registeredClient);
    }

    @Bean
    public TokenSettings tokenSettings() {
        // @formatter:off
        return TokenSettings.builder().accessTokenTimeToLive(Duration.ofMinutes(30L)).build();
        // @formatter:on
    }
}

The stake trace:

2022-03-03 18:08:48.875 TRACE 13257 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy        : Invoking SecurityContextHolderAwareRequestFilter (17/25)
2022-03-03 18:08:48.876 TRACE 13257 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy        : Invoking AnonymousAuthenticationFilter (18/25)
2022-03-03 18:08:49.037 TRACE 13257 --- [nio-8080-exec-2] o.s.s.w.a.AnonymousAuthenticationFilter  : Set SecurityContextHolder to AnonymousAuthenticationToken [Principal=anonymousUser, Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=0:0:0:0:0:0:0:1, SessionId=E12CB3A032D3C0C442783899676963FC], Granted Authorities=[ROLE_ANONYMOUS]]
2022-03-03 18:08:49.037 TRACE 13257 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy        : Invoking SessionManagementFilter (19/25)
2022-03-03 18:08:49.204 TRACE 13257 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy        : Invoking ExceptionTranslationFilter (20/25)
2022-03-03 18:08:49.360 TRACE 13257 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy        : Invoking FilterSecurityInterceptor (21/25)
2022-03-03 18:08:49.360 TRACE 13257 --- [nio-8080-exec-2] o.s.s.w.a.i.FilterSecurityInterceptor    : Did not re-authenticate AnonymousAuthenticationToken [Principal=anonymousUser, Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=0:0:0:0:0:0:0:1, SessionId=E12CB3A032D3C0C442783899676963FC], Granted Authorities=[ROLE_ANONYMOUS]] before authorizing
2022-03-03 18:08:49.360 TRACE 13257 --- [nio-8080-exec-2] o.s.s.w.a.i.FilterSecurityInterceptor    : Authorizing filter invocation [GET /userinfo] with attributes [authenticated]
2022-03-03 18:08:49.360 TRACE 13257 --- [nio-8080-exec-2] o.s.s.w.a.expression.WebExpressionVoter  : Voted to deny authorization
2022-03-03 18:08:49.361 TRACE 13257 --- [nio-8080-exec-2] o.s.s.w.a.i.FilterSecurityInterceptor    : Failed to authorize filter invocation [GET /userinfo] with attributes [authenticated] using AffirmativeBased [DecisionVoters=[org.springframework.security.web.access.expression.WebExpressionVoter@86d6bf7], AllowIfAllAbstainDecisions=false]
2022-03-03 18:08:49.512 TRACE 13257 --- [nio-8080-exec-2] o.s.s.w.a.ExceptionTranslationFilter     : Sending AnonymousAuthenticationToken [Principal=anonymousUser, Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=0:0:0:0:0:0:0:1, SessionId=E12CB3A032D3C0C442783899676963FC], Granted Authorities=[ROLE_ANONYMOUS]] to authentication entry point since access is denied

org.springframework.security.access.AccessDeniedException: Access is denied
    at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:73) ~[spring-security-core-5.6.1.jar:5.6.1]
    at org.springframework.security.access.intercept.AbstractSecurityInterceptor.attemptAuthorization(AbstractSecurityInterceptor.java:239) ~[spring-security-core-5.6.1.jar:5.6.1]
    at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:208) ~[spring-security-core-5.6.1.jar:5.6.1]
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:113) ~[spring-security-web-5.6.1.jar:5.6.1]
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:81) ~[spring-security-web-5.6.1.jar:5.6.1]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.6.1.jar:5.6.1]
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:122) ~[spring-security-web-5.6.1.jar:5.6.1]
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:116) ~[spring-security-web-5.6.1.jar:5.6.1]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.6.1.jar:5.6.1]
    at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:126) ~[spring-security-web-5.6.1.jar:5.6.1]
    at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:81) ~[spring-security-web-5.6.1.jar:5.6.1]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.6.1.jar:5.6.1]
    at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:109) ~[spring-security-web-5.6.1.jar:5.6.1]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.6.1.jar:5.6.1]
    at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:149) ~[spring-security-web-5.6.1.jar:5.6.1]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.6.1.jar:5.6.1]

Does anyone know how to fix this problem?

Tnx in advance
Mihajlo

6vl6ewon

6vl6ewon1#

请参阅参考文档中的OpenID Connect 1.0 UserInfo Endpoint,其中有一个示例配置演示了如何启用用户信息端点。另外,请查看OidcUserInfoTests,其中有一个配置演示了这一点。
它需要使用.oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt)JwtDecoder@Bean来验证JWT访问标记。

相关问题