|
1 | 1 | package stirling.software.proprietary.security.configuration; |
2 | 2 |
|
3 | 3 | import java.util.List; |
| 4 | +import java.util.regex.Pattern; |
4 | 5 |
|
5 | 6 | import org.springframework.beans.factory.annotation.Autowired; |
6 | 7 | import org.springframework.beans.factory.annotation.Qualifier; |
|
28 | 29 | import org.springframework.security.web.SecurityFilterChain; |
29 | 30 | import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; |
30 | 31 | import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository; |
| 32 | +import org.springframework.security.web.firewall.HttpFirewall; |
| 33 | +import org.springframework.security.web.firewall.StrictHttpFirewall; |
31 | 34 | import org.springframework.security.web.savedrequest.NullRequestCache; |
32 | 35 | import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher; |
33 | 36 | import org.springframework.web.cors.CorsConfiguration; |
@@ -136,6 +139,34 @@ public static PasswordEncoder passwordEncoder() { |
136 | 139 | return new BCryptPasswordEncoder(); |
137 | 140 | } |
138 | 141 |
|
| 142 | + /** |
| 143 | + * Configures HttpFirewall to allow non-ASCII characters in header values. This fixes issues |
| 144 | + * with reverse proxies (like Authelia) that may set headers with non-ASCII characters (e.g., |
| 145 | + * "Remote-User: Dvořák"). |
| 146 | + * |
| 147 | + * <p>By default, StrictHttpFirewall rejects header values containing non-ASCII characters. This |
| 148 | + * configuration allows valid UTF-8 encoded characters while maintaining security. |
| 149 | + * |
| 150 | + * @return Configured HttpFirewall that allows non-ASCII characters in headers |
| 151 | + */ |
| 152 | + @Bean |
| 153 | + public HttpFirewall httpFirewall() { |
| 154 | + StrictHttpFirewall firewall = new StrictHttpFirewall(); |
| 155 | + // Allow non-ASCII characters but continue to reject control characters such as newlines. |
| 156 | + // Pattern adapted from Spring Security's StrictHttpFirewall documentation. |
| 157 | + Pattern allowedChars = Pattern.compile("[\\p{IsAssigned}&&[^\\p{IsControl}]]*"); |
| 158 | + |
| 159 | + firewall.setAllowedHeaderValues( |
| 160 | + headerValue -> |
| 161 | + headerValue != null && allowedChars.matcher(headerValue).matches()); |
| 162 | + |
| 163 | + // Apply the same rules to parameter values for consistency. |
| 164 | + firewall.setAllowedParameterValues( |
| 165 | + parameterValue -> |
| 166 | + parameterValue != null && allowedChars.matcher(parameterValue).matches()); |
| 167 | + return firewall; |
| 168 | + } |
| 169 | + |
139 | 170 | @Bean |
140 | 171 | public CorsConfigurationSource corsConfigurationSource() { |
141 | 172 | List<String> configuredOrigins = null; |
|
0 commit comments