1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.syncope.sra.security.saml2;
20
21 import org.apache.syncope.sra.ApplicationContextUtils;
22 import org.apache.syncope.sra.security.LogoutRouteMatcher;
23 import org.apache.syncope.sra.security.PublicRouteMatcher;
24 import org.pac4j.saml.client.SAML2Client;
25 import org.slf4j.Logger;
26 import org.slf4j.LoggerFactory;
27 import org.springframework.cache.CacheManager;
28 import org.springframework.context.ConfigurableApplicationContext;
29 import org.springframework.security.authentication.ReactiveAuthenticationManager;
30 import org.springframework.security.config.web.server.SecurityWebFiltersOrder;
31 import org.springframework.security.config.web.server.ServerHttpSecurity;
32 import org.springframework.security.core.Authentication;
33 import org.springframework.security.web.server.authentication.AuthenticationWebFilter;
34 import org.springframework.security.web.server.authentication.logout.LogoutWebFilter;
35 import org.springframework.security.web.server.context.WebSessionServerSecurityContextRepository;
36 import org.springframework.web.server.WebFilter;
37 import reactor.core.publisher.Mono;
38
39 public final class SAML2SecurityConfigUtils {
40
41 private static final Logger LOG = LoggerFactory.getLogger(SAML2SecurityConfigUtils.class);
42
43 private static ReactiveAuthenticationManager authenticationManager() {
44 return authentication -> Mono.just(authentication).filter(Authentication::isAuthenticated);
45 }
46
47 public static void forLogin(
48 final ServerHttpSecurity http,
49 final SAML2Client saml2Client,
50 final PublicRouteMatcher publicRouteMatcher) {
51
52 ReactiveAuthenticationManager authenticationManager = authenticationManager();
53
54 SAML2WebSsoAuthenticationRequestWebFilter authRequestFilter =
55 new SAML2WebSsoAuthenticationRequestWebFilter(saml2Client);
56 http.addFilterAt(authRequestFilter, SecurityWebFiltersOrder.HTTP_BASIC);
57
58 AuthenticationWebFilter authenticationFilter =
59 new SAML2WebSsoAuthenticationWebFilter(authenticationManager, saml2Client);
60 authenticationFilter.setAuthenticationFailureHandler((exchange, ex) -> Mono.error(ex));
61 authenticationFilter.setSecurityContextRepository(new WebSessionServerSecurityContextRepository());
62 http.addFilterAt(authenticationFilter, SecurityWebFiltersOrder.AUTHENTICATION);
63
64 WebFilter anonymousRedirectFilter = new SAML2AnonymousWebFilter(publicRouteMatcher);
65 http.addFilterAt(anonymousRedirectFilter, SecurityWebFiltersOrder.AUTHENTICATION);
66 }
67
68 public static void forLogout(
69 final ServerHttpSecurity.AuthorizeExchangeSpec builder,
70 final SAML2Client saml2Client,
71 final CacheManager cacheManager,
72 final LogoutRouteMatcher logoutRouteMatcher,
73 final ConfigurableApplicationContext ctx) {
74
75 LogoutWebFilter logoutWebFilter = new LogoutWebFilter();
76 logoutWebFilter.setRequiresLogoutMatcher(logoutRouteMatcher);
77 logoutWebFilter.setLogoutHandler(new SAML2RequestServerLogoutHandler(saml2Client, cacheManager));
78 logoutWebFilter.setLogoutSuccessHandler((exchange, authentication) -> Mono.empty());
79
80 try {
81 SAML2ServerLogoutSuccessHandler logoutSuccessHandler = ApplicationContextUtils.getOrCreateBean(
82 ctx,
83 SAML2ServerLogoutSuccessHandler.class.getName(),
84 SAML2ServerLogoutSuccessHandler.class);
85
86 SAML2LogoutResponseWebFilter logoutResponseWebFilter =
87 new SAML2LogoutResponseWebFilter(saml2Client, logoutSuccessHandler, cacheManager);
88 builder.and().addFilterAt(logoutResponseWebFilter, SecurityWebFiltersOrder.LOGOUT);
89 } catch (ClassNotFoundException e) {
90 LOG.error("While creating instance of {}", SAML2ServerLogoutSuccessHandler.class.getName(), e);
91 }
92
93 builder.and().addFilterAt(logoutWebFilter, SecurityWebFiltersOrder.LOGOUT);
94 }
95
96 private SAML2SecurityConfigUtils() {
97
98 }
99 }