@Override public boolean doPostUpdateCredential( String userName, Object credential, UserStoreManager userStoreManager) throws UserStoreException { IdentityMgtConfig config = IdentityMgtConfig.getInstance(); UserIdentityClaimsDO userIdentityDTO = module.load(userName, userStoreManager); if (userIdentityDTO == null) { userIdentityDTO = new UserIdentityClaimsDO(userName); } // Do not timestamp if OTP enabled. boolean userOTPEnabled = userIdentityDTO.getOneTimeLogin(); if (config.isAuthPolicyExpirePasswordCheck() && !userOTPEnabled && (!userStoreManager.isReadOnly())) { Calendar currentTime = Calendar.getInstance(); userIdentityDTO.setPasswordTimeStamp(Calendar.getInstance().getTimeInMillis()); try { // Store the new timestamp after change password module.store(userIdentityDTO, userStoreManager); } catch (IdentityException e) { throw new UserStoreException(e.getMessage()); } } return true; }
/** Adding the user identity data to the claims set */ @Override public boolean doPostGetUserClaimValues( String userName, String[] claims, String profileName, Map<String, String> claimMap, UserStoreManager storeManager) throws UserStoreException { IdentityMgtConfig config = IdentityMgtConfig.getInstance(); if (!config.isListenerEnable()) { return true; } if (claimMap == null) { claimMap = new HashMap<String, String>(); } UserIdentityDataStore identityDataStore = IdentityMgtConfig.getInstance().getIdentityDataStore(); // check if there are identity claims boolean containsIdentityClaims = false; for (String claim : claims) { if (claim.contains(UserCoreConstants.ClaimTypeURIs.CHALLENGE_QUESTION_URI) || claim.contains(UserCoreConstants.ClaimTypeURIs.IDENTITY_CLAIM_URI)) { containsIdentityClaims = true; break; } } // if there are no identity claims, let it go if (!containsIdentityClaims) { return true; } // there is/are identity claim/s . load the dto UserIdentityClaimsDO identityDTO = identityDataStore.load(userName, storeManager); // if no user identity data found, just continue if (identityDTO == null) { return true; } // data found, add the values for security questions and identity claims for (String claim : claims) { if (identityDTO.getUserDataMap().containsKey(claim)) { claimMap.put(claim, identityDTO.getUserDataMap().get(claim)); } } return true; }
/** * As in the above method the user account lock claim, primary challenges claim will be separately * handled. Identity claims will be removed from the claim set before adding claims to the user * store. */ @Override public boolean doPreSetUserClaimValues( String userName, Map<String, String> claims, String profileName, UserStoreManager userStoreManager) throws UserStoreException { IdentityMgtConfig config = IdentityMgtConfig.getInstance(); if (!config.isListenerEnable()) { return true; } UserIdentityDataStore identityDataStore = IdentityMgtConfig.getInstance().getIdentityDataStore(); // To fix https://wso2.org/jira/browse/IDENTITY-1227 UserIdentityClaimsDO identityDTO = new UserIdentityClaimsDO(userName); // identityDTO = identityDataStore.load(userName, userStoreManager); // if (identityDTO == null) { // user doesn't exist in the system // return false; // } // removing identity claims and security questions Iterator<Entry<String, String>> it = claims.entrySet().iterator(); while (it.hasNext()) { Map.Entry<String, String> claim = it.next(); if (claim.getKey().contains(UserCoreConstants.ClaimTypeURIs.CHALLENGE_QUESTION_URI) || claim.getKey().contains(UserCoreConstants.ClaimTypeURIs.IDENTITY_CLAIM_URI)) { identityDTO.setUserIdentityDataClaim(claim.getKey(), claim.getValue()); it.remove(); } } // storing the identity claims and security questions try { identityDataStore.store(identityDTO, userStoreManager); } catch (IdentityException e) { throw new UserStoreException("Error while doPreSetUserClaimValues", e); } return true; }
/** * This method checks if the user account exist or is locked. If the account is locked, the * authentication process will be terminated after this method returning false. */ @Override public boolean doPreAuthenticate( String userName, Object credential, UserStoreManager userStoreManager) throws UserStoreException { if (log.isDebugEnabled()) { log.debug("Pre authenticator is called in IdentityMgtEventListener"); } IdentityMgtConfig config = IdentityMgtConfig.getInstance(); if (!config.isEnableAuthPolicy()) { return true; } if (config.isAuthPolicyAccountExistCheck() && !userStoreManager.isExistingUser(userName)) { log.warn("User name does not exist in system : " + userName); throw new UserStoreException(UserCoreConstants.ErrorCode.USER_DOES_NOT_EXIST); } UserIdentityClaimsDO userIdentityDTO = module.load(userName, userStoreManager); // if the account is locked, should not be able to log in if (userIdentityDTO != null && userIdentityDTO.isAccountLocked()) { // If unlock time is specified then unlock the account. if ((userIdentityDTO.getUnlockTime() != 0) && (System.currentTimeMillis() >= userIdentityDTO.getUnlockTime())) { userIdentityDTO.setAccountLock(false); userIdentityDTO.setUnlockTime(0); try { module.store(userIdentityDTO, userStoreManager); } catch (IdentityException e) { throw new UserStoreException("Error while saving user", e); } } else { log.warn( "User account is locked for user : "******". cannot login until the account is unlocked "); throw new UserStoreException(UserCoreConstants.ErrorCode.USER_IS_LOCKED); } } return true; }
/** * This method locks the created accounts based on the account policies or based on the account * confirmation method being used. Two account confirmation methods are used : Temporary Password * and Verification Code. In the case of temporary password is used the temporary password will be * emailed to the user. In the case of verification code, the code will be emailed to the user. * The security questions filter ad doPreAddUser will be persisted in this method. */ @Override public boolean doPostAddUser( String userName, Object credential, String[] roleList, Map<String, String> claims, String profile, UserStoreManager userStoreManager) throws UserStoreException { if (log.isDebugEnabled()) { log.debug("Post add user is called in IdentityMgtEventListener"); } IdentityMgtConfig config = IdentityMgtConfig.getInstance(); if (!config.isListenerEnable()) { return true; } // reading the value from the thread local UserIdentityClaimsDO userIdentityClaimsDO = (UserIdentityClaimsDO) threadLocalProperties.get().get(USER_IDENTITY_DO); if (config.isEnableUserAccountVerification()) { // empty password account creation if (threadLocalProperties.get().containsKey(EMPTY_PASSWORD_USED)) { // store identity data userIdentityClaimsDO.setAccountLock(false).setPasswordTimeStamp(System.currentTimeMillis()); try { module.store(userIdentityClaimsDO, userStoreManager); } catch (IdentityException e) { throw new UserStoreException("Error while doPostAddUser", e); } // store identity metadata UserRecoveryDataDO metadataDO = new UserRecoveryDataDO(); metadataDO .setUserName(userName) .setTenantId(userStoreManager.getTenantId()) .setCode((String) credential); // try { // UserIdentityManagementUtil.storeUserIdentityMetadata(metadataDO); // } catch (IdentityException e) { // throw new UserStoreException("Error while doPreAddUser", e); // } // set recovery data RecoveryProcessor processor = new RecoveryProcessor(); VerificationBean verificationBean = new VerificationBean(); try { verificationBean = processor.updateConfirmationCode(1, userName, userStoreManager.getTenantId()); } catch (IdentityException e) { // TODO Auto-generated catch block e.printStackTrace(); } // preparing a bean to send the email UserIdentityMgtBean bean = new UserIdentityMgtBean(); bean.setUserId(userName) .setConfirmationCode(verificationBean.getKey()) .setRecoveryType(IdentityMgtConstants.Notification.TEMPORARY_PASSWORD) .setEmail(claims.get(config.getAccountRecoveryClaim())); UserRecoveryDTO recoveryDto = new UserRecoveryDTO(userName); recoveryDto.setNotification(IdentityMgtConstants.Notification.ASK_PASSWORD); recoveryDto.setNotificationType("EMAIL"); recoveryDto.setTenantId(userStoreManager.getTenantId()); recoveryDto.setConfirmationCode(verificationBean.getKey()); NotificationDataDTO notificationDto = null; try { notificationDto = processor.recoverWithNotification(recoveryDto); } catch (IdentityException e) { if (log.isDebugEnabled()) { log.debug(e.getMessage()); } throw new UserStoreException("Error while sending notification. " + e.getMessage()); } if (notificationDto != null && notificationDto.isNotificationSent()) { return true; } else { return false; } // sending email // UserIdentityManagementUtil.notifyViaEmail(bean); } else { // none-empty passwords. lock account and persist /* This scenario needs to be validated. * userIdentityClaimsDO.setAccountLock(true) .setPasswordTimeStamp(System.currentTimeMillis()); try { UserIdentityManagementUtil.storeUserIdentityClaims(userIdentityClaimsDO, userStoreManager); } catch (IdentityException e) { throw new UserStoreException("Error while doPostAddUser", e); } String confirmationCode = UserIdentityManagementUtil.generateRandomConfirmationCode(); // store identity metadata UserRecoveryDataDO metadataDO = new UserRecoveryDataDO(); metadataDO.setUserName(userName).setTenantId(userStoreManager.getTenantId()) .setCode(confirmationCode); try { UserIdentityManagementUtil.storeUserIdentityMetadata(metadataDO); } catch (IdentityException e) { throw new UserStoreException("Error while doPostAddUser", e); } // sending a mail with the confirmation code UserIdentityMgtBean bean = new UserIdentityMgtBean(); bean.setUserId(userName) .setRecoveryType(IdentityMgtConstants.Notification.ACCOUNT_CONFORM) .setConfirmationCode(confirmationCode); UserIdentityManagementUtil.notifyViaEmail(bean); return true; */ } } // No account recoveries are defined, no email will be sent. if (config.isAuthPolicyAccountLockOnCreation()) { // accounts are locked. Admin should unlock userIdentityClaimsDO.setAccountLock(true); userIdentityClaimsDO.setPasswordTimeStamp(System.currentTimeMillis()); try { config.getIdentityDataStore().store(userIdentityClaimsDO, userStoreManager); } catch (IdentityException e) { throw new UserStoreException("Error while doPostAddUser", e); } } return true; }
/** * This method locks the accounts after a configured number of authentication failure attempts. * And unlocks accounts based on successful authentications. */ @Override public boolean doPostAuthenticate( String userName, boolean authenticated, UserStoreManager userStoreManager) throws UserStoreException { if (log.isDebugEnabled()) { log.debug("Post authenticator is called in IdentityMgtEventListener"); } IdentityMgtConfig config = IdentityMgtConfig.getInstance(); if (!config.isEnableAuthPolicy()) { return authenticated; } UserIdentityClaimsDO userIdentityDTO = module.load(userName, userStoreManager); if (userIdentityDTO == null) { userIdentityDTO = new UserIdentityClaimsDO(userName); } boolean userOTPEnabled = userIdentityDTO.getOneTimeLogin(); // One time password check if (authenticated && config.isAuthPolicyOneTimePasswordCheck() && (!userStoreManager.isReadOnly())) { // reset password of the user and notify user of the new password if (userOTPEnabled) { String password = UserIdentityManagementUtil.generateTemporaryPassword().toString(); userStoreManager.updateCredentialByAdmin(userName, password); // Get email user claim value String email = userStoreManager.getUserClaimValue( userName, UserCoreConstants.ClaimTypeURIs.EMAIL_ADDRESS, null); if (email == null) { throw new UserStoreException("No user email provided for user " + userName); } List<NotificationSendingModule> notificationModules = config.getNotificationSendingModules(); if (notificationModules != null) { NotificationDataDTO notificationData = new NotificationDataDTO(); NotificationData emailNotificationData = new NotificationData(); String emailTemplate = null; int tenantId = userStoreManager.getTenantId(); String firstName = null; try { firstName = Utils.getClaimFromUserStoreManager( userName, tenantId, "http://wso2.org/claims/givenname"); } catch (IdentityException e2) { throw new UserStoreException("Could not load user given name"); } emailNotificationData.setTagData("first-name", firstName); emailNotificationData.setTagData("user-name", userName); emailNotificationData.setTagData("otp-password", password); emailNotificationData.setSendTo(email); Config emailConfig = null; ConfigBuilder configBuilder = ConfigBuilder.getInstance(); try { emailConfig = configBuilder.loadConfiguration(ConfigType.EMAIL, StorageType.REGISTRY, tenantId); } catch (Exception e1) { throw new UserStoreException("Could not load the email template configuration"); } emailTemplate = emailConfig.getProperty("otp"); Notification emailNotification = null; try { emailNotification = NotificationBuilder.createNotification( "EMAIL", emailTemplate, emailNotificationData); } catch (Exception e) { throw new UserStoreException("Could not create the email notification"); } NotificationSender sender = new NotificationSender(); for (NotificationSendingModule notificationSendingModule : notificationModules) { if (IdentityMgtConfig.getInstance().isNotificationInternallyManaged()) { notificationSendingModule.setNotificationData(notificationData); notificationSendingModule.setNotification(emailNotification); sender.sendNotification(notificationSendingModule); notificationData.setNotificationSent(true); } } } else { throw new UserStoreException("No notification modules configured"); } } } // Password expire check. Not for OTP enabled users. if (authenticated && config.isAuthPolicyExpirePasswordCheck() && !userOTPEnabled && (!userStoreManager.isReadOnly())) { // TODO - password expire impl // Refactor adduser and change password api to stamp the time // Check user's expire time in the claim // if expired redirect to change password // else pass through /* long timestamp = userIdentityDTO.getPasswordTimeStamp(); // Only allow behavior to users with this claim. Intent bypass for admin? if (timestamp > 0) { Calendar passwordExpireTime = Calendar.getInstance(); passwordExpireTime.setTimeInMillis(timestamp); int expireDuration = config.getAuthPolicyPasswordExpireTime(); if (expireDuration > 0) { passwordExpireTime.add(Calendar.DATE, expireDuration); Calendar currentTime = Calendar.getInstance(); if (currentTime.compareTo(passwordExpireTime) > 0) { // password expired // set flag to redirect log.error("Password is expired ..........."); // throw new UserStoreException("Password is expired"); } } } */ } if (!authenticated && config.isAuthPolicyAccountLockOnFailure()) { userIdentityDTO.setFailAttempts(); // reading the max allowed #of failure attempts if (userIdentityDTO.getFailAttempts() >= config.getAuthPolicyMaxLoginAttempts()) { if (log.isDebugEnabled()) { log.debug( "User, " + userName + " has exceed the max failed login attempts. " + "User account would be locked"); } userIdentityDTO.setAccountLock(true); // lock time from the config int lockTime = IdentityMgtConfig.getInstance().getAuthPolicyLockingTime(); if (lockTime != 0) { userIdentityDTO.setUnlockTime(System.currentTimeMillis() + (lockTime * 60 * 1000)); } } try { module.store(userIdentityDTO, userStoreManager); } catch (IdentityException e) { throw new UserStoreException("Error while doPostAuthenticate", e); } } else { // if the account was locked due to account verification process, // the unlock the account and reset the number of failedAttempts if (userIdentityDTO.isAccountLocked() || userIdentityDTO.getFailAttempts() > 0) { userIdentityDTO.setAccountLock(false); userIdentityDTO.setFailAttempts(0); userIdentityDTO.setUnlockTime(0); try { module.store(userIdentityDTO, userStoreManager); } catch (IdentityException e) { throw new UserStoreException("Error while doPostAuthenticate", e); } } } return true; }