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

Dependency Injection issue in AuthFilter #8455

Open
count-emmolgus opened this issue Mar 5, 2024 · 4 comments
Open

Dependency Injection issue in AuthFilter #8455

count-emmolgus opened this issue Mar 5, 2024 · 4 comments
Labels

Comments

@count-emmolgus
Copy link

Hello.

While upgrading from Dropwizard 4.0.1 to Dropwizard 4.0.6 we noticed that we were getting Dependency Injection issues in the AuthFilter.
Digging some more, we noticed it seems as it is Dropwizard 4.0.3 that introduced the issue.
(I've had the same issue with Java 11 & 17)

I've created an simple poc that reproduces the issue (written in Kotlin, but should still be easily understood).
https://github.com/count-emmolgus/dropwizard-filter-issue

Debugging seems to imply that it occurs after authentication, when it tries to set the principal.

! at io.dropwizard.auth.JettyAuthenticationUtil.setJettyAuthenticationIfPossible(JettyAuthenticationUtil.java:27)
! at io.dropwizard.auth.AuthFilter.authenticate(AuthFilter.java:175)
! at com.example.HeaderFilter.filter(HeaderFilter.kt:32)

Initially I thought it was related to: #7989
But since the tests use DropwizardAppExtension instead of ResourceExtension to hoist the tests, together with it failing outside of the during ordinary runtime it shouldn't be the case.

This is the complete stacktrace:

ERROR [2024-03-05 13:40:36,472] io.dropwizard.jersey.errors.LoggingExceptionMapper: Error handling a request: 659e93e5a999ed4b
! java.lang.IllegalStateException: There is more than one active context for org.glassfish.jersey.process.internal.RequestScoped
! at org.jvnet.hk2.internal.ServiceLocatorImpl._resolveContext(ServiceLocatorImpl.java:2222)
! at org.jvnet.hk2.internal.ServiceLocatorImpl.access$000(ServiceLocatorImpl.java:107)
! at org.jvnet.hk2.internal.ServiceLocatorImpl$3.compute(ServiceLocatorImpl.java:162)
! at org.jvnet.hk2.internal.ServiceLocatorImpl$3.compute(ServiceLocatorImpl.java:158)
! at org.glassfish.hk2.utilities.cache.Cache$OriginThreadAwareFuture$1.call(Cache.java:74)
! at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
! at org.glassfish.hk2.utilities.cache.Cache$OriginThreadAwareFuture.run(Cache.java:131)
! at org.glassfish.hk2.utilities.cache.Cache.compute(Cache.java:176)
! at org.jvnet.hk2.internal.ServiceLocatorImpl.resolveContext(ServiceLocatorImpl.java:2236)
! at org.jvnet.hk2.internal.Utilities.createService(Utilities.java:2087)
! ... 67 common frames omitted
! Causing: org.glassfish.hk2.api.MultiException: A MultiException has 2 exceptions.  They are:
! 1. java.lang.IllegalStateException: There is more than one active context for org.glassfish.jersey.process.internal.RequestScoped
! 2. java.lang.IllegalStateException: While attempting to create a service for SystemDescriptor(
! implementation=org.glassfish.jersey.inject.hk2.InstanceSupplierFactoryBridge
! contracts={org.glassfish.jersey.internal.util.collection.Ref}
! scope=org.glassfish.jersey.process.internal.RequestScoped
! qualifiers={}
! descriptorType=PROVIDE_METHOD
! descriptorVisibility=NORMAL
! metadata=
! rank=0
! loader=org.glassfish.hk2.utilities.binding.AbstractBinder$2@1cf624e9
! proxiable=null
! proxyForSameScope=null
! analysisName=null
! id=25
! locatorId=0
! identityHashCode=11895337
! reified=true) in scope org.glassfish.jersey.process.internal.RequestScoped an error occured while locating the context
! 
! at org.jvnet.hk2.internal.Utilities.createService(Utilities.java:2103)
! at org.jvnet.hk2.internal.ServiceLocatorImpl.internalGetService(ServiceLocatorImpl.java:769)
! at org.jvnet.hk2.internal.ServiceLocatorImpl.internalGetService(ServiceLocatorImpl.java:732)
! at org.jvnet.hk2.internal.ServiceLocatorImpl.getService(ServiceLocatorImpl.java:710)
! at org.glassfish.jersey.inject.hk2.AbstractHk2InjectionManager.getInstance(AbstractHk2InjectionManager.java:150)
! at org.glassfish.jersey.inject.hk2.ImmediateHk2InjectionManager.getInstance(ImmediateHk2InjectionManager.java:30)
! at io.dropwizard.auth.JettyAuthenticationUtil.setJettyAuthenticationIfPossible(JettyAuthenticationUtil.java:27)
! at io.dropwizard.auth.AuthFilter.authenticate(AuthFilter.java:175)
! at com.example.HeaderFilter.filter(HeaderFilter.kt:32)
! at org.glassfish.jersey.server.ContainerFilteringStage.apply(ContainerFilteringStage.java:108)
! at org.glassfish.jersey.server.ContainerFilteringStage.apply(ContainerFilteringStage.java:44)
! at org.glassfish.jersey.process.internal.Stages.process(Stages.java:173)
! at org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:248)
! at org.glassfish.jersey.internal.Errors$1.call(Errors.java:248)
! at org.glassfish.jersey.internal.Errors$1.call(Errors.java:244)
! at org.glassfish.jersey.internal.Errors.process(Errors.java:292)
! at org.glassfish.jersey.internal.Errors.process(Errors.java:274)
! at org.glassfish.jersey.internal.Errors.process(Errors.java:244)
! at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:265)
! at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:235)
! at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:684)
! at org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:394)
! at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:346)
! at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:358)
! at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:311)
! at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:205)
! at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:764)
! at org.eclipse.jetty.servlet.ServletHandler$ChainEnd.doFilter(ServletHandler.java:1665)
! at io.dropwizard.servlets.ThreadNameFilter.doFilter(ThreadNameFilter.java:36)
! at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:202)
! at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1635)
! at io.dropwizard.jersey.filter.AllowedMethodsFilter.handle(AllowedMethodsFilter.java:46)
! at io.dropwizard.jersey.filter.AllowedMethodsFilter.doFilter(AllowedMethodsFilter.java:40)
! at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:202)
! at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1635)
! at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:527)
! at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:221)
! at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1381)
! at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:176)
! at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:484)
! at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:174)
! at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1303)
! at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:129)
! at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:122)
! at io.dropwizard.metrics.jetty11.InstrumentedHandler.handle(InstrumentedHandler.java:310)
! at io.dropwizard.jetty.ContextRoutingHandler.handle(ContextRoutingHandler.java:37)
! at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:122)
! at org.eclipse.jetty.server.handler.gzip.GzipHandler.handle(GzipHandler.java:822)
! at io.dropwizard.jetty.ZipExceptionHandlingGzipHandler.handle(ZipExceptionHandlingGzipHandler.java:26)
! at org.eclipse.jetty.server.handler.RequestLogHandler.handle(RequestLogHandler.java:46)
! at org.eclipse.jetty.server.handler.StatisticsHandler.handle(StatisticsHandler.java:173)
! at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:122)
! at org.eclipse.jetty.server.Server.handle(Server.java:563)
! at org.eclipse.jetty.server.HttpChannel$RequestDispatchable.dispatch(HttpChannel.java:1598)
! at org.eclipse.jetty.server.HttpChannel.dispatch(HttpChannel.java:753)
! at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:501)
! at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:287)
! at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:314)
! at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:100)
! at org.eclipse.jetty.io.SelectableChannelEndPoint$1.run(SelectableChannelEndPoint.java:53)
! at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.runTask(AdaptiveExecutionStrategy.java:421)
! at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.consumeTask(AdaptiveExecutionStrategy.java:390)
! at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.tryProduce(AdaptiveExecutionStrategy.java:277)
! at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.produce(AdaptiveExecutionStrategy.java:193)
! at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:969)
! at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.doRunJob(QueuedThreadPool.java:1194)
! at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:1149)
! at java.base/java.lang.Thread.run(Thread.java:840)
@zUniQueX
Copy link
Member

Hi @count-emmolgus. Thanks for reporting this!

After some debugging your problem seems to be caused by the different 'injection type'. All of our docs and tests regarding dropwizard-auth use an AuthFilter object in the AuthDynamicFeature, while you are using an AuthFilter class in your test. Jersey differentiates between these two modes of injection and handles them differently. When explicitly constructing the HeaderFilter and using it as an object, the test in your linked repository passes.

However, this doesn't seem to be an issue for resource classes. When changing the signature of helloWorld2 to

fun helloWorld2(@Context ref: Ref<HttpServletRequest>): String

the request ref gets injected just fine although you're registering the resource as a class.

Having that said, I'm not sure where the issue is caused from. I'll need some further investigation on this topic and maybe raise a Jersey issue for this.

@zUniQueX zUniQueX added the bug label Mar 20, 2024
@count-emmolgus
Copy link
Author

Hi @zUniQueX, thanks for looking into this.

For now being able to declare the filter as an object should work, since we'd be able to declare the injection on a per-field bases rather than in the constructor (even if we prefer using the constructor).

Another caveat that I forgot to mention that I find even more strange is that if you don't wrap the filter in the AuthDynamicFeature but rather register as it is, then the injections seems to be occurring as they should.
(Though then the filter is applied even in the resources not having the security annotation, as expected...)

Ergo changing:
register(AuthDynamicFeature(headerFilter))
to
register(headerFilter)

That was the initial thing that made me suspect a Dropwizard issue, since that class is a Dropwizard class.

@zUniQueX
Copy link
Member

@count-emmolgus After further investigation I've just filed a Jersey issue for this case because I could reproduce the behavior without any dropwizard-related classes. So I'll mark this issue as blocked for now.

@zUniQueX zUniQueX added blocked and removed blocked labels Apr 20, 2024
@zUniQueX
Copy link
Member

@count-emmolgus The issue is fixed in Jersey, so we'll just have to wait for the next release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants