View Javadoc
1   package edu.internet2.middleware.grouper.authentication.plugin;
2   
3   import edu.internet2.middleware.grouper.authentication.plugin.config.ClientProvider;
4   import edu.internet2.middleware.grouper.authentication.plugin.config.ClientProviders;
5   import edu.internet2.middleware.grouperClient.config.ConfigPropertiesCascadeBase;
6   import org.apache.commons.lang3.StringUtils;
7   import org.apache.commons.logging.Log;
8   import org.pac4j.core.client.Client;
9   import org.pac4j.core.client.Clients;
10  import org.pac4j.core.config.Config;
11  import org.pac4j.core.config.ConfigFactory;
12  import org.pac4j.core.matching.matcher.PathMatcher;
13  
14  import java.lang.reflect.InvocationTargetException;
15  
16  public class Pac4jConfigFactory implements ConfigFactory {
17      private static final Log LOGGER = GrouperAuthentication.getLogFactory().getInstance(Pac4jConfigFactory.class);
18  
19      @Override
20      public Config build(Object... parameters) {
21          ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
22          try {
23              Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
24  
25              ConfigPropertiesCascadeBase grouperConfig = ConfigUtils.getBestGrouperConfiguration();
26  
27              String provider;
28              if (grouperConfig.containsKey("external.authentication.mechanism")) {
29                  LOGGER.warn("you're using the deprecated key `external.authentication.mechanism`; please update to `external.authentication.provider`");
30                  provider = grouperConfig.propertyValueString("external.authentication.mechanism");
31              } else {
32                  provider = grouperConfig.propertyValueString("external.authentication.provider");
33              }
34  
35              if (StringUtils.isBlank(provider)) {
36                  String configFile = ConfigUtils.isGrouperUi() ? "grouper-ui.properties" : "grouper-ws.properties";
37                  throw new RuntimeException("External authentication is enabled (grouper.is.extAuth.enabled = true) "
38                          + "but the required property 'external.authentication.provider' is not configured. "
39                          + "Please set 'external.authentication.provider' to one of: cas, oidc, saml "
40                          + "(or a fully qualified class name implementing ClientProvider) "
41                          + "in " + configFile + ". "
42                          + "If you do not need external authentication, set 'grouper.is.extAuth.enabled' to false "
43                          + "in " + configFile + ".");
44              }
45  
46              Client client = getClient(provider);
47  
48              String callbackUrl = grouperConfig.propertyValueString("external.authentication.grouperContextUrl")
49                      + grouperConfig.propertyValueString("external.authentication.callbackUrl", "/callback");
50              final Clients clients = new Clients(callbackUrl, client);
51  
52              final Config config = new Config(clients);
53  
54              PathMatcher pathMatcher = new PathMatcher();
55  
56              String securityExclusionsPaths = grouperConfig.propertyValueString("external.authentication.exclusions", "/status");
57              if (securityExclusionsPaths != null) {
58                  for (String exclusion : securityExclusionsPaths.split(",")) {
59                      pathMatcher.excludeBranch(StringUtils.trim(exclusion));
60                  }
61              }
62              config.addMatcher("securityExclusions", pathMatcher);
63              return config;
64          } catch (IllegalAccessException | InstantiationException | NoSuchMethodException | InvocationTargetException e) {
65              throw new RuntimeException("problem configuring pac4j", e);
66          } finally {
67              Thread.currentThread().setContextClassLoader(classLoader);
68          }
69      }
70  
71      //TODO: can this be checked
72      @SuppressWarnings("unchecked")
73      private static Client getClient(String provider) throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
74          Class<? extends ClientProvider> providerClass;
75          //TODO: might be a better way of doing this
76          try {
77              providerClass = ClientProviders.fromString(provider).getProviderClass();
78          } catch (IllegalArgumentException e) {
79              try {
80                  providerClass = (Class<? extends ClientProvider>) Class.forName(provider);
81              } catch (ClassNotFoundException classNotFoundException) {
82                  throw new RuntimeException(classNotFoundException);
83              }
84          }
85          return providerClass.getDeclaredConstructor().newInstance().getClient();
86      }
87  }