1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package fr.paris.lutece.plugins.mylutece.modules.cas.authentication;
35
36 import fr.paris.lutece.plugins.mylutece.authentication.PortalAuthentication;
37 import fr.paris.lutece.plugins.mylutece.modules.cas.exception.CASAuthenticationException;
38 import fr.paris.lutece.plugins.mylutece.modules.cas.exception.CASUserKeyEmptyException;
39 import fr.paris.lutece.plugins.mylutece.modules.cas.exception.CASUserNotAuthorizedException;
40 import fr.paris.lutece.plugins.mylutece.modules.cas.service.CASPlugin;
41 import fr.paris.lutece.plugins.mylutece.modules.cas.service.ICASUserKeyService;
42 import fr.paris.lutece.portal.service.message.SiteMessage;
43 import fr.paris.lutece.portal.service.message.SiteMessageException;
44 import fr.paris.lutece.portal.service.message.SiteMessageService;
45 import fr.paris.lutece.portal.service.security.LoginRedirectException;
46 import fr.paris.lutece.portal.service.security.LuteceUser;
47 import fr.paris.lutece.portal.service.util.AppLogService;
48 import fr.paris.lutece.portal.service.util.AppPathService;
49 import fr.paris.lutece.portal.service.util.AppPropertiesService;
50
51 import org.apache.commons.lang3.StringUtils;
52
53 import org.jasig.cas.client.authentication.AttributePrincipal;
54
55 import java.io.Serializable;
56
57 import java.util.ArrayList;
58 import java.util.Arrays;
59 import java.util.HashMap;
60 import java.util.List;
61 import java.util.Map;
62 import java.util.Map.Entry;
63
64 import javax.security.auth.login.LoginException;
65
66 import javax.servlet.http.HttpServletRequest;
67
68
69
70
71
72
73
74 public class CASAuthentication extends PortalAuthentication implements Serializable
75 {
76
77
78
79
80
81
82 private static final long serialVersionUID = -4537783302819258998L;
83
84
85 private static final String PROPRETY_ATTRIBUTE_ROLES = "mylutece-cas.attributeRoles";
86
87
88 public static final String PROPERTY_USER_MAPPING_ATTRIBUTES = "mylutece-cas.userMappingAttributes";
89 public static final String PROPERTY_USER_MANDATORY_ATTRIBUTES = "mylutece-cas.userMandatoryAttributes";
90 public static final String PROPERTY_ROLES_ASSOCIATIONS = "mylutece-cas.rolesAssociations";
91 public static final String PROPERTY_URL_ERROR_LOGIN_PAGE = "mylutece-cas.urlErrorLoginPage";
92 public static final String PROPERTY_BACK_URL_ERROR = "mylutece-cas.backUrlError";
93 public static final String PROPERTY_MESSAGE_ERROR_LOGIN = "module.mylutece.cas.message.error.login";
94
95
96 public static final String CONSTANT_LUTECE_USER_PROPERTIES_PATH = "mylutece-cas.attribute";
97 public static final String CONSTANT_MANDATORY_ATTRIBUTE = "mylutece-cas.mandatoryAttribute";
98 public static final String CONSTANT_ROLE_ASSOCIATIONS_PATH = "mylutece-cas.roleAssociations";
99 public static final String CONSTANT_HTTP = "http://";
100 public static final String CONSTANT_HTTPS = "https://";
101 private static final String SEPARATOR = ",";
102 private String _strAuthServiceName;
103
104
105 private String _strPropertyDefaultRoleName;
106 private String _strAttributeKeyUsername;
107 private ICASUserKeyService cASUserKeyService;
108
109
110 private String[] ATTRIBUTE_ROLES;
111 private Map<String, String> USER_MANDATORY_ATTRIBUTES;
112 private Map<String, List<String>> ROLES_ASSOCIATIONS;
113 private Map<String, String> ATTRIBUTE_USER_MAPPING;
114
115
116
117
118 public CASAuthentication( )
119 {
120 super( );
121
122 String strAttributes = AppPropertiesService.getProperty( PROPRETY_ATTRIBUTE_ROLES );
123
124 if ( StringUtils.isNotBlank( strAttributes ) )
125 {
126 ATTRIBUTE_ROLES = strAttributes.split( SEPARATOR );
127 }
128 else
129 {
130 ATTRIBUTE_ROLES = new String[0];
131 }
132
133 String strUserMappingAttributes = AppPropertiesService.getProperty( PROPERTY_USER_MAPPING_ATTRIBUTES );
134 ATTRIBUTE_USER_MAPPING = new HashMap<>( );
135
136 if ( StringUtils.isNotBlank( strUserMappingAttributes ) )
137 {
138 String[] tabUserProperties = strUserMappingAttributes.split( SEPARATOR );
139 String userPropertie;
140
141 for ( int i = 0; i < tabUserProperties.length; i++ )
142 {
143 userPropertie = AppPropertiesService.getProperty( CONSTANT_LUTECE_USER_PROPERTIES_PATH + "." +
144 tabUserProperties[i] );
145
146 if ( StringUtils.isNotBlank( userPropertie ) )
147 {
148 ATTRIBUTE_USER_MAPPING.put( userPropertie, tabUserProperties[i] );
149 }
150 }
151 }
152
153 String strUserMandatoryAttributes = AppPropertiesService.getProperty( PROPERTY_USER_MANDATORY_ATTRIBUTES );
154 USER_MANDATORY_ATTRIBUTES = new HashMap<>( );
155
156 if ( StringUtils.isNotBlank( strUserMandatoryAttributes ) )
157 {
158 String[] tabUserMandatoryAttributes = strUserMandatoryAttributes.split( SEPARATOR );
159 String userMandatoryAttributes;
160
161 for ( int i = 0; i < tabUserMandatoryAttributes.length; i++ )
162 {
163 userMandatoryAttributes = AppPropertiesService.getProperty( CONSTANT_MANDATORY_ATTRIBUTE + "." +
164 tabUserMandatoryAttributes[i] + ".value" );
165 USER_MANDATORY_ATTRIBUTES.put( tabUserMandatoryAttributes[i], userMandatoryAttributes );
166 }
167 }
168
169 String strRolesAssociations = AppPropertiesService.getProperty( PROPERTY_ROLES_ASSOCIATIONS );
170 ROLES_ASSOCIATIONS = new HashMap<>( );
171
172 if ( StringUtils.isNotBlank( strRolesAssociations ) )
173 {
174 String[] tabRolesAssociations = strRolesAssociations.split( SEPARATOR );
175 String strRoleAssociations;
176
177 for ( int i = 0; i < tabRolesAssociations.length; i++ )
178 {
179 strRoleAssociations = AppPropertiesService.getProperty( CONSTANT_ROLE_ASSOCIATIONS_PATH + "." +
180 tabRolesAssociations[i] );
181
182 if ( StringUtils.isNotBlank( strRoleAssociations ) )
183 {
184 List<String> listAssociations = Arrays.asList( strRoleAssociations.split( SEPARATOR ) );
185 ROLES_ASSOCIATIONS.put( tabRolesAssociations[i], listAssociations );
186 }
187 }
188 }
189 }
190
191
192
193
194
195
196 public String getAuthServiceName( )
197 {
198 if ( _strAuthServiceName == null )
199 {
200 _strAuthServiceName = AppPropertiesService.getProperty( "mylutece-cas.service.name" );
201 }
202
203 return _strAuthServiceName;
204 }
205
206
207
208
209
210
211
212
213 public String getAuthType( HttpServletRequest request )
214 {
215 return HttpServletRequest.BASIC_AUTH;
216 }
217
218
219 @Override
220 public LuteceUser login( String strUserName, String strUserPassword, HttpServletRequest request )
221 throws LoginException, LoginRedirectException
222 {
223 LuteceUser user=null;
224 try {
225 user=getCasAuthenticatedUser(request);
226 } catch (CASAuthenticationException e) {
227
228 String strUrlErrorLoginPage = AppPropertiesService.getProperty( PROPERTY_URL_ERROR_LOGIN_PAGE );
229 String strBackUrlError = AppPropertiesService.getProperty( PROPERTY_BACK_URL_ERROR );
230
231 if ( StringUtils.isEmpty( strUrlErrorLoginPage ) )
232 {
233 try
234 {
235 SiteMessageService.setMessage( request, PROPERTY_MESSAGE_ERROR_LOGIN, null, " ", null, "",
236 SiteMessage.TYPE_STOP, null, strBackUrlError );
237 }
238 catch ( SiteMessageException lme )
239 {
240 strUrlErrorLoginPage = SiteMessageService.setSiteMessageUrl( AppPathService.getPortalUrl( ) );
241 }
242 }
243
244 if ( ( strUrlErrorLoginPage == null ) ||
245 ( !strUrlErrorLoginPage.startsWith( CONSTANT_HTTP ) &&
246 !strUrlErrorLoginPage.startsWith( CONSTANT_HTTPS ) ) )
247 {
248 strUrlErrorLoginPage = AppPathService.getBaseUrl( request ) + strUrlErrorLoginPage;
249 }
250
251 LoginRedirectException ex = new LoginRedirectException( strUrlErrorLoginPage );
252 throw ex;
253 }
254
255
256 return user;
257 }
258
259
260
261
262
263
264
265
266
267 public LuteceUser getHttpAuthenticatedUser( HttpServletRequest request )
268 {
269 LuteceUser user = null;
270 try
271 {
272 user = getCasAuthenticatedUser( request );
273 }
274 catch ( CASAuthenticationException e )
275 {
276 AppLogService.error( e.getMessage( ), e );
277 }
278
279
280 return user;
281 }
282
283
284
285
286
287
288
289
290
291
292
293 private LuteceUser getCasAuthenticatedUser( HttpServletRequest request )throws CASAuthenticationException
294 {
295 AttributePrincipal principal = (AttributePrincipal) request.getUserPrincipal( );
296
297 if ( principal != null )
298 {
299 String strCASUserLogin = cASUserKeyService.getKey( principal.getName( ),
300 principal.getAttributes( ).get( getAttributeUsernameKey( ) ) );
301
302 if ( strCASUserLogin != null )
303 {
304 CASUser/plugins/mylutece/modules/cas/authentication/CASUser.html#CASUser">CASUser user = new CASUser( strCASUserLogin, this );
305 List<String> listRoles = new ArrayList<>( );
306
307 if ( StringUtils.isNotBlank( getDefaultRoleName( ) ) )
308 {
309 listRoles.add( getDefaultRoleName( ) );
310 }
311
312 addUserRoles( principal, listRoles );
313 user.setRoles( listRoles );
314
315 addUserAttributes( principal, user );
316
317 if ( !isAuthorized( user ) )
318 {
319 AppLogService.debug( "Principal found, but user not Authorized" + principal.getName( ) );
320 throw new CASUserNotAuthorizedException();
321
322 }
323 return user;
324 }
325 else
326 {
327 AppLogService.error( "Principal found, but not username attribute can be found for " +
328 principal.getName( ) );
329 throw new CASUserKeyEmptyException();
330 }
331 }
332
333 return null;
334 }
335
336
337
338
339
340
341
342
343
344
345 private void addUserRoles( AttributePrincipal principal, List<String> roles )
346 {
347 for ( String strAttributeKey : ATTRIBUTE_ROLES )
348 {
349 Object attributeValue = principal.getAttributes( ).get( strAttributeKey );
350
351 if ( attributeValue instanceof String )
352 {
353 roles.add( (String) attributeValue );
354 addRolesAssociated( (String) attributeValue, roles );
355 }
356 else if ( attributeValue instanceof List )
357 {
358 for ( Object oValue : (List) attributeValue )
359 {
360 if ( oValue instanceof String )
361 {
362 roles.add( (String) oValue );
363 addRolesAssociated( (String) oValue, roles );
364 }
365 }
366 }
367 }
368 }
369
370
371
372
373
374
375
376
377
378 private void addUserAttributes( AttributePrincipal principal, CASUser user )
379 {
380 String strValue;
381
382 for ( Entry<String, Object> entry : ( (Map<String, Object>) principal.getAttributes( ) ).entrySet( ) )
383 {
384 strValue = null;
385
386 if ( entry.getValue( ) instanceof String )
387 {
388 strValue = (String) entry.getValue( );
389 }
390 else if ( entry.getValue( ) instanceof List )
391 {
392 strValue = getValueAttributeMultivalued( (List) entry.getValue( ) );
393 }
394
395 if ( strValue != null )
396 {
397 if ( ATTRIBUTE_USER_MAPPING.containsKey( entry.getKey( ) ) )
398 {
399 user.setUserInfo( ATTRIBUTE_USER_MAPPING.get( entry.getKey( ) ), strValue );
400 }
401 else
402 {
403 user.setUserInfo( entry.getKey( ), strValue );
404 }
405 }
406 }
407 }
408
409
410
411
412
413
414
415 public void logout( LuteceUser user )
416 {
417 }
418
419 public String[] getRolesByUser( LuteceUser user )
420 {
421 return user.getRoles( );
422 }
423
424
425
426
427
428
429 public LuteceUser getAnonymousUser( )
430 {
431 return new CASUser( LuteceUser.ANONYMOUS_USERNAME, this );
432 }
433
434
435
436
437
438
439
440
441
442
443
444
445
446 public boolean isUserInRole( LuteceUser user, HttpServletRequest request, String strRole )
447 {
448 if ( ( user == null ) || ( strRole == null ) )
449 {
450 return false;
451 }
452
453 String[] roles = user.getRoles( );
454
455 if ( roles != null )
456 {
457 for ( int i = 0; i < roles.length; i++ )
458 {
459 if ( strRole.equals( roles[i] ) )
460 {
461 return true;
462 }
463 }
464 }
465
466 return false;
467 }
468
469
470
471
472
473
474 public boolean isExternalAuthentication( )
475 {
476 return true;
477 }
478
479
480
481
482
483 public String getName( )
484 {
485 return CASPlugin.PLUGIN_NAME;
486 }
487
488
489
490
491
492 public String getPluginName( )
493 {
494 return CASPlugin.PLUGIN_NAME;
495 }
496
497 public ICASUserKeyService getCASUserKeyService( )
498 {
499 return cASUserKeyService;
500 }
501
502 public void setCASUserKeyService( ICASUserKeyService cASUserKeyService )
503 {
504 this.cASUserKeyService = cASUserKeyService;
505 }
506
507
508
509
510
511 private String getDefaultRoleName( )
512 {
513 if ( _strPropertyDefaultRoleName == null )
514 {
515 _strPropertyDefaultRoleName = AppPropertiesService.getProperty( "mylutece-cas.role.name" );
516 }
517
518 return _strPropertyDefaultRoleName;
519 }
520
521
522
523
524
525 private String getAttributeUsernameKey( )
526 {
527 if ( _strAttributeKeyUsername == null )
528 {
529 _strAttributeKeyUsername = AppPropertiesService.getProperty( "mylutece-cas.attributeKeyUsername" );
530 }
531
532 return _strAttributeKeyUsername;
533 }
534
535
536
537
538
539
540 private String getValueAttributeMultivalued( List lValues )
541 {
542 StringBuffer strBuffer = new StringBuffer( );
543 int ncpt = 1;
544
545 for ( Object oValue : lValues )
546 {
547 if ( oValue instanceof String )
548 {
549 strBuffer.append( (String) oValue );
550
551 if ( ncpt < lValues.size( ) )
552 {
553 strBuffer.append( SEPARATOR );
554 }
555
556 ncpt++;
557 }
558 }
559
560 return strBuffer.toString( );
561 }
562
563
564
565
566
567
568 private void addRolesAssociated( String strRole, List<String> roles )
569 {
570 if ( ROLES_ASSOCIATIONS.containsKey( strRole ) )
571 {
572 roles.addAll( ROLES_ASSOCIATIONS.get( strRole ) );
573 }
574 }
575
576
577
578
579
580
581 private boolean isAuthorized( LuteceUser user )
582 {
583 if ( !USER_MANDATORY_ATTRIBUTES.isEmpty( ) )
584 {
585 for ( Entry<String, String> entry : ( USER_MANDATORY_ATTRIBUTES ).entrySet( ) )
586 {
587 if ( ( StringUtils.isEmpty( user.getUserInfo( entry.getKey( ) ) ) ) ||
588 ( !StringUtils.isEmpty( entry.getValue( ) ) &&
589 !entry.getValue( ).equals( user.getUserInfo( entry.getKey( ) ) ) ) )
590 {
591 return false;
592 }
593 }
594 }
595
596 return true;
597 }
598 }