/** * This method checks if the updating claim is an user identity data or security question. * Identity data and security questions are updated by the identity store, therefore they will not * be added to the user store. Other claims are skipped to the set or update. */ @Override public boolean doPreSetUserClaimValue( String userName, String claimURI, String claimValue, String profileName, UserStoreManager userStoreManager) throws UserStoreException { IdentityMgtConfig config = IdentityMgtConfig.getInstance(); if (!config.isListenerEnable()) { return true; } UserIdentityDataStore identityDataStore = IdentityMgtConfig.getInstance().getIdentityDataStore(); UserIdentityClaimsDO identityDTO = null; // security questions and identity claims are updated at the identity store if (claimURI.contains(UserCoreConstants.ClaimTypeURIs.CHALLENGE_QUESTION_URI) || claimURI.contains(UserCoreConstants.ClaimTypeURIs.IDENTITY_CLAIM_URI)) { // identityDTO = identityDataStore.load(userName, userStoreManager); // if (identityDTO == null) { // no such user is added to the system // return false; // } // modified - why is it adding claim in preSet method? // identityDTO.setUserIdentityDataClaim(claimURI, claimValue); // return false; // this will cause // the whole listner to return and fail adding the cliam in doSetUserClaim return true; } else { // a simple user claim. add it to the user store return true; } }
public IdentityMgtEventListener() { module = IdentityMgtConfig.getInstance().getIdentityDataStore(); String adminUserName = IdentityMgtServiceComponent.getRealmService() .getBootstrapRealmConfiguration() .getAdminUserName(); try { IdentityMgtConfig config = IdentityMgtConfig.getInstance(); // Get the policy registry with the loaded policies. policyRegistry = config.getPolicyRegistry(); if (config.isListenerEnable()) { UserStoreManager userStoreMng = IdentityMgtServiceComponent.getRealmService().getBootstrapRealm().getUserStoreManager(); if (!userStoreMng.isReadOnly()) { userStoreMng.setUserClaimValue( adminUserName, UserIdentityDataStore.ACCOUNT_LOCK, Boolean.toString(false), null); } } } catch (UserStoreException e) { log.error("Error while init identity listener", e); } }
public RecoveryProcessor() { List<NotificationSendingModule> notificationSendingModules = IdentityMgtConfig.getInstance().getNotificationSendingModules(); this.defaultModule = notificationSendingModules.get(0); for (NotificationSendingModule module : notificationSendingModules) { this.modules.put(module.getNotificationType(), module); } this.dataStore = IdentityMgtConfig.getInstance().getRecoveryDataStore(); this.notificationSender = new NotificationSender(); questionProcessor = new ChallengeQuestionProcessor(); }
/** * Verifies user id with underline user store * * @param sequence TODO * @param userDTO bean class that contains user and tenant Information * @return true/false whether user is verified or not. If user is a tenant user then always return * false */ public VerificationBean verifyUserForRecovery(int sequence, UserDTO userDTO) { String userId = userDTO.getUserId(); int tenantId = userDTO.getTenantId(); boolean success = false; VerificationBean bean = null; try { UserStoreManager userStoreManager = IdentityMgtServiceComponent.getRealmService() .getTenantUserRealm(tenantId) .getUserStoreManager(); if (userStoreManager.isExistingUser(userId)) { if (IdentityMgtConfig.getInstance().isAuthPolicyAccountLockCheck()) { String accountLock = userStoreManager.getUserClaimValue(userId, UserIdentityDataStore.ACCOUNT_LOCK, null); if (!Boolean.parseBoolean(accountLock)) { success = true; } } else { success = true; } } else { log.error( "User with user name : " + userId + " does not exists in tenant domain : " + userDTO.getTenantDomain()); bean = new VerificationBean( VerificationBean.ERROR_CODE_INVALID_USER + " " + "User does not exists"); } if (success) { String internalCode = generateUserCode(sequence, userId); String key = UUID.randomUUID().toString(); UserRecoveryDataDO dataDO = new UserRecoveryDataDO(userId, tenantId, internalCode, key); if (sequence != 3) { dataStore.invalidate(userId, tenantId); } dataStore.store(dataDO); log.info( "User verification successful for user : "******" from tenant domain :" + userDTO.getTenantDomain()); bean = new VerificationBean(userId, getUserExternalCodeStr(internalCode)); } } catch (Exception e) { String errorMessage = "Error verifying user : "******" " + errorMessage); } if (bean == null) { bean = new VerificationBean(VerificationBean.ERROR_CODE_UNEXPECTED); } return bean; }
@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; }
/** This method is used to check pre conditions when changing the user password. */ public boolean doPreUpdateCredential( String userName, Object newCredential, Object oldCredential, UserStoreManager userStoreManager) throws UserStoreException { if (log.isDebugEnabled()) { log.debug("Pre update credential is called in IdentityMgtEventListener"); } IdentityMgtConfig config = IdentityMgtConfig.getInstance(); if (!config.isListenerEnable()) { return true; } try { // Enforcing the password policies. if (newCredential != null && (newCredential instanceof String && (newCredential.toString().trim().length() > 0))) { policyRegistry.enforcePasswordPolicies(newCredential.toString(), userName); } } catch (PolicyViolationException pe) { log.error(pe.getMessage()); throw new UserStoreException(pe.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 is used when the admin is updating the credentials with an empty credential. A * random password will be generated and will be mailed to the user. */ @Override public boolean doPreUpdateCredentialByAdmin( String userName, Object newCredential, UserStoreManager userStoreManager) throws UserStoreException { if (log.isDebugEnabled()) { log.debug("Pre update credential by admin is called in IdentityMgtEventListener"); } IdentityMgtConfig config = IdentityMgtConfig.getInstance(); if (!config.isListenerEnable()) { return true; } try { // Enforcing the password policies. if (newCredential != null && (newCredential instanceof StringBuffer && (newCredential.toString().trim().length() > 0))) { policyRegistry.enforcePasswordPolicies(newCredential.toString(), userName); } } catch (PolicyViolationException pe) { log.error(pe.getMessage()); throw new UserStoreException(pe.getMessage()); } if (newCredential == null || (newCredential instanceof StringBuffer && ((StringBuffer) newCredential).toString().trim().length() < 1)) { if (!config.isEnableTemporaryPassword()) { log.error("Empty passwords are not allowed"); return false; } if (log.isDebugEnabled()) { log.debug("Credentials are null. Using a temporary password as credentials"); } // temporary passwords will be used char[] temporaryPassword = UserIdentityManagementUtil.generateTemporaryPassword(); // setting the password value ((StringBuffer) newCredential) .replace(0, temporaryPassword.length, new String(temporaryPassword)); UserIdentityMgtBean bean = new UserIdentityMgtBean(); bean.setUserId(userName); bean.setConfirmationCode(newCredential.toString()); bean.setRecoveryType(IdentityMgtConstants.Notification.TEMPORARY_PASSWORD); log.debug("Sending the tempory password to the user " + userName); UserIdentityManagementUtil.notifyViaEmail(bean); } else { log.debug("Updating credentials of user " + userName + " by admin with a non-empty password"); } return true; }
/** Deleting user from the identity database. What are the registry keys ? */ @Override public boolean doPostDeleteUser(String userName, UserStoreManager userStoreManager) throws UserStoreException { IdentityMgtConfig config = IdentityMgtConfig.getInstance(); if (!config.isListenerEnable()) { return true; } // remove from the identity store try { IdentityMgtConfig.getInstance().getIdentityDataStore().remove(userName, userStoreManager); } catch (IdentityException e) { throw new UserStoreException("Error while doPostDeleteUser", e); } // deleting registry meta-data UserRegistry registry = null; try { registry = IdentityMgtServiceComponent.getRegistryService() .getConfigSystemRegistry(userStoreManager.getTenantId()); String identityKeyMgtPath = IdentityMgtConstants.IDENTITY_MANAGEMENT_KEYS + RegistryConstants.PATH_SEPARATOR + userStoreManager.getTenantId() + RegistryConstants.PATH_SEPARATOR + userName; if (registry.resourceExists(identityKeyMgtPath)) { registry.delete(identityKeyMgtPath); } } catch (RegistryException e) { log.error( "Error while deleting recovery data for user : "******" in tenant : " + userStoreManager.getTenantId(), 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; }
/* * TODO - Important. Refactor this method and use recoveryWithNotification instead. */ public NotificationDataDTO notifyWithEmail(UserRecoveryDTO notificationBean) throws IdentityException { String notificationAddress; String confirmationKey = null; NotificationSendingModule module = null; String userId = notificationBean.getUserId(); String domainName = notificationBean.getTenantDomain(); int tenantId = notificationBean.getTenantId(); confirmationKey = notificationBean.getConfirmationCode(); String userStore = IdentityUtil.extractDomainFromName(userId); String userName = UserCoreUtil.removeDomainFromName(userId); NotificationDataDTO notificationData = new NotificationDataDTO(); String type = notificationBean.getNotificationType(); if (type != null) { module = modules.get(type); } if (module == null) { module = defaultModule; } NotificationData emailNotificationData = new NotificationData(); String emailTemplate = null; notificationAddress = module.getNotificationAddress(userId, tenantId); if ((notificationAddress == null) || (notificationAddress.trim().length() < 0)) { log.warn("Notification address is not defined for user " + userId); } String firstName = Utils.getClaimFromUserStoreManager(userId, tenantId, "http://wso2.org/claims/givenname"); emailNotificationData.setTagData(FIRST_NAME, firstName); emailNotificationData.setTagData(USER_STORE_DOMAIN, userStore); emailNotificationData.setTagData(USER_NAME, userName); emailNotificationData.setTagData(TENANT_DOMAIN, domainName); emailNotificationData.setSendTo(notificationAddress); Config config = null; ConfigBuilder configBuilder = ConfigBuilder.getInstance(); try { config = configBuilder.loadConfiguration(ConfigType.EMAIL, StorageType.REGISTRY, tenantId); } catch (Exception e1) { throw new IdentityException( "Error occurred while loading email templates for user : "******"EMAIL", emailTemplate, emailNotificationData); } catch (Exception e) { throw new IdentityException( "Error occurred while creating notification from email template : " + emailTemplate, e); } notificationData.setNotificationAddress(notificationAddress); notificationData.setUserId(userId); notificationData.setDomainName(domainName); notificationData.setNotificationType(notificationBean.getNotificationType()); if (IdentityMgtConfig.getInstance().isNotificationInternallyManaged()) { module.setNotificationData(notificationData); module.setNotification(emailNotification); notificationSender.sendNotification(module); notificationData.setNotificationSent(true); } else { notificationData.setNotificationSent(false); notificationData.setNotificationCode(confirmationKey); } return notificationData; }
/** * Processing recovery * * @param recoveryDTO class that contains user and tenant Information * @return true if the reset request is processed successfully. * @throws IdentityException if fails */ public NotificationDataDTO recoverWithNotification(UserRecoveryDTO recoveryDTO) throws IdentityException { String notificationAddress; String secretKey = null; String confirmationKey = null; NotificationSendingModule module = null; boolean persistData = true; String userId = recoveryDTO.getUserId(); String domainName = recoveryDTO.getTenantDomain(); int tenantId = recoveryDTO.getTenantId(); String userStore = IdentityUtil.extractDomainFromName(userId); String userName = UserCoreUtil.removeDomainFromName(userId); TenantManager tenantManager = IdentityMgtServiceComponent.getRealmService().getTenantManager(); try { Tenant tenant = tenantManager.getTenant(tenantId); if (tenant != null) { domainName = tenant.getDomain(); } } catch (UserStoreException e) { if (log.isDebugEnabled()) { log.debug("No Tenant domain for tenant id " + tenantId, e); } } NotificationDataDTO notificationData = new NotificationDataDTO(); String internalCode = null; String type = recoveryDTO.getNotificationType(); if (type != null) { module = modules.get(type); } if (module == null) { module = defaultModule; } NotificationData emailNotificationData = new NotificationData(); String emailTemplate = null; notificationAddress = Utils.getEmailAddressForUser(userId, tenantId); String firstName = Utils.getClaimFromUserStoreManager(userId, tenantId, "http://wso2.org/claims/givenname"); emailNotificationData.setTagData(FIRST_NAME, firstName); emailNotificationData.setTagData(USER_STORE_DOMAIN, userStore); emailNotificationData.setTagData(USER_NAME, userName); emailNotificationData.setTagData(TENANT_DOMAIN, domainName); if ((notificationAddress == null) || (notificationAddress.trim().length() < 0)) { throw new IdentityException( "Notification sending failure. Notification address is not defined for user : "******"Building notification with data - First name: " + firstName + " User name: " + userId + " Send To: " + notificationAddress); } Config config = null; ConfigBuilder configBuilder = ConfigBuilder.getInstance(); try { config = configBuilder.loadConfiguration(ConfigType.EMAIL, StorageType.REGISTRY, tenantId); } catch (Exception e1) { throw new IdentityException("Error while loading email templates for user : "******"Error while getting user's external code string.", e); } secretKey = UUIDGenerator.generateUUID(); emailNotificationData.setTagData(CONFIRMATION_CODE, confirmationKey); emailTemplate = config.getProperty(IdentityMgtConstants.Notification.PASSWORD_RESET_RECOVERY); } else if (IdentityMgtConstants.Notification.ACCOUNT_CONFORM.equals(notification)) { confirmationKey = UUIDGenerator.generateUUID(); secretKey = UUIDGenerator.generateUUID(); emailNotificationData.setTagData(CONFIRMATION_CODE, confirmationKey); emailTemplate = config.getProperty(IdentityMgtConstants.Notification.ACCOUNT_CONFORM); } else if (IdentityMgtConstants.Notification.TEMPORARY_PASSWORD.equals(notification)) { String temporaryPassword = recoveryDTO.getTemporaryPassword(); // TODO if (temporaryPassword == null || temporaryPassword.trim().length() < 1) { char[] chars = IdentityMgtConfig.getInstance().getPasswordGenerator().generatePassword(); temporaryPassword = new String(chars); } Utils.updatePassword(userId, tenantId, temporaryPassword); emailNotificationData.setTagData(TEMPORARY_PASSWORD, temporaryPassword); emailTemplate = config.getProperty(IdentityMgtConstants.Notification.TEMPORARY_PASSWORD); persistData = false; } else if (IdentityMgtConstants.Notification.ACCOUNT_UNLOCK.equals(notification)) { emailTemplate = config.getProperty(IdentityMgtConstants.Notification.ACCOUNT_UNLOCK); persistData = false; } else if (IdentityMgtConstants.Notification.ACCOUNT_ID_RECOVERY.equals(notification)) { emailTemplate = config.getProperty(IdentityMgtConstants.Notification.ACCOUNT_ID_RECOVERY); persistData = false; } else if (IdentityMgtConstants.Notification.ASK_PASSWORD.equals(notification)) { if (firstName == null || firstName.isEmpty()) { emailNotificationData.setTagData(FIRST_NAME, userId); } internalCode = generateUserCode(2, userId); try { confirmationKey = getUserExternalCodeStr(internalCode); } catch (Exception e) { throw new IdentityException("Error while with recovering with password.", e); } secretKey = UUIDGenerator.generateUUID(); emailNotificationData.setTagData(CONFIRMATION_CODE, confirmationKey); emailTemplate = config.getProperty(IdentityMgtConstants.Notification.ASK_PASSWORD); } if (log.isDebugEnabled()) { log.debug("Notification type: " + notification); } } Notification emailNotification = null; try { emailNotification = NotificationBuilder.createNotification("EMAIL", emailTemplate, emailNotificationData); } catch (Exception e) { throw new IdentityException("Error when creating notification for user : " + userId, e); } notificationData.setNotificationAddress(notificationAddress); notificationData.setUserId(userId); notificationData.setDomainName(domainName); notificationData.setNotificationType(recoveryDTO.getNotificationType()); if (persistData) { UserRecoveryDataDO recoveryDataDO = new UserRecoveryDataDO(userId, tenantId, internalCode, secretKey); dataStore.invalidate(userId, tenantId); dataStore.store(recoveryDataDO); } if (IdentityMgtConfig.getInstance().isNotificationInternallyManaged()) { module.setNotificationData(notificationData); module.setNotification(emailNotification); notificationSender.sendNotification(module); notificationData.setNotificationSent(true); } else { notificationData.setNotificationSent(false); notificationData.setNotificationCode(confirmationKey); } return notificationData; }
/** * 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 will set the default/random password if the password provided is null. The thread * local parameter EMPTY_PASSWORD_USED will be used to track if the password empty in the * doPostAddUser. This method will filter the security question URIs from claims and put those to * the thread local properties. */ @Override public boolean doPreAddUser( String userName, Object credential, String[] roleList, Map<String, String> claims, String profile, UserStoreManager userStoreManager) throws UserStoreException { if (log.isDebugEnabled()) { log.debug("Pre add user is called in IdentityMgtEventListener"); } IdentityMgtConfig config = IdentityMgtConfig.getInstance(); if (!config.isListenerEnable()) { return true; } try { // Enforcing the password policies. if (credential != null && (credential instanceof StringBuffer && (credential.toString().trim().length() > 0))) { policyRegistry.enforcePasswordPolicies(credential.toString(), userName); } } catch (PolicyViolationException pe) { log.error(pe.getMessage()); throw new UserStoreException(pe.getMessage()); } // empty password account creation if (credential == null || (credential instanceof StringBuffer && (credential.toString().trim().length() < 1))) { if (!config.isEnableTemporaryPassword()) { log.error("Empty passwords are not allowed"); return false; } if (log.isDebugEnabled()) { log.debug("Credentials are null. Using a temporary password as credentials"); } // setting the thread-local to check in doPostAddUser threadLocalProperties.get().put(EMPTY_PASSWORD_USED, true); // temporary passwords will be used char[] temporaryPassword = UserIdentityManagementUtil.generateTemporaryPassword(); // setting the password value ((StringBuffer) credential) .replace(0, temporaryPassword.length, new String(temporaryPassword)); } // Filtering security question URIs from claims and add them to the thread local dto Map<String, String> userDataMap = new HashMap<String, String>(); // TODO why challenge Q 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)) { userDataMap.put(claim.getKey(), claim.getValue()); it.remove(); } } UserIdentityClaimsDO identityDTO = new UserIdentityClaimsDO(userName, userDataMap); // adding dto to thread local to be read again from the doPostAddUser method threadLocalProperties.get().put(USER_IDENTITY_DO, identityDTO); 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; }