Search code examples
javaspring-boottogglz

Togglz returns a 403 on feature toggle


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);
}

}

Solution

  • 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.