Skip to content

Commit cbe9c76

Browse files
committed
ExceptionHandlingConfigurer
1 parent 2fcbf77 commit cbe9c76

File tree

11 files changed

+286
-87
lines changed

11 files changed

+286
-87
lines changed

config/src/main/java/org/springframework/security/config/annotation/web/configurers/ExceptionHandlingConfigurer.java

Lines changed: 158 additions & 80 deletions
Large diffs are not rendered by default.

config/src/main/java/org/springframework/security/config/annotation/web/configurers/FormLoginConfigurer.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,10 @@ public FormLoginConfigurer<H> successForwardUrl(String forwardUrl) {
231231
public void init(H http) throws Exception {
232232
super.init(http);
233233
initDefaultLoginFilter(http);
234+
ExceptionHandlingConfigurer<H> exceptions = http.getConfigurer(ExceptionHandlingConfigurer.class);
235+
if (exceptions != null) {
236+
exceptions.defaultAuthenticationEntryPointFor(getAuthenticationEntryPoint(), "FACTOR_PASSWORD");
237+
}
234238
}
235239

236240
@Override

config/src/main/java/org/springframework/security/config/annotation/web/configurers/WebAuthnConfigurer.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
2929
import org.springframework.security.core.userdetails.UserDetailsService;
3030
import org.springframework.security.web.access.intercept.AuthorizationFilter;
31+
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
3132
import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter;
3233
import org.springframework.security.web.authentication.ui.DefaultResourcesFilter;
3334
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
@@ -150,6 +151,15 @@ public WebAuthnConfigurer<H> creationOptionsRepository(
150151
return this;
151152
}
152153

154+
@Override
155+
public void init(H http) throws Exception {
156+
ExceptionHandlingConfigurer<H> exceptions = http.getConfigurer(ExceptionHandlingConfigurer.class);
157+
if (exceptions != null) {
158+
exceptions.defaultAuthenticationEntryPointFor(new LoginUrlAuthenticationEntryPoint("/login"),
159+
"FACTOR_WEBAUTHN");
160+
}
161+
}
162+
153163
@Override
154164
public void configure(H http) throws Exception {
155165
UserDetailsService userDetailsService = getSharedOrBean(http, UserDetailsService.class)

config/src/main/java/org/springframework/security/config/annotation/web/configurers/X509Configurer.java

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,8 @@ public void init(H http) {
186186
.setSharedObject(AuthenticationEntryPoint.class, new Http403ForbiddenEntryPoint());
187187
ExceptionHandlingConfigurer<H> exceptions = http.getConfigurer(ExceptionHandlingConfigurer.class);
188188
if (exceptions != null) {
189-
exceptions.defaultAuthenticationEntryPointFor(new Http403ForbiddenEntryPoint(), AnyRequestMatcher.INSTANCE);
189+
exceptions.defaultAuthenticationEntryPointFor(new Http403ForbiddenEntryPoint(), AnyRequestMatcher.INSTANCE,
190+
"FACTOR_X509");
190191
}
191192
}
192193

@@ -248,10 +249,7 @@ private AuthorityGrantingAuthenticationProvider(AuthenticationProvider delegate)
248249
if (result == null) {
249250
return result;
250251
}
251-
return result
252-
.toBuilder()
253-
.authorities((a) -> a.add(new SimpleGrantedAuthority("FACTOR_X509")))
254-
.build();
252+
return result.toBuilder().authorities((a) -> a.add(new SimpleGrantedAuthority("FACTOR_X509"))).build();
255253
}
256254

257255
@Override

config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2LoginConfigurer.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
4242
import org.springframework.security.config.annotation.web.configurers.AbstractAuthenticationFilterConfigurer;
4343
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
44+
import org.springframework.security.config.annotation.web.configurers.ExceptionHandlingConfigurer;
4445
import org.springframework.security.config.annotation.web.configurers.SessionManagementConfigurer;
4546
import org.springframework.security.context.DelegatingApplicationListener;
4647
import org.springframework.security.core.Authentication;
@@ -374,6 +375,10 @@ public void init(B http) throws Exception {
374375
http.authenticationProvider(new OidcAuthenticationRequestChecker());
375376
}
376377
this.initDefaultLoginFilter(http);
378+
ExceptionHandlingConfigurer<B> exceptions = http.getConfigurer(ExceptionHandlingConfigurer.class);
379+
if (exceptions != null) {
380+
exceptions.defaultAuthenticationEntryPointFor(getAuthenticationEntryPoint(), "FACTOR_AUTHORIZATION_CODE");
381+
}
377382
}
378383

379384
@Override

config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/resource/OAuth2ResourceServerConfigurer.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,10 @@ public void init(H http) {
259259
if (authenticationProvider != null) {
260260
http.authenticationProvider(authenticationProvider);
261261
}
262+
ExceptionHandlingConfigurer<H> exceptions = http.getConfigurer(ExceptionHandlingConfigurer.class);
263+
if (exceptions != null) {
264+
exceptions.defaultAuthenticationEntryPointFor(this.authenticationEntryPoint, "FACTOR_BEARER");
265+
}
262266
}
263267

264268
@Override

config/src/main/java/org/springframework/security/config/annotation/web/configurers/ott/OneTimeTokenLoginConfigurer.java

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,15 @@
1616

1717
package org.springframework.security.config.annotation.web.configurers.ott;
1818

19+
import java.io.IOException;
1920
import java.util.Collections;
2021
import java.util.Map;
22+
import java.util.function.Function;
23+
import java.util.stream.Collectors;
2124

25+
import jakarta.servlet.ServletException;
2226
import jakarta.servlet.http.HttpServletRequest;
27+
import jakarta.servlet.http.HttpServletResponse;
2328

2429
import org.springframework.context.ApplicationContext;
2530
import org.springframework.http.HttpMethod;
@@ -35,8 +40,15 @@
3540
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
3641
import org.springframework.security.config.annotation.web.configurers.AbstractAuthenticationFilterConfigurer;
3742
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
43+
import org.springframework.security.config.annotation.web.configurers.ExceptionHandlingConfigurer;
3844
import org.springframework.security.core.Authentication;
45+
import org.springframework.security.core.AuthenticationException;
46+
import org.springframework.security.core.context.SecurityContextHolder;
47+
import org.springframework.security.core.context.SecurityContextHolderStrategy;
3948
import org.springframework.security.core.userdetails.UserDetailsService;
49+
import org.springframework.security.web.AuthenticationEntryPoint;
50+
import org.springframework.security.web.FormPostRedirectStrategy;
51+
import org.springframework.security.web.RedirectStrategy;
4052
import org.springframework.security.web.authentication.AuthenticationConverter;
4153
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
4254
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
@@ -55,6 +67,7 @@
5567
import org.springframework.security.web.util.matcher.RequestMatcher;
5668
import org.springframework.util.Assert;
5769
import org.springframework.util.StringUtils;
70+
import org.springframework.web.util.UriComponentsBuilder;
5871

5972
/**
6073
* An {@link AbstractHttpConfigurer} for One-Time Token Login.
@@ -134,6 +147,12 @@ public void init(H http) throws Exception {
134147
AuthenticationProvider authenticationProvider = getAuthenticationProvider();
135148
http.authenticationProvider(postProcess(authenticationProvider));
136149
intiDefaultLoginFilter(http);
150+
ExceptionHandlingConfigurer<H> exceptions = http.getConfigurer(ExceptionHandlingConfigurer.class);
151+
if (exceptions != null) {
152+
AuthenticationEntryPoint entryPoint = new PostAuthenticationEntryPoint(
153+
this.tokenGeneratingUrl + "?username={u}", Map.of("u", Authentication::getName));
154+
exceptions.defaultAuthenticationEntryPointFor(entryPoint, "FACTOR_OTT");
155+
}
137156
}
138157

139158
private void intiDefaultLoginFilter(H http) {
@@ -391,4 +410,52 @@ public ApplicationContext getContext() {
391410
return this.context;
392411
}
393412

413+
private static final class PostAuthenticationEntryPoint implements AuthenticationEntryPoint {
414+
415+
private final String entryPointUri;
416+
417+
private final Map<String, Function<Authentication, String>> params;
418+
419+
private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
420+
.getContextHolderStrategy();
421+
422+
private RedirectStrategy redirectStrategy = new FormPostRedirectStrategy();
423+
424+
private PostAuthenticationEntryPoint(String entryPointUri,
425+
Map<String, Function<Authentication, String>> params) {
426+
this.entryPointUri = entryPointUri;
427+
this.params = params;
428+
}
429+
430+
@Override
431+
public void commence(HttpServletRequest request, HttpServletResponse response,
432+
AuthenticationException authException) throws IOException, ServletException {
433+
Authentication authentication = getAuthentication(authException);
434+
Assert.notNull(authentication, "could not find authentication in order to perform post");
435+
Map<String, String> params = this.params.entrySet()
436+
.stream()
437+
.collect(Collectors.toMap(Map.Entry::getKey, (entry) -> entry.getValue().apply(authentication)));
438+
UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(this.entryPointUri);
439+
CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
440+
if (csrf != null) {
441+
builder.queryParam(csrf.getParameterName(), csrf.getToken());
442+
}
443+
String entryPointUrl = builder.build(false).expand(params).toUriString();
444+
this.redirectStrategy.sendRedirect(request, response, entryPointUrl);
445+
}
446+
447+
private Authentication getAuthentication(AuthenticationException authException) {
448+
Authentication authentication = authException.getAuthenticationRequest();
449+
if (authentication != null && authentication.isAuthenticated()) {
450+
return authentication;
451+
}
452+
authentication = this.securityContextHolderStrategy.getContext().getAuthentication();
453+
if (authentication != null && authentication.isAuthenticated()) {
454+
return authentication;
455+
}
456+
return null;
457+
}
458+
459+
}
460+
394461
}

config/src/main/java/org/springframework/security/config/annotation/web/configurers/saml2/Saml2LoginConfigurer.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import org.springframework.security.config.annotation.web.configurers.AbstractAuthenticationFilterConfigurer;
3434
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
3535
import org.springframework.security.config.annotation.web.configurers.CsrfConfigurer;
36+
import org.springframework.security.config.annotation.web.configurers.ExceptionHandlingConfigurer;
3637
import org.springframework.security.core.Authentication;
3738
import org.springframework.security.saml2.provider.service.authentication.AbstractSaml2AuthenticationRequest;
3839
import org.springframework.security.saml2.provider.service.authentication.OpenSaml5AuthenticationProvider;
@@ -305,6 +306,10 @@ public void init(B http) throws Exception {
305306
if (this.authenticationManager == null) {
306307
registerDefaultAuthenticationProvider(http);
307308
}
309+
ExceptionHandlingConfigurer<B> exceptions = http.getConfigurer(ExceptionHandlingConfigurer.class);
310+
if (exceptions != null) {
311+
exceptions.defaultAuthenticationEntryPointFor(getAuthenticationEntryPoint(), "FACTOR_SAML_RESPONSE");
312+
}
308313
}
309314

310315
/**

core/src/main/java/org/springframework/security/authorization/AuthorityAuthorizationDecision.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
* @author Marcus Da Coregio
2828
* @since 5.6
2929
*/
30-
public class AuthorityAuthorizationDecision extends AuthorizationDecision {
30+
public class AuthorityAuthorizationDecision extends AuthorizationDecision implements AuthorizationRequest {
3131

3232
@Serial
3333
private static final long serialVersionUID = -8338309042331376592L;
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* Copyright 2004-present the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.security.authorization;
18+
19+
import java.util.Collection;
20+
21+
import org.springframework.security.core.GrantedAuthority;
22+
23+
public interface AuthorizationRequest {
24+
25+
Collection<GrantedAuthority> getAuthorities();
26+
27+
}

0 commit comments

Comments
 (0)