micronaut-projects / micronaut-security

The official Micronaut security solution
Apache License 2.0
170 stars 126 forks source link

HTTP Client Filter for Client Credentials does not work for 'Function Application for Serverless' #1828

Open mattplanchant-sage opened 2 days ago

mattplanchant-sage commented 2 days ago

Expected Behavior

'Function Application for Serverless' app, generated via Micronaut Launch is configured as per the documentation (https://micronaut-projects.github.io/micronaut-security/latest/guide/#clientecredentialshttpclient) to automatically add an Authorization header to outgoing requests.

application.yml contains:

  security:
    enabled: true
    filter:
      enabled: false

Expecting to have Authorization header to outgoing requests.

Actual Behaviour

Seeing the following exception when I try to run a test using @MicronautLambdaTest:

Bean definition [io.micronaut.security.oauth2.routes.DefaultOauthController] could not be loaded: Failed to initialize the bean [class io.micronaut.security.oauth2.routes.DefaultOauthController]: io/micronaut/http/server/util/HttpHostResolver
io.micronaut.context.exceptions.BeanInstantiationException: Bean definition [io.micronaut.security.oauth2.routes.DefaultOauthController] could not be loaded: Failed to initialize the bean [class io.micronaut.security.oauth2.routes.DefaultOauthController]: io/micronaut/http/server/util/HttpHostResolver
    at io.micronaut.context.DefaultBeanContext.initializeContext(DefaultBeanContext.java:1983)
    at io.micronaut.context.DefaultApplicationContext.initializeContext(DefaultApplicationContext.java:307)
    at io.micronaut.context.DefaultBeanContext.configureAndStartContext(DefaultBeanContext.java:3314)
    at io.micronaut.context.DefaultBeanContext.start(DefaultBeanContext.java:345)
    at io.micronaut.context.DefaultApplicationContext.start(DefaultApplicationContext.java:215)

If I change the Gradle plugin from io.micronaut.library to io.micronaut.application then no exception and the header is added as expected.

Steps To Reproduce

No response

Environment Information

No response

Example Application

No response

Version

4.6.3

mattplanchant-sage commented 1 day ago

This isn't related to client credentials, it seems to be an issue with projects generated from Micronaut Launch which include aws-lambda, security-jwt and security-oauth2 along with the io.micronaut.library Gradle plugin.

Sample project here https://github.com/mplanchant/demo-gradle-lib-security/

The following error when running the generated test:

10:31:49.687 [Test worker] INFO  i.m.c.DefaultApplicationContext$RuntimeConfiguredEnvironment - Established active environments: [function, lambda]
10:31:49.765 [Test worker] ERROR i.m.f.aws.MicronautRequestHandler - Exception initializing handler
io.micronaut.context.exceptions.BeanInstantiationException: Bean definition [io.micronaut.security.oauth2.routes.DefaultOauthController] could not be loaded: Failed to initialize the bean [class io.micronaut.security.oauth2.routes.DefaultOauthController]: io/micronaut/http/server/util/HttpHostResolver
    at io.micronaut.context.DefaultBeanContext.initializeContext(DefaultBeanContext.java:1983)
    at io.micronaut.context.DefaultApplicationContext.initializeContext(DefaultApplicationContext.java:307)
    at io.micronaut.context.DefaultBeanContext.configureAndStartContext(DefaultBeanContext.java:3314)
    at io.micronaut.context.DefaultBeanContext.start(DefaultBeanContext.java:345)
    at io.micronaut.context.DefaultApplicationContext.start(DefaultApplicationContext.java:215)
    at io.micronaut.function.executor.AbstractExecutor.startEnvironment(AbstractExecutor.java:123)
    at io.micronaut.function.aws.MicronautRequestHandler.buildApplicationContext(MicronautRequestHandler.java:140)
    at io.micronaut.function.aws.MicronautRequestHandler.<init>(MicronautRequestHandler.java:67)
    at com.example.FunctionRequestHandler.<init>(FunctionRequestHandler.java:10)
    at com.example.FunctionRequestHandlerTest.setupServer(FunctionRequestHandlerTest.java:16)
    at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
    at java.base/java.lang.reflect.Method.invoke(Method.java:580)
    at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:766)
    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.interceptLifecycleMethod(TimeoutExtension.java:128)
    at org.junit.jupiter.engine.extension.TimeoutExtension.interceptBeforeAllMethod(TimeoutExtension.java:70)
    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.ClassBasedTestDescriptor.lambda$invokeBeforeAllMethods$14(ClassBasedTestDescriptor.java:412)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.invokeBeforeAllMethods(ClassBasedTestDescriptor.java:410)
    at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.before(ClassBasedTestDescriptor.java:216)
    at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.before(ClassBasedTestDescriptor.java:85)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:148)
    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)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
    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)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:198)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:169)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:93)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:58)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:141)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:57)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:103)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:85)
    at org.junit.platform.launcher.core.DelegatingLauncher.execute(DelegatingLauncher.java:47)
    at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.processAllTestClasses(JUnitPlatformTestClassProcessor.java:119)
    at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.access$000(JUnitPlatformTestClassProcessor.java:94)
    at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.stop(JUnitPlatformTestClassProcessor.java:89)
    at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:62)
    at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
    at java.base/java.lang.reflect.Method.invoke(Method.java:580)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
    at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
    at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
    at jdk.proxy1/jdk.proxy1.$Proxy2.stop(Unknown Source)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker$3.run(TestWorker.java:193)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:129)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:100)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:60)
    at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
    at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:119)
    at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:66)
    at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
    at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)
Caused by: io.micronaut.context.exceptions.BeanInstantiationException: Failed to initialize the bean [class io.micronaut.security.oauth2.routes.DefaultOauthController]: io/micronaut/http/server/util/HttpHostResolver
    at io.micronaut.context.AbstractInitializableBeanDefinitionAndReference.load(AbstractInitializableBeanDefinitionAndReference.java:131)
    at io.micronaut.context.DefaultBeanContext.loadEagerBeans(DefaultBeanContext.java:2669)
    at io.micronaut.context.DefaultBeanContext.initializeContext(DefaultBeanContext.java:1981)
    ... 80 common frames omitted
Caused by: java.lang.NoClassDefFoundError: io/micronaut/http/server/util/HttpHostResolver
    at io.micronaut.security.oauth2.routes.$DefaultOauthController$Definition.<clinit>(Unknown Source)
    at java.base/jdk.internal.misc.Unsafe.allocateInstance(Native Method)
    at java.base/java.lang.invoke.DirectMethodHandle.allocateInstance(DirectMethodHandle.java:501)
    at io.micronaut.core.io.service.SoftServiceLoader.lambda$collectDynamicServices$2(SoftServiceLoader.java:189)
    at io.micronaut.core.io.service.ServiceScanner$ServiceInstanceLoader.compute(ServiceScanner.java:402)
    at java.base/java.util.concurrent.RecursiveAction.exec(RecursiveAction.java:194)
    at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:387)
    at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1312)
    at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1843)
    at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1808)
    at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:188)
Caused by: java.lang.ClassNotFoundException: io.micronaut.http.server.util.HttpHostResolver
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
    at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:526)
    ... 11 common frames omitted
mattplanchant-sage commented 1 day ago

This seems to have been an issue since 4.6.0. The problem doesn't occur with 4.5.1.