View Javadoc
1   /*
2    * Copyright (c) 2002-2022, City of Paris
3    * All rights reserved.
4    *
5    * Redistribution and use in source and binary forms, with or without
6    * modification, are permitted provided that the following conditions
7    * are met:
8    *
9    *  1. Redistributions of source code must retain the above copyright notice
10   *     and the following disclaimer.
11   *
12   *  2. Redistributions in binary form must reproduce the above copyright notice
13   *     and the following disclaimer in the documentation and/or other materials
14   *     provided with the distribution.
15   *
16   *  3. Neither the name of 'Mairie de Paris' nor 'Lutece' nor the names of its
17   *     contributors may be used to endorse or promote products derived from
18   *     this software without specific prior written permission.
19   *
20   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
24   * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30   * POSSIBILITY OF SUCH DAMAGE.
31   *
32   * License 1.0
33   */
34  package fr.paris.lutece.portal.service.admin;
35  
36  import fr.paris.lutece.portal.service.security.AccessLogService;
37  import java.util.Collection;
38  import java.util.Enumeration;
39  import java.util.stream.Collectors;
40  
41  import javax.security.auth.login.LoginException;
42  import javax.servlet.http.HttpServletRequest;
43  import javax.servlet.http.HttpSession;
44  
45  import org.apache.commons.lang3.StringUtils;
46  
47  import fr.paris.lutece.portal.business.user.AdminUser;
48  import fr.paris.lutece.portal.business.user.AdminUserHome;
49  import fr.paris.lutece.portal.business.user.authentication.AdminAuthentication;
50  import fr.paris.lutece.portal.business.user.authentication.LuteceDefaultAdminAuthentication;
51  import fr.paris.lutece.portal.business.workgroup.AdminWorkgroupHome;
52  import fr.paris.lutece.portal.service.security.AccessLoggerConstants;
53  import fr.paris.lutece.portal.service.security.UserNotSignedException;
54  import fr.paris.lutece.portal.service.spring.SpringContextService;
55  import fr.paris.lutece.portal.service.util.AppLogService;
56  import fr.paris.lutece.util.url.UrlItem;
57  
58  /**
59   * This class provides a security service to register and check user authentication
60   */
61  public final class AdminAuthenticationService
62  {
63      /**
64       * Session attribute that stores the AdminUser object attached to the session
65       */
66      private static final String ATTRIBUTE_ADMIN_USER = "lutece_admin_user";
67      private static final String ATTRIBUTE_ADMIN_LOGIN_NEXT_URL = "luteceAdminLoginNextUrl";
68  
69      private static final String BEAN_ADMIN_AUTHENTICATION_MODULE = "adminAuthenticationModule";
70  
71      private static final String CONSTANT_ACTION_LOGIN_ADMINUSER = "user.loginAdminUser";
72      private static final String CONSTANT_ACTION_LOGOUT_ADMINUSER = "user.logoutAdminUser";
73      private static final String CONSTANT_BO = "BO";
74  
75      private static AdminAuthenticationServiceenticationService.html#AdminAuthenticationService">AdminAuthenticationService _singleton = new AdminAuthenticationService( );
76      private static AdminAuthentication _authentication;
77      private static boolean _bUseDefaultModule;
78  
79      /**
80       * Private constructor
81       */
82      private AdminAuthenticationService( )
83      {
84      }
85  
86      /**
87       * Initialize service
88       */
89      public static synchronized void init( )
90      {
91          _authentication = SpringContextService.getBean( BEAN_ADMIN_AUTHENTICATION_MODULE );
92          AppLogService.info( "Authentication module loaded : {}", _authentication.getAuthServiceName( ) );
93  
94          if ( _authentication.getClass( ).equals( LuteceDefaultAdminAuthentication.class ) )
95          {
96              _bUseDefaultModule = true;
97          }
98      }
99  
100     /**
101      * Get the unique instance of the Security Service
102      * 
103      * @return The instance
104      */
105     public static AdminAuthenticationService getInstance( )
106     {
107         return _singleton;
108     }
109 
110     /**
111      * Check whether the authentication service is configurer on the default module.
112      * 
113      * @return true if the default module is in use, false if another module is used
114      */
115     public boolean isDefaultModuleUsed( )
116     {
117         return _bUseDefaultModule;
118     }
119 
120     /**
121      * Gets the AdminUser attached to the current Http session
122      *
123      * @return A valid AdminUser object if found
124      * @param request
125      *            The Http request
126      * @throws AccessDeniedException
127      *             If the user cannot have access
128      * @throws UserNotSignedException
129      *             If the user is not signed
130      */
131     public AdminUser getRemoteUser( HttpServletRequest request ) throws UserNotSignedException, AccessDeniedException
132     {
133         AdminUser user = getRegisteredUser( request );
134 
135         if ( _authentication.isExternalAuthentication( ) )
136         {
137             if ( user == null )
138             {
139                 // User is not registered by Lutece, but it may be authenticated by another system
140                 user = _authentication.getHttpAuthenticatedUser( request );
141                 registerUser( request, user );
142                 AdminUserService.updateDateLastLogin( user.getUserId( ) );
143 
144                 // Start a new session
145                 throw new UserNotSignedException( );
146             }
147             else
148             {
149                 // user is already in session. for external auth, we check that the user hasn't changed in the external module .
150                 AdminUser newUser = _authentication.getHttpAuthenticatedUser( request );
151 
152                 if ( newUser == null )
153                 {
154                     throw new AccessDeniedException( "User not found while retrieving from external authentication" );
155                 }
156                 else
157                     if ( !newUser.getAccessCode( ).equals( user.getAccessCode( ) ) )
158                     {
159                         unregisterUser( request );
160                         registerUser( request, newUser );
161                         AdminUserService.updateDateLastLogin( user.getUserId( ) );
162 
163                         // Start a new session
164                         throw new UserNotSignedException( );
165                     }
166             }
167         }
168         else
169         // if not external authentication, just check if user is null or not
170         {
171             if ( user == null )
172             {
173                 // user is not signed
174                 throw new UserNotSignedException( );
175             }
176         }
177 
178         return user;
179     }
180 
181     /**
182      * Checks user's login with the Authentication service.
183      * 
184      * @param request
185      *            The Http request
186      * @param strAccessCode
187      *            The user's login
188      * @param strPassword
189      *            The user's password
190      * @throws LoginException
191      *             The LoginException
192      */
193     public void loginUser( HttpServletRequest request, final String strAccessCode, final String strPassword ) throws LoginException
194     {
195         AdminUser user = _authentication.login( strAccessCode, strPassword, request );
196 
197         AccessLogService.getInstance( ).info( AccessLoggerConstants.EVENT_TYPE_CONNECT, CONSTANT_ACTION_LOGIN_ADMINUSER, user, null, CONSTANT_BO );
198 
199         try
200         {
201             registerUser( request, user );
202         }
203         catch( UserNotSignedException | AccessDeniedException e )
204         {
205             throw new LoginException( );
206         }
207 
208         AdminUserService.updateDateLastLogin( user.getUserId( ) );
209     }
210 
211     /**
212      * Logout the user
213      * 
214      * @param request
215      *            The HTTP request
216      */
217     public void logoutUser( HttpServletRequest request )
218     {
219         AdminUser user;
220 
221         try
222         {
223             user = getRemoteUser( request );
224         }
225         catch( AccessDeniedException | UserNotSignedException e )
226         {
227             return;
228         }
229 
230         _authentication.logout( user );
231         unregisterUser( request );
232 
233         AccessLogService.getInstance( ).info( AccessLoggerConstants.EVENT_TYPE_CONNECT, CONSTANT_ACTION_LOGOUT_ADMINUSER, user, null, CONSTANT_BO );
234 
235     }
236 
237     /**
238      * Bind user : complete module user with local settings (roles, etc)
239      *
240      * @param user
241      *            The current user
242      * @throws AccessDeniedException
243      *             If the user cannot have access
244      * @throws UserNotSignedException
245      *             If the user is not signed
246      * @return The AdminUser
247      */
248     private AdminUser../../../../../fr/paris/lutece/portal/business/user/AdminUser.html#AdminUser">AdminUser bindUser( AdminUser user ) throws AccessDeniedException, UserNotSignedException
249     {
250         if ( user == null )
251         {
252             throw new UserNotSignedException( );
253         }
254 
255         // retrieve the user in local system from the access code
256         AdminUser bindUser = AdminUserHome.findUserByLogin( user.getAccessCode( ) );
257 
258         // only allow a user that is marked active
259         if ( ( bindUser == null ) || ( !bindUser.isStatusActive( ) ) )
260         {
261             throw new AccessDeniedException( "User " + bindUser + " is null or not active" );
262         }
263 
264         // set the rights for this user
265         bindUser.setRights( AdminUserHome.getRightsListForUser( bindUser.getUserId( ) ) );
266 
267         // set the rights for this user
268         bindUser.setRoles( AdminUserHome.getRolesListForUser( bindUser.getUserId( ) ) );
269 
270         // set the workgroups for this user
271         bindUser.setUserWorkgroups( AdminWorkgroupHome.getUserWorkgroups( bindUser ).stream( ).map( x -> x.getCode( ) ).collect( Collectors.toList( ) ) );
272 
273         return bindUser;
274     }
275 
276     /**
277      * Register the user in the Http session
278      *
279      * @param request
280      *            The Http request
281      * @param user
282      *            The current user
283      * @throws AccessDeniedException
284      *             If the user cannot have access
285      * @throws UserNotSignedException
286      *             If the user is not signed
287      */
288     public void registerUser( HttpServletRequest request, AdminUser user ) throws AccessDeniedException, UserNotSignedException
289     {
290         HttpSession session = request.getSession( true );
291         session.setAttribute( ATTRIBUTE_ADMIN_USER, bindUser( user ) );
292     }
293 
294     /**
295      * Unregister the user in the Http session
296      * 
297      * @param request
298      *            The Http request
299      */
300     public void unregisterUser( HttpServletRequest request )
301     {
302         HttpSession session = request.getSession( true );
303         session.removeAttribute( ATTRIBUTE_ADMIN_USER );
304     }
305 
306     /**
307      * Gets the Lutece user registered in the Http session
308      * 
309      * @param request
310      *            The HTTP request
311      * @return The User registered or null if the user has not been registered
312      */
313     public AdminUser getRegisteredUser( HttpServletRequest request )
314     {
315         HttpSession session = request.getSession( );
316 
317         if ( session != null )
318         {
319             return (AdminUser) session.getAttribute( ATTRIBUTE_ADMIN_USER );
320         }
321 
322         return null;
323     }
324 
325     /**
326      * Returns the authentication type : External or Lutece portal based
327      * 
328      * @return true if the user is already authenticated or false if it needs to login.
329      */
330     public boolean isExternalAuthentication( )
331     {
332         return _authentication.isExternalAuthentication( );
333     }
334 
335     /**
336      * Returns the Login page URL of the Authentication Service
337      * 
338      * @return The URL
339      */
340     public String getLoginPageUrl( )
341     {
342         return _authentication.getLoginPageUrl( );
343     }
344 
345     /**
346      * Returns the modification password page URL of the Authentication Service
347      * 
348      * @return The URL
349      */
350     public String getChangePasswordPageUrl( )
351     {
352         return _authentication.getChangePasswordPageUrl( );
353     }
354 
355     /**
356      * Returns the DoLogin URL of the Authentication Service
357      * 
358      * @return The URL
359      */
360     public String getDoLoginUrl( )
361     {
362         return _authentication.getDoLoginUrl( );
363     }
364 
365     /**
366      * Returns the DoLogout URL of the Authentication Service
367      * 
368      * @return The URL
369      */
370     public String getDoLogoutUrl( )
371     {
372         return _authentication.getDoLogoutUrl( );
373     }
374 
375     /**
376      * Returns the new account page URL of the Authentication Service
377      * 
378      * @return The URL
379      */
380     public String getNewAccountPageUrl( )
381     {
382         return _authentication.getNewAccountPageUrl( );
383     }
384 
385     /**
386      * Returns the view account page URL of the Authentication Service
387      * 
388      * @return The URL
389      */
390     public String getViewAccountPageUrl( )
391     {
392         return _authentication.getViewAccountPageUrl( );
393     }
394 
395     /**
396      * Returns the lost password URL of the Authentication Service
397      * 
398      * @return The URL
399      */
400     public String getLostPasswordPageUrl( )
401     {
402         return _authentication.getLostPasswordPageUrl( );
403     }
404 
405     /**
406      * Returns the lost login URL of the Authentication Service
407      * 
408      * @return The URL
409      */
410     public String getLostLoginPageUrl( )
411     {
412         return _authentication.getLostLoginPageUrl( );
413     }
414 
415     /**
416      * Returns the user list
417      *
418      * @return the collection of all users from the module
419      * @param strLastName
420      *            The last name
421      * @param strFirstName
422      *            The first name
423      * @param strEmail
424      *            The email
425      */
426     public Collection<AdminUser> getUserListFromModule( String strLastName, String strFirstName, String strEmail )
427     {
428         return _authentication.getUserList( strLastName, strFirstName, strEmail );
429     }
430 
431     /**
432      *
433      * @param strAccessCode
434      *            The login
435      * @return The AdminUser
436      */
437     public AdminUser getUserPublicDataFromModule( String strAccessCode )
438     {
439         return _authentication.getUserPublicData( strAccessCode );
440     }
441 
442     /**
443      * Set the admin login next url
444      * 
445      * @param request
446      *            the HTTP request
447      */
448     public void setLoginNextUrl( HttpServletRequest request )
449     {
450         String strNextUrl = request.getRequestURI( );
451         UrlItem/url/UrlItem.html#UrlItem">UrlItem url = new UrlItem( strNextUrl );
452         Enumeration enumParams = request.getParameterNames( );
453 
454         while ( enumParams.hasMoreElements( ) )
455         {
456             String strParamName = (String) enumParams.nextElement( );
457             url.addParameter( strParamName, request.getParameter( strParamName ) );
458         }
459 
460         HttpSession session = request.getSession( true );
461         session.setAttribute( ATTRIBUTE_ADMIN_LOGIN_NEXT_URL, url.getUrl( ) );
462     }
463 
464     /**
465      * Returns the url (asked before login) to redirect after login
466      * 
467      * @param request
468      *            The Http request
469      * @return The url asked before login
470      */
471     public String getLoginNextUrl( HttpServletRequest request )
472     {
473         String strNextUrl = StringUtils.EMPTY;
474         HttpSession session = request.getSession( false );
475 
476         if ( session != null )
477         {
478             strNextUrl = (String) session.getAttribute( ATTRIBUTE_ADMIN_LOGIN_NEXT_URL );
479             session.removeAttribute( ATTRIBUTE_ADMIN_LOGIN_NEXT_URL );
480         }
481 
482         return strNextUrl;
483     }
484 }