zyro23 / grails-spring-websocket

93 stars 28 forks source link

App wont run after trying to implement spring-security over websockets #64

Closed daptordarattler closed 6 years ago

daptordarattler commented 6 years ago

So i was looking at the sample to implement spring security over websockets, and I run into this problem

java.lang.IllegalArgumentException: Class name [org.grails.spring.aop.autoproxy.GroovyAwareInfrastructureAdvisorAutoProxyCreator] is not a known auto-proxy creator class
        at org.springframework.aop.config.AopConfigUtils.findPriorityForClass(AopConfigUtils.java:140)
        at org.springframework.aop.config.AopConfigUtils.registerOrEscalateApcAsRequired(AopConfigUtils.java:113)
        at org.springframework.aop.config.AopConfigUtils.registerAutoProxyCreatorIfNecessary(AopConfigUtils.java:74)
        at org.springframework.aop.config.AopConfigUtils.registerAutoProxyCreatorIfNecessary(AopConfigUtils.java:70)
        at org.springframework.context.annotation.AutoProxyRegistrar.registerBeanDefinitions(AutoProxyRegistrar.java:72)
        at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsFromRegistrars(ConfigurationClassBeanDefinitionReader.java:354)
        at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsForConfigurationClass(ConfigurationClassBeanDefinitionReader.java:143)
        at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitions(ConfigurationClassBeanDefinitionReader.java:116)
        at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:320)
        at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:228)
        at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:118)
        at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:687)
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:525)
        at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122)
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693)
        at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:303)
        at grails.boot.GrailsApp.run(GrailsApp.groovy:83)
        at grails.boot.GrailsApp.run(GrailsApp.groovy:387)
        at grails.boot.GrailsApp.run(GrailsApp.groovy:374)
        at grails.boot.GrailsApp$run.call(Unknown Source)
        at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:133)
        at com.play521.Application.main(Application.groovy:8)

2018-04-21 09:35:46.006 ERROR --- [           main] o.s.b.f.s.DefaultListableBeanFactory     : Destroy method on bean with name 'grailsApplicationPostProcessor' threw an exception

java.lang.IllegalStateException: ApplicationEventMulticaster not initialized - call 'refresh' before multicasting events via the context: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@cf65451: startup date [Sat Apr 21 09:35:39 GMT 2018]; root of context hierarchy
        at org.springframework.context.support.AbstractApplicationContext.getApplicationEventMulticaster(AbstractApplicationContext.java:414)
        at org.springframework.context.support.ApplicationListenerDetector.postProcessBeforeDestruction(ApplicationListenerDetector.java:97)
        at org.springframework.beans.factory.support.DisposableBeanAdapter.destroy(DisposableBeanAdapter.java:253)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroyBean(DefaultSingletonBeanRegistry.java:578)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroySingleton(DefaultSingletonBeanRegistry.java:554)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.destroySingleton(DefaultListableBeanFactory.java:961)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroySingletons(DefaultSingletonBeanRegistry.java:523)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.destroySingletons(DefaultListableBeanFactory.java:968)
        at org.springframework.context.support.AbstractApplicationContext.destroyBeans(AbstractApplicationContext.java:1030)
        at org.springframework.context.support.AbstractApplicationContext.doClose(AbstractApplicationContext.java:1006)
        at org.springframework.context.support.AbstractApplicationContext.close(AbstractApplicationContext.java:958)
        at org.springframework.boot.SpringApplication.handleRunFailure(SpringApplication.java:750)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:314)
        at grails.boot.GrailsApp.run(GrailsApp.groovy:83)
        at grails.boot.GrailsApp.run(GrailsApp.groovy:387)
        at grails.boot.GrailsApp.run(GrailsApp.groovy:374)
        at grails.boot.GrailsApp$run.call(Unknown Source)
        at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:133)
        at com.play521.Application.main(Application.groovy:8)

2018-04-21 09:35:46.006 ERROR --- [           main] o.s.b.f.s.DefaultListableBeanFactory     : Destroy method on bean with name 'org.springframework.boot.autoconfigure.internalCachingMetadataReaderFactory' threw an exception

java.lang.IllegalStateException: ApplicationEventMulticaster not initialized - call 'refresh' before multicasting events via the context: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@cf65451: startup date [Sat Apr 21 09:35:39 GMT 2018]; root of context hierarchy
        at org.springframework.context.support.AbstractApplicationContext.getApplicationEventMulticaster(AbstractApplicationContext.java:414)
        at org.springframework.context.support.ApplicationListenerDetector.postProcessBeforeDestruction(ApplicationListenerDetector.java:97)
        at org.springframework.beans.factory.support.DisposableBeanAdapter.destroy(DisposableBeanAdapter.java:253)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroyBean(DefaultSingletonBeanRegistry.java:578)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroySingleton(DefaultSingletonBeanRegistry.java:554)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.destroySingleton(DefaultListableBeanFactory.java:961)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroySingletons(DefaultSingletonBeanRegistry.java:523)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.destroySingletons(DefaultListableBeanFactory.java:968)
        at org.springframework.context.support.AbstractApplicationContext.destroyBeans(AbstractApplicationContext.java:1030)
        at org.springframework.context.support.AbstractApplicationContext.doClose(AbstractApplicationContext.java:1006)
        at org.springframework.context.support.AbstractApplicationContext.close(AbstractApplicationContext.java:958)
        at org.springframework.boot.SpringApplication.handleRunFailure(SpringApplication.java:750)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:314)
        at grails.boot.GrailsApp.run(GrailsApp.groovy:83)
        at grails.boot.GrailsApp.run(GrailsApp.groovy:387)
        at grails.boot.GrailsApp.run(GrailsApp.groovy:374)
        at grails.boot.GrailsApp$run.call(Unknown Source)
        at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:133)
        at com.play521.Application.main(Application.groovy:8)

Also added these to my dependency to try to solve the problem:


    compile "org.springframework.security:spring-security-config:5.0.4.RELEASE"
    compile "org.springframework.security:spring-security-messaging:5.0.4.RELEASE"
    compile "org.springframework.security:spring-security-web:5.0.4.RELEASE"

instead of this:

dependencies {
    compile "org.springframework.security:spring-security-config:5.0.3.RELEASE"
    compile "org.springframework.security:spring-security-messaging:5.0.3.RELEASE"
    compile "org.springframework.security:spring-security-web:5.0.3.RELEASE"
}

And customized my WebSecurityConfig a bit like this:

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
@EnableWebSecurity
class WebSecurityConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer {

    @Override
    void configureInbound(MessageSecurityMetadataSourceRegistry messages) {
        messages
                .nullDestMatcher().authenticated()
                .simpSubscribeDestMatchers("/user/queue/errors").permitAll()
                .simpDestMatchers("/app/**").permitAll()
//                .simpDestMatchers("/app/**").hasRole("permitAll")
                .simpSubscribeDestMatchers("/user/**", "/topic/**").permitAll()
//                .simpSubscribeDestMatchers("/user/**", "/topic/**").hasRole("permitAll")
                .simpTypeMatchers(SimpMessageType.MESSAGE, SimpMessageType.SUBSCRIBE).denyAll()
                .anyMessage().denyAll()
    }

}

I am very sure the problem is from the spring-security-config, message, & web dependencies. Because when I take them out and remove the config class, everything works fine again. here are my env details

grailsVersion=3.3.1
gormVersion=6.1.7.RELEASE
gradleWrapperVersion=3.5

ubuntu 17.10
openjdk version "1.8.0_151"

Let me know if you need more details to help me resolve this problem. thanks in advance

zyro23 commented 6 years ago

please check the referenced sample app (csrf protection disabled to make it shorter).

seems like spring-security-5.x does not work ootb with grails-3.3.x (or rather spring-boot-1.5.x).

so please try using the spring security version the spring-boot bom defines (by removing the versions from the spring security dependencies).

while i was not able to reproduce your problem exactly, i got another exception with spring-security-5.x:

Error creating bean with name 'mvcContentNegotiationManager' defined in org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.web.accept.ContentNegotiationManager]: Factory method 'mvcContentNegotiationManager' threw exception; nested exception is java.lang.AbstractMethodError: org.springframework.security.config.annotation.web.configuration.WebMvcSecurityConfiguration.configureContentNegotiation(Lorg/springframework/web/servlet/config/annotation/ContentNegotiationConfigurer;)

readme updated accordingly on master.

daptordarattler commented 6 years ago

Update: Got it working by checking the spring-security-core version to be 4.2.4 and used that version for

compile 'org.grails.plugins:spring-security-core:3.2.1'
//    compile "org.springframework.security:spring-security-config:4.2.4.RELEASE"
    compile "org.springframework.security:spring-security-messaging:4.2.4.RELEASE"
    compile "org.springframework.security:spring-security-web:4.2.4.RELEASE"

NOTE: spring-security-config:4.2.4.RELEASE is commented out

But when I include it like this: compile "org.springframework.security:spring-security-config:4.2.4.RELEASE" I get the following error:

2018-04-23 11:47:15.322 ERROR --- [           main] o.s.b.d.LoggingFailureAnalysisReporter   : 

***************************
APPLICATION FAILED TO START
***************************

Description:

Method springSecurityFilterChain in org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration required a bean named 'mvcHandlerMappingIntrospector' that could not be found.

Action:

Consider defining a bean named 'mvcHandlerMappingIntrospector' in your configuration.

Trying to figure out what spring-security-config needs or how to get a bean called mvcHandlerMappingIntrospector

zyro23 commented 6 years ago

as the sample app i referenced works there has to be something going on with your setup, i think.

e.g. now i see you are using the spring-security-core grails plugin. the readme and the sample app do not. that changes a lot. ref #63, for example.

also, without spring-security-config, you will be missing important classes for websocket security configuration like AbstractSecurityWebSocketMessageBrokerConfigurer.

a sample app replicating your setup and reproducing your problem/exception/stacktrace would be helpful. everything else means playing a guessing game..

daptordarattler commented 6 years ago

Ok after referencing issue u mentioned. the application runs fine with the right spring-security-core dependencies:

compile 'org.grails.plugins:spring-security-core:3.2.1'           
compile "org.springframework.security:spring-security-config"     
compile "org.springframework.security:spring-security-messaging"  

But I am not able to bind my WebSecurityConfig.groovy file. It always gives an error

2018-04-23 12:21:05.702 ERROR --- [           main] o.s.boot.SpringApplication               : Application startup failed

java.lang.IllegalArgumentException: Class name [org.grails.spring.aop.autoproxy.GroovyAwareInfrastructureAdvisorAutoProxyCreator] is not a known auto-proxy creator class
        at org.springframework.aop.config.AopConfigUtils.findPriorityForClass(AopConfigUtils.java:140)
        at org.springframework.aop.config.AopConfigUtils.registerOrEscalateApcAsRequired(AopConfigUtils.java:113)
        at org.springframework.aop.config.AopConfigUtils.registerAutoProxyCreatorIfNecessary(AopConfigUtils.java:74)
        at org.springframework.aop.config.AopConfigUtils.registerAutoProxyCreatorIfNecessary(AopConfigUtils.java:70)
        at org.springframework.context.annotation.AutoProxyRegistrar.registerBeanDefinitions(AutoProxyRegistrar.java:72)
        at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsFromRegistrars(ConfigurationClassBeanDefinitionReader.java:354)
        at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsForConfigurationClass(ConfigurationClassBeanDefinitionReader.java:143)
        at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitions(ConfigurationClassBeanDefinitionReader.java:116)
        at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:320)
        at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:228)
        at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:118)
        at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:687)
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:525)
        at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122)
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693)
        at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:303)
        at grails.boot.GrailsApp.run(GrailsApp.groovy:83)
        at grails.boot.GrailsApp.run(GrailsApp.groovy:387)
        at grails.boot.GrailsApp.run(GrailsApp.groovy:374)
        at grails.boot.GrailsApp$run.call(Unknown Source)
        at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:133)
        at com.play521.Application.main(Application.groovy:12)

2018-04-23 12:21:05.710 ERROR --- [           main] o.s.b.f.s.DefaultListableBeanFactory     : Destroy method on bean with name 'grailsApplicationPostProcessor' threw an exception

java.lang.IllegalStateException: ApplicationEventMulticaster not initialized - call 'refresh' before multicasting events via the context: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@21694e53: startup date [Mon Apr 23 12:21:00 GMT 2018]; root of context hierarchy
        at org.springframework.context.support.AbstractApplicationContext.getApplicationEventMulticaster(AbstractApplicationContext.java:414)
        at org.springframework.context.support.ApplicationListenerDetector.postProcessBeforeDestruction(ApplicationListenerDetector.java:97)
        at org.springframework.beans.factory.support.DisposableBeanAdapter.destroy(DisposableBeanAdapter.java:253)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroyBean(DefaultSingletonBeanRegistry.java:578)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroySingleton(DefaultSingletonBeanRegistry.java:554)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.destroySingleton(DefaultListableBeanFactory.java:961)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroySingletons(DefaultSingletonBeanRegistry.java:523)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.destroySingletons(DefaultListableBeanFactory.java:968)
        at org.springframework.context.support.AbstractApplicationContext.destroyBeans(AbstractApplicationContext.java:1030)
        at org.springframework.context.support.AbstractApplicationContext.doClose(AbstractApplicationContext.java:1006)
        at org.springframework.context.support.AbstractApplicationContext.close(AbstractApplicationContext.java:958)
        at org.springframework.boot.SpringApplication.handleRunFailure(SpringApplication.java:750)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:314)
        at grails.boot.GrailsApp.run(GrailsApp.groovy:83)
        at grails.boot.GrailsApp.run(GrailsApp.groovy:387)
        at grails.boot.GrailsApp.run(GrailsApp.groovy:374)
        at grails.boot.GrailsApp$run.call(Unknown Source)
        at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:133)
        at com.play521.Application.main(Application.groovy:12)

2018-04-23 12:21:05.711 ERROR --- [           main] o.s.b.f.s.DefaultListableBeanFactory     : Destroy method on bean with name 'org.springframework.boot.autoconfigure.internalCachingMetadataReaderFactory' threw an exception

java.lang.IllegalStateException: ApplicationEventMulticaster not initialized - call 'refresh' before multicasting events via the context: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@21694e53: startup date [Mon Apr 23 12:21:00 GMT 2018]; root of context hierarchy
        at org.springframework.context.support.AbstractApplicationContext.getApplicationEventMulticaster(AbstractApplicationContext.java:414)
        at org.springframework.context.support.ApplicationListenerDetector.postProcessBeforeDestruction(ApplicationListenerDetector.java:97)
        at org.springframework.beans.factory.support.DisposableBeanAdapter.destroy(DisposableBeanAdapter.java:253)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroyBean(DefaultSingletonBeanRegistry.java:578)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroySingleton(DefaultSingletonBeanRegistry.java:554)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.destroySingleton(DefaultListableBeanFactory.java:961)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroySingletons(DefaultSingletonBeanRegistry.java:523)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.destroySingletons(DefaultListableBeanFactory.java:968)
        at org.springframework.context.support.AbstractApplicationContext.destroyBeans(AbstractApplicationContext.java:1030)
        at org.springframework.context.support.AbstractApplicationContext.doClose(AbstractApplicationContext.java:1006)
        at org.springframework.context.support.AbstractApplicationContext.close(AbstractApplicationContext.java:958)
        at org.springframework.boot.SpringApplication.handleRunFailure(SpringApplication.java:750)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:314)
        at grails.boot.GrailsApp.run(GrailsApp.groovy:83)
        at grails.boot.GrailsApp.run(GrailsApp.groovy:387)
        at grails.boot.GrailsApp.run(GrailsApp.groovy:374)
        at grails.boot.GrailsApp$run.call(Unknown Source)
        at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:133)
        at com.play521.Application.main(Application.groovy:12)

And you keep mentioning a sample app, but I dont see it anywhere in the README.md, unless your talking about the sample code show in README.md, and currently I have not customized anything, yet I am still having the error

zyro23 commented 6 years ago

i am talking about this comment https://github.com/zyro23/grails-spring-websocket/issues/64#issuecomment-383291099 referencing this sample app for your issue: https://github.com/zyro23/grails-spring-websocket-issue-64/commit/760eeca6b8dcc2caf8c071f722fee2e6b9deb277

now i added a second branch spring-security-core-plugin that shows all is fine with the plugin being used, too... https://github.com/zyro23/grails-spring-websocket-issue-64/commit/f2e71685c8fd6d8f2c8e7a144a82f397f23c4ccb

daptordarattler commented 6 years ago

OK. Thanks for the sample application and feedback. I was able to get the application running, by doing it the way its defined in your sample. The problem is that, anytime I updated the WebSocketSecurityConfig, i would go and autowire it in the resources.groovy file like this:

import com.myapp.WebSocketSecurityConfig

// Place your Spring DSL code here
beans = {
    webSocketSecurityConfig(WebSocketSecurityConfig)
}

After getting rid of that line, the app runs fine.

However, endpoints access is not working as I would expect. For example, I have permitAll set on the /stomps/ in static rules `[pattern: '/stomp/', access: ['permitAll']]` but yet when I run the app, after connection is successfull, all the endpoints are not able to subscribe to any channels. This is the structure of my WebSocketSecurityConfig configureInbound method:

 @Override
    void configureInbound(MessageSecurityMetadataSourceRegistry messages) {
        println "Testing websocket filters"
        messages
                .nullDestMatcher().authenticated()
                .simpSubscribeDestMatchers("/user/queue/errors").permitAll()
                .simpDestMatchers("/app/**").permitAll()
                .simpDestMatchers("/bet/**").permitAll()
                .simpSubscribeDestMatchers("/user/**", "/topic/**").permitAll()
                .simpTypeMatchers(SimpMessageType.MESSAGE, SimpMessageType.SUBSCRIBE).permitAll()
                .anyMessage().permitAll()
    }

I get the feeling this is happening because the WebSocketSecurityConfig is not wired properly. Also I in your example, a user account is required to access the route, hence once logged in, there are no errors. It should be possible to permitAll on the stomp routes for testing or on certain channel subscription endpoints , right?

Thanks again, and hoping to get your feedback soon.

zyro23 commented 6 years ago

please provide a sample app reproducing the problem. i will take a look.

daptordarattler commented 6 years ago

Thanks, figured it out. Seems the security configuration inside the application.groovy does not affect the websocket endpoints and can only be controlled by the WebSocketSecurityConfig.groovy file. Hence After probing, I saw that I only had to update the configureInbound method like this to get it working:

@Override
    void configureInbound(MessageSecurityMetadataSourceRegistry messages) {
        println "Testing websocket filters"
        messages
                .nullDestMatcher().anonymous()
                .simpSubscribeDestMatchers("/user/queue/errors").permitAll()
                .simpDestMatchers("/app/**").permitAll()
                .simpDestMatchers("/bet/**").permitAll()
                .simpSubscribeDestMatchers("/user/**", "/topic/**").permitAll()
                .simpTypeMatchers(SimpMessageType.MESSAGE, SimpMessageType.SUBSCRIBE).denyAll()
                .anyMessage().denyAll()
    }

Then for specific roles the following works:

@Override
    void configureInbound(MessageSecurityMetadataSourceRegistry messages) {
        println "Testing websocket filters"
        messages
                .nullDestMatcher().anonymous()
                .simpSubscribeDestMatchers("/user/queue/errors").permitAll()
                .simpDestMatchers("/app/**").hasRole("USER")
                .simpDestMatchers("/bet/**").hasRole("USER")
                .simpSubscribeDestMatchers("/user/**", "/topic/**").hasRole("USER")
                .simpTypeMatchers(SimpMessageType.MESSAGE, SimpMessageType.SUBSCRIBE).denyAll()
                .anyMessage().denyAll()
    }

The key is in the line that checks for .nullDestMatcher().anonymous() where for all authenticated endpoints it should be .nullDestMatcher().authenticated()

Thanks for the back and forth. Appreciated

zyro23 commented 6 years ago

just for the sake of completeness, the security config in application.groovy (i.e. spring security web) does work. it secures the initial http request to /stomp/**.

now you changed the messaging security config from .nullDestMatcher().authenticated() to .nullDestMatcher().anonymous(). that configures the policy for the initial stomp messages (CONNECT or STOMP frames). as long as you have unauthenticated users which should be able to connect to the stomp broker, that has to be allowed (maybe permitAll should be preferred as that will work for anonymous as well as logged-in users).

glad you figured it out.