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 }