org.wso2.carbon.identity.password.policy.handler.PasswordPolicyValidationHandler.java Source code

Java tutorial

Introduction

Here is the source code for org.wso2.carbon.identity.password.policy.handler.PasswordPolicyValidationHandler.java

Source

/*
 * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.wso2.carbon.identity.password.policy.handler;

import org.apache.commons.lang.BooleanUtils;
import org.apache.commons.lang.NumberUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.identity.application.common.model.Property;
import org.wso2.carbon.identity.base.IdentityRuntimeException;
import org.wso2.carbon.identity.core.handler.InitConfig;
import org.wso2.carbon.identity.event.IdentityEventConstants;
import org.wso2.carbon.identity.event.IdentityEventException;
import org.wso2.carbon.identity.event.event.Event;
import org.wso2.carbon.identity.event.handler.AbstractEventHandler;
import org.wso2.carbon.identity.governance.IdentityGovernanceException;
import org.wso2.carbon.identity.governance.common.IdentityConnectorConfig;
import org.wso2.carbon.identity.mgt.policy.PolicyRegistry;
import org.wso2.carbon.identity.mgt.policy.PolicyViolationException;
import org.wso2.carbon.identity.mgt.policy.password.DefaultPasswordLengthPolicy;
import org.wso2.carbon.identity.mgt.policy.password.DefaultPasswordNamePolicy;
import org.wso2.carbon.identity.mgt.policy.password.DefaultPasswordPatternPolicy;
import org.wso2.carbon.identity.password.policy.constants.PasswordPolicyConstants;
import org.wso2.carbon.identity.password.policy.internal.IdentityPasswordPolicyServiceDataHolder;
import org.wso2.carbon.identity.password.policy.util.Utils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

public class PasswordPolicyValidationHandler extends AbstractEventHandler implements IdentityConnectorConfig {

    private static final Log log = LogFactory.getLog(PasswordPolicyValidationHandler.class);

    @Override
    public void handleEvent(Event event) throws IdentityEventException {

        Map<String, Object> eventProperties = event.getEventProperties();

        String userName = (String) eventProperties.get(IdentityEventConstants.EventProperty.USER_NAME);
        String tenantDomain = (String) eventProperties.get(IdentityEventConstants.EventProperty.TENANT_DOMAIN);
        Object credentials = eventProperties.get(IdentityEventConstants.EventProperty.CREDENTIAL);

        Property[] identityProperties;
        try {
            identityProperties = IdentityPasswordPolicyServiceDataHolder.getInstance()
                    .getIdentityGovernanceService().getConfiguration(getPropertyNames(), tenantDomain);
        } catch (IdentityGovernanceException e) {
            throw new IdentityEventException("Error while retrieving password policy properties.", e);
        }

        /*initialize to default values*/
        boolean passwordPolicyValidation = false;
        String pwMinLength = "6";
        String pwMaxLength = "12";
        String pwPattern = "^((?=.*\\\\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[!@#$%&*])).{0,100}$";
        String errorMsg = "Password pattern policy violated. Password should contain a digit[0-9], a lower case "
                + "letter[a-z], an upper case letter[A-Z], one of !@#$%&* characters";

        for (Property identityProperty : identityProperties) {

            if (identityProperty == null) {
                continue;
            }

            String propertyName = identityProperty.getName();
            String propertyValue = identityProperty.getValue();

            if (PasswordPolicyConstants.PW_POLICY_ENABLE.equals(propertyName)) {
                passwordPolicyValidation = BooleanUtils.toBoolean(propertyValue);
                if (!passwordPolicyValidation) {
                    if (log.isDebugEnabled()) {
                        log.debug("Password Policy validation is disabled");
                    }
                    return;
                }
                continue;
            } else if (PasswordPolicyConstants.PW_POLICY_MIN_LENGTH.equals(propertyName)) {
                if (NumberUtils.isNumber(propertyValue) && Integer.parseInt(propertyValue) > 0) {
                    pwMinLength = propertyValue;
                } else {
                    log.warn("Password Policy MIN Length is not correct hence using default value: " + pwMinLength);
                }
                continue;
            } else if (PasswordPolicyConstants.PW_POLICY_MAX_LENGTH.equals(propertyName)) {
                if (NumberUtils.isNumber(propertyValue) && Integer.parseInt(propertyValue) > 0) {
                    pwMaxLength = propertyValue;
                } else {
                    log.warn("Password Policy MAX Length is not correct hence using default value: " + pwMaxLength);
                }
                continue;
            } else if (PasswordPolicyConstants.PW_POLICY_PATTERN.equals(propertyName)) {
                if (StringUtils.isNotBlank(propertyValue)) {
                    pwPattern = propertyValue;
                } else {
                    log.warn("Password Policy Pattern is not correct hence using default value: " + pwPattern);
                }
                continue;
            } else if (PasswordPolicyConstants.PW_POLICY_ERROR_MSG.equals(propertyName)) {
                if (StringUtils.isNotBlank(propertyValue)) {
                    errorMsg = propertyValue;
                } else {
                    log.warn("Password Policy Error Msg cannot be Empty hence using default Msg: " + errorMsg);
                }
                continue;
            }
        }

        PolicyRegistry policyRegistry = new PolicyRegistry();

        String pwLengthPolicyCls = configs.getModuleProperties()
                .getProperty(PasswordPolicyConstants.PW_POLICY_LENGTH_CLASS);
        String pwNamePolicyCls = configs.getModuleProperties()
                .getProperty(PasswordPolicyConstants.PW_POLICY_NAME_CLASS);
        String pwPatternPolicyCls = configs.getModuleProperties()
                .getProperty(PasswordPolicyConstants.PW_POLICY_PATTERN_CLASS);
        try {
            if (StringUtils.isNotBlank(pwLengthPolicyCls)) {
                DefaultPasswordLengthPolicy defaultPasswordLengthPolicy = (DefaultPasswordLengthPolicy) Class
                        .forName(pwLengthPolicyCls).newInstance();
                HashMap pwPolicyLengthParams = new HashMap<String, String>();
                pwPolicyLengthParams.put("min.length", pwMinLength);
                pwPolicyLengthParams.put("max.length", pwMaxLength);
                defaultPasswordLengthPolicy.init(pwPolicyLengthParams);
                policyRegistry.addPolicy(defaultPasswordLengthPolicy);
            }

            if (StringUtils.isNotBlank(pwNamePolicyCls)) {
                DefaultPasswordNamePolicy defaultPasswordNamePolicy = (DefaultPasswordNamePolicy) Class
                        .forName(pwNamePolicyCls).newInstance();
                policyRegistry.addPolicy(defaultPasswordNamePolicy);
            }

            if (StringUtils.isNotBlank(pwPatternPolicyCls)) {
                DefaultPasswordPatternPolicy defaultPasswordPatternPolicy = (DefaultPasswordPatternPolicy) Class
                        .forName(pwPatternPolicyCls).newInstance();
                HashMap pwPolicyPatternParams = new HashMap<String, String>();
                pwPolicyPatternParams.put("pattern", pwPattern);
                pwPolicyPatternParams.put("errorMsg", errorMsg);
                defaultPasswordPatternPolicy.init(pwPolicyPatternParams);
                policyRegistry.addPolicy(defaultPasswordPatternPolicy);
            }
        } catch (Exception e) {
            throw Utils.handleEventException(
                    PasswordPolicyConstants.ErrorMessages.ERROR_CODE_LOADING_PASSWORD_POLICY_CLASSES, null, e);
        }

        try {
            policyRegistry.enforcePasswordPolicies(credentials.toString(), userName);
        } catch (PolicyViolationException e) {
            throw Utils.handleEventException(
                    PasswordPolicyConstants.ErrorMessages.ERROR_CODE_VALIDATING_PASSWORD_POLICY, e.getMessage(), e);
        }
    }

    @Override
    public String getName() {
        return "passwordPolicy";
    }

    @Override
    public String getFriendlyName() {
        return "Password Patterns";
    }

    @Override
    public String getCategory() {
        return "Password Policies";
    }

    @Override
    public String getSubCategory() {
        return "DEFAULT";
    }

    @Override
    public int getOrder() {
        return 0;
    }

    @Override
    public Map<String, String> getPropertyNameMapping() {
        Map<String, String> nameMapping = new HashMap<>();
        nameMapping.put(PasswordPolicyConstants.PW_POLICY_ENABLE, "Enable Password Policy Feature");
        nameMapping.put(PasswordPolicyConstants.PW_POLICY_MIN_LENGTH, "Password Policy Min Length");
        nameMapping.put(PasswordPolicyConstants.PW_POLICY_MAX_LENGTH, "Password Policy Max Length");
        nameMapping.put(PasswordPolicyConstants.PW_POLICY_PATTERN, "Password Policy Pattern");
        nameMapping.put(PasswordPolicyConstants.PW_POLICY_ERROR_MSG, "Password Policy Error Message");
        return nameMapping;
    }

    @Override
    public Map<String, String> getPropertyDescriptionMapping() {
        Map<String, String> descriptionMapping = new HashMap<>();
        descriptionMapping.put(PasswordPolicyConstants.PW_POLICY_ENABLE, "Enable password pattern policy");
        descriptionMapping.put(PasswordPolicyConstants.PW_POLICY_PATTERN, "Allowed password regex pattern");
        descriptionMapping.put(PasswordPolicyConstants.PW_POLICY_ERROR_MSG,
                "Error message for invalid password patterns");
        return descriptionMapping;
    }

    @Override
    public void init(InitConfig configuration) throws IdentityRuntimeException {
        super.init(configuration);
        IdentityPasswordPolicyServiceDataHolder.getInstance().getBundleContext()
                .registerService(IdentityConnectorConfig.class.getName(), this, null);
    }

    public String[] getPropertyNames() {

        List<String> properties = new ArrayList<>();
        properties.add(PasswordPolicyConstants.PW_POLICY_ENABLE);
        properties.add(PasswordPolicyConstants.PW_POLICY_MIN_LENGTH);
        properties.add(PasswordPolicyConstants.PW_POLICY_MAX_LENGTH);
        properties.add(PasswordPolicyConstants.PW_POLICY_PATTERN);
        properties.add(PasswordPolicyConstants.PW_POLICY_ERROR_MSG);
        return properties.toArray(new String[properties.size()]);
    }

    public Properties getDefaultPropertyValues(String tenantDomain) throws IdentityGovernanceException {
        Map<String, String> defaultProperties = new HashMap<>();
        defaultProperties.put(PasswordPolicyConstants.PW_POLICY_ENABLE,
                configs.getModuleProperties().getProperty(PasswordPolicyConstants.PW_POLICY_ENABLE));
        defaultProperties.put(PasswordPolicyConstants.PW_POLICY_MIN_LENGTH,
                configs.getModuleProperties().getProperty(PasswordPolicyConstants.PW_POLICY_MIN_LENGTH));
        defaultProperties.put(PasswordPolicyConstants.PW_POLICY_MAX_LENGTH,
                configs.getModuleProperties().getProperty(PasswordPolicyConstants.PW_POLICY_MAX_LENGTH));
        defaultProperties.put(PasswordPolicyConstants.PW_POLICY_PATTERN,
                configs.getModuleProperties().getProperty(PasswordPolicyConstants.PW_POLICY_PATTERN));
        defaultProperties.put(PasswordPolicyConstants.PW_POLICY_ERROR_MSG,
                configs.getModuleProperties().getProperty(PasswordPolicyConstants.PW_POLICY_ERROR_MSG));
        Properties properties = new Properties();
        properties.putAll(defaultProperties);
        return properties;
    }

    @Override
    public Map<String, String> getDefaultPropertyValues(String[] propertyNames, String tenantDomain)
            throws IdentityGovernanceException {
        return null;
    }
}