【问题标题】:insufficient_scope response from userinfo endpoint and missing scopes in jwt token来自 userinfo 端点的 insufficient_scope 响应和 jwt 令牌中缺少的范围
【发布时间】:2023-02-15 13:30:53
【问题描述】:

我将Spring Authorization Server从0.3.1迁移到1.0.0后,发现userInfo端点返回403insufficient_scope,验证两个版本之间的登录过程后发现POST oauth2/token端点不是返回范围 jwt 令牌也不包含范围,但是在尝试登录时已经提到了 URL 中的范围参数。

我正在使用以下配置:

        registeredClient = RegisteredClient.withId(new ObjectId().toString())
                .clientId(oauthClient)
                .clientSecret(passwordEncoder().encode(oauthClientSecret))
                .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_POST)
                .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
                .clientAuthenticationMethod(ClientAuthenticationMethod.NONE)
                .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
                .authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN)
                .redirectUris(uris -> uris.addAll(redirectUris))
                .scope(OidcScopes.OPENID)
                .scope(OidcScopes.PROFILE)
                .tokenSettings(TokenSettings
                        .builder()
                        .accessTokenTimeToLive(Duration.ofHours(8))
                        .build())
                .clientSettings(ClientSettings
                        .builder()
                        .requireProofKey(true)
                        .requireAuthorizationConsent(false)
                        .build())
                .build();

这是 Http 配置:

    SecurityFilterChain securityFilterChain = http
            .authorizeHttpRequests(authorizeRequests -> authorizeRequests
                    .requestMatchers(WELL_KNOWN_OPENID_CONFIGURATION).permitAll()
                    .requestMatchers("/logout-success").permitAll()
                    .requestMatchers("/api/health/status").permitAll()
                    .requestMatchers("/assets/**", "/webjars/**", "/login").permitAll()
                    .anyRequest().authenticated())
            .formLogin(form -> form
                    .loginPage("/login")
                    .failureUrl("/login-error")
                    .usernameParameter("username")
                    .passwordParameter("password")
                    .permitAll())
            .logout()
            .logoutSuccessUrl("/logout-success")
            .deleteCookies("JSESSIONID")
            .invalidateHttpSession(true)
            .and()
            .build();

我正在使用这些 URL 来测试登录流程:

http://localhost:9000/oauth2/authorize?scope=openid&response_type=code&client_id=<client_id>&code_challenge=<code_challenge>&code_challenge_method=S256&redirect_uri=https://frontlocal:4600


http://localhost:9000/oauth2/token?grant_type=authorization_code&scope=openid&code=<code>&code_verifier=<code_verifer>&client_id=<client_id>&redirect_uri=https://frontlocal:4600

更新

2023-01-26T20:30:11.030+01:00 TRACE 150437 --- [io-9000-exec-10] o.s.security.web.FilterChainProxy        : Invoking OAuth2TokenEndpointFilter (20/23)
2023-01-26T20:30:11.031+01:00 TRACE 150437 --- [io-9000-exec-10] o.s.security.web.FilterChainProxy        : Invoking OAuth2TokenIntrospectionEndpointFilter (21/23)
2023-01-26T20:30:11.031+01:00 TRACE 150437 --- [io-9000-exec-10] o.s.security.web.FilterChainProxy        : Invoking OAuth2TokenRevocationEndpointFilter (22/23)
2023-01-26T20:30:11.031+01:00 TRACE 150437 --- [io-9000-exec-10] o.s.security.web.FilterChainProxy        : Invoking OidcUserInfoEndpointFilter (23/23)
2023-01-26T20:30:11.031+01:00 TRACE 150437 --- [io-9000-exec-10] o.s.s.authentication.ProviderManager     : Authenticating request with OidcUserInfoAuthenticationProvider (1/13)
2023-01-26T20:30:13.819+01:00 TRACE 150437 --- [io-9000-exec-10] a.o.a.OidcUserInfoAuthenticationProvider : Retrieved authorization with access token
2023-01-26T20:30:13.821+01:00 DEBUG 150437 --- [io-9000-exec-10] .s.a.DefaultAuthenticationEventPublisher : No event was found for the exception org.springframework.security.oauth2.core.OAuth2AuthenticationException
2023-01-26T20:30:13.822+01:00 TRACE 150437 --- [io-9000-exec-10] s.s.o.s.a.o.w.OidcUserInfoEndpointFilter : User info request failed: [insufficient_scope] 

org.springframework.security.oauth2.core.OAuth2AuthenticationException: null
    at org.springframework.security.oauth2.server.authorization.oidc.authentication.OidcUserInfoAuthenticationProvider.authenticate(OidcUserInfoAuthenticationProvider.java:99) ~[spring-security-oauth2-authorization-server-1.0.0.jar:1.0.0]
    at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:182) ~[spring-security-core-6.0.1.jar:6.0.1]
    at org.springframework.security.authentication.ObservationAuthenticationManager.lambda$authenticate$1(ObservationAuthenticationManager.java:53) ~[spring-security-core-6.0.1.jar:6.0.1]
    at io.micrometer.observation.Observation.observe(Observation.java:559) ~[micrometer-observation-1.10.2.jar:1.10.2]
    at org.springframework.security.authentication.ObservationAuthenticationManager.authenticate(ObservationAuthenticationManager.java:52) ~[spring-security-core-6.0.1.jar:6.0.1]
    at org.springframework.security.oauth2.server.authorization.oidc.web.OidcUserInfoEndpointFilter.doFilterInternal(OidcUserInfoEndpointFilter.java:116) ~[spring-security-oauth2-authorization-server-1.0.0.jar:1.0.0]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.0.3.jar:6.0.3]
    at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:186) ~[spring-security-web-6.0.1.jar:6.0.1]
    at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:173) ~[spring-security-web-6.0.1.jar:6.0.1]
    at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:134) ~[spring-security-web-6.0.1.jar:6.0.1]
    at org.springframework.security.oauth2.server.authorization.web.OAuth2TokenRevocationEndpointFilter.doFilterInternal(OAuth2TokenRevocationEndpointFilter.java:103) ~[spring-security-oauth2-authorization-server-1.0.0.jar:1.0.0]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.0.3.jar:6.0.3]
    at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:186) ~[spring-security-web-6.0.1.jar:6.0.1]
    at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:173) ~[spring-security-web-6.0.1.jar:6.0.1]
    at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:134) ~[spring-security-web-6.0.1.jar:6.0.1]
    at org.springframework.security.oauth2.server.authorization.web.OAuth2TokenIntrospectionEndpointFilter.doFilterInternal(OAuth2TokenIntrospectionEndpointFilter.java:106) ~[spring-security-oauth2-authorization-server-1.0.0.jar:1.0.0]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.0.3.jar:6.0.3]
    at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:186) ~[spring-security-web-6.0.1.jar:6.0.1]
    at org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:173) ~[spring-security-web-6.0.1.jar:6.0.1]
    at org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:134) ~[spring-security-web-6.0.1.jar:6.0.1]
    at org.springframework.security.oauth2.server.authorization.web.OAuth2TokenEndpointFilter.doFilterInternal(OAuth2TokenEndpointFilter.java:147) ~[spring-security-oauth2-authorization-server-1.0.0.jar:1.0.0]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.0.3.jar:6.0.3]
    ...
    ...

2023-01-26T20:30:13.827+01:00 TRACE 150437 --- [io-9000-exec-10] o.s.s.w.header.writers.HstsHeaderWriter  : Not injecting HSTS header since it did not match request to [Is Secure]

【问题讨论】:

  • 你有enabled openid connect吗?在 1.0 中默认情况下不再启用它。
  • @SteveRiesenberg 我尝试了你在回复中提供的内容,但它不起作用,而且我认为我已经通过以下代码激活了 OIDC:authorizationServerConfigurer.oidc(oidc -&gt; oidc.userInfoEndpoint(userInfo -&gt; userInfo.userInfoMapper(userInfoMapper)));
  • 您能否提供整个安全配置(如果您有多个过滤器链,请同时提供这两种配置)?我还想知道你为什么要在你的 RegisteredClient 中设置 .clientAuthenticationMethod(ClientAuthenticationMethod.NONE) 因为你有客户机密?
  • 通过logging.level.org.springframework.security=trace 为所有 spring security(包括 auth 服务器)启用跟踪日志记录并在此处提供日志也可能会有所帮助。
  • @SteveRiesenberg 能否请您查看更新后的问题中的跟踪日志,如您所见,它在验证令牌中的范围时出现错误,并且我已经验证数据库中没有保存任何范围。关于此方法.clientAuthenticationMethod(ClientAuthenticationMethod.NONE),我添加它是因为我正在将该应用程序用于 SPA,如果我删除它,它不会给我访问令牌

标签: spring-boot spring-security oauth-2.0 openid-connect spring-authorization-server


【解决方案1】:

添加openid范围在spring-authorization-server/samples/messages-client/src/main/resources/application.yml


          messaging-client-authorization-code:
            provider: spring
            client-id: messaging-client
            client-secret: secret
            authorization-grant-type: authorization_code
            redirect-uri: "http://127.0.0.1:8080/authorized"
            scope: openid, message.read,message.write
            client-name: messaging-client-authorization-code

这是示例 http 请求/响应:

GET http://127.0.0.1:9000/userinfo
Authorization: Bearer <your token>

###

{
  "sub": "user1"
}

适用于 spring-authorization-server 1.0.0 版

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-02-01
    • 1970-01-01
    • 2016-03-08
    • 2019-05-31
    • 2017-05-13
    • 2017-10-03
    • 2015-04-22
    • 2023-03-15
    相关资源
    最近更新 更多