pTi
pTi

Reputation: 357

Keycloak multiple security Q&As for a user not work

Referring this git repo (https://github.com/keycloak/keycloak/blob/master/examples/providers/authenticator/secret-question.ftl) I manage to add a security question which can use to ask from user in the event of “forget password” for additional level of security. However, in the current system, there is provision of storing only one security Q&A. I am looking to modify this to include the following:

functionality be extended to include 3 security Q&As which is popular practice. I modified the keycloak secret-question.ftl to include 2 more questions.

But there is no way to store the additional questions and answers extracted from the ui form in the UserCredentialValueModel SecretQuestionRequiredAction.java).

I am new to KeyCloak and need guide.

Upvotes: 2

Views: 914

Answers (2)

Ahmad Alarbeed
Ahmad Alarbeed

Reputation: 1

I did something like this, and really worked for me. in my case I have 5 security questions, 3 required and 2 optional.

@Override
public void processAction(RequiredActionContext context) {

    for (int i = 1; i <= 5; i++) {

        var securityQuestionId = context.getHttpRequest().getDecodedFormParameters().getFirst("securityQuestion" + i);
        var securityAnswer = context.getHttpRequest().getDecodedFormParameters().getFirst("securityAnswer" + i);

        if (i <= 3 && (StringUtil.isBlank(securityQuestionId) || StringUtil.isBlank(securityAnswer))) {
            context.failure();
            return;
        }

        if (i >= 4 && (StringUtil.isBlank(securityQuestionId) || StringUtil.isBlank(securityAnswer))) {
            continue;
        }

        var encodedAnswer = EncoderUtil.encode(securityAnswer);

        sqcp.createCredential(context.getRealm(), context.getUser(), SecurityQuestionCredentialModel.createSecurityQuestion(
            securityQuestion.getId(), securityQuestion.getQuestion(), encodedAnswer));
    }

    context.success();
}

Upvotes: 0

Gregory Ledray
Gregory Ledray

Reputation: 1197

I got this to work. I had to do the following:

  1. Modify the frontend .ftl files to add the additional question(s)
  2. Modify the SecretQuestionSecretData model to store multiple answers to those questions. If you are also storing multiple questions, then you'd need to modify the SecretQuestion Credential model file too.
  3. When created by a user in the secret-question-config.ftl file the credentials will be retrievable in processAction. Amend this to store the additional data.
  4. Amend the getter/setters for the model and providers and factories as necessary
  5. Modify SecretQuestionAuthenticator to NOT call isValid. Instead perform the check directly. Calling isValid won't work because the example code takes the data model and transforms it into a new data model which can only retrieve up to 1 piece of data - a string from challenge(). Instead of performing such a transformation, just do the isValid work in the method which calls isValid.
  6. I removed the cookie related code so that the check always runs regardless of if a cookie is set.

Upvotes: 1

Related Questions