Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

In Blueriq the HTTP security configuration is implemented in Java using a Configurer bean, as shown below.

Code Block
titleHttp security configuration
package com.aquima.web.boot;

import com.aquima.interactions.project.impl.XssSafeValueFormatter;
import com.aquima.interactions.project.impl.xss.IXssBlacklist;
import com.aquima.interactions.project.impl.xss.IXssWhitelist;
import com.aquima.web.config.properties.SecurityConfigProperties;
import com.aquima.web.security.headers.ClickJackingProtectionHeaderWriter;
import com.aquima.web.security.headers.ContentTypeOptionsHeaderWriter;
import com.aquima.web.security.headers.StrictTransportProtectionHeaderWriter;
import com.aquima.web.security.headers.XssProtectionHeaderWriter;
import com.aquima.web.util.MvcRedirectHelper;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
import org.springframework.security.web.context.SecurityContextRepository;

@Configuration
@Order(50)
@ConditionalOnProperty(name = "blueriq.security.http.interactions.enabled", havingValue = "true", matchIfMissing = true)
public class RuntimeWebSecurityConfigurer extends WebSecurityConfigurerAdapter {

  private static final Logger LOG = LoggerFactory.getLogger(RuntimeWebSecurityConfigurer.class);

  @Autowired
  @Qualifier("blueriqAuthenticationManager")
  private AuthenticationManager authManager;

  @Autowired
  private SecurityConfigProperties securityProperties;

  @Autowired
  private MvcRedirectHelper redirectHelper;

  @Autowired
  private SecurityContextRepository securityContextRepository;

  public static class Mappings {
    public static final String TRIGGER_SECURITY_CHECK = "/server/noaccess.html";
    public static final String PERFORM_SECURITY_CHECK = "/server/securityCheck";
    public static final String LOGIN_PAGE = "/server/session/login.html";
    public static final String LOGOUT_PAGE = "/server/session/logout.html";
    public static final String LOGIN_SUCCESS_URL = "/server/start?loginSuccess=true";
    public static final String LOGIN_PAGE_ERROR = "/server/session/login.html?loginError=true";
  }

  @Override
  protected AuthenticationManager authenticationManager() throws Exception {
    return this.authManager;
  }

  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http //
        .csrf().disable() //
        .headers() //
        .defaultsDisabled() //
        .addHeaderWriter(new ClickJackingProtectionHeaderWriter(this.securityProperties)) //
        .addHeaderWriter(new StrictTransportProtectionHeaderWriter(this.securityProperties)) //
        .addHeaderWriter(new ContentTypeOptionsHeaderWriter(this.securityProperties)) //
        .addHeaderWriter(new XssProtectionHeaderWriter(this.securityProperties)) //
        .and() //
        .sessionManagement() //
        .sessionFixation() //
        .none() //
        .and() //
        .authorizeRequests() //
        .antMatchers(this.redirectHelper.getNoAccessPath()) //
        .authenticated() //
        .and() //
        .formLogin() //
        .defaultSuccessUrl(Mappings.LOGIN_SUCCESS_URL, true) //
        .loginPage(Mappings.LOGIN_PAGE) //
        .loginProcessingUrl(Mappings.PERFORM_SECURITY_CHECK) //
        .permitAll() //
        .failureUrl(Mappings.LOGIN_PAGE_ERROR) //
        .and() //
        .anonymous() //
        .key("doesNotMatter").and() //
        .securityContext() //
        .securityContextRepository(securityContextRepository);
  }

  @Bean
  @ConditionalOnMissingBean(SecurityContextRepository.class)
  public SecurityContextRepository defaultSecurityContextRepository() {
    if (LOG.isInfoEnabled()) {
      LOG.info("Using default security context repository");
    }

    HttpSessionSecurityContextRepository repository = new HttpSessionSecurityContextRepository();
    repository.setDisableUrlRewriting(true);

    return repository;
  }

  @Autowired(required = false)
  public void registerXssWhitelist(IXssWhitelist whitelist) {
    XssSafeValueFormatter.register(whitelist);
  }

  @Autowired(required = false)
  public void registerXssBlacklist(IXssBlacklist blacklist) {
    XssSafeValueFormatter.register(blacklist);
  }

}

...

6. Noaccess.html

Blueriq uses a mechanism that whenever a flow is started, it is checked if the flow requires authentication and the current user has matching credentials. If this is not the case, the user is automatically redirected to the virtual page noaccess.html. This page does not exist, but is merely there to redirect to the login page as shown in the excerpt below from the HTTP security configuration.

Code Block
.authorizeRequests()
.antMatchers(redirectHelper.getNoAccessPath()).authenticated()
.and()

 

If one chooses to configure a custom security approach, for instance by passing through credentials via HTTP headers, noaccess.html is not in reach, and users are already logged in at the moment they reach Blueriq. A custom page that indicates that no access is allowed is in that case out of Blueriq's hands and the responsibility of the project.

...