[英]Spring authorization server authenticate for each client
I'm trying to build an Identity Provider using Spring authorization-server that third party applications are going to use for FIM (federated identity management).我正在尝试使用第三方应用程序将用于 FIM(联合身份管理)的 Spring 授权服务器构建身份提供者。
We want each OAuth client to require authentication (if a user tries to login with a different client they would need to authenticate for each client).我们希望每个 OAuth 客户端都需要身份验证(如果用户尝试使用不同的客户端登录,则他们需要为每个客户端进行身份验证)。
Out of the box the flow looks like this:开箱即用的流程如下所示:
So there's 2 issues.所以有2个问题。
/oauth2/authorize
endpoint just checks whether or not the sessions principal is authenticated, it doesn't care or know which client the principal was meant for. /oauth2/authorize
端点只检查会话主体是否经过身份验证,它不关心或不知道主体是针对哪个客户端的。/login
endpoint, so during authentication it doesn't know which client is used./login
端点,因此在身份验证期间它不知道使用哪个客户端。 My best bet here is that I should:我最好的选择是我应该:
oauth2/authorize
endpoint redirection to /login
include the query parameter client_id
oauth2/authorize
端点重定向到/login
包括查询参数client_id
AuthenticationFilter
that also adds the client_id
to the User principalAuthenticationFilter
,它还将client_id
添加到用户主体authorizationRequestConverter
for the oauth2/authorize
endpoint and validate that the client in the request is the same as the client stored on the authenticated principaloauth2/authorize
authorizationRequestConverter
的 authorizationRequestConverter 并验证请求中的客户端与存储在经过身份验证的主体上的客户端相同Am I missing anything or do anyone know of a simpler way of doing this?我错过了什么或者有人知道更简单的方法吗?
Based on your last comment, it seems one possibility is to simply require authentication every time, or at least every time an authorization is requested.根据您最后的评论,似乎一种可能性是每次都只需要身份验证,或者至少每次请求授权时都需要。 In that case, you could clear out the authentication after the authorization code is issued to the client, using a
Filter
.在这种情况下,您可以在向客户端发出授权码后使用
Filter
清除身份验证。 This doesn't seem ideal and will result in a poor user experience, but may achieve your requirement.这看起来不太理想,会导致糟糕的用户体验,但可能会达到您的要求。
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
@Order(1)
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http)
throws Exception {
OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);
// ...
// Add filter to remove the SecurityContext after successful authorization
http.addFilterAfter(new RemoveSecurityContextOnAuthorizationFilter(), LogoutFilter.class);
return http.build();
}
private static final class RemoveSecurityContextOnAuthorizationFilter extends OncePerRequestFilter {
private SecurityContextHolderStrategy securityContextHolderStrategy =
SecurityContextHolder.getContextHolderStrategy();
private final LogoutHandler logoutHandler = new CompositeLogoutHandler(
new CookieClearingLogoutHandler("JSESSIONID"),
new SecurityContextLogoutHandler()
);
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
try {
filterChain.doFilter(request, response);
} finally {
String locationHeader = response.getHeader(HttpHeaders.LOCATION);
if (locationHeader != null) {
UriComponents uriComponents = UriComponentsBuilder.fromUriString(locationHeader).build();
if (uriComponents.getQueryParams().containsKey("code")) {
Authentication authentication = this.securityContextHolderStrategy.getContext().getAuthentication();
this.logoutHandler.logout(request, response, authentication);
}
}
}
}
}
// ...
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.