Coverage Summary for Class: DynamicAuthenticationProvider (org.kitodo.production.security)

Class Class, % Method, % Line, %
DynamicAuthenticationProvider 0% (0/1) 0% (0/12) 0% (0/57)


 /*
  * (c) Kitodo. Key to digital objects e. V. <contact@kitodo.org>
  *
  * This file is part of the Kitodo project.
  *
  * It is licensed under GNU General Public License version 3 or later.
  *
  * For the full copyright and license information, please read the
  * GPL3-License.txt file that was distributed with this source code.
  */
 
 package org.kitodo.production.security;
 
 import java.util.Objects;
 
 import javax.enterprise.context.RequestScoped;
 import javax.inject.Named;
 
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 import org.kitodo.config.ConfigCore;
 import org.kitodo.config.enums.ParameterCore;
 import org.kitodo.data.database.beans.LdapGroup;
 import org.kitodo.data.database.beans.User;
 import org.kitodo.production.helper.Helper;
 import org.kitodo.production.helper.LocaleHelper;
 import org.kitodo.production.security.password.SecurityPasswordEncoder;
 import org.kitodo.production.services.ServiceManager;
 import org.kitodo.production.services.data.ImportService;
 import org.springframework.security.authentication.AuthenticationProvider;
 import org.springframework.security.authentication.AuthenticationServiceException;
 import org.springframework.security.authentication.DisabledException;
 import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
 import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.core.SpringSecurityMessageSource;
 import org.springframework.security.ldap.DefaultSpringSecurityContextSource;
 import org.springframework.security.ldap.authentication.BindAuthenticator;
 import org.springframework.security.ldap.authentication.LdapAuthenticationProvider;
 
 /**
  * A custom authentication provider which supports the change of authentication
  * type (database or ldap) and details (e.g. ldap server url) during runtime.
  */
 @Named("AuthenticationController")
 @RequestScoped
 public class DynamicAuthenticationProvider implements AuthenticationProvider {
     private static final Logger logger = LogManager.getLogger(DynamicAuthenticationProvider.class);
 
     private static volatile DynamicAuthenticationProvider instance = null;
     private AuthenticationProvider daoAuthenticationProvider = null;
     private AuthenticationProvider ldapAuthenticationProvider = null;
 
     private boolean ldapAuthentication;
     private DefaultSpringSecurityContextSource ldapContextSource = null;
     private BindAuthenticator bindAuthenticator = null;
     private final LdapUserDetailsContextMapper ldapUserDetailsContextMapper = new LdapUserDetailsContextMapper();
 
     /**
      * The private Constructor which initially reads the local config.
      */
     private DynamicAuthenticationProvider() {
         readLocalConfig();
     }
 
     /**
      * Return singleton variable of type DynamicAuthenticationProvider.
      *
      * @return unique instance of DynamicAuthenticationProvider
      */
     public static DynamicAuthenticationProvider getInstance() {
         DynamicAuthenticationProvider localReference = instance;
         if (Objects.isNull(localReference)) {
             synchronized (DynamicAuthenticationProvider.class) {
                 localReference = instance;
                 if (Objects.isNull(localReference)) {
                     localReference = new DynamicAuthenticationProvider();
                     instance = localReference;
                 }
             }
         }
         return localReference;
     }
 
     @Override
     public Authentication authenticate(Authentication authentication) {
         try {
             User user = ServiceManager.getUserService().getByLdapLoginOrLogin(authentication.getName());
             if (!user.isActive()) {
                 throw new DisabledException(SpringSecurityMessageSource.getAccessor().getMessage(
                     "AbstractUserDetailsAuthenticationProvider.disabled",
                     Helper.getString(LocaleHelper.getCurrentLocale(), "errorUserIsDisabled")));
             }
             LdapGroup ldapGroup = user.getLdapGroup();
             if (ldapAuthentication && Objects.nonNull(ldapGroup)) {
                 if (Objects.isNull(ldapGroup.getLdapServer())) {
                     throw new AuthenticationServiceException("No LDAP server specified on user's LDAP group");
                 }
                 configureAuthenticationProvider(ldapGroup.getLdapServer().getUrl(), ldapGroup.getUserDN());
                 if (ldapGroup.getUserDN().contains("{ldaplogin}")) {
                     authentication = new UsernamePasswordAuthenticationToken(user.getLdapLogin(), authentication.getCredentials());
                 }
                 return ldapAuthenticationProvider.authenticate(authentication);
             } else {
                 return daoAuthenticationProvider.authenticate(authentication);
             }
         } catch (RuntimeException problem) {
             // if login fails because of some unchecked exception, log it
             // when in debug mode
             logger.debug(problem.getLocalizedMessage(), problem);
             // rethrow exception
             throw problem;
         }
     }
 
     @Override
     public boolean supports(Class<?> authentication) {
         return UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication);
     }
 
     /**
      * This method activates ldap authentication and configures ldap url and userDn
      * pattern.
      *
      * @param url
      *            The url to ldap server.
      * @param userDn
      *            The user dn pattern.
      */
     private void configureAuthenticationProvider(String url, String userDn) {
         if (Objects.isNull(this.ldapContextSource)) {
             this.ldapContextSource = new DefaultSpringSecurityContextSource(url);
         } else {
             this.ldapContextSource.setUrl(url);
         }
         this.ldapContextSource.afterPropertiesSet();
 
         if (Objects.isNull(this.bindAuthenticator)) {
             this.bindAuthenticator = new BindAuthenticator(ldapContextSource);
         }
         bindAuthenticator.setUserDnPatterns(convertUserDn(userDn));
 
         LdapAuthenticationProvider ldapAuthenticationProvider = new LdapAuthenticationProvider(bindAuthenticator);
         ldapAuthenticationProvider.setUserDetailsContextMapper(this.ldapUserDetailsContextMapper);
 
         this.ldapAuthenticationProvider = ldapAuthenticationProvider;
     }
 
     private void activateDatabaseAuthentication() {
         DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
         daoAuthenticationProvider.setUserDetailsService(ServiceManager.getUserService());
         daoAuthenticationProvider.setPasswordEncoder(new SecurityPasswordEncoder());
         this.daoAuthenticationProvider = daoAuthenticationProvider;
     }
 
     /**
      * This activates the Ldap authentication with initial url and userDn. These
      * values are later replace by the user information when authentication is
      * performed.
      */
     private void activateLdapAuthentication() {
         configureAuthenticationProvider("ldap://0.0.0.0", "no userDn");
     }
 
     private void readLocalConfig() {
         setLdapAuthentication(ConfigCore.getBooleanParameterOrDefaultValue(ParameterCore.LDAP_USE));
     }
 
     private String[] convertUserDn(String userDn) {
         return new String[] {userDn.replaceFirst("\\{(?:ldap)?login}", "{0}") };
     }
 
     /**
      * Gets ldapAuthentication.
      *
      * @return The ldapAuthentication.
      */
     public boolean isLdapAuthentication() {
         return ldapAuthentication;
     }
 
     /**
      * Sets ldapAuthentication.
      *
      * @param ldapAuthentication
      *            The ldapAuthentication.
      */
     public void setLdapAuthentication(boolean ldapAuthentication) {
         this.ldapAuthentication = ldapAuthentication;
         if (ldapAuthentication) {
             activateLdapAuthentication();
         }
         activateDatabaseAuthentication();
     }
 }