Spring OAuth 授权服务器需要范围 [英] Spring OAuth Authorization Server Requires Scope

查看:35
本文介绍了Spring OAuth 授权服务器需要范围的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们目前正在使用 Spring OAuth 授权服务器,但目前不使用 OAuth 规范中的范围"参数.这有点让人头疼,因为 Spring OAuth 授权服务器要求在请求授权代码时明确要求该范围.

来自DefaultOAuth2RequestValidator:

if (requestScopes.isEmpty()) {throw new InvalidScopeException("Empty scope (无论是客户端还是用户都不允许请求的范围)");}

然而,这直接违反了 OAuth 2.0 规范:

<前>4.1.1.授权请求客户端通过添加以下内容来构造请求 URI授权端点 URI 的查询组件的参数根据附录 B 使用application/x-www-form-urlencoded"格式:响应类型需要.值必须设置为代码".客户编号需要.2.2 节中描述的客户端标识符.重定向uri可选.如第 3.1.2 节所述.范围可选.访问请求的范围描述为第 3.3 节.状态推荐.客户端用于维护的不透明值请求和回调之间的状态.授权服务器在重定向用户代理时包含此值给客户.该参数应该用于防止跨站点请求伪造,如第 10.12 节所述.

Spring Authorization Server 这样做是否有明确的原因?我知道我可以用我自己的验证器替换验证器,但我很好奇为什么这是默认设置,以防万一我因为遗留原因而错过了除此之外的任何其他理解.

谢谢.

编辑

对于那些正在寻找遵循规范的替代实现的人,这是我的.它只是检查如果客户端被限制在某些范围内,那么只有请求的范围是必需的,并且请求的范围必须在分配的客户端范围列表中.如果客户端没有分配范围,则此实现假定它们被允许使用任何范围(与资源相同的假设).还不太确定这意味着什么,或者它是否真的正确.如果不是,请告诉我.

import java.util.Set;导入 org.apache.commons.collections.CollectionUtils;导入 org.springframework.security.oauth2.common.exceptions.InvalidScopeException;导入 org.springframework.security.oauth2.provider.AuthorizationRequest;导入 org.springframework.security.oauth2.provider.ClientDetails;导入 org.springframework.security.oauth2.provider.TokenRequest;公共类 OAuth2RequestValidator实现 org.springframework.security.oauth2.provider.OAuth2RequestValidator {@覆盖public void validateScope(final AuthorizationRequest authorizationRequest,最终 ClientDetails 客户端)抛出 InvalidScopeException {this.validateScope(authorizationRequest.getScope(), client.getScope());}@覆盖公共无效validateScope(最终TokenRequest tokenRequest,最终ClientDetails客户端)抛出 InvalidScopeException {this.validateScope(tokenRequest.getScope(), client.getScope());}私有无效validateScope(最终集请求范围,最终集客户端范围){如果 (!CollectionUtils.isEmpty(clientScopes)) {如果(CollectionUtils.isEmpty(requestScopes)){抛出新的 InvalidScopeException(空范围(客户端或用户是"+ "不允许请求的范围)");}for(最终字符串范围:requestScopes){如果(!clientScopes.contains(范围)){throw new InvalidScopeException("无效范围:" + scope, clientScopes);}}}}}

解决方案

根据 DefaultOAuth2RequestFactory,如果客户端没有提供作用域,将使用为客户端注册的作用域.

DefaultOAuth2RequestFactory.java

私有集extractScopes(Map requestParameters, String clientId) {设置<字符串>范围 = OAuth2Utils.parseParameterList(requestParameters.get(OAuth2Utils.SCOPE));ClientDetails clientDetails = clientDetailsS​​ervice.loadClientByClientId(clientId);if ((scopes == null || scopes.isEmpty())) {//如果传入的数据中没有指定作用域,则使用客户端注册的默认值//(规范允许我们在此选项和完全拒绝请求之间进行选择,因此我们将采用//最不讨厌的选择作为默认值).范围 = clientDetails.getScope();}如果(检查用户范围){scopes = checkUserScopes(scopes, clientDetails);}返回范围;}

因此您可以使用默认all"范围或类似的范围配置您的客户端,例如

public void configure(ClientDetailsS​​erviceConfigurer clients) 抛出异常 {客户.inMemory().withClient("client").secret("secret").authorizedGrantTypes("authorization_code", "client_credentials").scopes("all");

We're currently using the Spring OAuth Authorization Server but currently do not use the "scope" parameter from the OAuth specification. This has been a bit of a pain point as the Spring OAuth Authorization Server requires that scope be explicitly required when requesting an authorization code.

From DefaultOAuth2RequestValidator:

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

This however goes directly against the OAuth 2.0 specification:

 4.1.1.  Authorization Request

    The client constructs the request URI by adding the following   
 parameters to the query component of the authorization endpoint URI   
 using the "application/x-www-form-urlencoded" format, per Appendix B:

    response_type
          REQUIRED.  Value MUST be set to "code".

    client_id
          REQUIRED.  The client identifier as described in Section 2.2.

    redirect_uri
          OPTIONAL.  As described in Section 3.1.2.

    scope
          OPTIONAL.  The scope of the access request as described by
          Section 3.3.

    state
          RECOMMENDED.  An opaque value used by the client to maintain
          state between the request and callback.  The authorization
          server includes this value when redirecting the user-agent back
          to the client.  The parameter SHOULD be used for preventing
          cross-site request forgery as described in Section 10.12.

Is there an explicit reason why the Spring Authorization Server does this? I know that I can replace the validator with my own but I'm curious as to why this is the default in case I'm missing any understanding other than it being this way for legacy reasons.

Thank you.

EDIT

For those looking for an alternative implementation that follows the specification, here is mine. It simply checks that if the client is restricted to certain scopes, only then the requested scope is required and that the requested scope must be in the list of assigned client scopes. If the client has no assigned scopes, this implementation assumes they are allowed use of any scope (same assumption that is made for resources). Not quite sure yet the implications of this or if it's genuinely correct. Please let me know if it is not.

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);
        }
      }
    }
  }

}

解决方案

According to the DefaultOAuth2RequestFactory, if no scope is supplied by the client, the scope registered for the client will be used.

DefaultOAuth2RequestFactory.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;
}

So you could configure your client with a default scope of "all" or something similar e.g.

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

这篇关于Spring OAuth 授权服务器需要范围的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆