title: FF4J - Spring Boot - Custom Authorization Manager
body: <p>I am trying to create a standalone feature flag server (centrally managed feature flag micro-service) backed by spring boot starters provided by FF4J. I was able to get it up and running with the web-console and REST API as well. I am now trying to just add the support of custom authorization manager as provided in the wiki, but based on the sample provided there, I am unclear as to how the authorization manager would be aware of the user context when it gets accessed from a different microservice which is implementing the feature. Below I have provided all the relevant code snippets. If you notice in <code>CustomAuthorizationManager</code> class, I have a <code>currentUserThreadLocal</code> variable, not sure how or who is going to set that at run time for FF4J to verify the user's role. Any help on this is really appreciated, as I having issues understanding how this works.</p>
  
  <p>Also note, there is a <code>toJson</code> method in authorization manager that needs to be overridden, not sure what needs to go over there, any help with that is also appreciated.</p>
  
  <p><strong>Custom Authorization Manager</strong></p>
  
  <pre><code>public class CustomAuthorizationManager implements AuthorizationsManager {
  
      private static final Logger LOG = LoggerFactory.getLogger(FeatureFlagServerFeignTimeoutProperties.class);
      private ThreadLocal&lt;String&gt; currentUserThreadLocal = new ThreadLocal&lt;String&gt;();
      private List&lt;UserRoleBean&gt; userRoles;
  
      @Autowired
      private SecurityServiceFeignClient securityServiceFeignClient;
  
      @PostConstruct
      public void init() {
          try {
              userRoles = securityServiceFeignClient.fetchAllUserRoles();
          } catch (Exception ex) {
              LOG.error("Error while loading user roles", ex);
              userRoles = new ArrayList&lt;&gt;();
          }
      }
  
      @Override
      public String getCurrentUserName() {
          return currentUserThreadLocal.get();
      }
  
      @Override
      public Set&lt;String&gt; getCurrentUserPermissions() {
          String currentUser = getCurrentUserName();
  
          Set&lt;String&gt; roles = new HashSet&lt;&gt;();
          if (userRoles.size() != 0) {
              roles = userRoles.stream().filter(userRole -&gt; userRole.getUserLogin().equals(currentUser))
                      .map(userRole -&gt; userRole.getRoleName()).collect(Collectors.toSet());
          } else {
              LOG.warn(
                      "No user roles available, check startup logs to check possible errors during loading of user roles, returning empty");
          }
  
          return roles;
      }
  
      @Override
      public Set&lt;String&gt; listAllPermissions() {
          Set&lt;String&gt; roles = new HashSet&lt;&gt;();
          if (userRoles.size() != 0) {
              roles = userRoles.stream().map(userRole -&gt; userRole.getRoleName()).collect(Collectors.toSet());
          } else {
              LOG.warn(
                      "No user roles available, check startup logs to check possible errors during loading of user roles, returning empty");
          }
          return roles;
      }
  
      @Override
      public String toJson() {
          return null;
      }
  
  }
  </code></pre>
  
  <p><strong>FF4J config</strong></p>
  
  <pre><code>@Configuration
  @ConditionalOnClass({ ConsoleServlet.class, FF4jDispatcherServlet.class })
  public class Ff4jConfig extends SpringBootServletInitializer {
  
      @Autowired
      private DataSource dataSource;
  
      @Bean
      public ServletRegistrationBean&lt;FF4jDispatcherServlet&gt; ff4jDispatcherServletRegistrationBean(
              FF4jDispatcherServlet ff4jDispatcherServlet) {
          ServletRegistrationBean&lt;FF4jDispatcherServlet&gt; bean = new ServletRegistrationBean&lt;FF4jDispatcherServlet&gt;(
                  ff4jDispatcherServlet, "/feature-web-console/*");
          bean.setName("ff4j-console");
          bean.setLoadOnStartup(1);
          return bean;
      }
  
      @Bean
      @ConditionalOnMissingBean
      public FF4jDispatcherServlet getFF4jDispatcherServlet() {
          FF4jDispatcherServlet ff4jConsoleServlet = new FF4jDispatcherServlet();
          ff4jConsoleServlet.setFf4j(getFF4j());
          return ff4jConsoleServlet;
      }
  
      @Bean
      public FF4j getFF4j() {
          FF4j ff4j = new FF4j();
          ff4j.setFeatureStore(new FeatureStoreSpringJdbc(dataSource));
          ff4j.setPropertiesStore(new PropertyStoreSpringJdbc(dataSource));
          ff4j.setEventRepository(new EventRepositorySpringJdbc(dataSource));
  
          // Set authorization
          CustomAuthorizationManager custAuthorizationManager = new CustomAuthorizationManager();
          ff4j.setAuthorizationsManager(custAuthorizationManager);
  
          // Enable audit mode
          ff4j.audit(true);
  
          return ff4j;
      }
  
  }
  </code></pre>
  
  <p><strong>pom.xml</strong></p>
  
  <pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
  &lt;project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"&gt;
      &lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;
  
      &lt;groupId&gt;com.example&lt;/groupId&gt;
      &lt;artifactId&gt;feature-flag-server&lt;/artifactId&gt;
      &lt;version&gt;1.0.0-SNAPSHOT&lt;/version&gt;
      &lt;name&gt;feature-flag-server&lt;/name&gt;
  
      &lt;parent&gt;
          &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
          &lt;artifactId&gt;spring-boot-starter-parent&lt;/artifactId&gt;
          &lt;version&gt;2.2.1.RELEASE&lt;/version&gt;
      &lt;/parent&gt;
  
      &lt;properties&gt;
          &lt;java.version&gt;1.8&lt;/java.version&gt;
          &lt;spring-cloud.version&gt;Hoxton.RC2&lt;/spring-cloud.version&gt;
          &lt;ff4j.version&gt;1.8.2&lt;/ff4j.version&gt;
      &lt;/properties&gt;
  
      &lt;dependencyManagement&gt;
          &lt;dependencies&gt;
              &lt;dependency&gt;
                  &lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;
                  &lt;artifactId&gt;spring-cloud-dependencies&lt;/artifactId&gt;
                  &lt;version&gt;${spring-cloud.version}&lt;/version&gt;
                  &lt;type&gt;pom&lt;/type&gt;
                  &lt;scope&gt;import&lt;/scope&gt;
              &lt;/dependency&gt;
          &lt;/dependencies&gt;
      &lt;/dependencyManagement&gt;
  
      &lt;dependencies&gt;
          &lt;dependency&gt;
              &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
              &lt;artifactId&gt;spring-boot-starter-data-jdbc&lt;/artifactId&gt;
          &lt;/dependency&gt;
  
          &lt;dependency&gt;
              &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
              &lt;artifactId&gt;spring-boot-starter-web&lt;/artifactId&gt;
          &lt;/dependency&gt;
  
          &lt;dependency&gt;
              &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
              &lt;artifactId&gt;spring-boot-starter-actuator&lt;/artifactId&gt;
          &lt;/dependency&gt;
  
          &lt;dependency&gt;
              &lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;
              &lt;artifactId&gt;spring-cloud-starter-config&lt;/artifactId&gt;
          &lt;/dependency&gt;
  
          &lt;dependency&gt;
              &lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;
              &lt;artifactId&gt;spring-cloud-starter-netflix-eureka-client&lt;/artifactId&gt;
              &lt;exclusions&gt;
                  &lt;!-- resolve swagger dependency issue - start --&gt;
                  &lt;exclusion&gt;
                      &lt;groupId&gt;com.google.guava&lt;/groupId&gt;
                      &lt;artifactId&gt;guava&lt;/artifactId&gt;
                  &lt;/exclusion&gt;
                  &lt;!-- resolve swagger dependency issue - end --&gt;
              &lt;/exclusions&gt;
          &lt;/dependency&gt;
  
          &lt;dependency&gt;
              &lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;
              &lt;artifactId&gt;spring-cloud-starter-openfeign&lt;/artifactId&gt;
          &lt;/dependency&gt;
  
          &lt;dependency&gt;
              &lt;groupId&gt;mysql&lt;/groupId&gt;
              &lt;artifactId&gt;mysql-connector-java&lt;/artifactId&gt;
              &lt;scope&gt;runtime&lt;/scope&gt;
          &lt;/dependency&gt;
  
          &lt;dependency&gt;
              &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
              &lt;artifactId&gt;spring-boot-starter-test&lt;/artifactId&gt;
              &lt;scope&gt;test&lt;/scope&gt;
              &lt;exclusions&gt;
                  &lt;exclusion&gt;
                      &lt;groupId&gt;org.junit.vintage&lt;/groupId&gt;
                      &lt;artifactId&gt;junit-vintage-engine&lt;/artifactId&gt;
                  &lt;/exclusion&gt;
              &lt;/exclusions&gt;
          &lt;/dependency&gt;
  
          &lt;!-- FF4J dependencies - start --&gt;
          &lt;dependency&gt;
              &lt;groupId&gt;org.ff4j&lt;/groupId&gt;
              &lt;artifactId&gt;ff4j-spring-boot-starter&lt;/artifactId&gt;
              &lt;version&gt;${ff4j.version}&lt;/version&gt;
          &lt;/dependency&gt;
  
          &lt;dependency&gt;
              &lt;groupId&gt;org.ff4j&lt;/groupId&gt;
              &lt;artifactId&gt;ff4j-store-springjdbc&lt;/artifactId&gt;
              &lt;version&gt;${ff4j.version}&lt;/version&gt;
          &lt;/dependency&gt;
  
          &lt;dependency&gt;
              &lt;groupId&gt;org.ff4j&lt;/groupId&gt;
              &lt;artifactId&gt;ff4j-web&lt;/artifactId&gt;
              &lt;version&gt;${ff4j.version}&lt;/version&gt;
          &lt;/dependency&gt;
          &lt;!-- FF4J dependencies - end --&gt;
      &lt;/dependencies&gt;
  
      &lt;build&gt;
          &lt;finalName&gt;${project.artifactId}&lt;/finalName&gt;
          &lt;plugins&gt;
              &lt;plugin&gt;
                  &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
                  &lt;artifactId&gt;spring-boot-maven-plugin&lt;/artifactId&gt;
              &lt;/plugin&gt;
          &lt;/plugins&gt;
      &lt;/build&gt;
  &lt;/project&gt;
  </code></pre>