Search in sources :

Example 11 with CredentialModel

use of org.keycloak.credential.CredentialModel in project keycloak by keycloak.

the class BackwardsCompatibilityUserStorage method isValid.

@Override
public boolean isValid(RealmModel realm, UserModel user, CredentialInput input) {
    MyUser myUser = users.get(translateUserName(user.getUsername()));
    if (myUser == null)
        return false;
    if (input.getType().equals(UserCredentialModel.PASSWORD)) {
        if (!(input instanceof PasswordUserCredentialModel))
            return false;
        CredentialModel hashedPassword = myUser.hashedPassword;
        if (hashedPassword == null) {
            log.warnf("Password not set for user %s", user.getUsername());
            return false;
        }
        PasswordUserCredentialModel userCredentialModel = (PasswordUserCredentialModel) input;
        // Those are not supposed to be set when calling this method in Keycloak 4.8.3 for password credential
        assertNull(userCredentialModel.getDevice());
        assertNull(userCredentialModel.getAlgorithm());
        PasswordPolicy policy = session.getContext().getRealm().getPasswordPolicy();
        PasswordHashProvider hashProvider = getHashProvider(policy);
        String rawPassword = userCredentialModel.getValue();
        // Compatibility with 4.8.3 - using "legacy" signature of this method
        return hashProvider.verify(rawPassword, hashedPassword);
    } else if (isOTPType(input.getType())) {
        UserCredentialModel otpCredential = (UserCredentialModel) input;
        // Special hardcoded OTP, which is always considered valid
        if ("123456".equals(otpCredential.getValue())) {
            return true;
        }
        CredentialModel storedOTPCredential = myUser.otp;
        if (storedOTPCredential == null) {
            log.warnf("Not found credential for the user %s", user.getUsername());
            return false;
        }
        TimeBasedOTP validator = new TimeBasedOTP(storedOTPCredential.getAlgorithm(), storedOTPCredential.getDigits(), storedOTPCredential.getPeriod(), realm.getOTPPolicy().getLookAheadWindow());
        return validator.validateTOTP(otpCredential.getValue(), storedOTPCredential.getValue().getBytes());
    } else {
        log.infof("Not supported to validate credential of type '%s' for user '%s'", input.getType(), user.getUsername());
        return false;
    }
}
Also used : PasswordUserCredentialModel(org.keycloak.models.credential.PasswordUserCredentialModel) PasswordUserCredentialModel(org.keycloak.models.credential.PasswordUserCredentialModel) UserCredentialModel(org.keycloak.models.UserCredentialModel) CredentialModel(org.keycloak.credential.CredentialModel) TimeBasedOTP(org.keycloak.models.utils.TimeBasedOTP) PasswordPolicy(org.keycloak.models.PasswordPolicy) PasswordUserCredentialModel(org.keycloak.models.credential.PasswordUserCredentialModel) UserCredentialModel(org.keycloak.models.UserCredentialModel) PasswordHashProvider(org.keycloak.credential.hash.PasswordHashProvider)

Example 12 with CredentialModel

use of org.keycloak.credential.CredentialModel in project keycloak by keycloak.

the class CredentialModelTest method testCredentialCRUD.

@Test
@ModelTest
public void testCredentialCRUD(KeycloakSession session) throws Exception {
    AtomicReference<String> passwordId = new AtomicReference<>();
    AtomicReference<String> otp1Id = new AtomicReference<>();
    AtomicReference<String> otp2Id = new AtomicReference<>();
    KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession currentSession) -> {
        RealmModel realm = currentSession.realms().getRealmByName("test");
        UserModel user = currentSession.users().getUserByUsername(realm, "test-user@localhost");
        List<CredentialModel> list = currentSession.userCredentialManager().getStoredCredentialsStream(realm, user).collect(Collectors.toList());
        Assert.assertEquals(1, list.size());
        passwordId.set(list.get(0).getId());
        // Create 2 OTP credentials (password was already created)
        CredentialModel otp1 = OTPCredentialModel.createFromPolicy(realm, "secret1");
        CredentialModel otp2 = OTPCredentialModel.createFromPolicy(realm, "secret2");
        otp1 = currentSession.userCredentialManager().createCredential(realm, user, otp1);
        otp2 = currentSession.userCredentialManager().createCredential(realm, user, otp2);
        otp1Id.set(otp1.getId());
        otp2Id.set(otp2.getId());
    });
    KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession currentSession) -> {
        RealmModel realm = currentSession.realms().getRealmByName("test");
        UserModel user = currentSession.users().getUserByUsername(realm, "test-user@localhost");
        // Assert priorities: password, otp1, otp2
        List<CredentialModel> list = currentSession.userCredentialManager().getStoredCredentialsStream(realm, user).collect(Collectors.toList());
        assertOrder(list, passwordId.get(), otp1Id.get(), otp2Id.get());
        // Assert can't move password when newPreviousCredential not found
        Assert.assertFalse(currentSession.userCredentialManager().moveCredentialTo(realm, user, passwordId.get(), "not-known"));
        // Assert can't move credential when not found
        Assert.assertFalse(currentSession.userCredentialManager().moveCredentialTo(realm, user, "not-known", otp2Id.get()));
        // Move otp2 up 1 position
        Assert.assertTrue(currentSession.userCredentialManager().moveCredentialTo(realm, user, otp2Id.get(), passwordId.get()));
    });
    KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession currentSession) -> {
        RealmModel realm = currentSession.realms().getRealmByName("test");
        UserModel user = currentSession.users().getUserByUsername(realm, "test-user@localhost");
        // Assert priorities: password, otp2, otp1
        List<CredentialModel> list = currentSession.userCredentialManager().getStoredCredentialsStream(realm, user).collect(Collectors.toList());
        assertOrder(list, passwordId.get(), otp2Id.get(), otp1Id.get());
        // Move otp2 to the top
        Assert.assertTrue(currentSession.userCredentialManager().moveCredentialTo(realm, user, otp2Id.get(), null));
    });
    KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession currentSession) -> {
        RealmModel realm = currentSession.realms().getRealmByName("test");
        UserModel user = currentSession.users().getUserByUsername(realm, "test-user@localhost");
        // Assert priorities: otp2, password, otp1
        List<CredentialModel> list = currentSession.userCredentialManager().getStoredCredentialsStream(realm, user).collect(Collectors.toList());
        assertOrder(list, otp2Id.get(), passwordId.get(), otp1Id.get());
        // Move password down
        Assert.assertTrue(currentSession.userCredentialManager().moveCredentialTo(realm, user, passwordId.get(), otp1Id.get()));
    });
    KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession currentSession) -> {
        RealmModel realm = currentSession.realms().getRealmByName("test");
        UserModel user = currentSession.users().getUserByUsername(realm, "test-user@localhost");
        // Assert priorities: otp2, otp1, password
        List<CredentialModel> list = currentSession.userCredentialManager().getStoredCredentialsStream(realm, user).collect(Collectors.toList());
        assertOrder(list, otp2Id.get(), otp1Id.get(), passwordId.get());
        // Remove otp2 down two positions
        Assert.assertTrue(currentSession.userCredentialManager().moveCredentialTo(realm, user, otp2Id.get(), passwordId.get()));
    });
    KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession currentSession) -> {
        RealmModel realm = currentSession.realms().getRealmByName("test");
        UserModel user = currentSession.users().getUserByUsername(realm, "test-user@localhost");
        // Assert priorities: otp2, otp1, password
        List<CredentialModel> list = currentSession.userCredentialManager().getStoredCredentialsStream(realm, user).collect(Collectors.toList());
        assertOrder(list, otp1Id.get(), passwordId.get(), otp2Id.get());
        // Remove password
        Assert.assertTrue(currentSession.userCredentialManager().removeStoredCredential(realm, user, passwordId.get()));
    });
    KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession currentSession) -> {
        RealmModel realm = currentSession.realms().getRealmByName("test");
        UserModel user = currentSession.users().getUserByUsername(realm, "test-user@localhost");
        // Assert priorities: otp2, password
        List<CredentialModel> list = currentSession.userCredentialManager().getStoredCredentialsStream(realm, user).collect(Collectors.toList());
        assertOrder(list, otp1Id.get(), otp2Id.get());
    });
}
Also used : RealmModel(org.keycloak.models.RealmModel) UserModel(org.keycloak.models.UserModel) CredentialModel(org.keycloak.credential.CredentialModel) OTPCredentialModel(org.keycloak.models.credential.OTPCredentialModel) KeycloakSession(org.keycloak.models.KeycloakSession) AtomicReference(java.util.concurrent.atomic.AtomicReference) ModelTest(org.keycloak.testsuite.arquillian.annotation.ModelTest) ModelTest(org.keycloak.testsuite.arquillian.annotation.ModelTest) Test(org.junit.Test) AbstractTestRealmKeycloakTest(org.keycloak.testsuite.AbstractTestRealmKeycloakTest)

Example 13 with CredentialModel

use of org.keycloak.credential.CredentialModel 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 14 with CredentialModel

use of org.keycloak.credential.CredentialModel 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)

Example 15 with CredentialModel

use of org.keycloak.credential.CredentialModel in project keycloak by keycloak.

the class AccountCredentialResource method removeCredential.

/**
 * Remove a credential of current user
 *
 * @param credentialId ID of the credential, which will be removed
 */
@Path("{credentialId}")
@DELETE
@NoCache
public void removeCredential(@PathParam("credentialId") final String credentialId) {
    auth.require(AccountRoles.MANAGE_ACCOUNT);
    CredentialModel credential = session.userCredentialManager().getStoredCredentialById(realm, user, credentialId);
    if (credential == null) {
        throw new NotFoundException("Credential not found");
    }
    session.userCredentialManager().removeStoredCredential(realm, user, credentialId);
}
Also used : CredentialModel(org.keycloak.credential.CredentialModel) NotFoundException(javax.ws.rs.NotFoundException) Path(javax.ws.rs.Path) DELETE(javax.ws.rs.DELETE) NoCache(org.jboss.resteasy.annotations.cache.NoCache)

Aggregations

CredentialModel (org.keycloak.credential.CredentialModel)36 Test (org.junit.Test)14 OTPCredentialModel (org.keycloak.models.credential.OTPCredentialModel)14 PasswordCredentialModel (org.keycloak.models.credential.PasswordCredentialModel)14 UserCredentialModel (org.keycloak.models.UserCredentialModel)10 RealmModel (org.keycloak.models.RealmModel)8 UserModel (org.keycloak.models.UserModel)7 NotFoundException (javax.ws.rs.NotFoundException)6 Path (javax.ws.rs.Path)5 AbstractAuthTest (org.keycloak.testsuite.AbstractAuthTest)5 CredentialRepresentation (org.keycloak.representations.idm.CredentialRepresentation)4 NoCache (org.jboss.resteasy.annotations.cache.NoCache)3 CredentialProvider (org.keycloak.credential.CredentialProvider)3 CachedUserModel (org.keycloak.models.cache.CachedUserModel)3 UserRepresentation (org.keycloak.representations.idm.UserRepresentation)3 ModelTest (org.keycloak.testsuite.arquillian.annotation.ModelTest)3 LinkedList (java.util.LinkedList)2 AtomicReference (java.util.concurrent.atomic.AtomicReference)2 Consumes (javax.ws.rs.Consumes)2 DELETE (javax.ws.rs.DELETE)2