use of org.wso2.carbon.identity.core.model.IdentityErrorMsgContext in project carbon-identity-framework by wso2.
the class WorkflowPendingUserAuthnHandler method validatePendingApproval.
/**
* Validate whether the user account approval is pending.
*
* @param username Username.
* @throws IdentityEventException If an error occurred while validating pending approval.
*/
private void validatePendingApproval(String username, int tenantId) throws IdentityEventException {
boolean isPendingApproval;
try {
Entity entity = new Entity(MultitenantUtils.getTenantAwareUsername(username), WFConstant.WORKFLOW_ENTITY_TYPE, tenantId);
WorkflowManagementService workflowManagementService = new WorkflowManagementServiceImpl();
isPendingApproval = workflowManagementService.entityHasPendingWorkflowsOfType(entity, WFConstant.WORKFLOW_REQUEST_TYPE);
} catch (WorkflowException e) {
throw new IdentityEventException("Error occurred while checking the pending approvals for " + "the account of the user: " + username, e);
} catch (IdentityRuntimeException e) {
throw new IdentityEventException("Can't find the tenant domain for the user: " + username, e);
}
if (isPendingApproval) {
IdentityErrorMsgContext customErrorMessageContext = new IdentityErrorMsgContext(IdentityCoreConstants.USER_ACCOUNT_PENDING_APPROVAL_ERROR_CODE);
IdentityUtil.setIdentityErrorMsg(customErrorMessageContext);
throw new IdentityEventException(WorkflowErrorConstants.ErrorMessages.ERROR_CODE_USER_ACCOUNT_PENDING_APPROVAL.getCode(), WorkflowErrorConstants.ErrorMessages.ERROR_CODE_USER_ACCOUNT_PENDING_APPROVAL.getMessage());
}
}
use of org.wso2.carbon.identity.core.model.IdentityErrorMsgContext in project carbon-identity-framework by wso2.
the class DefaultStepHandler method doAuthentication.
protected void doAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationContext context, AuthenticatorConfig authenticatorConfig) throws FrameworkException {
SequenceConfig sequenceConfig = context.getSequenceConfig();
int currentStep = context.getCurrentStep();
StepConfig stepConfig = sequenceConfig.getStepMap().get(currentStep);
ApplicationAuthenticator authenticator = authenticatorConfig.getApplicationAuthenticator();
if (authenticator == null) {
LOG.error("Authenticator is null for AuthenticatorConfig: " + authenticatorConfig.getName());
return;
}
String idpName = FrameworkConstants.LOCAL_IDP_NAME;
if (context.getExternalIdP() != null && authenticator instanceof FederatedApplicationAuthenticator) {
idpName = context.getExternalIdP().getIdPName();
}
try {
context.setAuthenticatorProperties(FrameworkUtils.getAuthenticatorPropertyMapFromIdP(context.getExternalIdP(), authenticator.getName()));
AuthenticatorFlowStatus status = authenticator.process(request, response, context);
request.setAttribute(FrameworkConstants.RequestParams.FLOW_STATUS, status);
if (LOG.isDebugEnabled()) {
LOG.debug(authenticator.getName() + " returned: " + status.toString());
}
if (status == AuthenticatorFlowStatus.INCOMPLETE) {
context.setCurrentAuthenticator(authenticator.getName());
if (LOG.isDebugEnabled()) {
LOG.debug(authenticator.getName() + " is redirecting");
}
return;
}
if (authenticator instanceof FederatedApplicationAuthenticator) {
if (context.getSubject().getUserName() == null) {
// Set subject identifier as the default username for federated users
String authenticatedSubjectIdentifier = context.getSubject().getAuthenticatedSubjectIdentifier();
context.getSubject().setUserName(authenticatedSubjectIdentifier);
}
if (context.getSubject().getFederatedIdPName() == null && context.getExternalIdP() != null) {
// Setting identity provider's name
context.getSubject().setFederatedIdPName(idpName);
}
if (context.getSubject().getTenantDomain() == null) {
// Setting service provider's tenant domain as the default tenant for federated users
String tenantDomain = context.getTenantDomain();
context.getSubject().setTenantDomain(tenantDomain);
}
try {
// Check if the user id is available for the user. If the user id is not available or cannot be
// resolved, UserIdNotFoundException is thrown.
String userId = context.getSubject().getUserId();
if (LOG.isDebugEnabled()) {
LOG.debug("User id is available for user: " + userId);
}
} catch (UserIdNotFoundException e) {
String tenantDomain = context.getSubject().getTenantDomain();
int tenantId = IdentityTenantUtil.getTenantId(tenantDomain);
String authenticatedSubjectIdentifier = context.getSubject().getAuthenticatedSubjectIdentifier();
String federatedIdPName = context.getSubject().getFederatedIdPName();
try {
int idpId = UserSessionStore.getInstance().getIdPId(federatedIdPName, tenantId);
String userId = UserSessionStore.getInstance().getFederatedUserId(authenticatedSubjectIdentifier, tenantId, idpId);
try {
if (userId == null) {
userId = UUID.randomUUID().toString();
UserSessionStore.getInstance().storeUserData(userId, authenticatedSubjectIdentifier, tenantId, idpId);
}
} catch (DuplicatedAuthUserException e1) {
String msg = "User authenticated is already persisted. Username: " + authenticatedSubjectIdentifier + " Tenant Domain:" + tenantDomain + " IdP: " + federatedIdPName;
LOG.warn(msg);
if (LOG.isDebugEnabled()) {
LOG.debug(msg, e1);
}
// Since duplicate entry was found, let's try to get the ID again.
userId = UserSessionStore.getInstance().getFederatedUserId(authenticatedSubjectIdentifier, tenantId, idpId);
}
context.getSubject().setUserId(userId);
} catch (UserSessionException e2) {
LOG.error("Error while resolving the user id for federated user.", e2);
}
}
}
AuthenticatedIdPData authenticatedIdPData = getAuthenticatedIdPData(context, idpName);
// store authenticated user
AuthenticatedUser authenticatedUser = context.getSubject();
stepConfig.setAuthenticatedUser(authenticatedUser);
authenticatedIdPData.setUser(authenticatedUser);
authenticatorConfig.setAuthenticatorStateInfo(context.getStateInfo());
stepConfig.setAuthenticatedAutenticator(authenticatorConfig);
// store authenticated idp
stepConfig.setAuthenticatedIdP(idpName);
authenticatedIdPData.setIdpName(idpName);
authenticatedIdPData.addAuthenticator(authenticatorConfig);
// add authenticated idp data to the session wise map
context.getCurrentAuthenticatedIdPs().put(idpName, authenticatedIdPData);
// Add SAML federated idp session index into the authentication step history.
String idpSessionIndex = null;
String parameterName = FEDERATED_IDP_SESSION_ID + idpName;
AuthHistory authHistory = new AuthHistory(authenticator.getName(), idpName);
if (context.getParameters() != null && context.getParameters().containsKey(parameterName)) {
Object idpSessionIndexParamValue = context.getParameter(parameterName);
if (idpSessionIndexParamValue != null) {
idpSessionIndex = idpSessionIndexParamValue.toString();
}
}
if (StringUtils.isNotBlank(context.getCurrentAuthenticator()) && StringUtils.isNotBlank(idpSessionIndex)) {
authHistory.setIdpSessionIndex(idpSessionIndex);
authHistory.setRequestType(context.getRequestType());
}
Serializable startTime = context.getAnalyticsData(FrameworkConstants.AnalyticsData.CURRENT_AUTHENTICATOR_START_TIME);
if (startTime instanceof Long) {
authHistory.setDuration((long) startTime - System.currentTimeMillis());
}
authHistory.setSuccess(true);
context.addAuthenticationStepHistory(authHistory);
String initiator = null;
if (stepConfig.getAuthenticatedUser() != null) {
initiator = stepConfig.getAuthenticatedUser().toFullQualifiedUsername();
}
String data = "Step: " + stepConfig.getOrder() + ", IDP: " + stepConfig.getAuthenticatedIdP() + ", Authenticator:" + stepConfig.getAuthenticatedAutenticator().getName();
if (!isLegacyAuditLogsDisabled()) {
audit.info(String.format(AUDIT_MESSAGE, initiator, "Authenticate", "ApplicationAuthenticationFramework", data, SUCCESS));
}
} catch (InvalidCredentialsException e) {
if (LOG.isDebugEnabled()) {
LOG.debug("A login attempt was failed due to invalid credentials", e);
}
String data = "Step: " + stepConfig.getOrder() + ", IDP: " + idpName + ", Authenticator:" + authenticatorConfig.getName();
String initiator = null;
if (e.getUser() != null) {
initiator = e.getUser().toFullQualifiedUsername();
} else if (context.getSubject() != null) {
initiator = context.getSubject().toFullQualifiedUsername();
}
if (!isLegacyAuditLogsDisabled()) {
audit.warn(String.format(AUDIT_MESSAGE, initiator, "Authenticate", "ApplicationAuthenticationFramework", data, FAILURE));
}
handleFailedAuthentication(request, response, context, authenticatorConfig, e.getUser());
} catch (AuthenticationFailedException e) {
IdentityErrorMsgContext errorContext = IdentityUtil.getIdentityErrorMsg();
if (errorContext != null) {
Throwable rootCause = ExceptionUtils.getRootCause(e);
if (!IdentityCoreConstants.ADMIN_FORCED_USER_PASSWORD_RESET_VIA_OTP_ERROR_CODE.equals(errorContext.getErrorCode()) && !(rootCause instanceof UserStoreClientException) && !IdentityCoreConstants.USER_ACCOUNT_LOCKED_ERROR_CODE.equals(errorContext.getErrorCode()) && !IdentityCoreConstants.USER_ACCOUNT_DISABLED_ERROR_CODE.equals(errorContext.getErrorCode()) && !IdentityCoreConstants.USER_ACCOUNT_NOT_CONFIRMED_ERROR_CODE.equals(errorContext.getErrorCode())) {
if (LOG.isDebugEnabled()) {
LOG.debug("Authentication failed exception!", e);
}
LOG.error("Authentication failed exception! " + e.getMessage());
} else {
if (LOG.isDebugEnabled()) {
LOG.debug("Authentication failed exception!", e);
}
}
} else {
if (LOG.isDebugEnabled()) {
LOG.debug("Authentication failed exception!", e);
}
LOG.error("Authentication failed exception! " + e.getMessage());
}
String data = "Step: " + stepConfig.getOrder() + ", IDP: " + idpName + ", Authenticator:" + authenticatorConfig.getName();
String initiator = null;
if (e.getUser() != null) {
initiator = e.getUser().toFullQualifiedUsername();
} else if (context.getSubject() != null) {
initiator = context.getSubject().toFullQualifiedUsername();
}
if (!isLegacyAuditLogsDisabled()) {
audit.warn(String.format(AUDIT_MESSAGE, initiator, "Authenticate", "ApplicationAuthenticationFramework", data, FAILURE));
}
handleFailedAuthentication(request, response, context, authenticatorConfig, e.getUser());
} catch (LogoutFailedException e) {
throw new FrameworkException(e.getMessage(), e);
}
stepConfig.setCompleted(true);
}
use of org.wso2.carbon.identity.core.model.IdentityErrorMsgContext in project carbon-identity-framework by wso2.
the class DefaultStepHandler method getRedirectUrl.
private String getRedirectUrl(HttpServletRequest request, HttpServletResponse response, AuthenticationContext context, String authenticatorNames, String showAuthFailureReason, String retryParam, String loginPage) throws IOException, URISyntaxException {
IdentityErrorMsgContext errorContext = IdentityUtil.getIdentityErrorMsg();
IdentityUtil.clearIdentityErrorMsg();
retryParam = handleIdentifierFirstLogin(context, retryParam);
String otp = (String) context.getProperty(FrameworkConstants.PASSWORD_PROPERTY);
context.getProperties().remove(FrameworkConstants.PASSWORD_PROPERTY);
// If recaptcha is enabled and the Basic Authenticator is in the authenticator list for this page, the recaptcha
// params set by the Basic Authenticator need to be added to new URL generated for the multi option page.
// Currently, there is no method to check whether recaptcha has been enabled without manually reading the
// captcha-config.properties file. Hence, this fragment is always executed without the check, but will not
// alter the final URL if recaptcha is not enabled. This filters out the recaptcha params from the redirect
// URL previously set by an authenticator and generates a query string to be appended to the new redirect URL.
StringBuilder reCaptchaParamString = new StringBuilder("");
StringBuilder errorParamString = new StringBuilder("");
String basicAuthRedirectUrl = ((CommonAuthResponseWrapper) response).getRedirectURL();
if (StringUtils.isNotBlank(basicAuthRedirectUrl)) {
List<NameValuePair> queryParameters = new URIBuilder(basicAuthRedirectUrl).getQueryParams();
List<NameValuePair> reCaptchaParameters = queryParameters.stream().filter(param -> FrameworkConstants.RECAPTCHA_API_PARAM.equals(param.getName()) || FrameworkConstants.RECAPTCHA_KEY_PARAM.equals(param.getName()) || FrameworkConstants.RECAPTCHA_PARAM.equals(param.getName()) || FrameworkConstants.RECAPTCHA_RESEND_CONFIRMATION_PARAM.equals(param.getName())).collect(Collectors.toList());
for (NameValuePair reCaptchaParam : reCaptchaParameters) {
reCaptchaParamString.append("&").append(reCaptchaParam.getName()).append("=").append(reCaptchaParam.getValue());
}
if (errorContext == null) {
List<NameValuePair> errorContextParams = queryParameters.stream().filter(param -> FrameworkConstants.ERROR_CODE.equals(param.getName()) || FrameworkConstants.LOCK_REASON.equals(param.getName()) || FrameworkConstants.REMAINING_ATTEMPTS.equals(param.getName()) || FrameworkConstants.FAILED_USERNAME.equals(param.getName())).collect(Collectors.toList());
if (errorContextParams.size() > 0) {
for (NameValuePair errorParams : errorContextParams) {
errorParamString.append("&").append(errorParams.getName()).append("=").append(errorParams.getValue());
}
}
}
}
if (showAuthFailureReason != null && "true".equals(showAuthFailureReason)) {
if (errorContext != null) {
String errorCode = errorContext.getErrorCode();
String reason = null;
if (errorCode.contains(":")) {
String[] errorCodeReason = errorCode.split(":", 2);
if (errorCodeReason.length > 1) {
errorCode = errorCodeReason[0];
reason = errorCodeReason[1];
}
}
int remainingAttempts = errorContext.getMaximumLoginAttempts() - errorContext.getFailedLoginAttempts();
if (LOG.isDebugEnabled()) {
StringBuilder debugString = new StringBuilder();
debugString.append("Identity error message context is not null. Error details are as follows.");
debugString.append("errorCode : " + errorCode + "\n");
debugString.append("username : " + request.getParameter("username") + "\n");
debugString.append("remainingAttempts : " + remainingAttempts);
LOG.debug(debugString.toString());
}
if (UserCoreConstants.ErrorCode.INVALID_CREDENTIAL.equals(errorCode)) {
retryParam = retryParam + "&errorCode=" + errorCode + "&failedUsername=" + URLEncoder.encode(request.getParameter("username"), "UTF-8") + "&remainingAttempts=" + remainingAttempts;
return response.encodeRedirectURL(loginPage + ("?" + context.getContextIdIncludedQueryParams())) + "&authenticators=" + URLEncoder.encode(authenticatorNames, "UTF-8") + retryParam + reCaptchaParamString.toString();
} else if (UserCoreConstants.ErrorCode.USER_IS_LOCKED.equals(errorCode)) {
String redirectURL;
if (remainingAttempts == 0) {
if (StringUtils.isBlank(reason)) {
redirectURL = response.encodeRedirectURL(loginPage + ("?" + context.getContextIdIncludedQueryParams())) + "&errorCode=" + errorCode + "&failedUsername=" + URLEncoder.encode(request.getParameter("username"), "UTF-8") + "&remainingAttempts=0" + "&authenticators=" + URLEncoder.encode(authenticatorNames, "UTF-8") + retryParam + reCaptchaParamString;
} else {
redirectURL = response.encodeRedirectURL(loginPage + ("?" + context.getContextIdIncludedQueryParams())) + "&errorCode=" + errorCode + "&lockedReason=" + reason + "&failedUsername=" + URLEncoder.encode(request.getParameter("username"), "UTF-8") + "&remainingAttempts=0" + "&authenticators=" + URLEncoder.encode(authenticatorNames, "UTF-8") + retryParam + reCaptchaParamString;
}
} else {
if (StringUtils.isBlank(reason)) {
redirectURL = response.encodeRedirectURL(loginPage + ("?" + context.getContextIdIncludedQueryParams())) + "&errorCode=" + errorCode + "&failedUsername=" + URLEncoder.encode(request.getParameter("username"), "UTF-8") + "&authenticators=" + URLEncoder.encode(authenticatorNames, "UTF-8") + retryParam + reCaptchaParamString;
} else {
redirectURL = response.encodeRedirectURL(loginPage + ("?" + context.getContextIdIncludedQueryParams())) + "&errorCode=" + errorCode + "&lockedReason=" + reason + "&failedUsername=" + URLEncoder.encode(request.getParameter("username"), "UTF-8") + "&authenticators=" + URLEncoder.encode(authenticatorNames, "UTF-8") + retryParam + reCaptchaParamString.toString();
}
}
return redirectURL;
} else if (IdentityCoreConstants.USER_ACCOUNT_NOT_CONFIRMED_ERROR_CODE.equals(errorCode)) {
retryParam = "&authFailure=true&authFailureMsg=account.confirmation.pending";
String username = request.getParameter("username");
Object domain = IdentityUtil.threadLocalProperties.get().get(RE_CAPTCHA_USER_DOMAIN);
if (domain != null) {
username = IdentityUtil.addDomainToName(username, domain.toString());
}
retryParam = retryParam + "&errorCode=" + errorCode + "&failedUsername=" + URLEncoder.encode(username, "UTF-8");
return response.encodeRedirectURL(loginPage + ("?" + context.getContextIdIncludedQueryParams())) + "&authenticators=" + URLEncoder.encode(authenticatorNames, "UTF-8") + retryParam + reCaptchaParamString.toString();
} else if (IdentityCoreConstants.USER_INVALID_CREDENTIALS.equals(errorCode)) {
retryParam = "&authFailure=true&authFailureMsg=login.fail.message";
String username = request.getParameter("username");
Object domain = IdentityUtil.threadLocalProperties.get().get(RE_CAPTCHA_USER_DOMAIN);
if (domain != null) {
username = IdentityUtil.addDomainToName(username, domain.toString());
}
retryParam = retryParam + "&errorCode=" + errorCode + "&failedUsername=" + URLEncoder.encode(username, "UTF-8");
return response.encodeRedirectURL(loginPage + ("?" + context.getContextIdIncludedQueryParams())) + "&authenticators=" + URLEncoder.encode(authenticatorNames, "UTF-8") + retryParam + reCaptchaParamString.toString();
} else if (IdentityCoreConstants.ADMIN_FORCED_USER_PASSWORD_RESET_VIA_OTP_ERROR_CODE.equals(errorCode)) {
String username = request.getParameter("username");
return response.encodeRedirectURL(("accountrecoveryendpoint/confirmrecovery.do?" + context.getContextIdIncludedQueryParams())) + "&username=" + URLEncoder.encode(username, "UTF-8") + "&confirmation=" + otp + reCaptchaParamString.toString();
} else {
if (StringUtils.isNotBlank(retryParam) && StringUtils.isNotBlank(reason)) {
retryParam = "&authFailure=true&authFailureMsg=" + URLEncoder.encode(reason, "UTF-8");
}
retryParam += "&errorCode=" + errorCode + "&failedUsername=" + URLEncoder.encode(request.getParameter("username"), "UTF-8");
return response.encodeRedirectURL(loginPage + ("?" + context.getContextIdIncludedQueryParams())) + "&authenticators=" + URLEncoder.encode(authenticatorNames, "UTF-8") + retryParam + reCaptchaParamString.toString();
}
} else {
return response.encodeRedirectURL(loginPage + ("?" + context.getContextIdIncludedQueryParams())) + "&authenticators=" + URLEncoder.encode(authenticatorNames, "UTF-8") + retryParam + reCaptchaParamString.toString() + errorParamString;
}
} else {
String errorCode = errorContext != null ? errorContext.getErrorCode() : null;
if (UserCoreConstants.ErrorCode.USER_IS_LOCKED.equals(errorCode)) {
String redirectURL;
redirectURL = response.encodeRedirectURL(loginPage + ("?" + context.getContextIdIncludedQueryParams())) + "&failedUsername=" + URLEncoder.encode(request.getParameter("username"), "UTF-8") + "&authenticators=" + URLEncoder.encode(authenticatorNames, "UTF-8") + retryParam + reCaptchaParamString.toString();
return redirectURL;
} else if (IdentityCoreConstants.ADMIN_FORCED_USER_PASSWORD_RESET_VIA_OTP_ERROR_CODE.equals(errorCode)) {
String username = request.getParameter("username");
return response.encodeRedirectURL(("accountrecoveryendpoint/confirmrecovery.do?" + context.getContextIdIncludedQueryParams())) + "&username=" + URLEncoder.encode(username, "UTF-8") + "&confirmation=" + otp + reCaptchaParamString.toString();
} else {
return response.encodeRedirectURL(loginPage + ("?" + context.getContextIdIncludedQueryParams())) + "&authenticators=" + URLEncoder.encode(authenticatorNames, "UTF-8") + retryParam + reCaptchaParamString.toString();
}
}
}
use of org.wso2.carbon.identity.core.model.IdentityErrorMsgContext in project carbon-identity-framework by wso2.
the class IdentityUtilTest method testIdentityErrorMsg.
@Test(dataProvider = "getIdentityErrorMsgTestData")
public void testIdentityErrorMsg(String code, int failedAttempts, int maxAttempts) throws Exception {
IdentityErrorMsgContext msgContext = new IdentityErrorMsgContext(code, failedAttempts, maxAttempts);
assertNull(IdentityUtil.getIdentityErrorMsg(), "Error msg should be null initially");
IdentityUtil.setIdentityErrorMsg(msgContext);
assertEquals(IdentityUtil.getIdentityErrorMsg().getErrorCode(), code, String.format("Error code mismatch for " + "input: code = %s, failedAttempts = %d, maxAttempts = %d.", code, failedAttempts, maxAttempts));
assertEquals(IdentityUtil.getIdentityErrorMsg().getFailedLoginAttempts(), failedAttempts, String.format("Login attempt mismatch for input: code = %s, failedAttempts = %d, maxAttempts = %d.", code, failedAttempts, maxAttempts));
assertEquals(IdentityUtil.getIdentityErrorMsg().getMaximumLoginAttempts(), maxAttempts, String.format("Max attempt mismatch for input: code = %s, failedAttempts = %d, maxAttempts = %d.", code, failedAttempts, maxAttempts));
IdentityUtil.clearIdentityErrorMsg();
assertNull(IdentityUtil.getIdentityErrorMsg(), "Error msg should be null after being cleared");
}
use of org.wso2.carbon.identity.core.model.IdentityErrorMsgContext 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);
}
}
Aggregations