/* * Copyright (c) 2014, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * * WSO2 Inc. licenses this file to you 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.mgt; import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.identity.base.IdentityException; import org.wso2.carbon.identity.mgt.constants.IdentityMgtConstants; import org.wso2.carbon.identity.mgt.dto.ChallengeQuestionDTO; import org.wso2.carbon.identity.mgt.dto.ChallengeQuestionIdsDTO; import org.wso2.carbon.identity.mgt.dto.UserChallengesDTO; import org.wso2.carbon.identity.mgt.internal.IdentityMgtServiceComponent; import org.wso2.carbon.identity.mgt.util.Utils; import org.wso2.carbon.registry.core.Collection; import org.wso2.carbon.registry.core.Registry; import org.wso2.carbon.registry.core.RegistryConstants; import org.wso2.carbon.registry.core.Resource; import org.wso2.carbon.registry.core.exceptions.RegistryException; import org.wso2.carbon.user.core.UserStoreException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * process user challenges and questions */ public class ChallengeQuestionProcessor { private static final Log log = LogFactory.getLog(ChallengeQuestionProcessor.class); /** * @return * @throws IdentityException */ public List<ChallengeQuestionDTO> getAllChallengeQuestions() throws IdentityException { List<ChallengeQuestionDTO> questionDTOs = new ArrayList<ChallengeQuestionDTO>(); try { int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(); Registry registry = IdentityMgtServiceComponent.getRegistryService(). getConfigSystemRegistry(tenantId); if (registry.resourceExists(IdentityMgtConstants.IDENTITY_MANAGEMENT_QUESTIONS)) { Collection collection = (Collection) registry. get(IdentityMgtConstants.IDENTITY_MANAGEMENT_QUESTIONS); String[] children = collection.getChildren(); for (String child : children) { Resource resource = registry.get(child); String question = resource.getProperty("question"); String isPromoteQuestion = resource.getProperty("isPromoteQuestion"); String questionSetId = resource.getProperty("questionSetId"); if (question != null) { ChallengeQuestionDTO questionDTO = new ChallengeQuestionDTO(); questionDTO.setQuestion(question); if (isPromoteQuestion != null) { questionDTO.setPromoteQuestion(Boolean.parseBoolean(isPromoteQuestion)); } if (questionSetId != null) { questionDTO.setQuestionSetId(questionSetId); } questionDTO.setPromoteQuestion(false); questionDTOs.add(questionDTO); } } } } catch (RegistryException e) { throw IdentityException.error(e.getMessage(), e); } return questionDTOs; } /** * @param questionDTOs * @throws IdentityException */ public void setChallengeQuestions(ChallengeQuestionDTO[] questionDTOs) throws IdentityException { Registry registry = null; try { int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(); registry = IdentityMgtServiceComponent.getRegistryService().getConfigSystemRegistry(tenantId); if (!registry.resourceExists(IdentityMgtConstants.IDENTITY_MANAGEMENT_PATH)) { Collection securityQuestionResource = registry.newCollection(); registry.put(IdentityMgtConstants.IDENTITY_MANAGEMENT_PATH, securityQuestionResource); } Resource identityMgtResource = registry.get(IdentityMgtConstants.IDENTITY_MANAGEMENT_PATH); if (identityMgtResource != null) { String questionCollectionPath = IdentityMgtConstants.IDENTITY_MANAGEMENT_QUESTIONS; if (registry.resourceExists(questionCollectionPath)) { registry.delete(questionCollectionPath); } Collection questionCollection = registry.newCollection(); registry.put(questionCollectionPath, questionCollection); for (int i = 0; i < questionDTOs.length; i++) { Resource resource = registry.newResource(); resource.addProperty("question", questionDTOs[i].getQuestion()); resource.addProperty("isPromoteQuestion", String.valueOf(questionDTOs[i].isPromoteQuestion())); resource.addProperty("questionSetId", questionDTOs[i].getQuestionSetId()); registry.put(IdentityMgtConstants.IDENTITY_MANAGEMENT_QUESTIONS + RegistryConstants.PATH_SEPARATOR + "question" + i + RegistryConstants.PATH_SEPARATOR, resource); } } } catch (RegistryException e) { throw IdentityException.error("Error while setting challenge question.", e); } } /** * // TODO manage oder * * @param userName * @param tenantId * @param adminService * @return */ public UserChallengesDTO[] getChallengeQuestionsOfUser(String userName, int tenantId, boolean adminService) { List<UserChallengesDTO> challengesDTOs = new ArrayList<UserChallengesDTO>(); try { if (log.isDebugEnabled()) { log.debug("Retrieving Challenge question from the user profile."); } List<String> challengesUris = getChallengeQuestionUris(userName, tenantId); for (int i = 0; i < challengesUris.size(); i++) { String challengesUri = challengesUris.get(i).trim(); String challengeValue = Utils.getClaimFromUserStoreManager(userName, tenantId, challengesUri); String[] challengeValues = challengeValue. split(IdentityMgtConfig.getInstance().getChallengeQuestionSeparator()); if (challengeValues != null && challengeValues.length == 2) { UserChallengesDTO dto = new UserChallengesDTO(); dto.setId(challengesUri); dto.setQuestion(challengeValues[0].trim()); if (adminService) { dto.setAnswer(challengeValues[1].trim()); } dto.setOrder(i); dto.setPrimary(false); challengesDTOs.add(dto); } } } catch (Exception e) { String msg = "No associated challenge question found for the user"; if(log.isDebugEnabled()){ log.debug(msg, e); } } if (!challengesDTOs.isEmpty()) { return challengesDTOs.toArray(new UserChallengesDTO[challengesDTOs.size()]); } else { return new UserChallengesDTO[0]; } } public UserChallengesDTO getUserChallengeQuestion(String userName, int tenantId, boolean adminService) throws IdentityMgtServiceException { UserChallengesDTO dto = null; List<UserChallengesDTO> challengesDTOs = new ArrayList<UserChallengesDTO>(); try { if (log.isDebugEnabled()) { log.debug("Retrieving Challenge question from the user profile."); } List<String> challengesUris = getChallengeQuestionUris(userName, tenantId); for (int i = 0; i < challengesUris.size(); i++) { String challengesUri = challengesUris.get(i).trim(); String challengeValue = Utils.getClaimFromUserStoreManager(userName, tenantId, challengesUri); String[] challengeValues = challengeValue.split(IdentityMgtConfig.getInstance() .getChallengeQuestionSeparator()); if (challengeValues != null && challengeValues.length == 2) { dto = new UserChallengesDTO(); dto.setId(challengesUri); dto.setQuestion(challengeValues[0].trim()); if (adminService) { dto.setAnswer(challengeValues[1].trim()); } dto.setOrder(i); dto.setPrimary(false); challengesDTOs.add(dto); } } } catch (Exception e) { String msg = "No associated challenge question found for the user"; if(log.isDebugEnabled()){ log.debug(msg, e); } } return dto; } public UserChallengesDTO getUserChallengeQuestion(String userName, int tenantId, String challengesUri) throws IdentityMgtServiceException { UserChallengesDTO dto = null; try { if (log.isDebugEnabled()) { log.debug("Retrieving Challenge question from the user profile."); } String challengeValue = Utils.getClaimFromUserStoreManager(userName, tenantId, challengesUri); if (challengeValue != null) { String[] challengeValues = challengeValue.split(IdentityMgtConfig.getInstance() .getChallengeQuestionSeparator()); if (challengeValues != null && challengeValues.length == 2) { dto = new UserChallengesDTO(); dto.setId(challengesUri); dto.setQuestion(challengeValues[0].trim()); } } else { dto = new UserChallengesDTO(); dto.setError("Challenge questions have not been answered by the user: " + userName); } } catch (Exception e) { String errorMsg = "Error while getting the challenge questions for the user: " + userName; if(log.isDebugEnabled()){ log.debug(errorMsg, e); } dto = new UserChallengesDTO(); dto.setError(errorMsg); throw new IdentityMgtServiceException(errorMsg,e); } return dto; } public ChallengeQuestionIdsDTO getUserChallengeQuestionIds(String userName, int tenantId) throws IdentityMgtServiceException { ChallengeQuestionIdsDTO dto = new ChallengeQuestionIdsDTO(); if (log.isDebugEnabled()) { log.debug("Retrieving Challenge question ids from the user profile."); } List<String> challengesUris = getChallengeQuestionUris(userName, tenantId); if (challengesUris.isEmpty()) { String msg = "No associated challenge question found for the user"; if (log.isDebugEnabled()) { log.debug(msg); } throw new IdentityMgtServiceException(msg); } String[] ids = new String[challengesUris.size()]; for (int i = 0; i < challengesUris.size(); i++) { ids[i] = challengesUris.get(i).trim(); } dto.setIds(ids); return dto; } /** * @param userName * @param tenantId * @return */ public List<String> getChallengeQuestionUris(String userName, int tenantId) throws IdentityMgtServiceException{ if (log.isDebugEnabled()) { log.debug("Challenge Question from the user profile."); } List<String> challenges = new ArrayList<String>(); String claimValue = null; String[] challengesUris; try { claimValue = Utils.getClaimFromUserStoreManager(userName, tenantId, "http://wso2.org/claims/challengeQuestionUris"); } catch (IdentityException e) { throw new IdentityMgtServiceException("Error while getting cliams.", e); } if (claimValue != null) { if (claimValue.contains(IdentityMgtConfig.getInstance().getChallengeQuestionSeparator())) { challengesUris = claimValue.split(IdentityMgtConfig.getInstance().getChallengeQuestionSeparator()); } else { challengesUris = new String[]{claimValue.trim()}; } for (String challengesUri : challengesUris) { if (StringUtils.isNotBlank(challengesUri)) { challenges.add(challengesUri.trim()); } } } return challenges; } /** * @param userName * @param tenantId * @return */ public int getNoOfChallengeQuestions(String userName, int tenantId) throws IdentityMgtServiceException { List<String> questions = getChallengeQuestionUris(userName, tenantId); return questions.size(); } /** * @param userName * @param tenantId * @param challengesDTOs * @throws IdentityException */ public void setChallengesOfUser(String userName, int tenantId, UserChallengesDTO[] challengesDTOs) throws IdentityException { try { if (log.isDebugEnabled()) { log.debug("Challenge Question from the user profile."); } List<String> challengesUris = new ArrayList<String>(); String challengesUrisValue = ""; String separator = IdentityMgtConfig.getInstance().getChallengeQuestionSeparator(); if (!ArrayUtils.isEmpty(challengesDTOs)) { for (UserChallengesDTO dto : challengesDTOs) { if (dto.getId() != null && dto.getQuestion() != null && dto.getAnswer() != null) { String oldValue = Utils. getClaimFromUserStoreManager(userName, tenantId, dto.getId().trim()); if (oldValue != null && oldValue.contains(separator)) { String oldAnswer = oldValue.split(separator)[1]; if (!oldAnswer.trim().equals(dto.getAnswer().trim())) { String claimValue = dto.getQuestion().trim() + separator + Utils.doHash(dto.getAnswer().trim().toLowerCase()); Utils.setClaimInUserStoreManager(userName, tenantId, dto.getId().trim(), claimValue); } } else { String claimValue = dto.getQuestion().trim() + separator + Utils.doHash(dto.getAnswer().trim().toLowerCase()); Utils.setClaimInUserStoreManager(userName, tenantId, dto.getId().trim(), claimValue); } challengesUris.add(dto.getId().trim()); } } for (String challengesUri : challengesUris) { if ("".equals(challengesUrisValue)) { challengesUrisValue = challengesUri; } else { challengesUrisValue = challengesUrisValue + IdentityMgtConfig.getInstance().getChallengeQuestionSeparator() + challengesUri; } } Utils.setClaimInUserStoreManager(userName, tenantId, "http://wso2.org/claims/challengeQuestionUris", challengesUrisValue); } } catch (org.wso2.carbon.user.api.UserStoreException e) { String msg = "No associated challenge question found for the user"; throw IdentityException.error(msg, e); } } /** * @param userName * @param tenantId * @param challengesDTOs * @return */ public boolean verifyChallengeQuestion(String userName, int tenantId, UserChallengesDTO[] challengesDTOs) { boolean verification = false; try { if (log.isDebugEnabled()) { log.debug("Challenge Question from the user profile."); } UserChallengesDTO[] storedDto = getChallengeQuestionsOfUser(userName, tenantId, true); for (UserChallengesDTO challengesDTO : challengesDTOs) { if (challengesDTO.getAnswer() == null || challengesDTO.getAnswer().trim().length() < 1) { return false; } for (UserChallengesDTO dto : storedDto) { if ((challengesDTO.getId() == null || !challengesDTO.getId().trim().equals(dto.getId())) && (challengesDTO.getQuestion() == null || !challengesDTO.getQuestion(). trim().equals(dto.getQuestion()))) { continue; } String hashedAnswer = Utils.doHash(challengesDTO.getAnswer().trim().toLowerCase()); if (hashedAnswer.equals(dto.getAnswer())) { verification = true; } else { return false; } } } } catch (Exception e) { String msg = "No associated challenge question found for the user"; log.debug(msg, e); } return verification; } public boolean verifyUserChallengeAnswer(String userName, int tenantId, UserChallengesDTO challengesDTO) { boolean verification = false; try { if (log.isDebugEnabled()) { log.debug("Challenge Question from the user profile."); } UserChallengesDTO[] storedDto = getChallengeQuestionsOfUser(userName, tenantId, true); if (challengesDTO.getAnswer() == null || challengesDTO.getAnswer().trim().length() < 1) { return false; } for (UserChallengesDTO dto : storedDto) { if (dto.getId().equals(challengesDTO.getId())) { String hashedAnswer = Utils.doHash(challengesDTO.getAnswer().trim() .toLowerCase()); if (hashedAnswer.equals(dto.getAnswer())) { verification = true; } else { return false; } } } } catch (Exception e) { String msg = "No associated challenge question found for the user"; log.debug(msg, e); } return verification; } /** * @param userName * @param tenantId * @return */ public UserChallengesDTO[] getPrimaryChallengeQuestionsOfUser(String userName, int tenantId) { List<UserChallengesDTO> challengesDTOs = new ArrayList<>(); try { if (log.isDebugEnabled()) { log.debug("Challenge Question from the user profile."); } String claimValue; claimValue = Utils.getClaimFromUserStoreManager(userName, tenantId, "http://wso2.org/claims/primaryChallengeQuestion"); String[] challenges = claimValue.split(IdentityMgtConfig.getInstance().getChallengeQuestionSeparator()); for (String challenge : challenges) { UserChallengesDTO dto = new UserChallengesDTO(); String question = challenge.substring(0, challenge.indexOf("=")); dto.setQuestion(question); dto.setPrimary(true); challengesDTOs.add(dto); } } catch (Exception e) { String msg = "No associated challenge question found for the user"; log.debug(msg, e); } if (!challengesDTOs.isEmpty()) { return challengesDTOs.toArray(new UserChallengesDTO[challengesDTOs.size()]); } else { return new UserChallengesDTO[0]; } } /** * @param userName * @param tenantId * @param userChallengesDTOs * @return * @throws UserStoreException */ public boolean verifyPrimaryChallengeQuestion(String userName, int tenantId, UserChallengesDTO[] userChallengesDTOs) { boolean verification = false; try { if (log.isDebugEnabled()) { log.debug("Challenge Question from the user profile for user " + userName); } String claimValue = Utils.getClaimFromUserStoreManager(userName, tenantId, "http://wso2.org/claims/primaryChallengeQuestion"); if (claimValue == null) { log.debug("No associated challenge question found for the user " + userName); return false; } String[] challenges = claimValue.split(IdentityMgtConfig.getInstance().getChallengeQuestionSeparator()); Map<String, String> challengeMap = new HashMap<String, String>(); for (int i = 0; i < challenges.length; i = i + 2) { challengeMap.put(challenges[i], challenges[i + 1]); } for (UserChallengesDTO userChallengesDTO : userChallengesDTOs) { for (Map.Entry<String, String> entry : challengeMap.entrySet()) { String challengeQuestion = entry.getKey(); if (challengeQuestion.equals(userChallengesDTO.getQuestion().trim())) { String challengeAnswer = entry.getValue(); if (challengeAnswer.equals(Utils. doHash(userChallengesDTO.getAnswer().trim().toLowerCase()))) { verification = true; } else { return false; } } } } } catch (Exception e) { log.debug("No associated challenge question found for the user " + userName, e); } return verification; } }