View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
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          // private constructor for static utility class
98      }
99  }