44import org .springframework .context .annotation .Bean ;
55import org .springframework .context .annotation .Configuration ;
66import org .springframework .http .HttpMethod ;
7+ import org .springframework .security .authentication .BadCredentialsException ;
8+ import org .springframework .security .authentication .InternalAuthenticationServiceException ;
9+ import org .springframework .security .authentication .LockedException ;
710import org .springframework .security .config .annotation .web .builders .HttpSecurity ;
811import org .springframework .security .config .annotation .web .configuration .EnableWebSecurity ;
912import org .springframework .security .config .annotation .web .configurers .AbstractHttpConfigurer ;
10- import org .springframework .security .config .annotation .web .configurers .HeadersConfigurer ;
1113import org .springframework .security .oauth2 .server .resource .web .DefaultBearerTokenResolver ;
1214import org .springframework .security .web .SecurityFilterChain ;
15+ import org .springframework .security .web .authentication .AuthenticationFailureHandler ;
16+ import org .springframework .security .web .authentication .ExceptionMappingAuthenticationFailureHandler ;
17+ import org .springframework .security .web .util .matcher .AntPathRequestMatcher ;
18+ import org .springframework .security .web .util .matcher .OrRequestMatcher ;
19+ import org .springframework .security .web .util .matcher .RequestMatcher ;
20+
21+ import jakarta .servlet .http .HttpServletRequest ;
22+ import java .util .Map ;
23+ import java .util .regex .Pattern ;
1324
1425@ Configuration
1526@ EnableWebSecurity
@@ -20,21 +31,55 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti
2031 final var bearerTokenResolver = new DefaultBearerTokenResolver ();
2132 bearerTokenResolver .setAllowUriQueryParameter (true );
2233
23- return http .headers (headersConfig ->
24- headersConfig .cacheControl (HeadersConfigurer .CacheControlConfig ::disable )
25- )
26- .formLogin (AbstractHttpConfigurer ::disable )
27- .oauth2ResourceServer (oauth2Config ->
28- oauth2Config
29- .bearerTokenResolver (bearerTokenResolver )
30- .jwt (jwtConfig -> jwtConfig .jwtAuthenticationConverter (new FafAuthenticationConverter ()))
31- )
32- .authorizeHttpRequests (authorizeConfig ->
33- authorizeConfig
34- .requestMatchers (HttpMethod .OPTIONS ).permitAll ()
35- // Swagger UI
36- .requestMatchers ("/swagger-ui/**" , "/swagger-resources/**" , "/v3/api-docs/**" , "/" ).permitAll ()
37- // Webapp folder
38- .requestMatchers ("/css/*" , "/favicon.ico" , "/robots.txt" ).permitAll ()).build ();
34+ // @formatter:off
35+ http .csrf (csrfConfig -> csrfConfig .requireCsrfProtectionMatcher (new RequestMatcher () {
36+ private final Pattern allowedMethods = Pattern .compile ("^(GET|HEAD|TRACE|OPTIONS)$" );
37+ private final RequestMatcher matcher = new OrRequestMatcher (
38+ new AntPathRequestMatcher ("/oauth/authorize" ),
39+ new AntPathRequestMatcher ("/login" ));
40+
41+ @ Override
42+ public boolean matches (HttpServletRequest request ) {
43+ return matcher .matches (request ) && !allowedMethods .matcher (request .getMethod ()).matches ();
44+ }
45+ }));
46+ http .headers (headersConfig -> headersConfig .cacheControl ().disable ());
47+ http .formLogin (AbstractHttpConfigurer ::disable );
48+ http .oauth2ResourceServer (oauth2Config -> {
49+ oauth2Config .bearerTokenResolver (bearerTokenResolver );
50+ oauth2Config .jwt (jwtConfig -> jwtConfig .jwtAuthenticationConverter (new FafAuthenticationConverter ()));
51+ });
52+ http .authorizeRequests (authorizeConfig -> {
53+ authorizeConfig .requestMatchers (HttpMethod .OPTIONS ).permitAll ();
54+ // Swagger UI
55+ authorizeConfig .requestMatchers (
56+ "/swagger-ui/**" ,
57+ "/swagger-resources/**" ,
58+ "/v3/api-docs/**" ,
59+ "/"
60+ ).permitAll ();
61+ // Webapp folder
62+ authorizeConfig .requestMatchers (
63+ "/css/*" ,
64+ "/favicon.ico" ,
65+ "/robots.txt"
66+ ).permitAll ();
67+ });
68+ // @formatter:on
69+ return http .build ();
70+ }
71+
72+ @ Bean
73+ public AuthenticationFailureHandler authenticationFailureHandler () {
74+ Map <Object , String > exceptionMappings = Map .of (
75+ InternalAuthenticationServiceException .class .getCanonicalName (), "/login?error=serverError" ,
76+ BadCredentialsException .class .getCanonicalName (), "/login?error=badCredentials" ,
77+ LockedException .class .getCanonicalName (), "/login?error=locked"
78+ );
79+
80+ final ExceptionMappingAuthenticationFailureHandler result = new ExceptionMappingAuthenticationFailureHandler ();
81+ result .setExceptionMappings (exceptionMappings );
82+ result .setDefaultFailureUrl ("/login?error=unknown" );
83+ return result ;
3984 }
4085}
0 commit comments