Embedded Front End
Flowable Engage provides a dedicated JavaScript front end that can either be deployed to any HTML capable server or run embedded directly within the Flowable Server.
To run the front end embedded within the Flowable Server add the
following dependency to the pom.xml
file of the project:
<dependency>
<groupId>com.flowable.work</groupId>
<artifactId>flowable-work-frontend</artifactId>
</dependency>
The front end provides user interfaces for both Flowable Work and Flowable Engage. The Engage interface can be deactivated if only Work features are made available. |
In addition you need to provide the correct Spring Boot Security
configuration to allow access to the embedded front end.
This is done by adding a class e.g., called SecurityConfiguration
as a sibling
of the Spring Boot Application class containing the following configuration:
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.HttpStatusEntryPoint;
import org.springframework.security.web.authentication.RememberMeServices;
import org.springframework.security.web.authentication.logout.HttpStatusReturningLogoutSuccessHandler;
import org.springframework.security.web.authentication.rememberme.AbstractRememberMeServices;
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
import org.springframework.security.web.util.matcher.AnyRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
import com.flowable.autoconfigure.security.FlowablePlatformSecurityProperties;
import com.flowable.core.spring.security.web.authentication.AjaxAuthenticationFailureHandler;
import com.flowable.core.spring.security.web.authentication.AjaxAuthenticationSuccessHandler;
import com.flowable.platform.common.security.SecurityConstants;
@Configuration
@Order(10)
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
protected ObjectProvider<RememberMeServices> rememberMeServicesObjectProvider;
@Autowired
protected FlowablePlatformSecurityProperties flowableSecurityProperties;
@Override
protected void configure(HttpSecurity http) throws Exception {
RememberMeServices rememberMeServices = rememberMeServicesObjectProvider.getIfAvailable();
String key = null;
if (rememberMeServices instanceof AbstractRememberMeServices) {
key = ((AbstractRememberMeServices) rememberMeServices).getKey();
}
if (flowableSecurityProperties.getRest().getCsrf().isEnabled()) {
http.csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.ignoringRequestMatchers((RequestMatcher) request -> request.getHeader(HttpHeaders.AUTHORIZATION) != null);
} else {
http.csrf().disable();
}
http
.headers().frameOptions().sameOrigin()
.and()
.rememberMe()
.key(key)
.rememberMeServices(rememberMeServicesObjectProvider.getIfAvailable())
.and()
.logout()
.logoutSuccessHandler(new HttpStatusReturningLogoutSuccessHandler())
.logoutUrl("/auth/logout")
.and()
.exceptionHandling()
.defaultAuthenticationEntryPointFor(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED), AnyRequestMatcher.INSTANCE)
.and()
.formLogin()
.loginProcessingUrl("/auth/login")
.successHandler(new AjaxAuthenticationSuccessHandler())
.failureHandler(new AjaxAuthenticationFailureHandler())
.and()
.authorizeRequests()
.antMatchers("/analytics-api/**").hasAuthority(SecurityConstants.ACCESS_REPORTS_METRICS)
.antMatchers("/template-api/**").hasAuthority(SecurityConstants.ACCESS_TEMPLATE_MANAGEMENT)
.antMatchers("/work-object-api/**").hasAuthority(SecurityConstants.ACCESS_WORKOBJECT_API)
// allow context root for all (it triggers the loading of the initial page)
.antMatchers("/").permitAll()
.antMatchers(
"/**/*.svg", "/**/*.ico", "/**/*.png", "/**/*.woff2", "/**/*.css",
"/**/*.woff", "/**/*.html", "/**/*.js",
"/**/index.html").permitAll()
.anyRequest().authenticated()
.and()
.httpBasic();
}
}