use of org.wso2.carbon.identity.captcha.util.CaptchaHttpServletRequestWrapper in project identity-governance by wso2-extensions.
the class CaptchaFilter method doFilter.
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
try {
if (!CaptchaDataHolder.getInstance().isReCaptchaEnabled()) {
filterChain.doFilter(servletRequest, servletResponse);
return;
}
// May need multiple reads of request body value from connectors.
if (servletRequest instanceof HttpServletRequest) {
String currentPath = ((HttpServletRequest) servletRequest).getRequestURI();
if (StringUtils.isNotBlank(currentPath) && CaptchaUtil.isPathAvailable(currentPath, CaptchaDataHolder.getInstance().getReCaptchaRequestWrapUrls())) {
servletRequest = new CaptchaHttpServletRequestWrapper((HttpServletRequest) servletRequest);
}
}
List<CaptchaConnector> captchaConnectors = CaptchaDataHolder.getInstance().getCaptchaConnectors();
CaptchaConnector selectedCaptchaConnector = null;
for (CaptchaConnector captchaConnector : captchaConnectors) {
if (captchaConnector.canHandle(servletRequest, servletResponse) && (selectedCaptchaConnector == null || captchaConnector.getPriority() > selectedCaptchaConnector.getPriority())) {
selectedCaptchaConnector = captchaConnector;
}
}
if (selectedCaptchaConnector == null) {
filterChain.doFilter(servletRequest, servletResponse);
return;
}
// Check whether captcha is required or will reach to the max failed attempts with the current attempt.
CaptchaPreValidationResponse captchaPreValidationResponse = selectedCaptchaConnector.preValidate(servletRequest, servletResponse);
if (captchaPreValidationResponse == null) {
// Captcha connector failed to response. Default is success.
filterChain.doFilter(servletRequest, servletResponse);
return;
}
HttpServletRequest httpRequest = (HttpServletRequest) servletRequest;
HttpServletResponse httpResponse = (HttpServletResponse) servletResponse;
if (captchaPreValidationResponse.isCaptchaValidationRequired()) {
try {
boolean validCaptcha = selectedCaptchaConnector.verifyCaptcha(servletRequest, servletResponse);
if (!validCaptcha) {
log.warn("Captcha validation failed for the user.");
httpResponse.sendRedirect(CaptchaUtil.getOnFailRedirectUrl(httpRequest.getHeader("referer"), captchaPreValidationResponse.getOnCaptchaFailRedirectUrls(), captchaPreValidationResponse.getCaptchaAttributes()));
return;
}
} catch (CaptchaClientException e) {
log.warn("Captcha validation failed for the user. Cause : " + e.getMessage());
httpResponse.sendRedirect(CaptchaUtil.getOnFailRedirectUrl(httpRequest.getHeader("referer"), captchaPreValidationResponse.getOnCaptchaFailRedirectUrls(), captchaPreValidationResponse.getCaptchaAttributes()));
return;
}
}
// Enable reCaptcha for the destination.
if (captchaPreValidationResponse.isEnableCaptchaForRequestPath()) {
if (captchaPreValidationResponse.getCaptchaAttributes() != null) {
for (Map.Entry<String, String> parameter : captchaPreValidationResponse.getCaptchaAttributes().entrySet()) {
servletRequest.setAttribute(parameter.getKey(), parameter.getValue());
}
}
doFilter(captchaPreValidationResponse, servletRequest, servletResponse, filterChain);
return;
}
// Below the no. of max failed attempts, including the current attempt
if (!captchaPreValidationResponse.isPostValidationRequired() || (!captchaPreValidationResponse.isCaptchaValidationRequired() && !captchaPreValidationResponse.isMaxFailedLimitReached())) {
doFilter(captchaPreValidationResponse, servletRequest, servletResponse, filterChain);
return;
}
CaptchaHttpServletResponseWrapper responseWrapper = new CaptchaHttpServletResponseWrapper(httpResponse);
doFilter(captchaPreValidationResponse, servletRequest, responseWrapper, filterChain);
CaptchaPostValidationResponse postValidationResponse = selectedCaptchaConnector.postValidate(servletRequest, responseWrapper);
// Check whether this attempt is failed
if (postValidationResponse == null || postValidationResponse.isSuccessfulAttempt()) {
if (responseWrapper.isRedirect()) {
httpResponse.sendRedirect(responseWrapper.getRedirectURL());
}
return;
}
if (postValidationResponse.isEnableCaptchaResponsePath() && responseWrapper.isRedirect()) {
httpResponse.sendRedirect(CaptchaUtil.getUpdatedUrl(responseWrapper.getRedirectURL(), postValidationResponse.getCaptchaAttributes()));
}
} catch (CaptchaException e) {
log.error("Error occurred in processing captcha.", e);
((HttpServletResponse) servletResponse).sendRedirect(CaptchaUtil.getErrorPage("Server Error", "Something " + "went wrong. Please try again"));
}
}
use of org.wso2.carbon.identity.captcha.util.CaptchaHttpServletRequestWrapper in project identity-governance by wso2-extensions.
the class PasswordRecoveryReCaptchaConnector method preValidate.
@Override
public CaptchaPreValidationResponse preValidate(ServletRequest servletRequest, ServletResponse servletResponse) throws CaptchaException {
CaptchaPreValidationResponse preValidationResponse = new CaptchaPreValidationResponse();
boolean forgotPasswordRecaptchaEnabled = checkReCaptchaEnabledForForgotPassoword(servletRequest, FORGOT_PASSWORD_RECAPTCHA_ENABLE);
String pathUrl = ((HttpServletRequest) servletRequest).getRequestURI();
if (forgotPasswordRecaptchaEnabled && (CaptchaUtil.isPathAvailable(pathUrl, ACCOUNT_SECURITY_QUESTION_URL) || CaptchaUtil.isPathAvailable(pathUrl, ACCOUNT_SECURITY_QUESTIONS_URL) || CaptchaUtil.isPathAvailable(pathUrl, RECOVER_PASSWORD_URL))) {
preValidationResponse.setCaptchaValidationRequired(true);
}
// Handle recover with Email option.
if (pathUrl.equals(RECOVER_PASSWORD_URL)) {
return preValidationResponse;
}
// Handle recover with security questions option.
HttpServletRequest httpServletRequestWrapper;
try {
httpServletRequestWrapper = new CaptchaHttpServletRequestWrapper((HttpServletRequest) servletRequest);
preValidationResponse.setWrappedHttpServletRequest(httpServletRequestWrapper);
} catch (IOException e) {
log.error("Error occurred while wrapping ServletRequest.", e);
return preValidationResponse;
}
String path = httpServletRequestWrapper.getRequestURI();
User user = new User();
boolean initializationFlow = false;
if (CaptchaUtil.isPathAvailable(path, ACCOUNT_SECURITY_QUESTION_URL) || CaptchaUtil.isPathAvailable(path, ACCOUNT_SECURITY_QUESTIONS_URL)) {
user.setUserName(servletRequest.getParameter("username"));
if (StringUtils.isNotBlank(servletRequest.getParameter("realm"))) {
user.setUserStoreDomain(servletRequest.getParameter("realm"));
} else {
user.setUserStoreDomain(IdentityUtil.getPrimaryDomainName());
}
user.setTenantDomain(servletRequest.getParameter("tenant-domain"));
initializationFlow = true;
} else {
JsonObject requestObject;
try {
try (InputStream in = httpServletRequestWrapper.getInputStream()) {
requestObject = new JsonParser().parse(IOUtils.toString(in)).getAsJsonObject();
}
} catch (IOException e) {
return preValidationResponse;
}
UserRecoveryDataStore userRecoveryDataStore = JDBCRecoveryDataStore.getInstance();
try {
UserRecoveryData userRecoveryData = userRecoveryDataStore.load(requestObject.get("key").getAsString());
if (userRecoveryData != null) {
user = userRecoveryData.getUser();
}
} catch (IdentityRecoveryException e) {
return preValidationResponse;
}
}
if (StringUtils.isBlank(user.getUserName())) {
// Invalid Request
return preValidationResponse;
}
if (StringUtils.isBlank(user.getTenantDomain())) {
user.setTenantDomain(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME);
}
Property[] connectorConfigs;
try {
connectorConfigs = identityGovernanceService.getConfiguration(new String[] { RECOVERY_QUESTION_PASSWORD_RECAPTCHA_ENABLE, RECOVERY_QUESTION_PASSWORD_RECAPTCHA_MAX_FAILED_ATTEMPTS }, user.getTenantDomain());
} catch (IdentityGovernanceException e) {
throw new CaptchaServerException("Unable to retrieve connector configs.", e);
}
String connectorEnabled = null;
String maxAttemptsStr = null;
for (Property connectorConfig : connectorConfigs) {
if ((RECOVERY_QUESTION_PASSWORD_RECAPTCHA_ENABLE).equals(connectorConfig.getName())) {
connectorEnabled = connectorConfig.getValue();
} else if ((RECOVERY_QUESTION_PASSWORD_RECAPTCHA_MAX_FAILED_ATTEMPTS).equals(connectorConfig.getName())) {
maxAttemptsStr = connectorConfig.getValue();
}
}
if (!Boolean.parseBoolean(connectorEnabled)) {
return preValidationResponse;
}
if (StringUtils.isBlank(maxAttemptsStr) || !NumberUtils.isNumber(maxAttemptsStr)) {
log.warn("Invalid configuration found in the PasswordRecoveryReCaptchaConnector for the tenant - " + user.getTenantDomain());
return preValidationResponse;
}
int maxFailedAttempts = Integer.parseInt(maxAttemptsStr);
int tenantId;
try {
tenantId = IdentityTenantUtil.getTenantId(user.getTenantDomain());
} catch (Exception e) {
// Invalid tenant
return preValidationResponse;
}
try {
if (CaptchaDataHolder.getInstance().getAccountLockService().isAccountLocked(user.getUserName(), user.getTenantDomain(), user.getUserStoreDomain())) {
return preValidationResponse;
}
} catch (AccountLockServiceException e) {
if (log.isDebugEnabled()) {
log.debug("Error while validating if account is locked for user: " + user.getUserName() + " of user " + "store domain: " + user.getUserStoreDomain() + " and tenant domain: " + user.getTenantDomain());
}
return preValidationResponse;
}
Map<String, String> claimValues = CaptchaUtil.getClaimValues(user, tenantId, new String[] { FAIL_ATTEMPTS_CLAIM });
if (claimValues == null || claimValues.isEmpty()) {
// Invalid user
return preValidationResponse;
}
int currentFailedAttempts = 0;
if (NumberUtils.isNumber(claimValues.get(FAIL_ATTEMPTS_CLAIM))) {
currentFailedAttempts = Integer.parseInt(claimValues.get(FAIL_ATTEMPTS_CLAIM));
}
HttpServletResponse httpServletResponse = ((HttpServletResponse) servletResponse);
if (currentFailedAttempts > maxFailedAttempts) {
if (initializationFlow) {
httpServletResponse.setHeader("reCaptcha", "true");
httpServletResponse.setHeader("reCaptchaKey", CaptchaDataHolder.getInstance().getReCaptchaSiteKey());
httpServletResponse.setHeader("reCaptchaAPI", CaptchaDataHolder.getInstance().getReCaptchaAPIUrl());
} else {
preValidationResponse.setCaptchaValidationRequired(true);
preValidationResponse.setMaxFailedLimitReached(true);
addPostValidationData(servletRequest);
}
} else if (currentFailedAttempts == maxFailedAttempts && !initializationFlow) {
addPostValidationData(servletRequest);
}
return preValidationResponse;
}
Aggregations