是否可以在 spring 安全性中仅使用刷新令牌来请求访问令牌 oauth2?没有基本身份验证? [英] Is possible ask for an acces token oauth2 just with refresh token in spring security? without basic authentication?
问题描述
我想知道在 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 token
和 refresh
一个使用具有不同参数的相同端点.管理这些的方法是:
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屋!