Skip to content

Commit dab32cb

Browse files
committed
Add Authorization-Requesting AccessDeniedHandler
When access is denied, if we have a way to obtain the missing authorities, this class allows that way to be specified.
1 parent 8273772 commit dab32cb

File tree

4 files changed

+130
-1
lines changed

4 files changed

+130
-1
lines changed

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

Lines changed: 2 additions & 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;
@@ -39,6 +39,7 @@ public AuthorityAuthorizationDecision(boolean granted, Collection<GrantedAuthori
3939
this.authorities = authorities;
4040
}
4141

42+
@Override
4243
public Collection<GrantedAuthority> getAuthorities() {
4344
return this.authorities;
4445
}
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+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
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.web;
18+
19+
import org.springframework.security.authorization.AuthorizationRequest;
20+
21+
public interface AuthorizationEntryPoint extends AuthenticationEntryPoint {
22+
23+
boolean authorizes(AuthorizationRequest authorizationRequest);
24+
25+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
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.web;
18+
19+
import java.io.IOException;
20+
import java.util.ArrayList;
21+
import java.util.List;
22+
23+
import jakarta.servlet.ServletException;
24+
import jakarta.servlet.http.HttpServletRequest;
25+
import jakarta.servlet.http.HttpServletResponse;
26+
27+
import org.springframework.security.access.AccessDeniedException;
28+
import org.springframework.security.authentication.InsufficientAuthenticationException;
29+
import org.springframework.security.authorization.AuthorizationDeniedException;
30+
import org.springframework.security.authorization.AuthorizationRequest;
31+
import org.springframework.security.core.AuthenticationException;
32+
import org.springframework.security.web.access.AccessDeniedHandler;
33+
import org.springframework.security.web.access.AccessDeniedHandlerImpl;
34+
35+
public final class AuthorizationRequestingAccessDeniedHandler implements AccessDeniedHandler {
36+
37+
private final List<AuthorizationEntryPoint> entries;
38+
39+
private final AccessDeniedHandler delegate = new AccessDeniedHandlerImpl();
40+
41+
public AuthorizationRequestingAccessDeniedHandler(List<AuthorizationEntryPoint> entries) {
42+
this.entries = new ArrayList<>(entries);
43+
}
44+
45+
@Override
46+
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException access)
47+
throws IOException, ServletException {
48+
AuthorizationRequest authorizationRequest = authorizationRequest(access);
49+
if (authorizationRequest == null) {
50+
this.delegate.handle(request, response, access);
51+
return;
52+
}
53+
for (AuthorizationEntryPoint entry : this.entries) {
54+
if (entry.authorizes(authorizationRequest)) {
55+
AuthenticationException iae = new InsufficientAuthenticationException("access denied", access);
56+
entry.commence(request, response, iae);
57+
return;
58+
}
59+
}
60+
this.delegate.handle(request, response, access);
61+
}
62+
63+
private AuthorizationRequest authorizationRequest(AccessDeniedException access) {
64+
if (access instanceof AuthorizationRequest request) {
65+
return request;
66+
}
67+
if (!(access instanceof AuthorizationDeniedException denied)) {
68+
return null;
69+
}
70+
if (!(denied.getAuthorizationResult() instanceof AuthorizationRequest request)) {
71+
return null;
72+
}
73+
return request;
74+
}
75+
76+
}

0 commit comments

Comments
 (0)