1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.syncope.core.spring.security;
20
21 import java.util.List;
22 import org.apache.syncope.common.keymaster.client.api.ConfParamOps;
23 import org.apache.syncope.common.keymaster.client.api.DomainOps;
24 import org.apache.syncope.common.lib.types.IdRepoEntitlement;
25 import org.apache.syncope.core.persistence.api.dao.AccessTokenDAO;
26 import org.apache.syncope.core.persistence.api.dao.AnySearchDAO;
27 import org.apache.syncope.core.persistence.api.dao.DelegationDAO;
28 import org.apache.syncope.core.persistence.api.dao.GroupDAO;
29 import org.apache.syncope.core.persistence.api.dao.RealmDAO;
30 import org.apache.syncope.core.persistence.api.dao.RoleDAO;
31 import org.apache.syncope.core.persistence.api.dao.UserDAO;
32 import org.apache.syncope.core.provisioning.api.AuditManager;
33 import org.apache.syncope.core.provisioning.api.ConnectorManager;
34 import org.apache.syncope.core.provisioning.api.MappingManager;
35 import org.apache.syncope.core.provisioning.api.UserProvisioningManager;
36 import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
37 import org.springframework.context.annotation.Bean;
38 import org.springframework.context.annotation.Configuration;
39 import org.springframework.security.authentication.AuthenticationManager;
40 import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
41 import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
42 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
43 import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
44 import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
45 import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
46 import org.springframework.security.web.SecurityFilterChain;
47 import org.springframework.security.web.access.AccessDeniedHandler;
48 import org.springframework.security.web.access.intercept.AuthorizationFilter;
49 import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
50 import org.springframework.security.web.firewall.DefaultHttpFirewall;
51 import org.springframework.security.web.firewall.HttpFirewall;
52 import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
53
54 @EnableWebSecurity
55 @EnableMethodSecurity(prePostEnabled = true)
56 @Configuration(proxyBeanMethods = false)
57 public class WebSecurityContext {
58
59 @Bean
60 public HttpFirewall allowUrlEncodedSlashHttpFirewall() {
61 DefaultHttpFirewall firewall = new DefaultHttpFirewall();
62 firewall.setAllowUrlEncodedSlash(true);
63 return firewall;
64 }
65
66 @Bean
67 public WebSecurityCustomizer webSecurityCustomizer(final HttpFirewall allowUrlEncodedSlashHttpFirewall) {
68 return web -> web.httpFirewall(allowUrlEncodedSlashHttpFirewall);
69 }
70
71 @Bean
72 public SecurityFilterChain filterChain(
73 final HttpSecurity http,
74 final UsernamePasswordAuthenticationProvider usernamePasswordAuthenticationProvider,
75 final AccessDeniedHandler accessDeniedHandler,
76 final AuthDataAccessor dataAccessor,
77 final DefaultCredentialChecker defaultCredentialChecker) throws Exception {
78
79 AuthenticationManager authenticationManager = http.getSharedObject(AuthenticationManagerBuilder.class).
80 parentAuthenticationManager(null).
81 authenticationProvider(usernamePasswordAuthenticationProvider).
82 build();
83 http.authenticationManager(authenticationManager);
84
85 SyncopeAuthenticationDetailsSource authenticationDetailsSource =
86 new SyncopeAuthenticationDetailsSource();
87
88 SyncopeBasicAuthenticationEntryPoint basicAuthenticationEntryPoint =
89 new SyncopeBasicAuthenticationEntryPoint();
90 basicAuthenticationEntryPoint.setRealmName("Apache Syncope authentication");
91 http.httpBasic(customizer -> customizer.
92 authenticationEntryPoint(basicAuthenticationEntryPoint).
93 authenticationDetailsSource(authenticationDetailsSource));
94
95 JWTAuthenticationFilter jwtAuthenticationFilter = new JWTAuthenticationFilter(
96 authenticationManager,
97 basicAuthenticationEntryPoint,
98 authenticationDetailsSource,
99 dataAccessor,
100 defaultCredentialChecker);
101 http.addFilterBefore(jwtAuthenticationFilter, BasicAuthenticationFilter.class);
102
103 MustChangePasswordFilter mustChangePasswordFilter = new MustChangePasswordFilter();
104 http.addFilterBefore(mustChangePasswordFilter, AuthorizationFilter.class);
105
106 http.authorizeHttpRequests(customizer -> customizer.
107 requestMatchers(AntPathRequestMatcher.antMatcher("/actuator/**")).
108 hasAuthority(IdRepoEntitlement.ANONYMOUS).
109 requestMatchers(AntPathRequestMatcher.antMatcher("/**")).permitAll());
110 http.securityContext(AbstractHttpConfigurer::disable);
111 http.sessionManagement(AbstractHttpConfigurer::disable);
112 http.headers(AbstractHttpConfigurer::disable);
113 http.csrf(AbstractHttpConfigurer::disable);
114 http.exceptionHandling(customizer -> customizer.accessDeniedHandler(accessDeniedHandler));
115
116 return http.build();
117 }
118
119 @ConditionalOnMissingBean
120 @Bean
121 public UsernamePasswordAuthenticationProvider usernamePasswordAuthenticationProvider(
122 final SecurityProperties securityProperties,
123 final DomainOps domainOps,
124 final AuthDataAccessor dataAccessor,
125 final UserProvisioningManager provisioningManager,
126 final DefaultCredentialChecker credentialChecker) {
127
128 return new UsernamePasswordAuthenticationProvider(
129 domainOps,
130 dataAccessor,
131 provisioningManager,
132 credentialChecker,
133 securityProperties);
134 }
135
136 @Bean
137 public AccessDeniedHandler accessDeniedHandler() {
138 return new SyncopeAccessDeniedHandler();
139 }
140
141 @ConditionalOnMissingBean
142 @Bean
143 public AuthDataAccessor authDataAccessor(
144 final SecurityProperties securityProperties,
145 final RealmDAO realmDAO,
146 final UserDAO userDAO,
147 final GroupDAO groupDAO,
148 final AnySearchDAO anySearchDAO,
149 final AccessTokenDAO accessTokenDAO,
150 final ConfParamOps confParamOps,
151 final RoleDAO roleDAO,
152 final DelegationDAO delegationDAO,
153 final ConnectorManager connectorManager,
154 final AuditManager auditManager,
155 final MappingManager mappingManager,
156 final List<JWTSSOProvider> jwtSSOProviders) {
157
158 return new AuthDataAccessor(
159 securityProperties,
160 realmDAO,
161 userDAO,
162 groupDAO,
163 anySearchDAO,
164 accessTokenDAO,
165 confParamOps,
166 roleDAO,
167 delegationDAO,
168 connectorManager,
169 auditManager,
170 mappingManager,
171 jwtSSOProviders);
172 }
173 }