View Javadoc
1   /*
2    * Copyright 2012-2025 CodeLibs Project and the Others.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13   * either express or implied. See the License for the specific language
14   * governing permissions and limitations under the License.
15   */
16  package org.codelibs.fess.sso;
17  
18  import java.util.ArrayList;
19  import java.util.List;
20  
21  import org.apache.logging.log4j.LogManager;
22  import org.apache.logging.log4j.Logger;
23  import org.codelibs.fess.Constants;
24  import org.codelibs.fess.mylasta.action.FessUserBean;
25  import org.codelibs.fess.util.ComponentUtil;
26  import org.lastaflute.web.login.credential.LoginCredential;
27  import org.lastaflute.web.response.ActionResponse;
28  
29  /**
30   * Manager class for coordinating SSO (Single Sign-On) authentication operations.
31   *
32   * This class serves as the central coordinator for SSO authentication in Fess.
33   * It manages registered SSO authenticators, determines when SSO is available,
34   * and delegates authentication operations to the appropriate SSO provider based
35   * on the current configuration.
36   */
37  public class SsoManager {
38      /** Logger for this class. */
39      private static final Logger logger = LogManager.getLogger(SsoManager.class);
40  
41      /** List of registered SSO authenticators. */
42      protected final List<SsoAuthenticator> authenticatorList = new ArrayList<>();
43  
44      /**
45       * Default constructor for creating a new SsoManager instance.
46       */
47      public SsoManager() {
48          // Default constructor
49      }
50  
51      /**
52       * Checks whether SSO authentication is available and configured.
53       *
54       * @return true if SSO is configured and available, false otherwise
55       */
56      public boolean available() {
57          final String ssoType = getSsoType();
58          if (logger.isDebugEnabled()) {
59              logger.debug("sso.type: {}", ssoType);
60          }
61          return !Constants.NONE.equals(ssoType);
62      }
63  
64      /**
65       * Attempts to obtain login credentials using the configured SSO authenticator.
66       *
67       * @return The login credential from SSO authentication, or null if SSO is not available
68       *         or no credential could be obtained
69       */
70      public LoginCredential getLoginCredential() {
71          if (available()) {
72              final SsoAuthenticator authenticator = getAuthenticator();
73              if (authenticator != null) {
74                  return authenticator.getLoginCredential();
75              }
76          }
77          return null;
78      }
79  
80      /**
81       * Gets the appropriate response for the specified SSO response type.
82       *
83       * @param responseType The type of SSO response required (e.g., METADATA, LOGOUT)
84       * @return The action response from the SSO authenticator, or null if SSO is not available
85       */
86      public ActionResponse getResponse(final SsoResponseType responseType) {
87          if (available()) {
88              final SsoAuthenticator authenticator = getAuthenticator();
89              if (authenticator != null) {
90                  return authenticator.getResponse(responseType);
91              }
92          }
93          return null;
94      }
95  
96      /**
97       * Performs logout operations for the specified user using SSO.
98       *
99       * @param user The user to logout
100      * @return The logout URL from the SSO authenticator, or null if SSO is not available
101      */
102     public String logout(final FessUserBean user) {
103         if (available()) {
104             final SsoAuthenticator authenticator = getAuthenticator();
105             if (authenticator != null) {
106                 return authenticator.logout(user);
107             }
108         }
109         return null;
110     }
111 
112     /**
113      * Gets the SSO authenticator instance for the configured SSO type.
114      *
115      * @return The SSO authenticator instance, or null if not found
116      */
117     protected SsoAuthenticator getAuthenticator() {
118         String ssoType = getSsoType();
119         // Backward compatibility: map legacy "aad" (Azure AD) to "entraid" (Entra ID)
120         if ("aad".equals(ssoType)) {
121             ssoType = "entraid";
122         }
123         final String name = ssoType + "Authenticator";
124         if (ComponentUtil.hasComponent(name)) {
125             return ComponentUtil.getComponent(name);
126         }
127         return null;
128     }
129 
130     /**
131      * Gets the configured SSO type from the system configuration.
132      *
133      * @return The SSO type string from configuration
134      */
135     protected String getSsoType() {
136         return ComponentUtil.getFessConfig().getSsoType();
137     }
138 
139     /**
140      * Gets all registered SSO authenticators.
141      *
142      * @return Array of all registered SSO authenticators
143      */
144     public SsoAuthenticator[] getAuthenticators() {
145         return authenticatorList.toArray(new SsoAuthenticator[authenticatorList.size()]);
146     }
147 
148     /**
149      * Registers an SSO authenticator with this manager.
150      *
151      * @param authenticator The SSO authenticator to register
152      */
153     public void register(final SsoAuthenticator authenticator) {
154         if (logger.isInfoEnabled()) {
155             logger.info("Loaded SsoAuthenticator: {}", authenticator.getClass().getSimpleName());
156         }
157         authenticatorList.add(authenticator);
158     }
159 }