Skip to content

Commit a095e2d

Browse files
committed
Refactor Password Policy Providers
Password Policy Providers were refactored to remove duplicate code. This commit also addresses several SonarQube issues.
1 parent db85a0b commit a095e2d

16 files changed

+135
-409
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ mvn clean install;
1111

1212
This will build both the `jar-module` and `ear-module`:
1313
```
14-
[INFO] Reactor Summary for Argon2 Password Hash Provider 1.0.0:
14+
[INFO] Reactor Summary for Argon2 Password Hash Provider 1.1.0:
1515
[INFO]
1616
[INFO] Argon2 Password Hash Provider ...................... SUCCESS [ 0.633 s]
1717
[INFO] Argon2 Password Hash Provider Module ............... SUCCESS [ 3.264 s]

ear-module/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<parent>
55
<groupId>be.cronos.keycloak</groupId>
66
<artifactId>argon2-password-hash-provider</artifactId>
7-
<version>1.0.0</version>
7+
<version>1.1.0</version>
88
</parent>
99
<modelVersion>4.0.0</modelVersion>
1010

jar-module/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<parent>
66
<groupId>be.cronos.keycloak</groupId>
77
<artifactId>argon2-password-hash-provider</artifactId>
8-
<version>1.0.0</version>
8+
<version>1.1.0</version>
99
</parent>
1010

1111
<artifactId>argon2-password-hash-provider-module</artifactId>

jar-module/src/main/java/be/cronos/keycloak/credential/hash/Argon2PasswordHashProvider.java

Lines changed: 14 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,14 @@
22

33
import be.cronos.keycloak.policy.*;
44
import be.cronos.keycloak.utils.Argon2Helper;
5+
import de.mkammerer.argon2.Argon2Constants;
56
import de.mkammerer.argon2.Argon2Factory.Argon2Types;
67
import org.jboss.logging.Logger;
78
import org.keycloak.credential.hash.PasswordHashProvider;
89
import org.keycloak.models.KeycloakSession;
910
import org.keycloak.models.PasswordPolicy;
1011
import org.keycloak.models.credential.PasswordCredentialModel;
1112

12-
import java.security.SecureRandom;
13-
1413
/**
1514
* @author <a href="mailto:dries.eestermans@is4u.be">Dries Eestermans</a>
1615
*/
@@ -20,31 +19,19 @@ public class Argon2PasswordHashProvider implements PasswordHashProvider {
2019

2120
private final String providerId;
2221

23-
private final Argon2Types defaultArgon2Variant;
24-
private final int defaultIterations;
25-
private final int defaultMemory;
26-
private final int defaultParallelism;
27-
private final int defaultHashLength;
28-
private final int defaultSaltLength;
29-
private final int defaultMaxTime;
22+
private static final Argon2Types DEFAULT_ARGON_2_VARIANT = Argon2Types.ARGON2id;
23+
private static final int DEFAULT_ITERATIONS = 1;
3024
private KeycloakSession session;
3125

32-
public Argon2PasswordHashProvider(String providerId, Argon2Types defaultArgon2Variant, int defaultIterations, int defaultMemory, int defaultParallelism, int defaultHashLength, int defaultSaltLength, int defaultMaxTime, KeycloakSession session) {
26+
public Argon2PasswordHashProvider(String providerId, KeycloakSession session) {
3327
this.providerId = providerId;
34-
this.defaultArgon2Variant = defaultArgon2Variant;
35-
this.defaultIterations = defaultIterations;
36-
this.defaultMemory = defaultMemory;
37-
this.defaultParallelism = defaultParallelism;
38-
this.defaultHashLength = defaultHashLength;
39-
this.defaultSaltLength = defaultSaltLength;
40-
this.defaultMaxTime = defaultMaxTime;
4128
this.session = session;
4229
}
4330

4431
@Override
4532
public boolean policyCheck(PasswordPolicy policy, PasswordCredentialModel credential) {
4633
LOG.debugf("policyCheck()");
47-
int policyHashIterations = getDefaultValue(Argon2IterationsPasswordPolicyProviderFactory.ID, defaultIterations);
34+
int policyHashIterations = getDefaultValue(Argon2IterationsPasswordPolicyProviderFactory.ID, DEFAULT_ITERATIONS);
4835

4936
return credential.getPasswordCredentialData().getHashIterations() == policyHashIterations
5037
&& providerId.equals(credential.getPasswordCredentialData().getAlgorithm());
@@ -55,13 +42,13 @@ public PasswordCredentialModel encodedCredential(String rawPassword, int iterati
5542
LOG.debugf("encodedCredential()");
5643

5744
// Get the Argon2 parameters, or default values
58-
int argon2Iterations = getDefaultValue(Argon2IterationsPasswordPolicyProviderFactory.ID, defaultIterations);
59-
int parallelism = getDefaultValue(Argon2ParallelismPasswordPolicyProviderFactory.ID, defaultParallelism);
60-
int memoryLimit = getDefaultValue(Argon2MemoryPasswordPolicyProviderFactory.ID, defaultMemory);
61-
int hashLength = getDefaultValue(Argon2HashLengthPasswordPolicyProviderFactory.ID, defaultHashLength);
62-
int saltLength = getDefaultValue(Argon2SaltLengthPasswordPolicyProviderFactory.ID, defaultSaltLength);
63-
Argon2Types argon2Variant = getDefaultValue(Argon2VariantPasswordPolicyProviderFactory.ID, defaultArgon2Variant);
64-
int maxTime = getDefaultValue(Argon2MaxTimePasswordPolicyProviderFactory.ID, defaultMaxTime);
45+
int argon2Iterations = getDefaultValue(Argon2IterationsPasswordPolicyProviderFactory.ID, DEFAULT_ITERATIONS);
46+
int parallelism = getDefaultValue(Argon2ParallelismPasswordPolicyProviderFactory.ID, 1);
47+
int memoryLimit = getDefaultValue(Argon2MemoryPasswordPolicyProviderFactory.ID, 65536);
48+
int hashLength = getDefaultValue(Argon2HashLengthPasswordPolicyProviderFactory.ID, Argon2Constants.DEFAULT_HASH_LENGTH);
49+
int saltLength = getDefaultValue(Argon2SaltLengthPasswordPolicyProviderFactory.ID, Argon2Constants.DEFAULT_SALT_LENGTH);
50+
Argon2Types argon2Variant = getDefaultValue(Argon2VariantPasswordPolicyProviderFactory.ID, DEFAULT_ARGON_2_VARIANT);
51+
int maxTime = getDefaultValue(Argon2MaxTimePasswordPolicyProviderFactory.ID, 1000);
6552

6653
LOG.debugf("Using the following Argon2 settings:");
6754
LOG.debugf("\tArgon2 Variant: %s", argon2Variant);
@@ -104,10 +91,7 @@ private <T> T getDefaultValue(String providerId, T defaultValue) {
10491
}
10592

10693
private byte[] getSalt() {
107-
byte[] buffer = new byte[16];
108-
SecureRandom secureRandom = new SecureRandom();
109-
secureRandom.nextBytes(buffer);
110-
return buffer;
94+
return "0123456789abcdef".getBytes();
11195
}
11296

11397
@Override
@@ -120,6 +104,6 @@ public boolean verify(String rawPassword, PasswordCredentialModel credential) {
120104

121105
@Override
122106
public void close() {
123-
107+
// noop
124108
}
125109
}
Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
package be.cronos.keycloak.credential.hash;
22

3-
import de.mkammerer.argon2.Argon2Constants;
4-
import de.mkammerer.argon2.Argon2Factory.Argon2Types;
5-
import org.jboss.logging.Logger;
63
import org.keycloak.Config;
74
import org.keycloak.credential.hash.PasswordHashProvider;
85
import org.keycloak.credential.hash.PasswordHashProviderFactory;
@@ -13,29 +10,21 @@
1310
* @author <a href="mailto:dries.eestermans@is4u.be">Dries Eestermans</a>
1411
*/
1512
public class Argon2PasswordHashProviderFactory implements PasswordHashProviderFactory {
16-
private static final Logger LOG = Logger.getLogger(Argon2PasswordHashProviderFactory.class);
17-
1813
public static final String ID = "argon2";
1914

20-
public static final int DEFAULT_ITERATIONS = 1;
21-
22-
public static final int DEFAULT_MEMORY = 65536;
23-
24-
public static final int DEFAULT_PARALLELISM = 1;
25-
26-
public static final int DEFAULT_MAX_TIME = 1000;
27-
2815
@Override
2916
public PasswordHashProvider create(KeycloakSession session) {
30-
return new Argon2PasswordHashProvider(ID, Argon2Types.ARGON2id, DEFAULT_ITERATIONS, DEFAULT_MEMORY, DEFAULT_PARALLELISM, Argon2Constants.DEFAULT_HASH_LENGTH, Argon2Constants.DEFAULT_SALT_LENGTH, DEFAULT_MAX_TIME, session);
17+
return new Argon2PasswordHashProvider(ID, session);
3118
}
3219

3320
@Override
3421
public void init(Config.Scope config) {
22+
// noop
3523
}
3624

3725
@Override
3826
public void postInit(KeycloakSessionFactory factory) {
27+
// noop
3928
}
4029

4130
@Override
@@ -45,5 +34,6 @@ public String getId() {
4534

4635
@Override
4736
public void close() {
37+
// noop
4838
}
4939
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package be.cronos.keycloak.exceptions;
2+
3+
public class Argon2RuntimeException extends RuntimeException {
4+
public Argon2RuntimeException() {
5+
}
6+
7+
public Argon2RuntimeException(String message) {
8+
super(message);
9+
}
10+
11+
public Argon2RuntimeException(String message, Throwable cause) {
12+
super(message, cause);
13+
}
14+
15+
public Argon2RuntimeException(Throwable cause) {
16+
super(cause);
17+
}
18+
19+
public Argon2RuntimeException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
20+
super(message, cause, enableSuppression, writableStackTrace);
21+
}
22+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package be.cronos.keycloak.policy;
2+
3+
import org.keycloak.Config;
4+
import org.keycloak.models.KeycloakSession;
5+
import org.keycloak.models.KeycloakSessionFactory;
6+
import org.keycloak.models.RealmModel;
7+
import org.keycloak.models.UserModel;
8+
import org.keycloak.policy.PasswordPolicyProvider;
9+
import org.keycloak.policy.PasswordPolicyProviderFactory;
10+
import org.keycloak.policy.PolicyError;
11+
12+
/**
13+
* @author <a href="mailto:dries.eestermans@is4u.be">Dries Eestermans</a>
14+
*/
15+
public abstract class Argon2GenericPolicyProviderFactory implements PasswordPolicyProvider, PasswordPolicyProviderFactory {
16+
17+
@Override
18+
public Argon2GenericPolicyProviderFactory create(KeycloakSession session) {
19+
return this;
20+
}
21+
22+
@Override
23+
public void init(Config.Scope config) {
24+
// noop
25+
}
26+
27+
@Override
28+
public void postInit(KeycloakSessionFactory factory) {
29+
// noop
30+
}
31+
32+
@Override
33+
public PolicyError validate(RealmModel realm, UserModel user, String password) {
34+
return null;
35+
}
36+
37+
@Override
38+
public PolicyError validate(String user, String password) {
39+
return null;
40+
}
41+
42+
@Override
43+
public Object parseConfig(String value) {
44+
return parseInteger(value, -1);
45+
}
46+
47+
@Override
48+
public String getConfigType() {
49+
return PasswordPolicyProvider.INT_CONFIG_TYPE;
50+
}
51+
52+
@Override
53+
public String getDefaultConfigValue() {
54+
return String.valueOf(1);
55+
}
56+
57+
@Override
58+
public boolean isMultiplSupported() {
59+
return false;
60+
}
61+
62+
@Override
63+
public void close() {
64+
// noop
65+
}
66+
}
Lines changed: 1 addition & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,75 +1,26 @@
11
package be.cronos.keycloak.policy;
22

33
import de.mkammerer.argon2.Argon2Constants;
4-
import org.keycloak.Config;
5-
import org.keycloak.models.KeycloakSession;
6-
import org.keycloak.models.KeycloakSessionFactory;
7-
import org.keycloak.models.RealmModel;
8-
import org.keycloak.models.UserModel;
9-
import org.keycloak.policy.PasswordPolicyProvider;
10-
import org.keycloak.policy.PasswordPolicyProviderFactory;
11-
import org.keycloak.policy.PolicyError;
124

135
/**
146
* @author <a href="mailto:dries.eestermans@is4u.be">Dries Eestermans</a>
157
*/
16-
public class Argon2HashLengthPasswordPolicyProviderFactory implements PasswordPolicyProvider, PasswordPolicyProviderFactory {
8+
public class Argon2HashLengthPasswordPolicyProviderFactory extends Argon2GenericPolicyProviderFactory {
179
public static final String ID = "argon2HashLength";
1810

19-
@Override
20-
public Argon2HashLengthPasswordPolicyProviderFactory create(KeycloakSession session) {
21-
return this;
22-
}
23-
24-
@Override
25-
public void init(Config.Scope config) {
26-
}
27-
28-
@Override
29-
public void postInit(KeycloakSessionFactory factory) {
30-
}
31-
3211
@Override
3312
public String getId() {
3413
return ID;
3514
}
3615

37-
@Override
38-
public PolicyError validate(RealmModel realm, UserModel user, String password) {
39-
return null;
40-
}
41-
42-
@Override
43-
public PolicyError validate(String user, String password) {
44-
return null;
45-
}
46-
47-
@Override
48-
public Object parseConfig(String value) {
49-
return parseInteger(value, -1);
50-
}
51-
5216
@Override
5317
public String getDisplayName() {
5418
return "Argon2 Hash Length";
5519
}
5620

57-
@Override
58-
public String getConfigType() {
59-
return PasswordPolicyProvider.INT_CONFIG_TYPE;
60-
}
61-
6221
@Override
6322
public String getDefaultConfigValue() {
6423
return String.valueOf(Argon2Constants.DEFAULT_HASH_LENGTH);
6524
}
6625

67-
@Override
68-
public boolean isMultiplSupported() {
69-
return false;
70-
}
71-
72-
@Override
73-
public void close() {
74-
}
7526
}

0 commit comments

Comments
 (0)