use of org.wso2.carbon.identity.governance.listener.IdentityMgtEventListener in project carbon-identity-framework by wso2.
the class IdentityMgtEventListener method doPostAuthenticate.
/**
* 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 (!isEnable()) {
return true;
}
IdentityUtil.threadLocalProperties.get().remove(IdentityCoreConstants.USER_ACCOUNT_STATE);
String domainName = userStoreManager.getRealmConfiguration().getUserStoreProperty(UserCoreConstants.RealmConfig.PROPERTY_DOMAIN_NAME);
String usernameWithDomain = IdentityUtil.addDomainToName(userName, domainName);
boolean isUserExistInCurrentDomain = userStoreManager.isExistingUser(usernameWithDomain);
if (authenticated && isUserExistInCurrentDomain) {
if (isUserExistInCurrentDomain) {
UserIdentityClaimsDO userIdentityDTO = module.load(userName, userStoreManager);
userIdentityDTO.setLastLogonTime(System.currentTimeMillis());
try {
module.store(userIdentityDTO, userStoreManager);
} catch (IdentityException e) {
throw new UserStoreException(String.format("Error while saving user store data : %s for user : %s.", UserIdentityDataStore.LAST_LOGON_TIME, userName), e);
}
}
}
// Top level try and finally blocks are used to unset thread local variables
try {
if (!IdentityUtil.threadLocalProperties.get().containsKey(DO_POST_AUTHENTICATE)) {
IdentityUtil.threadLocalProperties.get().put(DO_POST_AUTHENTICATE, true);
if (log.isDebugEnabled()) {
log.debug("Post authenticator is called in IdentityMgtEventListener");
}
IdentityMgtConfig config = IdentityMgtConfig.getInstance();
if (!config.isEnableAuthPolicy()) {
return true;
}
UserIdentityClaimsDO userIdentityDTO = module.load(userName, userStoreManager);
if (userIdentityDTO == null) {
userIdentityDTO = new UserIdentityClaimsDO(userName);
userIdentityDTO.setTenantId(userStoreManager.getTenantId());
}
boolean userOTPEnabled = userIdentityDTO.getOneTimeLogin();
// One time password check
if (authenticated && config.isAuthPolicyOneTimePasswordCheck() && (!userStoreManager.isReadOnly()) && userOTPEnabled) {
// reset password of the user and notify user of the new password
String password = new String(UserIdentityManagementUtil.generateTemporaryPassword());
userStoreManager.updateCredentialByAdmin(userName, password);
// Get email user claim value
String email = userStoreManager.getUserClaimValue(userName, UserCoreConstants.ClaimTypeURIs.EMAIL_ADDRESS, null);
if (StringUtils.isBlank(email)) {
throw new UserStoreException("No user email provided for user : " + userName);
}
List<NotificationSendingModule> notificationModules = config.getNotificationSendingModules();
if (notificationModules != null) {
NotificationDataDTO notificationData = new NotificationDataDTO();
if (MessageContext.getCurrentMessageContext() != null && MessageContext.getCurrentMessageContext().getProperty(MessageContext.TRANSPORT_HEADERS) != null) {
Map<String, String> transportHeaderMap = (Map) MessageContext.getCurrentMessageContext().getProperty(MessageContext.TRANSPORT_HEADERS);
if (MapUtils.isNotEmpty(transportHeaderMap)) {
TransportHeader[] transportHeadersArray = new TransportHeader[transportHeaderMap.size()];
int i = 0;
for (Map.Entry<String, String> entry : transportHeaderMap.entrySet()) {
TransportHeader transportHeader = new TransportHeader();
transportHeader.setHeaderName(entry.getKey());
transportHeader.setHeaderValue(entry.getValue());
transportHeadersArray[i] = transportHeader;
++i;
}
notificationData.setTransportHeaders(transportHeadersArray);
}
}
NotificationData emailNotificationData = new NotificationData();
String emailTemplate = null;
int tenantId = userStoreManager.getTenantId();
String firstName = null;
String userStoreDomain = userStoreManager.getRealmConfiguration().getUserStoreProperty(UserCoreConstants.RealmConfig.PROPERTY_DOMAIN_NAME);
String domainSpecificUserName = UserCoreUtil.addDomainToName(userName, userStoreDomain);
String tenantDomain = IdentityTenantUtil.getTenantDomain(userStoreManager.getTenantId());
try {
firstName = Utils.getClaimFromUserStoreManager(domainSpecificUserName, tenantId, UserCoreConstants.ClaimTypeURIs.GIVEN_NAME);
} catch (IdentityException e2) {
throw new UserStoreException("Could not load user given name", e2);
}
emailNotificationData.setTagData("first-name", firstName);
emailNotificationData.setTagData("user-name", userName);
emailNotificationData.setTagData("otp-password", password);
emailNotificationData.setTagData("userstore-domain", userStoreDomain);
emailNotificationData.setTagData("tenant-domain", tenantDomain);
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 for user : " + userName, e1);
}
emailTemplate = emailConfig.getProperty("otp");
Notification emailNotification = null;
try {
emailNotification = NotificationBuilder.createNotification(EMAIL_NOTIFICATION_TYPE, emailTemplate, emailNotificationData);
} catch (Exception e) {
throw new UserStoreException("Could not create the email notification for template: " + emailTemplate, e);
}
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
}
if (!authenticated && config.isAuthPolicyAccountLockOnFailure()) {
// reading the max allowed #of failure attempts
if (isUserExistInCurrentDomain) {
userIdentityDTO.setFailAttempts();
if (userIdentityDTO.getFailAttempts() >= config.getAuthPolicyMaxLoginAttempts()) {
log.info("User, " + userName + " has exceed the max failed login attempts. " + "User account would be locked");
IdentityErrorMsgContext customErrorMessageContext = new IdentityErrorMsgContext(UserCoreConstants.ErrorCode.USER_IS_LOCKED + ":" + IdentityMgtConstants.LockedReason.MAX_ATTEMTS_EXCEEDED.toString(), userIdentityDTO.getFailAttempts(), config.getAuthPolicyMaxLoginAttempts());
IdentityUtil.setIdentityErrorMsg(customErrorMessageContext);
IdentityUtil.threadLocalProperties.get().put(IdentityCoreConstants.USER_ACCOUNT_STATE, UserCoreConstants.ErrorCode.USER_IS_LOCKED);
if (log.isDebugEnabled()) {
log.debug("Username :" + userName + "Exceeded the maximum login attempts. User locked, ErrorCode :" + UserCoreConstants.ErrorCode.USER_IS_LOCKED);
}
userIdentityDTO.getUserDataMap().put(UserIdentityDataStore.ACCOUNT_LOCKED_REASON, IdentityMgtConstants.LockedReason.MAX_ATTEMTS_EXCEEDED.toString());
userIdentityDTO.setAccountLock(true);
userIdentityDTO.setFailAttempts(0);
// lock time from the config
int lockTime = IdentityMgtConfig.getInstance().getAuthPolicyLockingTime();
if (lockTime != 0) {
userIdentityDTO.setUnlockTime(System.currentTimeMillis() + (lockTime * 60 * 1000L));
}
} else {
IdentityErrorMsgContext customErrorMessageContext = new IdentityErrorMsgContext(UserCoreConstants.ErrorCode.INVALID_CREDENTIAL, userIdentityDTO.getFailAttempts(), config.getAuthPolicyMaxLoginAttempts());
IdentityUtil.setIdentityErrorMsg(customErrorMessageContext);
if (log.isDebugEnabled()) {
log.debug("Username :" + userName + "Invalid Credential, ErrorCode :" + UserCoreConstants.ErrorCode.INVALID_CREDENTIAL);
}
}
try {
module.store(userIdentityDTO, userStoreManager);
} catch (IdentityException e) {
throw new UserStoreException("Error while saving user store data for user : " + userName, e);
}
} else {
if (log.isDebugEnabled()) {
log.debug("User, " + userName + " is not exists in " + domainName);
}
}
} else {
// the unlock the account and reset the number of failedAttempts
if (userIdentityDTO.isAccountLocked() || userIdentityDTO.getFailAttempts() > 0 || userIdentityDTO.getAccountLock()) {
userIdentityDTO.getUserDataMap().put(UserIdentityDataStore.ACCOUNT_LOCKED_REASON, "");
userIdentityDTO.setAccountLock(false);
userIdentityDTO.setFailAttempts(0);
userIdentityDTO.setUnlockTime(0);
try {
module.store(userIdentityDTO, userStoreManager);
} catch (IdentityException e) {
throw new UserStoreException("Error while saving user store data for user : " + userName, e);
}
}
}
}
return true;
} finally {
// Remove thread local variable
IdentityUtil.threadLocalProperties.get().remove(DO_POST_AUTHENTICATE);
}
}
use of org.wso2.carbon.identity.governance.listener.IdentityMgtEventListener in project carbon-identity-framework by wso2.
the class IdentityMgtEventListener method doPreUpdateCredential.
/**
* This method is used to check pre conditions when changing the user
* password.
*/
@Override
public boolean doPreUpdateCredential(String userName, Object newCredential, Object oldCredential, UserStoreManager userStoreManager) throws UserStoreException {
if (!isEnable()) {
return true;
}
if (log.isDebugEnabled()) {
log.debug("Pre update credential is called in IdentityMgtEventListener");
}
try {
if (!IdentityUtil.threadLocalProperties.get().containsKey(DO_PRE_UPDATE_CREDENTIAL)) {
IdentityUtil.threadLocalProperties.get().put(DO_PRE_UPDATE_CREDENTIAL, true);
IdentityMgtConfig config = IdentityMgtConfig.getInstance();
UserIdentityDataStore identityDataStore = IdentityMgtConfig.getInstance().getIdentityDataStore();
UserIdentityClaimsDO identityDTO = identityDataStore.load(userName, userStoreManager);
boolean isAccountDisabled = false;
if (identityDTO != null) {
isAccountDisabled = identityDTO.getIsAccountDisabled();
} else {
throw new UserStoreException("Cannot get the user account active status.");
}
if (isAccountDisabled) {
IdentityErrorMsgContext customErrorMessageContext = new IdentityErrorMsgContext(IdentityCoreConstants.USER_ACCOUNT_DISABLED_ERROR_CODE);
IdentityUtil.setIdentityErrorMsg(customErrorMessageContext);
// account is already disabled and trying to update the credential without enabling it
log.warn("Trying to update credential of a disabled user account. This is not permitted.");
throw new UserStoreException("User account is disabled, can't update credential without enabling.");
}
try {
// Enforcing the password policies.
if (newCredential != null && (newCredential instanceof String && (newCredential.toString().trim().length() > 0))) {
policyRegistry.enforcePasswordPolicies(newCredential.toString(), userName);
}
} catch (PolicyViolationException pe) {
throw new UserStoreException(pe.getMessage(), pe);
}
}
return true;
} finally {
// Remove thread local variable
IdentityUtil.threadLocalProperties.get().remove(DO_PRE_UPDATE_CREDENTIAL);
}
}
use of org.wso2.carbon.identity.governance.listener.IdentityMgtEventListener in project carbon-identity-framework by wso2.
the class IdentityMgtEventListener method doPostAddUser.
/**
* 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 (!isEnable()) {
return true;
}
// Top level try and finally blocks are used to unset thread local variables
try {
if (!IdentityUtil.threadLocalProperties.get().containsKey(DO_POST_ADD_USER)) {
IdentityUtil.threadLocalProperties.get().put(DO_POST_ADD_USER, true);
if (log.isDebugEnabled()) {
log.debug("Post add user is called in IdentityMgtEventListener");
}
IdentityMgtConfig config = IdentityMgtConfig.getInstance();
// reading the value from the thread local
UserIdentityClaimsDO userIdentityClaimsDO = (UserIdentityClaimsDO) IdentityUtil.threadLocalProperties.get().get(USER_IDENTITY_DO);
if (config.isEnableUserAccountVerification() && IdentityUtil.threadLocalProperties.get().containsKey(EMPTY_PASSWORD_USED)) {
// empty password account creation
String domainName = ((org.wso2.carbon.user.core.UserStoreManager) userStoreManager).getRealmConfiguration().getUserStoreProperty(UserCoreConstants.RealmConfig.PROPERTY_DOMAIN_NAME);
if (!UserCoreConstants.PRIMARY_DEFAULT_DOMAIN_NAME.equals(domainName)) {
userName = domainName + UserCoreConstants.DOMAIN_SEPARATOR + userName;
}
// store identity data
userIdentityClaimsDO.getUserDataMap().put(UserIdentityDataStore.ACCOUNT_LOCKED_REASON, "");
userIdentityClaimsDO.setAccountLock(false);
try {
module.store(userIdentityClaimsDO, userStoreManager);
} catch (IdentityException e) {
// roleback user
userStoreManager.deleteUser(userName);
throw new UserStoreException("Error while saving user store for user : " + userName, e);
}
// store identity metadata
UserRecoveryDataDO metadataDO = new UserRecoveryDataDO();
metadataDO.setUserName(userName).setTenantId(userStoreManager.getTenantId()).setCode((String) credential);
// set recovery data
RecoveryProcessor processor = new RecoveryProcessor();
UserRecoveryDTO recoveryDto = new UserRecoveryDTO(userName);
recoveryDto.setNotification(IdentityMgtConstants.Notification.ASK_PASSWORD);
recoveryDto.setNotificationType("EMAIL");
recoveryDto.setTenantId(userStoreManager.getTenantId());
NotificationDataDTO notificationDto = null;
try {
notificationDto = processor.recoverWithNotification(recoveryDto);
} catch (IdentityException e) {
// roleback user
userStoreManager.deleteUser(userName);
throw new UserStoreException("Error while sending notification for user : " + userName, e);
}
return notificationDto != null && notificationDto.isNotificationSent();
}
// No account recoveries are defined, no email will be sent.
if (config.isAuthPolicyAccountLockOnCreation()) {
// accounts are locked. Admin should unlock
userIdentityClaimsDO.getUserDataMap().put(UserIdentityDataStore.ACCOUNT_LOCKED_REASON, IdentityMgtConstants.LockedReason.UNVERIFIED.toString());
userIdentityClaimsDO.setAccountLock(true);
try {
config.getIdentityDataStore().store(userIdentityClaimsDO, userStoreManager);
} catch (IdentityException e) {
// roleback user
userStoreManager.deleteUser(userName);
throw new UserStoreException("Error while saving user store data for user : " + userName, e);
}
}
// When claims available in user add request like http://wso2.org/claims/identity/accountLocked
if (!config.isEnableUserAccountVerification() && !config.isAuthPolicyAccountLockOnCreation() && userIdentityClaimsDO != null) {
try {
if (log.isDebugEnabled()) {
log.debug("Storing identity-mgt claims since they are available in the addUser request");
}
module.store(userIdentityClaimsDO, userStoreManager);
} catch (IdentityException e) {
// roleback user
userStoreManager.deleteUser(userName);
throw new UserStoreException("Error while saving user store data for user : " + userName, e);
}
}
}
return true;
} finally {
// Remove thread local variable
IdentityUtil.threadLocalProperties.get().remove(DO_POST_ADD_USER);
IdentityUtil.threadLocalProperties.get().remove(EMPTY_PASSWORD_USED);
IdentityUtil.threadLocalProperties.get().remove(USER_IDENTITY_DO);
}
}
use of org.wso2.carbon.identity.governance.listener.IdentityMgtEventListener in project carbon-identity-framework by wso2.
the class IdentityMgtServiceComponent method activate.
@Activate
protected void activate(ComponentContext context) {
Dictionary<String, String> props = new Hashtable<String, String>();
props.put(CarbonConstants.AXIS2_CONFIG_SERVICE, AxisObserver.class.getName());
context.getBundleContext().registerService(AxisObserver.class.getName(), new IdentityMgtDeploymentInterceptor(), props);
init();
if (log.isDebugEnabled()) {
log.debug("Identity Management Listener is enabled");
}
ServiceRegistration serviceRegistration = context.getBundleContext().registerService(UserOperationEventListener.class.getName(), new IdentityMgtEventListener(), null);
if (serviceRegistration != null) {
if (log.isDebugEnabled()) {
log.debug("Identity Management - UserOperationEventListener registered.");
}
} else {
log.error("Identity Management - UserOperationEventListener could not be registered.");
}
UserOperationsNotificationListener notificationListener = new UserOperationsNotificationListener();
ServiceRegistration userOperationNotificationSR = context.getBundleContext().registerService(UserOperationEventListener.class.getName(), notificationListener, null);
context.getBundleContext().registerService(TenantMgtListener.class.getName(), new TenantManagementListener(), null);
context.getBundleContext().registerService(UserOperationEventListener.class.getName(), new UserSessionTerminationListener(), null);
if (userOperationNotificationSR != null) {
if (log.isDebugEnabled()) {
log.debug("Identity Management - UserOperationNotificationListener registered.");
}
} else {
log.error("Identity Management - UserOperationNotificationListener could not be registered.");
}
ServiceRegistration identityUserIdResolverListener = context.getBundleContext().registerService(UserOperationEventListener.class.getName(), new IdentityUserIdResolverListener(), null);
if (identityUserIdResolverListener != null) {
if (log.isDebugEnabled()) {
log.debug("Identity Management - IdentityUserIdResolverListener registered.");
}
} else {
log.error("Identity Management - IdentityUserIdResolverListener could not be registered.");
}
ServiceRegistration identityUserNameResolverListener = context.getBundleContext().registerService(UserOperationEventListener.class.getName(), new IdentityUserNameResolverListener(), null);
if (identityUserNameResolverListener != null) {
if (log.isDebugEnabled()) {
log.debug("Identity Management - IdentityUserNameResolverListener registered.");
}
} else {
log.error("Identity Management - IdentityUserNameResolverListener could not be registered.");
}
if (log.isDebugEnabled()) {
log.debug("Identity Management bundle is activated");
}
RegistryCleanUpService registryCleanUpService = new RegistryCleanUpService(IdentityMgtConfig.getInstance().getRegistryCleanUpPeriod(), IdentityMgtConfig.getInstance().getRegistryCleanUpPeriod());
registryCleanUpService.activateCleanUp();
// Set user session mapping enabled.
IdentityMgtServiceDataHolder.getInstance().setUserSessionMappingEnabled(FrameworkUtils.isUserSessionMappingEnabled());
}
use of org.wso2.carbon.identity.governance.listener.IdentityMgtEventListener in project carbon-identity-framework by wso2.
the class IdentityMgtEventListener method doPreUpdateCredentialByAdmin.
/**
* 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 (!isEnable()) {
return true;
}
if (log.isDebugEnabled()) {
log.debug("Pre update credential by admin is called in IdentityMgtEventListener");
}
// Top level try and finally blocks are used to unset thread local variables
try {
if (!IdentityUtil.threadLocalProperties.get().containsKey(DO_PRE_UPDATE_CREDENTIAL_BY_ADMIN)) {
IdentityUtil.threadLocalProperties.get().put(DO_PRE_UPDATE_CREDENTIAL_BY_ADMIN, true);
IdentityMgtConfig config = IdentityMgtConfig.getInstance();
UserIdentityDataStore identityDataStore = IdentityMgtConfig.getInstance().getIdentityDataStore();
UserIdentityClaimsDO identityDTO = identityDataStore.load(userName, userStoreManager);
boolean isAccountDisabled = false;
if (identityDTO != null) {
isAccountDisabled = identityDTO.getIsAccountDisabled();
} else {
throw new UserStoreException("Cannot get the user account active status.");
}
if (isAccountDisabled) {
IdentityErrorMsgContext customErrorMessageContext = new IdentityErrorMsgContext(IdentityCoreConstants.USER_ACCOUNT_DISABLED_ERROR_CODE);
IdentityUtil.setIdentityErrorMsg(customErrorMessageContext);
// account is already disabled and trying to update the credential without enabling it
log.warn("Trying to update credential of a disabled user account. This is not permitted.");
throw new UserStoreException("User account is disabled, can't update credential without enabling.");
}
try {
// Enforcing the password policies.
if (newCredential != null && (newCredential instanceof StringBuffer && (newCredential.toString().trim().length() > 0))) {
policyRegistry.enforcePasswordPolicies(newCredential.toString(), userName);
}
} catch (PolicyViolationException pe) {
throw new UserStoreException(pe.getMessage(), pe);
}
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);
if (log.isDebugEnabled()) {
log.debug("Sending the temporary password to the user " + userName);
}
UserIdentityManagementUtil.notifyViaEmail(bean);
} else {
if (log.isDebugEnabled()) {
log.debug("Updating credentials of user " + userName + " by admin with a non-empty password");
}
}
}
return true;
} finally {
// Remove thread local variable
IdentityUtil.threadLocalProperties.get().remove(DO_PRE_UPDATE_CREDENTIAL_BY_ADMIN);
}
}
Aggregations