A tested password hash provider using Scrypt for Keycloak. Tested for version 12.0.1.
You must have docker
installed to integration test this JAR.
gradle test
A keycloak docker image is built on the fly with the output of gradle shadowJar
(a JAR file built at shadowJar.archiveFile.get().asFile.absolutePath
, typically build/libs/keycloak-scrypt.jar
). That JAR is copied to /opt/jboss/keycloak/standalone/deployments/
inside the container.
This can be used as a template for all Keycloak extensions.
Add the output of gradle shadowJar
(typically build/libs/keycloak-scrypt.jar
) to /opt/jboss/keycloak/standalone/deployments/
inside the container.
-
Add the appropriate Keycloak dependencies. You need the SPIs to correctly encode the password for account creation:
def keycloakVersion = "12.0.1" implementation(group: 'org.keycloak', name: 'keycloak-admin-client', version: "$keycloakVersion") implementation "org.keycloak:keycloak-server-spi:$keycloakVersion" implementation "org.keycloak:keycloak-server-spi-private:$keycloakVersion" implementation platform("org.keycloak.bom:keycloak-bom-parent:$keycloakVersion")
-
Create a Keycloak admin client.
-
Update your realm to support
scrypt
as a password algorithm. This will also make all further passwords encoded in Scrypt when user accounts are created in this realm.// Retrieve your realm from the keycloak admin client RealmResource realm = ... RealmRepresentation realmRepresentation = realm.toRepresentation(); realmRepresentation.setPasswordPolicy("hashAlgorithm(scrypt)"); realm.update(realmRepresentation);
-
Create a user with the Server SPI representation of credentials. For example:
UserRepresentation user = new UserRepresentation(); user.setEnabled(true); String email = UUID.randomUUID().toString() + "@abc.com"; String username = UUID.randomUUID().toString(); String password = UUID.randomUUID().toString(); String hashedPassword = SCryptUtil.scrypt(password, 16384, 8, 1); user.setEmail(email); user.setUsername(username); PasswordCredentialModel credentialModel = PasswordCredentialModel.createFromValues(ScryptHashProvider.ID, new byte[0], 1, hashedPassword); CredentialRepresentation credential = ModelToRepresentation.toRepresentation(credentialModel); credential.setTemporary(false); user.setCredentials(Collections.singletonList(credential)); realm.users().create(user);
Observe iterations are not used. The hash parameters for this package are N = 16384, R = 8, p = 1.