Spring OAuth授权服务器需要范围

loe*_*sak 6 spring spring-boot spring-security-oauth2

我们目前使用的是Spring OAuth授权服务器,但目前不使用OAuth规范中的“ scope”参数。这有点令人痛苦,因为Spring OAuth Authorization Server要求在请求授权代码时明确要求范围。

DefaultOAuth2RequestValidator

if (requestScopes.isEmpty()) {
    throw new InvalidScopeException("Empty scope (either the client or the user is not allowed the requested scopes)");
}
Run Code Online (Sandbox Code Playgroud)

但是,这直接违反了OAuth 2.0规范:

4.1.1。授权请求

    客户端通过添加以下内容来构造请求URI   
 授权端点URI的查询组件的参数   
 根据附录B,使用“ application / x-www-form-urlencoded”格式:

    response_type
          需要。值必须设置为“代码”。

    client_id
          需要。客户标识符,如第2.2节所述。

    redirect_uri
          可选的。如3.1.2节所述。

    范围
          可选的。访问请求的范围,如
          第3.3节。

    州
          推荐的。客户端用来维护的不透明值
          请求和回调之间的状态。授权
          服务器将用户代理重定向回时包括此值
          给客户。该参数应用于防止
          第10.12节中所述的跨站点伪造请求。

Spring Authorization Server这样做有明确的原因吗?我知道我可以用自己的验证器替换它,但是我很好奇为什么这是默认设置,以防万一我遗漏了任何其他理解,但出于遗留原因却不是这样。

谢谢。

编辑

对于那些寻求遵循规范的替代实现的人,这里是我的。它只是检查是否将客户端限制在某些范围内,才需要请求的范围,并且所请求的范围必须在已分配的客户端范围列表中。如果客户端没有分配的范围,则此实现假定允许它们使用任何范围(对资源所做的相同假设)。尚不确定此含义或它是否确实正确。如果不是,请告诉我。

import java.util.Set;

import org.apache.commons.collections.CollectionUtils;
import org.springframework.security.oauth2.common.exceptions.InvalidScopeException;
import org.springframework.security.oauth2.provider.AuthorizationRequest;
import org.springframework.security.oauth2.provider.ClientDetails;
import org.springframework.security.oauth2.provider.TokenRequest;

public class OAuth2RequestValidator
    implements org.springframework.security.oauth2.provider.OAuth2RequestValidator {

  @Override
  public void validateScope(final AuthorizationRequest authorizationRequest,
      final ClientDetails client)
      throws InvalidScopeException {
    this.validateScope(authorizationRequest.getScope(), client.getScope());
  }

  @Override
  public void validateScope(final TokenRequest tokenRequest, final ClientDetails client)
      throws InvalidScopeException {
    this.validateScope(tokenRequest.getScope(), client.getScope());
  }

  private void validateScope(
      final Set<String> requestScopes, 
      final Set<String> clientScopes) {
    if (!CollectionUtils.isEmpty(clientScopes)) {
      if (CollectionUtils.isEmpty(requestScopes)) {
        throw new InvalidScopeException(
            "Empty scope (either the client or the user is "
              + "not allowed the requested scopes)");
      }

      for (final String scope : requestScopes) {
        if (!clientScopes.contains(scope)) {
          throw new InvalidScopeException("Invalid scope: " + scope, clientScopes);
        }
      }
    }
  }

}
Run Code Online (Sandbox Code Playgroud)

小智 4

根据 DefaultOAuth2RequestFactory,如果客户端未提供范围,则将使用为客户端注册的范围。

默认OAuth2RequestFactory.java

private Set<String> extractScopes(Map<String, String> requestParameters, String clientId) {
    Set<String> scopes = OAuth2Utils.parseParameterList(requestParameters.get(OAuth2Utils.SCOPE));
    ClientDetails clientDetails = clientDetailsService.loadClientByClientId(clientId);

    if ((scopes == null || scopes.isEmpty())) {
        // If no scopes are specified in the incoming data, use the default values registered with the client
        // (the spec allows us to choose between this option and rejecting the request completely, so we'll take the
        // least obnoxious choice as a default).
        scopes = clientDetails.getScope();
    }

    if (checkUserScopes) {
        scopes = checkUserScopes(scopes, clientDetails);
    }
    return scopes;
}
Run Code Online (Sandbox Code Playgroud)

因此,您可以使用默认范围“全部”或类似的内容配置您的客户端,例如

public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
    clients.inMemory()
            .withClient("client").secret("secret")
            .authorizedGrantTypes("authorization_code", "client_credentials")
            .scopes("all");
Run Code Online (Sandbox Code Playgroud)