Skip to content

Commit

Permalink
Add AuthorizeReturnObject
Browse files Browse the repository at this point in the history
Closes gh-14597
  • Loading branch information
jzheaux committed Mar 18, 2024
1 parent c611b7e commit e5e915b
Show file tree
Hide file tree
Showing 18 changed files with 759 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,13 @@ public void denyAllPreAuthorizeDeniesAccess() {
assertThatExceptionOfType(AccessDeniedException.class).isThrownBy(this.prePostSecured::denyAllMethod);
}

@Test
public void nestedDenyAllPostAuthorizeDeniesAccess() {
SecurityContextHolder.getContext().setAuthentication(this.anne);
assertThatExceptionOfType(AccessDeniedException.class)
.isThrownBy(() -> this.secured.myObject().denyAllMethod());
}

interface SecuredInterface {

@PostAuthorize("hasRole('X')")
Expand Down Expand Up @@ -134,6 +141,10 @@ void publicCallsPrivate() {
privateMethod();
}

NestedObject myObject() {
return new NestedObject();
}

}

static class SecuredImplSubclass extends SecuredImpl {
Expand All @@ -157,4 +168,13 @@ void denyAllMethod() {

}

static class NestedObject {

@PostAuthorize("denyAll")
void denyAllMethod() {

}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,31 @@ public void preFilterMethodWhenListThenFilters() {
assertThat(this.prePostSecured.postFilterMethod(objects)).containsExactly("apple", "aubergine");
}

@Test
public void nestedDenyAllPostFilterDeniesAccess() {
assertThat(this.prePostSecured.myObject().denyAllMethod()).isEmpty();
}

static class PrePostSecured {

@PostFilter("filterObject.startsWith('a')")
List<String> postFilterMethod(List<String> objects) {
return objects;
}

NestedObject myObject() {
return new NestedObject();
}

}

static class NestedObject {

@PostFilter("filterObject == null")
List<String> denyAllMethod() {
return new ArrayList<>(List.of("deny"));
}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,13 @@ public void denyAllPreAuthorizeDeniesAccess() {
assertThatExceptionOfType(AccessDeniedException.class).isThrownBy(this.prePostSecured::denyAllMethod);
}

@Test
public void nestedDenyAllPreAuthorizeDeniesAccess() {
SecurityContextHolder.getContext().setAuthentication(this.anne);
assertThatExceptionOfType(AccessDeniedException.class)
.isThrownBy(() -> this.secured.myObject().denyAllMethod());
}

interface SecuredInterface {

@PreAuthorize("hasRole('X')")
Expand Down Expand Up @@ -134,6 +141,10 @@ void publicCallsPrivate() {
privateMethod();
}

NestedObject myObject() {
return new NestedObject();
}

}

static class SecuredImplSubclass extends SecuredImpl {
Expand All @@ -157,4 +168,13 @@ void denyAllMethod() {

}

static class NestedObject {

@PreAuthorize("denyAll")
void denyAllMethod() {

}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,31 @@ public void preFilterMethodWhenListThenFilters() {
assertThat(this.prePostSecured.preFilterMethod(objects)).containsExactly("apple", "aubergine");
}

@Test
public void nestedDenyAllPreFilterDeniesAccess() {
assertThat(this.prePostSecured.myObject().denyAllMethod(new ArrayList<>(List.of("deny")))).isEmpty();
}

static class PrePostSecured {

@PreFilter("filterObject.startsWith('a')")
List<String> preFilterMethod(List<String> objects) {
return objects;
}

NestedObject myObject() {
return new NestedObject();
}

}

static class NestedObject {

@PreFilter("filterObject == null")
List<String> denyAllMethod(List<String> list) {
return list;
}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
import java.util.ArrayList;
import java.util.List;

import org.aopalliance.intercept.MethodInterceptor;

import org.springframework.aop.framework.AopInfrastructureBean;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.config.BeanDefinition;
Expand All @@ -27,6 +29,7 @@
import org.springframework.context.annotation.Role;
import org.springframework.security.authorization.AuthorizationAdvisorProxyFactory;
import org.springframework.security.authorization.method.AuthorizationAdvisor;
import org.springframework.security.authorization.method.AuthorizeReturnObjectMethodInterceptor;

@Configuration(proxyBeanMethods = false)
final class AuthorizationProxyConfiguration implements AopInfrastructureBean {
Expand All @@ -41,4 +44,17 @@ static AuthorizationAdvisorProxyFactory authorizationProxyFactory(ObjectProvider
return factory;
}

@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
static MethodInterceptor authorizeReturnObjectMethodInterceptor(ObjectProvider<AuthorizationAdvisor> provider,
AuthorizationAdvisorProxyFactory authorizationProxyFactory) {
AuthorizeReturnObjectMethodInterceptor interceptor = new AuthorizeReturnObjectMethodInterceptor(
authorizationProxyFactory);
List<AuthorizationAdvisor> advisors = new ArrayList<>();
provider.forEach(advisors::add);
advisors.add(interceptor);
authorizationProxyFactory.setAdvisors(advisors);
return interceptor;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, B
registerAsAdvisor("postAuthorizeAuthorization", registry);
registerAsAdvisor("securedAuthorization", registry);
registerAsAdvisor("jsr250Authorization", registry);
registerAsAdvisor("authorizeReturnObject", registry);
}

private void registerAsAdvisor(String prefix, BeanDefinitionRegistry registry) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
import java.util.ArrayList;
import java.util.List;

import org.aopalliance.intercept.MethodInterceptor;

import org.springframework.aop.framework.AopInfrastructureBean;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.config.BeanDefinition;
Expand All @@ -27,6 +29,7 @@
import org.springframework.context.annotation.Role;
import org.springframework.security.authorization.ReactiveAuthorizationAdvisorProxyFactory;
import org.springframework.security.authorization.method.AuthorizationAdvisor;
import org.springframework.security.authorization.method.AuthorizeReturnObjectMethodInterceptor;

@Configuration(proxyBeanMethods = false)
final class ReactiveAuthorizationProxyConfiguration implements AopInfrastructureBean {
Expand All @@ -42,4 +45,17 @@ static ReactiveAuthorizationAdvisorProxyFactory authorizationProxyFactory(
return factory;
}

@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
static MethodInterceptor authorizeReturnObjectMethodInterceptor(ObjectProvider<AuthorizationAdvisor> provider,
ReactiveAuthorizationAdvisorProxyFactory authorizationProxyFactory) {
AuthorizeReturnObjectMethodInterceptor interceptor = new AuthorizeReturnObjectMethodInterceptor(
authorizationProxyFactory);
List<AuthorizationAdvisor> advisors = new ArrayList<>();
provider.forEach(advisors::add);
advisors.add(interceptor);
authorizationProxyFactory.setAdvisors(advisors);
return interceptor;
}

}
Loading

0 comments on commit e5e915b

Please sign in to comment.