是否可以在 spring 安全性中仅使用刷新令牌来请求访问令牌 oauth2?没有基本身份验证? [英] Is possible ask for an acces token oauth2 just with refresh token in spring security? without basic authentication?

查看:50
本文介绍了是否可以在 spring 安全性中仅使用刷新令牌来请求访问令牌 oauth2?没有基本身份验证?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道在 spring oauth2 中是否可以仅使用另一个刷新令牌获得一对新令牌(访问令牌和刷新令牌),而无需基本身份验证(没有 clientId 和 clientSecret,有什么办法吗?

I would like to know if in spring oauth2 is possible get a new pair tokens (access token and refresh token) just using another refresh token, without the basic authentication (without clientId and clientSecret, is there any way?

例如:

具有基本身份验证

curl -u clientId:clientSecret -X POST 'http://myapplication.oauth2/accounts/oauth/token?grant_type=refresh_token&client_id=<CLIENT_ID>&refresh_token='-v

curl -u clientId:clientSecret -X POST 'http://myapplication.oauth2/accounts/oauth/token?grant_type=refresh_token&client_id=<CLIENT_ID>&refresh_token=' -v

无基本身份验证

curl -u -X POST 'http://myapplication.oauth2/accounts/oauth/token?grant_type=refresh_token&client_id=<CLIENT_ID>&refresh_token=' -v

curl -u -X POST 'http://myapplication.oauth2/accounts/oauth/token?grant_type=refresh_token&client_id=<CLIENT_ID>&refresh_token=' -v

我注意到 spring 中的 sprint BasicAuthenticationFilter 使用下面的验证,可能会覆盖此过滤器并仅使用刷新令牌进行身份验证.

I note that sprint BasicAuthenticationFilter in spring uses validation bellow, maybe override this filter and make the authentication just with refresh token.

String header = request.getHeader("Authorization");

if (header == null || !header.toLowerCase().startsWith("basic ")) {
  chain.doFilter(request, response);
  return;
}

推荐答案

简短的回答是否定的.用于管理 Spring Oauth 2 端点的类如下:

The short answer is no. The class used to manage the Spring Oauth 2 endpoints is the following one:

@FrameworkEndpoint
public class TokenEndpoint extends AbstractEndpoint

这两个请求,我的意思是,获取 access tokenrefresh 一个使用具有不同参数的相同端点.管理这些的方法是:

Both requests, I mean, get access token and refresh one use the same endpoint with different parameters. And the method to manage those ones is:

@RequestMapping(
  value = {"/oauth/token"},
  method = {RequestMethod.POST}
)
public ResponseEntity<OAuth2AccessToken> postAccessToken(Principal principal, @RequestParam Map<String, String> parameters) throws HttpRequestMethodNotSupportedException {
  if (!(principal instanceof Authentication)) {
    throw new InsufficientAuthenticationException("There is no client authentication. Try adding an appropriate authentication filter.");
  } else {
    String clientId = this.getClientId(principal);
    ... 

如您所见,需要一个 Principal 对象(在本例中由基本身份验证提供).

As you can see, a Principal object is required (in this case provided by the Basic Authentication).

甚至,如果您将项目的安全性配置为允许该 url 而不检查身份验证,您将实现输入"在上面的方法中,但您将收到 InsufficientAuthenticationException 因为没有提供 Authentication 实例.

Even, if you configure the security of your project to permit that url without checking authentication, you will achieve to "enter" in above method but you will receive an InsufficientAuthenticationException because no Authentication instance has been provided.

1. 创建自定义 AuthenticationProvider 将不起作用,因为之前调用了方法 postAccessToken.所以你会收到一个 InsufficientAuthenticationException.

1. Create a custom AuthenticationProvider will not work because the method postAccessToken is invoked before. So you will receive an InsufficientAuthenticationException.

2. 创建一个 OncePerRequestFilter 并将其配置为在处理当前请求之前执行:

2. Create a OncePerRequestFilter and configure it to execute before process the current request:

    @Override
    protected void configure(HttpSecurity http) throws Exception {
      http...
        .anyRequest().authenticated()
        .and()
        .addFilterBefore(myCustomFilter, UsernamePasswordAuthenticationFilter.class);
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
      web.ignoring()
            .antMatchers(POST, "/accounts/oauth/**");
    }

带有类似于"的代码:

@Component
public class CustomAuthenticationFilter extends OncePerRequestFilter {

  @Override
  protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
                                FilterChain filterChain) throws ServletException, IOException {
    ...
    SecurityContextHolder.getContext().setAuthentication(
            new UsernamePasswordAuthenticationToken("existingUser",
                    "passwordOfExistingUser",
                    Collections.emptyList()));
    ...
    filterChain.doFilter(request, response);
}

这种方法的问题是TokenEndpoint 中的主体来自 HttpServletRequest 而不是 Spring 上下文,正如您所看到的调试 BasicAuthenticationFilter 类.

The problem with this approach is the principal in TokenEndpoint comes from the HttpServletRequest not from Spring context, as you can see debugging BasicAuthenticationFilter class.

在您的自定义过滤器中,您可以尝试使用反射在 userPrincipal 属性中设置一个值,但是,正如您可以验证的那样,request 有几个内部 请求属性"这可能是一个太棘手的选择".

In your custom filter you can try, using reflection, set a value in userPrincipal property but, as you can verify, request has several "internal request properties" and that could be a "too tricky option".

总而言之,Oauth 标准需要用户/通行证才能访问资源,如果您想在几乎提供的端点中解决此问题,那么该项目可能不是您想要的.

In summary, Oauth standard needs user/pass to access to the resources, if you want to workaround in almost of provided endpoints maybe that project is not what you are looking for.

我不建议这样做,但如果您仍然想继续使用这种方法,有一种方法可以将您自己的值包含在 TokenEndpoint 接收的 principal 参数中班级.

I do not recommend that but if you still want to go ahead with this approach, there is a way to include your own value inside the principal parameter received by TokenEndpoint class.

重要的是要考虑到 BasicAuthorizationFilter 仍将执行,但是您可以通过自己的对象覆盖 Spring 主体对象.

It is important to take into account BasicAuthorizationFilter will be still executed, however you will be able to override the Spring principal object by your own one.

为此,我们可以重用之前的 CustomAuthenticationFilter 但现在您必须包含您需要的过滤器,我的意思是,允许的 url、参数等您将打开门",所以要小心你允许和不允许的东西.

For this, we can reuse the previous CustomAuthenticationFilter but now your have to include the filters you need, I mean, allowed urls, parameters, etc You are going to "open the doors", so be careful about what you allow and not.

在这种情况下的不同之处在于,我们将在扩展 WebSecurityConfigurerAdapter 的类中添加配置,而不是:

The difference in this case is, instead of add the configuration in our class that extends WebSecurityConfigurerAdapter we are going to do it in:

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

  @Autowired
  private CustomAuthenticationFilter customAuthenticationFilter;
  ...

  @Override
  public void configure(AuthorizationServerSecurityConfigurer security) {
    security.checkTokenAccess("isAuthenticated()");
    security.addTokenEndpointAuthenticationFilter(customAuthenticationFilter);
  }
  ...

这篇关于是否可以在 spring 安全性中仅使用刷新令牌来请求访问令牌 oauth2?没有基本身份验证?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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