use of org.wso2.carbon.identity.recovery.model.ChallengeQuestion in project identity-governance by wso2-extensions.
the class PostAuthnMissingChallengeQuestionsHandlerTest method testBeforeRequestingChallengeQuestionFlow.
@Test(description = "Test the flow of challenge question post authentication handler before requesting challenge " + "questions from the user")
public void testBeforeRequestingChallengeQuestionFlow() throws Exception {
AuthenticationContext context = spy(new AuthenticationContext());
when(context.getTenantDomain()).thenReturn("carbon.super");
IdentityProvider residentIdp = spy(new IdentityProvider());
IdentityProviderProperty[] idpProperties = new IdentityProviderProperty[1];
IdentityProviderProperty idpProp = new IdentityProviderProperty();
idpProp.setName(IdentityRecoveryConstants.ConnectorConfig.FORCE_ADD_PW_RECOVERY_QUESTION);
idpProp.setValue("true");
idpProperties[0] = idpProp;
residentIdp.setIdpProperties(idpProperties);
mockedIdentityProviderManager.when(IdentityProviderManager::getInstance).thenReturn(identityProviderManager);
when(identityProviderManager.getResidentIdP("carbon.super")).thenReturn(residentIdp);
SequenceConfig sequenceConfig = spy(new SequenceConfig());
AuthenticatedUser user = spy(new AuthenticatedUser());
user.setUserName("admin");
when(sequenceConfig.getAuthenticatedUser()).thenReturn(user);
context.setSequenceConfig(sequenceConfig);
mockedMultitenantUtils.when(() -> MultitenantUtils.getTenantDomain("admin")).thenReturn("carbon.super");
mockedUtils.when(() -> Utils.getTenantId("carbon.super")).thenReturn(-1234);
mockedIdentityRecoveryServiceDataHolder.when(IdentityRecoveryServiceDataHolder::getInstance).thenReturn(frameworkServiceDataHolder);
RealmService realmService = mock(RealmService.class);
UserStoreManager userStoreManager = mock(UserStoreManager.class);
UserRealm userRealm = mock(UserRealm.class);
when(userRealm.getUserStoreManager()).thenReturn(userStoreManager);
when(realmService.getTenantUserRealm(-1234)).thenReturn(userRealm);
when(frameworkServiceDataHolder.getRealmService()).thenReturn(realmService);
when(userRealm.getUserStoreManager()).thenReturn(userStoreManager);
Map<String, String> claimsMap = new HashMap<>();
when(userStoreManager.getUserClaimValues("admin", new String[] { IdentityRecoveryConstants.CHALLENGE_QUESTION_URI }, UserCoreConstants.DEFAULT_PROFILE)).thenReturn(claimsMap);
List<ChallengeQuestion> challengeQuestions = new ArrayList<>();
ChallengeQuestion challengeQuestion = spy(new ChallengeQuestion());
challengeQuestion.setQuestionSetId("dummy_set");
challengeQuestion.setQuestionId("dummy_id");
challengeQuestion.setQuestion("dummy_question");
challengeQuestions.add(challengeQuestion);
when(challengeQuestionManager.getAllChallengeQuestions("carbon.super")).thenReturn(challengeQuestions);
mockedChallengeQuestionManager.when(ChallengeQuestionManager::getInstance).thenReturn(challengeQuestionManager);
doNothing().doThrow(Exception.class).when(httpServletResponse).sendRedirect((String) any());
when(configurationFacade.getAuthenticationEndpointURL()).thenReturn("");
when(ConfigurationFacade.getInstance()).thenReturn(configurationFacade);
PostAuthnHandlerFlowStatus flowStatus = PostAuthnMissingChallengeQuestionsHandler.getInstance().handle(httpServletRequest, httpServletResponse, context);
String expectedResult = PostAuthnHandlerFlowStatus.INCOMPLETE.name();
assertEquals(flowStatus.name(), expectedResult);
}
use of org.wso2.carbon.identity.recovery.model.ChallengeQuestion in project identity-governance by wso2-extensions.
the class SecurityQuestionPasswordRecoveryManager method validateUserChallengeQuestions.
public ChallengeQuestionResponse validateUserChallengeQuestions(UserChallengeAnswer[] userChallengeAnswer, String code, org.wso2.carbon.identity.recovery.model.Property[] properties) throws IdentityRecoveryException {
UserRecoveryDataStore userRecoveryDataStore = JDBCRecoveryDataStore.getInstance();
UserRecoveryData userRecoveryData = userRecoveryDataStore.load(code);
// if return data from load, it means the code is validated. Otherwise it returns exceptions.
User user = userRecoveryData.getUser();
validateFunctionalityForUser(user);
try {
boolean isRecoveryEnable = Boolean.parseBoolean(Utils.getRecoveryConfigs(IdentityRecoveryConstants.ConnectorConfig.QUESTION_BASED_PW_RECOVERY, userRecoveryData.getUser().getTenantDomain()));
if (!isRecoveryEnable) {
throw Utils.handleClientException(IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_QUESTION_BASED_RECOVERY_NOT_ENABLE, null);
}
verifyUserExists(user);
if (Utils.isAccountDisabled(user)) {
throw Utils.handleClientException(IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_DISABLED_ACCOUNT, user.getUserName());
} else if (Utils.isAccountLocked(user)) {
throw Utils.handleClientException(IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_LOCKED_ACCOUNT, user.getUserName());
}
if (userChallengeAnswer == null) {
String error = "Challenge answers cannot be found for user: " + userRecoveryData.getUser();
throw Utils.handleClientException(IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_CHALLENGE_QUESTION_NOT_FOUND, error);
}
String challengeQuestionSeparator = IdentityUtil.getProperty(IdentityRecoveryConstants.ConnectorConfig.QUESTION_CHALLENGE_SEPARATOR);
if (StringUtils.isEmpty(challengeQuestionSeparator)) {
challengeQuestionSeparator = IdentityRecoveryConstants.DEFAULT_CHALLENGE_QUESTION_SEPARATOR;
}
if (RecoverySteps.VALIDATE_CHALLENGE_QUESTION.equals(userRecoveryData.getRecoveryStep())) {
if (userChallengeAnswer.length > 1) {
throw Utils.handleClientException(IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_MULTIPLE_QUESTION_NOT_ALLOWED, null);
}
ChallengeQuestionManager challengeQuestionManager = ChallengeQuestionManager.getInstance();
boolean verified = challengeQuestionManager.verifyUserChallengeAnswer(userRecoveryData.getUser(), userChallengeAnswer[0]);
if (verified) {
boolean resetFailedLoginCount = false;
userRecoveryDataStore.invalidate(code);
String remainingSetIds = userRecoveryData.getRemainingSetIds();
ChallengeQuestionResponse challengeQuestionResponse = new ChallengeQuestionResponse();
String secretKey = UUIDGenerator.generateUUID();
challengeQuestionResponse.setCode(secretKey);
UserRecoveryData recoveryData = new UserRecoveryData(userRecoveryData.getUser(), secretKey, RecoveryScenarios.QUESTION_BASED_PWD_RECOVERY);
if (StringUtils.isNotBlank(remainingSetIds)) {
String[] ids = remainingSetIds.split(challengeQuestionSeparator);
ChallengeQuestion challengeQuestion = challengeQuestionManager.getUserChallengeQuestion(userRecoveryData.getUser(), ids[0]);
challengeQuestionResponse.setQuestion(challengeQuestion);
recoveryData.setRecoveryStep(RecoverySteps.VALIDATE_CHALLENGE_QUESTION);
challengeQuestionResponse.setStatus(IdentityRecoveryConstants.RECOVERY_STATUS_INCOMPLETE);
if (ids.length > 1) {
for (int i = 1; i < ids.length; i++) {
if (i == 1) {
remainingSetIds = ids[1];
} else {
remainingSetIds = remainingSetIds + challengeQuestionSeparator + ids[i];
}
}
recoveryData.setRemainingSetIds(remainingSetIds);
}
} else {
resetFailedLoginCount = true;
recoveryData.setRecoveryStep(RecoverySteps.UPDATE_PASSWORD);
challengeQuestionResponse.setStatus(IdentityRecoveryConstants.RECOVERY_STATUS_COMPLETE);
}
userRecoveryDataStore.store(recoveryData);
// Reset password recovery failed attempts
if (isPerUserFunctionalityLockingEnabled) {
resetRecoveryPasswordProperties(userRecoveryData.getUser(), resetFailedLoginCount);
} else {
resetRecoveryPasswordFailedAttempts(userRecoveryData.getUser(), resetFailedLoginCount);
}
return challengeQuestionResponse;
} else {
throw Utils.handleClientException(IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_INVALID_ANSWER_FOR_SECURITY_QUESTION, null);
}
} else if (RecoverySteps.VALIDATE_ALL_CHALLENGE_QUESTION.equals(userRecoveryData.getRecoveryStep())) {
String allChallengeQuestions = userRecoveryData.getRemainingSetIds();
if (StringUtils.isNotBlank(allChallengeQuestions)) {
String[] requestedQuestions = allChallengeQuestions.split(challengeQuestionSeparator);
if (requestedQuestions.length != userChallengeAnswer.length) {
throw Utils.handleClientException(IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_NEED_TO_ANSWER_TO_REQUESTED_QUESTIONS, null);
}
validateQuestion(requestedQuestions, userChallengeAnswer);
// Validate whether user answered all the requested questions
} else {
String error = "Could not find requested challenge questions for user: " + userRecoveryData.getUser();
throw Utils.handleClientException(IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_CHALLENGE_QUESTION_NOT_FOUND, error);
}
ChallengeQuestionManager challengeQuestionManager = ChallengeQuestionManager.getInstance();
for (int i = 0; i < userChallengeAnswer.length; i++) {
boolean verified = challengeQuestionManager.verifyUserChallengeAnswer(userRecoveryData.getUser(), userChallengeAnswer[i]);
if (!verified) {
// handleAnswerVerificationFail(userRecoveryData.getUser());
throw Utils.handleClientException(IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_INVALID_ANSWER_FOR_SECURITY_QUESTION, null);
}
}
// Reset password recovery failed attempts
if (isPerUserFunctionalityLockingEnabled) {
resetRecoveryPasswordProperties(userRecoveryData.getUser(), true);
} else {
resetRecoveryPasswordFailedAttempts(userRecoveryData.getUser(), true);
}
userRecoveryDataStore.invalidate(code);
ChallengeQuestionResponse challengeQuestionResponse = new ChallengeQuestionResponse();
String secretKey = UUIDGenerator.generateUUID();
challengeQuestionResponse.setCode(secretKey);
challengeQuestionResponse.setStatus(IdentityRecoveryConstants.RECOVERY_STATUS_COMPLETE);
UserRecoveryData recoveryData = new UserRecoveryData(userRecoveryData.getUser(), secretKey, RecoveryScenarios.QUESTION_BASED_PWD_RECOVERY);
recoveryData.setRecoveryStep(RecoverySteps.UPDATE_PASSWORD);
userRecoveryDataStore.store(recoveryData);
return challengeQuestionResponse;
} else {
throw Utils.handleClientException(IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_INVALID_CODE, null);
}
} catch (IdentityRecoveryClientException e) {
if (isPerUserFunctionalityLockingEnabled) {
handleAnswerVerificationFailInFunctionalityLockMode(userRecoveryData.getUser());
throw e;
}
handleAnswerVerificationFail(userRecoveryData.getUser());
throw e;
}
}
use of org.wso2.carbon.identity.recovery.model.ChallengeQuestion in project identity-governance by wso2-extensions.
the class SecurityQuestionPasswordRecoveryManager method initiateUserChallengeQuestion.
public ChallengeQuestionResponse initiateUserChallengeQuestion(User user) throws IdentityRecoveryException {
Utils.validateEmailUsername(user.getUserName());
if (StringUtils.isBlank(user.getTenantDomain())) {
user.setTenantDomain(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME);
log.info("initiateUserChallengeQuestion :Tenant domain is not in the request. set to default for user : " + user.getUserName());
}
if (StringUtils.isBlank(user.getUserStoreDomain())) {
user.setUserStoreDomain(IdentityUtil.getPrimaryDomainName());
log.info("initiateUserChallengeQuestion :User store domain is not in the request. set to default for user" + " : " + user.getUserName());
}
boolean isNotificationInternallyManaged = Boolean.parseBoolean(Utils.getRecoveryConfigs(IdentityRecoveryConstants.ConnectorConfig.NOTIFICATION_INTERNALLY_MANAGE, user.getTenantDomain()));
boolean isRecoveryEnable = Boolean.parseBoolean(Utils.getRecoveryConfigs(IdentityRecoveryConstants.ConnectorConfig.QUESTION_BASED_PW_RECOVERY, user.getTenantDomain()));
if (!isRecoveryEnable) {
throw Utils.handleClientException(IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_QUESTION_BASED_RECOVERY_NOT_ENABLE, null);
}
verifyUserExists(user);
validateFunctionalityForUser(user);
UserRecoveryDataStore userRecoveryDataStore = JDBCRecoveryDataStore.getInstance();
userRecoveryDataStore.invalidate(user);
String challengeQuestionSeparator = IdentityUtil.getProperty(IdentityRecoveryConstants.ConnectorConfig.QUESTION_CHALLENGE_SEPARATOR);
if (StringUtils.isEmpty(challengeQuestionSeparator)) {
challengeQuestionSeparator = IdentityRecoveryConstants.DEFAULT_CHALLENGE_QUESTION_SEPARATOR;
}
if (Utils.isAccountDisabled(user)) {
throw Utils.handleClientException(IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_DISABLED_ACCOUNT, user.getUserName());
} else if (Utils.isAccountLocked(user)) {
throw Utils.handleClientException(IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_LOCKED_ACCOUNT, user.getUserName());
}
boolean isNotificationSendWhenInitiatingPWRecovery = Boolean.parseBoolean(Utils.getRecoveryConfigs(IdentityRecoveryConstants.ConnectorConfig.NOTIFICATION_SEND_RECOVERY_SECURITY_START, user.getTenantDomain()));
if (isNotificationInternallyManaged && isNotificationSendWhenInitiatingPWRecovery) {
try {
triggerNotification(user, IdentityRecoveryConstants.NOTIFICATION_TYPE_PASSWORD_RESET_INITIATE, null);
} catch (Exception e) {
log.warn("Error while sending password reset initiating notification to user :" + user.getUserName());
}
}
int minNoOfQuestionsToAnswer = Integer.parseInt(Utils.getRecoveryConfigs(IdentityRecoveryConstants.ConnectorConfig.QUESTION_MIN_NO_ANSWER, user.getTenantDomain()));
ChallengeQuestionManager challengeQuestionManager = ChallengeQuestionManager.getInstance();
String[] ids = challengeQuestionManager.getUserChallengeQuestionIds(user);
if (ids == null || ids.length == 0) {
throw Utils.handleClientException(IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_CHALLENGE_QUESTION_NOT_FOUND, user.getUserName());
}
if (ids.length > minNoOfQuestionsToAnswer) {
ids = getRandomQuestionIds(ids, minNoOfQuestionsToAnswer);
}
String metaData = null;
for (int i = 1; i < ids.length; i++) {
if (i == 1) {
metaData = ids[1];
} else {
metaData = metaData + challengeQuestionSeparator + ids[i];
}
}
ChallengeQuestion userChallengeQuestion = challengeQuestionManager.getUserChallengeQuestion(user, ids[0]);
ChallengeQuestionResponse challengeQuestionResponse = new ChallengeQuestionResponse(userChallengeQuestion);
String secretKey = UUIDGenerator.generateUUID();
UserRecoveryData recoveryData = new UserRecoveryData(user, secretKey, RecoveryScenarios.QUESTION_BASED_PWD_RECOVERY, RecoverySteps.VALIDATE_CHALLENGE_QUESTION);
recoveryData.setRemainingSetIds(metaData);
challengeQuestionResponse.setCode(secretKey);
if (ids.length > 1) {
challengeQuestionResponse.setStatus(IdentityRecoveryConstants.RECOVERY_STATUS_INCOMPLETE);
}
userRecoveryDataStore.store(recoveryData);
return challengeQuestionResponse;
}
use of org.wso2.carbon.identity.recovery.model.ChallengeQuestion in project identity-governance by wso2-extensions.
the class ChallengeQuestionManagementAdminService method getChallengeQuestionsForUser.
/**
* Get all challenge questions applicable for a user based on his locale. If we can't find any question in his
* locale we return challenge questions from the default en_US locale.
*
* @param user
* @return
* @throws IdentityRecoveryServerException
*/
public ChallengeQuestion[] getChallengeQuestionsForUser(User user) throws IdentityRecoveryException {
if (user == null) {
log.error("User object provided is null.");
throw new IdentityRecoveryClientException("User object provided is null.");
}
String tenantDomain = CarbonContext.getThreadLocalCarbonContext().getTenantDomain();
List<ChallengeQuestion> challengeQuestionList;
try {
challengeQuestionList = questionManager.getAllChallengeQuestionsForUser(tenantDomain, user);
return challengeQuestionList.toArray(new ChallengeQuestion[challengeQuestionList.size()]);
} catch (IdentityRecoveryException e) {
String errorMgs = "Error loading challenge questions for user : %s@%s.";
log.error(String.format(errorMgs, user.getUserName(), tenantDomain), e);
throw new IdentityRecoveryException(String.format(errorMgs, user.getUserName(), tenantDomain), e);
}
}
use of org.wso2.carbon.identity.recovery.model.ChallengeQuestion in project identity-governance by wso2-extensions.
the class ChallengeQuestionManagementAdminService method getChallengeQuestionsOfTenant.
/**
* Get all challenge questions registered for a tenant.
*
* @param tenantDomain
* @return
* @throws IdentityRecoveryException
*/
public ChallengeQuestion[] getChallengeQuestionsOfTenant(String tenantDomain) throws IdentityRecoveryException {
List<ChallengeQuestion> challengeQuestionList;
checkCrossTenantAccess(tenantDomain);
try {
challengeQuestionList = questionManager.getAllChallengeQuestions(tenantDomain);
return challengeQuestionList.toArray(new ChallengeQuestion[challengeQuestionList.size()]);
} catch (IdentityRecoveryException e) {
String errorMgs = "Error loading challenge questions for tenant : %s.";
log.error(String.format(errorMgs, tenantDomain), e);
throw new IdentityRecoveryException(String.format(errorMgs, tenantDomain), e);
}
}
Aggregations