1

I have implemented togglz into my spring boot application. I can even access the Togglz console, and I have tested the restrictions with the FeatureManager. However, if I go to the togglz console and try to change the activation strategy or enable/disable a feature, I get a 403 Forbidden error page.

In other words, I can access /togglz/index but I cannot access/call /togglz/edit

In my WebMvcConfigurer class:

@Bean
public FilterRegistrationBean<TogglzFilter> togglzRegistration() {
    FilterRegistrationBean<TogglzFilter> reg = new FilterRegistrationBean<>();
    reg.setFilter(new TogglzFilter());
    reg.addUrlPatterns("/*");
    reg.setName("TogglzFilter");
    return reg;
}

@Bean
public ServletRegistrationBean<TogglzConsoleServlet> togglzConsoleServlet() {
    ServletRegistrationBean<TogglzConsoleServlet> reg = new ServletRegistrationBean<>();
    reg.setServlet(new TogglzConsoleServlet());
    reg.setName("TogglzConsoleServlet");
    reg.addUrlMappings("/togglz/*");
    return reg;
}

In my TogglzConfiguration:

@Component
public class TogglzConfiguration implements TogglzConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(TogglzConfiguration.class);

@Autowired
private ResourceLoader resourceLoader;

@Override
public Class<? extends Feature> getFeatureClass() {
    return Features.class;
}

@Override
public StateRepository getStateRepository() {
    try {
        return new FileBasedStateRepository(
                resourceLoader.getResource("classpath:/togglz.properties").getFile()
                );
    } catch (IOException ex) {
        LOGGER.error(ex.getMessage(),ex);
        throw new RuntimeException(ex);
    }

}

@Override
public UserProvider getUserProvider() {

    return new UserProvider() {
        @Override
        public FeatureUser getCurrentUser() {
                return new SimpleFeatureUser("admin", true);
        }
    };
}


}

My Features class:

public enum Features implements Feature {

@Label("Inventory Initiation")
@TestingUI
TESTING_UI_INITIATE_INVENTORY,

@Label("Random Warehouse Creation")
@TestingUI
TESTING_UI_CREATE_WAREHOUSE
;


public boolean isActive() {
    return FeatureContext.getFeatureManager().isActive(this);
}

}
eancu
  • 53
  • 9
  • The Togglz Console supports CSRF tokens provided by Spring Security and friends. I could imagine that this causes some issues for you. See: https://github.com/togglz/togglz/blob/master/console/src/main/java/org/togglz/console/handlers/edit/EditPageHandler.java#L94-L100 – chkal Jul 28 '18 at 07:06
  • So I guess this could happen if you have some CSRF protection in place which isn't integrated with Togglz... – chkal Jul 28 '18 at 07:11
  • indeed we do! it would explain a lot as to why the console is accessible but the edit request (if it is REST or whatever) does not trigger. do you have any examples or documentation for implementation with togglz? thank you for the response, it means a lot – eancu Jul 30 '18 at 05:51
  • Sorry for the delay. See my answer below. – chkal Aug 04 '18 at 06:53

4 Answers4

1

It looks like you are using some kind of CSRF protection in your application. At least this would explain why only POST requests are broken.

The Togglz Console provides an SPI for obtaining CSRF token that need to be embedded in forms:

https://github.com/togglz/togglz/blob/master/servlet/src/main/java/org/togglz/servlet/spi/CSRFTokenProvider.java

Togglz ships with support for Spring Security CSRF protection:

https://github.com/togglz/togglz/blob/master/spring-security/src/main/java/org/togglz/spring/security/SpringSecurityTokenProvider.java

Togglz is using the JDK's ServiceLoader facility to find providers. So in case of Spring Security there is simply a file referencing the implementation class:

https://github.com/togglz/togglz/blob/master/spring-security/src/main/resources/META-INF/services/org.togglz.servlet.spi.CSRFTokenProvider

So if you want to integrate some 3rd party CSRF protection framework with Togglz, you have to:

  • Implement CSRFTokenProvider
  • Add a file META-INF/services/org.togglz.servlet.spi.CSRFTokenProvider to your classpath and add the fully qualified class name of the implementation class to it.
chkal
  • 5,598
  • 21
  • 26
  • I had csrf turned on by spring security and had the same problem. I needed just to add the dependency `org.togglz:togglz-spring-security` and that helped. – Roman T May 24 '19 at 11:59
0

Which configuration do you have in application.yml for togglz? Most likely you're missing secure: false there:

togglz:
  enabled: true
  console:
    enabled: true
    secured: false
  • no, it doesn't change anything. I should note that the url that is causing me the 403 is not /togglz/index but /togglz/edit – eancu Jul 27 '18 at 01:11
  • You're not using togglz spring boot starter, that's why the configuratiom is not working. I highly recommend you use togglz-spring-boot-starter instead: https://www.togglz.org/documentation/spring-boot-starter.html – Rui Figueira Jul 27 '18 at 08:01
  • you're right, i am not. but it's because togglz-spring-boot-starter is dependent on the spring security class and my service does not use spring security but OAuth2 for single sign on across all services – eancu Jul 27 '18 at 08:45
  • hold on, the SpringSecurityUserProvider class is a togglz class, I will look into implementing this if possible however, the module is @ConditionalOnMissingClass org.springframework.security.config.annotation.web.configuration.EnableWebSecurity which I have – eancu Jul 27 '18 at 08:52
0

Same here. Since I'm a newbie in Java and Spring so I stuck when tried to implement CSRFTokenProvider from @chkal solution.

So I hit the Togglz API to enable/disable a feature. Both return 200 OK with HTML content (similar with index page from togglz console).

Enable

curl --location --request POST '{host}/{context_path}/togglz-console/edit?f=FEATURE_ONE&enabled=enabled'

Disable

curl --location --request POST '{host}/{context_path}/togglz-console/edit?f=FEATURE_ONE'

application.yml

...

togglz:
  console:
    enabled: true
    path: /togglz-console
    secured: false
    use-management-port: false
  features:
    FEATURE_ONE:
      enabled: true

build.gradle

...

  implementation "org.togglz:togglz-spring-boot-starter:2.6.1.Final"
  implementation "org.togglz:togglz-console:2.6.1.Final"
  implementation "org.togglz:togglz-spring-security:2.6.1.Final"

Note: This is not answering the question above but can be an alternative

Update: I was experience this because my InputStream has been read (by a filter bean) and only read once

Tri Asmoro
  • 51
  • 7
0

I have disabled the csrf protection in togglz via properties file:

togglz.console.validate-c-s-r-f-token=false

If you use yaml instead of properties files, the file should look like this:

...
togglz:
  console:
    validate-c-s-r-f-token: false

You should note, that disabling the csrf token validation is not recommended, because it will degrade the security of your application.

wulfovitch
  • 3,216
  • 2
  • 24
  • 15