diff --git a/model/mongo/src/main/java/org/keycloak/connections/mongo/updater/impl/DefaultMongoUpdaterProvider.java b/model/mongo/src/main/java/org/keycloak/connections/mongo/updater/impl/DefaultMongoUpdaterProvider.java index 0b4cea7514..889281c776 100755 --- a/model/mongo/src/main/java/org/keycloak/connections/mongo/updater/impl/DefaultMongoUpdaterProvider.java +++ b/model/mongo/src/main/java/org/keycloak/connections/mongo/updater/impl/DefaultMongoUpdaterProvider.java @@ -32,6 +32,7 @@ import org.keycloak.connections.mongo.updater.impl.updates.Update1_3_0; import org.keycloak.connections.mongo.updater.impl.updates.Update1_4_0; import org.keycloak.connections.mongo.updater.impl.updates.Update1_7_0; import org.keycloak.connections.mongo.updater.impl.updates.Update1_8_0; +import org.keycloak.connections.mongo.updater.impl.updates.Update1_9_2; import org.keycloak.models.KeycloakSession; import java.util.Date; @@ -55,7 +56,8 @@ public class DefaultMongoUpdaterProvider implements MongoUpdaterProvider { Update1_3_0.class, Update1_4_0.class, Update1_7_0.class, - Update1_8_0.class + Update1_8_0.class, + Update1_9_2.class }; @Override diff --git a/model/mongo/src/main/java/org/keycloak/connections/mongo/updater/impl/updates/Update1_9_2.java b/model/mongo/src/main/java/org/keycloak/connections/mongo/updater/impl/updates/Update1_9_2.java new file mode 100644 index 0000000000..7c91a29dc7 --- /dev/null +++ b/model/mongo/src/main/java/org/keycloak/connections/mongo/updater/impl/updates/Update1_9_2.java @@ -0,0 +1,62 @@ +/* + * Copyright 2016 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed 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.keycloak.connections.mongo.updater.impl.updates; + +import com.mongodb.BasicDBList; +import com.mongodb.BasicDBObject; +import com.mongodb.DBCollection; +import com.mongodb.WriteResult; +import org.keycloak.hash.Pbkdf2PasswordHashProvider; +import org.keycloak.models.KeycloakSession; +import org.keycloak.models.UserCredentialModel; +import org.keycloak.models.utils.HmacOTP; + +/** + * @author Marek Posolda + */ +public class Update1_9_2 extends Update { + + @Override + public String getId() { + return "1.9.2"; + } + + @Override + public void update(KeycloakSession session) { + BasicDBList orArgs = new BasicDBList(); + orArgs.add(new BasicDBObject("type", UserCredentialModel.PASSWORD)); + orArgs.add(new BasicDBObject("type", UserCredentialModel.PASSWORD_HISTORY)); + + BasicDBObject elemMatch = new BasicDBObject("$or", orArgs); + elemMatch.put("algorithm", HmacOTP.HMAC_SHA1); + + BasicDBObject query = new BasicDBObject("credentials", new BasicDBObject("$elemMatch", elemMatch)); + + BasicDBObject update = new BasicDBObject("$set", new BasicDBObject("credentials.$.algorithm", Pbkdf2PasswordHashProvider.ID)); + + DBCollection users = db.getCollection("users"); + + // Not sure how to do in single query + int countModified = 1; + while (countModified > 0) { + WriteResult wr = users.update(query, update, false, true); + countModified = wr.getN(); + log.debugf("%d credentials modified in current iteration during upgrade to 1.8", countModified); + } + } +} diff --git a/server-spi/src/main/java/org/keycloak/models/utils/RepresentationToModel.java b/server-spi/src/main/java/org/keycloak/models/utils/RepresentationToModel.java index 970fd7eede..d07902d374 100755 --- a/server-spi/src/main/java/org/keycloak/models/utils/RepresentationToModel.java +++ b/server-spi/src/main/java/org/keycloak/models/utils/RepresentationToModel.java @@ -1284,7 +1284,15 @@ public class RepresentationToModel { if (cred.getDigits() != null) hashedCred.setDigits(cred.getDigits()); if (cred.getAlgorithm() != null) { - hashedCred.setAlgorithm(cred.getAlgorithm()); + + // Could happen when migrating from some early version + if ((UserCredentialModel.PASSWORD.equals(cred.getType()) || UserCredentialModel.PASSWORD_HISTORY.equals(cred.getType())) && + (cred.getAlgorithm().equals(HmacOTP.HMAC_SHA1))) { + hashedCred.setAlgorithm(Pbkdf2PasswordHashProvider.ID); + } else { + hashedCred.setAlgorithm(cred.getAlgorithm()); + } + } else { if (UserCredentialModel.PASSWORD.equals(cred.getType()) || UserCredentialModel.PASSWORD_HISTORY.equals(cred.getType())) { hashedCred.setAlgorithm(Pbkdf2PasswordHashProvider.ID);