Search in sources :

Example 1 with OTPCredentialModel

use of org.keycloak.models.credential.OTPCredentialModel in project keycloak by keycloak.

the class CredentialHelper method createOTPCredential.

/**
 * Create OTP credential either in userStorage or local storage (Keycloak DB)
 *
 * @return true if credential was successfully created either in the user storage or Keycloak DB. False if error happened (EG. during HOTP validation)
 */
public static boolean createOTPCredential(KeycloakSession session, RealmModel realm, UserModel user, String totpCode, OTPCredentialModel credentialModel) {
    CredentialProvider otpCredentialProvider = session.getProvider(CredentialProvider.class, "keycloak-otp");
    String totpSecret = credentialModel.getOTPSecretData().getValue();
    UserCredentialModel otpUserCredential = new UserCredentialModel("", realm.getOTPPolicy().getType(), totpSecret);
    boolean userStorageCreated = session.userCredentialManager().updateCredential(realm, user, otpUserCredential);
    String credentialId = null;
    if (userStorageCreated) {
        logger.debugf("Created OTP credential for user '%s' in the user storage", user.getUsername());
    } else {
        CredentialModel createdCredential = otpCredentialProvider.createCredential(realm, user, credentialModel);
        credentialId = createdCredential.getId();
    }
    // If the type is HOTP, call verify once to consume the OTP used for registration and increase the counter.
    UserCredentialModel credential = new UserCredentialModel(credentialId, otpCredentialProvider.getType(), totpCode);
    return session.userCredentialManager().isValid(realm, user, credential);
}
Also used : UserCredentialModel(org.keycloak.models.UserCredentialModel) CredentialModel(org.keycloak.credential.CredentialModel) OTPCredentialModel(org.keycloak.models.credential.OTPCredentialModel) CredentialProvider(org.keycloak.credential.CredentialProvider) UserCredentialModel(org.keycloak.models.UserCredentialModel)

Example 2 with OTPCredentialModel

use of org.keycloak.models.credential.OTPCredentialModel in project keycloak by keycloak.

the class OTPFormAuthenticator method validateOTP.

public void validateOTP(AuthenticationFlowContext context) {
    MultivaluedMap<String, String> inputData = context.getHttpRequest().getDecodedFormParameters();
    String otp = inputData.getFirst("otp");
    String credentialId = inputData.getFirst("selectedCredentialId");
    if (credentialId == null || credentialId.isEmpty()) {
        OTPCredentialModel defaultOtpCredential = getCredentialProvider(context.getSession()).getDefaultCredential(context.getSession(), context.getRealm(), context.getUser());
        credentialId = defaultOtpCredential == null ? "" : defaultOtpCredential.getId();
    }
    context.getEvent().detail(Details.SELECTED_CREDENTIAL_ID, credentialId);
    context.form().setAttribute(SELECTED_OTP_CREDENTIAL_ID, credentialId);
    UserModel userModel = context.getUser();
    if (!enabledUser(context, userModel)) {
        // error in context is set in enabledUser/isDisabledByBruteForce
        return;
    }
    if (otp == null) {
        Response challengeResponse = challenge(context, null);
        context.challenge(challengeResponse);
        return;
    }
    boolean valid = context.getSession().userCredentialManager().isValid(context.getRealm(), context.getUser(), new UserCredentialModel(credentialId, getCredentialProvider(context.getSession()).getType(), otp));
    if (!valid) {
        context.getEvent().user(userModel).error(Errors.INVALID_USER_CREDENTIALS);
        Response challengeResponse = challenge(context, Messages.INVALID_TOTP, Validation.FIELD_OTP_CODE);
        context.failureChallenge(AuthenticationFlowError.INVALID_CREDENTIALS, challengeResponse);
        return;
    }
    context.success();
}
Also used : UserModel(org.keycloak.models.UserModel) Response(javax.ws.rs.core.Response) OTPCredentialModel(org.keycloak.models.credential.OTPCredentialModel) UserCredentialModel(org.keycloak.models.UserCredentialModel)

Example 3 with OTPCredentialModel

use of org.keycloak.models.credential.OTPCredentialModel in project keycloak by keycloak.

the class BasicAuthOTPAuthenticator method checkOtp.

private boolean checkOtp(AuthenticationFlowContext context, String otp) {
    OTPCredentialModel preferredCredential = getCredentialProvider(context.getSession()).getDefaultCredential(context.getSession(), context.getRealm(), context.getUser());
    boolean valid = getCredentialProvider(context.getSession()).isValid(context.getRealm(), context.getUser(), new UserCredentialModel(preferredCredential.getId(), getCredentialProvider(context.getSession()).getType(), otp));
    if (!valid) {
        context.getEvent().user(context.getUser()).error(Errors.INVALID_USER_CREDENTIALS);
        if (context.getExecution().isRequired()) {
            Response challengeResponse = challenge(context, Messages.INVALID_TOTP, Validation.FIELD_OTP_CODE);
            context.failureChallenge(AuthenticationFlowError.INVALID_CREDENTIALS, challengeResponse);
        } else {
            context.attempted();
        }
        return false;
    }
    return true;
}
Also used : Response(javax.ws.rs.core.Response) OTPCredentialModel(org.keycloak.models.credential.OTPCredentialModel) UserCredentialModel(org.keycloak.models.UserCredentialModel)

Example 4 with OTPCredentialModel

use of org.keycloak.models.credential.OTPCredentialModel in project keycloak by keycloak.

the class CredentialModelBackwardsCompatibilityTest method testCredentialModelOTP.

@Test
public void testCredentialModelOTP() {
    CredentialModel otp = OTPCredentialModel.createTOTP("456123", 6, 30, "someAlg");
    Assert.assertEquals("456123", otp.getValue());
    Assert.assertEquals(6, otp.getDigits());
    Assert.assertEquals(30, otp.getPeriod());
    Assert.assertEquals("someAlg", otp.getAlgorithm());
    // Change something and assert it is changed
    otp.setValue("789789");
    Assert.assertEquals("789789", otp.getValue());
    // Test clone
    OTPCredentialModel cloned = OTPCredentialModel.createFromCredentialModel(otp);
    Assert.assertEquals("789789", cloned.getOTPSecretData().getValue());
    Assert.assertEquals(6, cloned.getOTPCredentialData().getDigits());
    Assert.assertEquals("someAlg", cloned.getOTPCredentialData().getAlgorithm());
}
Also used : CredentialModel(org.keycloak.credential.CredentialModel) PasswordCredentialModel(org.keycloak.models.credential.PasswordCredentialModel) OTPCredentialModel(org.keycloak.models.credential.OTPCredentialModel) OTPCredentialModel(org.keycloak.models.credential.OTPCredentialModel) Test(org.junit.Test)

Example 5 with OTPCredentialModel

use of org.keycloak.models.credential.OTPCredentialModel in project keycloak by keycloak.

the class UpdateTotp method processAction.

@Override
public void processAction(RequiredActionContext context) {
    EventBuilder event = context.getEvent();
    event.event(EventType.UPDATE_TOTP);
    MultivaluedMap<String, String> formData = context.getHttpRequest().getDecodedFormParameters();
    String challengeResponse = formData.getFirst("totp");
    String totpSecret = formData.getFirst("totpSecret");
    String mode = formData.getFirst("mode");
    String userLabel = formData.getFirst("userLabel");
    OTPPolicy policy = context.getRealm().getOTPPolicy();
    OTPCredentialModel credentialModel = OTPCredentialModel.createFromPolicy(context.getRealm(), totpSecret, userLabel);
    if (Validation.isBlank(challengeResponse)) {
        Response challenge = context.form().setAttribute("mode", mode).addError(new FormMessage(Validation.FIELD_OTP_CODE, Messages.MISSING_TOTP)).createResponse(UserModel.RequiredAction.CONFIGURE_TOTP);
        context.challenge(challenge);
        return;
    } else if (!validateOTPCredential(context, challengeResponse, credentialModel, policy)) {
        Response challenge = context.form().setAttribute("mode", mode).addError(new FormMessage(Validation.FIELD_OTP_CODE, Messages.INVALID_TOTP)).createResponse(UserModel.RequiredAction.CONFIGURE_TOTP);
        context.challenge(challenge);
        return;
    }
    OTPCredentialProvider otpCredentialProvider = (OTPCredentialProvider) context.getSession().getProvider(CredentialProvider.class, "keycloak-otp");
    final Stream<CredentialModel> otpCredentials = (otpCredentialProvider.isConfiguredFor(context.getRealm(), context.getUser())) ? context.getSession().userCredentialManager().getStoredCredentialsByTypeStream(context.getRealm(), context.getUser(), OTPCredentialModel.TYPE) : Stream.empty();
    if (otpCredentials.count() >= 1 && Validation.isBlank(userLabel)) {
        Response challenge = context.form().setAttribute("mode", mode).addError(new FormMessage(Validation.FIELD_OTP_LABEL, Messages.MISSING_TOTP_DEVICE_NAME)).createResponse(UserModel.RequiredAction.CONFIGURE_TOTP);
        context.challenge(challenge);
        return;
    }
    if (!CredentialHelper.createOTPCredential(context.getSession(), context.getRealm(), context.getUser(), challengeResponse, credentialModel)) {
        Response challenge = context.form().setAttribute("mode", mode).addError(new FormMessage(Validation.FIELD_OTP_CODE, Messages.INVALID_TOTP)).createResponse(UserModel.RequiredAction.CONFIGURE_TOTP);
        context.challenge(challenge);
        return;
    }
    context.success();
}
Also used : Response(javax.ws.rs.core.Response) EventBuilder(org.keycloak.events.EventBuilder) CredentialModel(org.keycloak.credential.CredentialModel) OTPCredentialModel(org.keycloak.models.credential.OTPCredentialModel) OTPCredentialProvider(org.keycloak.credential.OTPCredentialProvider) CredentialProvider(org.keycloak.credential.CredentialProvider) OTPCredentialModel(org.keycloak.models.credential.OTPCredentialModel) OTPPolicy(org.keycloak.models.OTPPolicy) FormMessage(org.keycloak.models.utils.FormMessage) OTPCredentialProvider(org.keycloak.credential.OTPCredentialProvider)

Aggregations

OTPCredentialModel (org.keycloak.models.credential.OTPCredentialModel)9 OTPPolicy (org.keycloak.models.OTPPolicy)4 UserCredentialModel (org.keycloak.models.UserCredentialModel)4 Response (javax.ws.rs.core.Response)3 CredentialModel (org.keycloak.credential.CredentialModel)3 UserModel (org.keycloak.models.UserModel)3 CredentialProvider (org.keycloak.credential.CredentialProvider)2 EventBuilder (org.keycloak.events.EventBuilder)2 Consumes (javax.ws.rs.Consumes)1 POST (javax.ws.rs.POST)1 Path (javax.ws.rs.Path)1 Test (org.junit.Test)1 OTPCredentialProvider (org.keycloak.credential.OTPCredentialProvider)1 RealmModel (org.keycloak.models.RealmModel)1 PasswordCredentialModel (org.keycloak.models.credential.PasswordCredentialModel)1 OTPCredentialData (org.keycloak.models.credential.dto.OTPCredentialData)1 OTPSecretData (org.keycloak.models.credential.dto.OTPSecretData)1 FormMessage (org.keycloak.models.utils.FormMessage)1 HmacOTP (org.keycloak.models.utils.HmacOTP)1 TimeBasedOTP (org.keycloak.models.utils.TimeBasedOTP)1