Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AuthorizationAnnotationUtils.findUniqueAnnotation is broken when interface is inherited #13490

Closed
ggili opened this issue Jul 12, 2023 · 6 comments
Assignees
Labels
in: core An issue in spring-security-core type: bug A general bug
Milestone

Comments

@ggili
Copy link

ggili commented Jul 12, 2023

Describe the bug
When using @RolesAllowed annotation on interface level and inheriting that interface with another interface spring detects @RolesAllowed as a duplicate.

`
org.springframework.core.annotation.AnnotationConfigurationException: Found more than one annotation of type interface jakarta.annotation.security.RolesAllowed attributed to public void com.example.demo.Service1.doSomethig() Please remove the duplicate annotations and publish a bean to handle your authorization logic.

at org.springframework.security.authorization.method.AuthorizationAnnotationUtils.findUniqueAnnotation(AuthorizationAnnotationUtils.java:65)
at org.springframework.security.authorization.method.Jsr250AuthorizationManager$Jsr250AuthorizationManagerRegistry.findAnnotation(Jsr250AuthorizationManager.java:115)
at org.springframework.security.authorization.method.Jsr250AuthorizationManager$Jsr250AuthorizationManagerRegistry.findJsr250Annotation(Jsr250AuthorizationManager.java:108)
at org.springframework.security.authorization.method.Jsr250AuthorizationManager$Jsr250AuthorizationManagerRegistry.resolveManager(Jsr250AuthorizationManager.java:91)
at org.springframework.security.authorization.method.AbstractAuthorizationManagerRegistry.lambda$getManager$1(AbstractAuthorizationManagerRegistry.java:50)
at java.base/java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1708)
at org.springframework.security.authorization.method.AbstractAuthorizationManagerRegistry.getManager(AbstractAuthorizationManagerRegistry.java:50)
at org.springframework.security.authorization.method.Jsr250AuthorizationManager.check(Jsr250AuthorizationManager.java:82)
at org.springframework.security.authorization.method.Jsr250AuthorizationManager.check(Jsr250AuthorizationManager.java:48)
at org.springframework.security.config.annotation.method.configuration.DeferringObservationAuthorizationManager.check(DeferringObservationAuthorizationManager.java:47)
at org.springframework.security.authorization.method.AuthorizationManagerBeforeMethodInterceptor.attemptAuthorization(AuthorizationManagerBeforeMethodInterceptor.java:252)
at org.springframework.security.authorization.method.AuthorizationManagerBeforeMethodInterceptor.invoke(AuthorizationManagerBeforeMethodInterceptor.java:198)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:756)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:708)
at com.example.demo.Service1$$SpringCGLIB$$0.doSomethig(<generated>)
at com.example.demo.DemoApplicationTests.contextLoads(DemoApplicationTests.java:18)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:727)
at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:156)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:147)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:86)
at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(InterceptingExecutableInvoker.java:103)
at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.lambda$invoke$0(InterceptingExecutableInvoker.java:93)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:92)
at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:86)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:217)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:213)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:138)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:68)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)

`

To Reproduce
Please see the below code. The doSomething method is annotated with RolesAllowed. The subinterface not. But still the spring duplicate check will detect as duplicate.

public interface MyGenericService { @RolesAllowed("ABC") void doSomethig(); }

public interface Specific1 extends MyGenericService { }

@Service public class Service1 implements Specific1 { @Override public void doSomethig() { System.out.println("Do Something1."); } }

Expected behavior

Should not fail with duplicate annotation exception since its not 'redefining'.

Sample

Please run the 'AnnotationIssueTests' unit test.

My sample project.

Reports that include a sample will take priority over reports that do not.
At times, we may require a sample, so it is good to try and include a sample up front.

@ggili ggili added status: waiting-for-triage An issue we've not yet triaged type: bug A general bug labels Jul 12, 2023
@ggili ggili changed the title AuthorizationAnnotationUtils.findUniqueAnnotation is broken when interface has multi inheritance AuthorizationAnnotationUtils.findUniqueAnnotation is broken when interface is inherited Jul 12, 2023
@saugion
Copy link

saugion commented Jul 14, 2023

I have the same issue with a method annotated with @PreAuthorize. If I debug I see the annotated method is found twice, same class and same proxy

@saugion
Copy link

saugion commented Aug 16, 2023

Any news on this? It's a big issue for many of our projects

@ahdadou
Copy link

ahdadou commented Oct 24, 2023

Hello @saulgiordani
Did you find something ??

@saugion
Copy link

saugion commented Oct 25, 2023

we ended up refactoring the code...

@ahdadou
Copy link

ahdadou commented Oct 25, 2023

In my case, I cannot do that, so I need to find a solution :/

@kse-music
Copy link
Contributor

It was fixed by commit and #14407

@jzheaux jzheaux added this to the 6.4.0-M2 milestone Jul 18, 2024
@marcusdacoregio marcusdacoregio added in: core An issue in spring-security-core and removed status: waiting-for-triage An issue we've not yet triaged labels Jul 30, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: core An issue in spring-security-core type: bug A general bug
Projects
None yet
Development

No branches or pull requests

6 participants