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_DISCONNECT, 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 <T extends AdminUser> T bindUser(T 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         T bindUser = AdminUserHome.findUserByLogin( user.getAccessCode( ),user );
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 user;
274     }
275 
276    
277     
278     
279     /**
280      * Register the user in the Http session
281      *
282      * @param request
283      *            The Http request
284      * @param user
285      *            The current user
286      * @throws AccessDeniedException
287      *             If the user cannot have access
288      * @throws UserNotSignedException
289      *             If the user is not signed
290      */
291     public <T extends AdminUser> void registerUser( HttpServletRequest request,  T user ) throws AccessDeniedException, UserNotSignedException
292     {
293         HttpSession session = request.getSession( true );
294         session.setAttribute( ATTRIBUTE_ADMIN_USER, bindUser( user ) );
295     }
296     
297     
298     
299 
300     /**
301      * Unregister the user in the Http session
302      * 
303      * @param request
304      *            The Http request
305      */
306     public void unregisterUser( HttpServletRequest request )
307     {
308         HttpSession session = request.getSession( true );
309         session.removeAttribute( ATTRIBUTE_ADMIN_USER );
310     }
311 
312     /**
313      * Gets the Lutece user registered in the Http session
314      * 
315      * @param request
316      *            The HTTP request
317      * @return The User registered or null if the user has not been registered
318      */
319     public AdminUser getRegisteredUser( HttpServletRequest request )
320     {
321         HttpSession session = request.getSession( );
322 
323         if ( session != null )
324         {
325             return (AdminUser) session.getAttribute( ATTRIBUTE_ADMIN_USER );
326         }
327 
328         return null;
329     }
330 
331     /**
332      * Returns the authentication type : External or Lutece portal based
333      * 
334      * @return true if the user is already authenticated or false if it needs to login.
335      */
336     public boolean isExternalAuthentication( )
337     {
338         return _authentication.isExternalAuthentication( );
339     }
340 
341     /**
342      * Returns the Login page URL of the Authentication Service
343      * 
344      * @return The URL
345      */
346     public String getLoginPageUrl( )
347     {
348         return _authentication.getLoginPageUrl( );
349     }
350 
351     /**
352      * Returns the modification password page URL of the Authentication Service
353      * 
354      * @return The URL
355      */
356     public String getChangePasswordPageUrl( )
357     {
358         return _authentication.getChangePasswordPageUrl( );
359     }
360 
361     /**
362      * Returns the DoLogin URL of the Authentication Service
363      * 
364      * @return The URL
365      */
366     public String getDoLoginUrl( )
367     {
368         return _authentication.getDoLoginUrl( );
369     }
370 
371     /**
372      * Returns the DoLogout URL of the Authentication Service
373      * 
374      * @return The URL
375      */
376     public String getDoLogoutUrl( )
377     {
378         return _authentication.getDoLogoutUrl( );
379     }
380 
381     /**
382      * Returns the new account page URL of the Authentication Service
383      * 
384      * @return The URL
385      */
386     public String getNewAccountPageUrl( )
387     {
388         return _authentication.getNewAccountPageUrl( );
389     }
390 
391     /**
392      * Returns the view account page URL of the Authentication Service
393      * 
394      * @return The URL
395      */
396     public String getViewAccountPageUrl( )
397     {
398         return _authentication.getViewAccountPageUrl( );
399     }
400 
401     /**
402      * Returns the lost password URL of the Authentication Service
403      * 
404      * @return The URL
405      */
406     public String getLostPasswordPageUrl( )
407     {
408         return _authentication.getLostPasswordPageUrl( );
409     }
410 
411     /**
412      * Returns the lost login URL of the Authentication Service
413      * 
414      * @return The URL
415      */
416     public String getLostLoginPageUrl( )
417     {
418         return _authentication.getLostLoginPageUrl( );
419     }
420 
421     /**
422      * Returns the user list
423      *
424      * @return the collection of all users from the module
425      * @param strLastName
426      *            The last name
427      * @param strFirstName
428      *            The first name
429      * @param strEmail
430      *            The email
431      */
432     public Collection<AdminUser> getUserListFromModule( String strLastName, String strFirstName, String strEmail )
433     {
434         return _authentication.getUserList( strLastName, strFirstName, strEmail );
435     }
436 
437     /**
438      *
439      * @param strAccessCode
440      *            The login
441      * @return The AdminUser
442      */
443     public AdminUser getUserPublicDataFromModule( String strAccessCode )
444     {
445         return _authentication.getUserPublicData( strAccessCode );
446     }
447 
448     /**
449      * Set the admin login next url
450      * 
451      * @param request
452      *            the HTTP request
453      */
454     public void setLoginNextUrl( HttpServletRequest request )
455     {
456         String strNextUrl = request.getRequestURI( );
457         UrlItem/url/UrlItem.html#UrlItem">UrlItem url = new UrlItem( strNextUrl );
458         Enumeration enumParams = request.getParameterNames( );
459 
460         while ( enumParams.hasMoreElements( ) )
461         {
462             String strParamName = (String) enumParams.nextElement( );
463             url.addParameter( strParamName, request.getParameter( strParamName ) );
464         }
465 
466         HttpSession session = request.getSession( true );
467         session.setAttribute( ATTRIBUTE_ADMIN_LOGIN_NEXT_URL, url.getUrl( ) );
468     }
469 
470     /**
471      * Returns the url (asked before login) to redirect after login
472      * 
473      * @param request
474      *            The Http request
475      * @return The url asked before login
476      */
477     public String getLoginNextUrl( HttpServletRequest request )
478     {
479         String strNextUrl = StringUtils.EMPTY;
480         HttpSession session = request.getSession( false );
481 
482         if ( session != null )
483         {
484             strNextUrl = (String) session.getAttribute( ATTRIBUTE_ADMIN_LOGIN_NEXT_URL );
485             session.removeAttribute( ATTRIBUTE_ADMIN_LOGIN_NEXT_URL );
486         }
487 
488         return strNextUrl;
489     }
490     
491     /**
492      * 
493      * @return the name of the authentication module load
494      */
495 	public String getAuthServiceName() 
496 	{
497 		return _authentication.getAuthServiceName();
498 	}
499     
500 }