Search in sources :

Example 1 with CaptchaHttpServletRequestWrapper

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"));
    }
}
Also used : CaptchaConnector(org.wso2.carbon.identity.captcha.connector.CaptchaConnector) CaptchaClientException(org.wso2.carbon.identity.captcha.exception.CaptchaClientException) CaptchaHttpServletRequestWrapper(org.wso2.carbon.identity.captcha.util.CaptchaHttpServletRequestWrapper) HttpServletResponse(javax.servlet.http.HttpServletResponse) CaptchaPostValidationResponse(org.wso2.carbon.identity.captcha.connector.CaptchaPostValidationResponse) HttpServletRequest(javax.servlet.http.HttpServletRequest) CaptchaPreValidationResponse(org.wso2.carbon.identity.captcha.connector.CaptchaPreValidationResponse) CaptchaHttpServletResponseWrapper(org.wso2.carbon.identity.captcha.util.CaptchaHttpServletResponseWrapper) Map(java.util.Map) CaptchaException(org.wso2.carbon.identity.captcha.exception.CaptchaException)

Example 2 with CaptchaHttpServletRequestWrapper

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;
}
Also used : AccountLockServiceException(org.wso2.carbon.identity.handler.event.account.lock.exception.AccountLockServiceException) CaptchaHttpServletRequestWrapper(org.wso2.carbon.identity.captcha.util.CaptchaHttpServletRequestWrapper) User(org.wso2.carbon.identity.application.common.model.User) InputStream(java.io.InputStream) JsonObject(com.google.gson.JsonObject) HttpServletResponse(javax.servlet.http.HttpServletResponse) CaptchaServerException(org.wso2.carbon.identity.captcha.exception.CaptchaServerException) IOException(java.io.IOException) CaptchaClientException(org.wso2.carbon.identity.captcha.exception.CaptchaClientException) CaptchaException(org.wso2.carbon.identity.captcha.exception.CaptchaException) IOException(java.io.IOException) CaptchaServerException(org.wso2.carbon.identity.captcha.exception.CaptchaServerException) IdentityRecoveryException(org.wso2.carbon.identity.recovery.IdentityRecoveryException) IdentityGovernanceException(org.wso2.carbon.identity.governance.IdentityGovernanceException) AccountLockServiceException(org.wso2.carbon.identity.handler.event.account.lock.exception.AccountLockServiceException) IdentityGovernanceException(org.wso2.carbon.identity.governance.IdentityGovernanceException) CaptchaPreValidationResponse(org.wso2.carbon.identity.captcha.connector.CaptchaPreValidationResponse) HttpServletRequest(javax.servlet.http.HttpServletRequest) UserRecoveryData(org.wso2.carbon.identity.recovery.model.UserRecoveryData) UserRecoveryDataStore(org.wso2.carbon.identity.recovery.store.UserRecoveryDataStore) IdentityRecoveryException(org.wso2.carbon.identity.recovery.IdentityRecoveryException) Property(org.wso2.carbon.identity.application.common.model.Property) JsonParser(com.google.gson.JsonParser)

Aggregations

HttpServletRequest (javax.servlet.http.HttpServletRequest)2 HttpServletResponse (javax.servlet.http.HttpServletResponse)2 CaptchaPreValidationResponse (org.wso2.carbon.identity.captcha.connector.CaptchaPreValidationResponse)2 CaptchaClientException (org.wso2.carbon.identity.captcha.exception.CaptchaClientException)2 CaptchaException (org.wso2.carbon.identity.captcha.exception.CaptchaException)2 CaptchaHttpServletRequestWrapper (org.wso2.carbon.identity.captcha.util.CaptchaHttpServletRequestWrapper)2 JsonObject (com.google.gson.JsonObject)1 JsonParser (com.google.gson.JsonParser)1 IOException (java.io.IOException)1 InputStream (java.io.InputStream)1 Map (java.util.Map)1 Property (org.wso2.carbon.identity.application.common.model.Property)1 User (org.wso2.carbon.identity.application.common.model.User)1 CaptchaConnector (org.wso2.carbon.identity.captcha.connector.CaptchaConnector)1 CaptchaPostValidationResponse (org.wso2.carbon.identity.captcha.connector.CaptchaPostValidationResponse)1 CaptchaServerException (org.wso2.carbon.identity.captcha.exception.CaptchaServerException)1 CaptchaHttpServletResponseWrapper (org.wso2.carbon.identity.captcha.util.CaptchaHttpServletResponseWrapper)1 IdentityGovernanceException (org.wso2.carbon.identity.governance.IdentityGovernanceException)1 AccountLockServiceException (org.wso2.carbon.identity.handler.event.account.lock.exception.AccountLockServiceException)1 IdentityRecoveryException (org.wso2.carbon.identity.recovery.IdentityRecoveryException)1