Skip to content

Commit 2daa907

Browse files
authored
Add support for salt in import with sha passwords (#319)
1 parent 87bee0c commit 2daa907

2 files changed

Lines changed: 51 additions & 0 deletions

File tree

src/main/java/com/descope/model/user/request/BatchUserPasswordSha.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,5 @@
1212
public class BatchUserPasswordSha {
1313
String hash;
1414
String type;
15+
String salt;
1516
}

src/test/java/com/descope/sdk/mgmt/impl/UserServiceImplTest.java

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1262,6 +1262,56 @@ void testFunctionalBatchWithShaPassword() throws Exception {
12621262
userService.delete(loginId);
12631263
}
12641264

1265+
@RetryingTest(value = 3, suspendForMs = 30000, onExceptions = RateLimitExceededException.class)
1266+
void testFunctionalBatchWithShaPasswordAndSalt() throws Exception {
1267+
// Generate a random salt
1268+
SecureRandom random = new SecureRandom();
1269+
byte[] saltBytes = new byte[16];
1270+
random.nextBytes(saltBytes);
1271+
1272+
// Convert salt to hex string
1273+
StringBuilder hexSalt = new StringBuilder();
1274+
for (byte b : saltBytes) {
1275+
hexSalt.append(String.format("%02x", b));
1276+
}
1277+
1278+
String loginId = TestUtils.getRandomName("u-");
1279+
String email = TestUtils.getRandomName("test-") + "@descope.com";
1280+
String phone = "+1-555-555-5555";
1281+
String name = "Sha Salted User";
1282+
String password = "This is a sha test with salt";
1283+
1284+
// Create SHA-256 hash with salt (salt + password)
1285+
MessageDigest digest = MessageDigest.getInstance("SHA-256");
1286+
digest.update(password.getBytes("UTF-8"));
1287+
byte[] hashBytes = digest.digest(saltBytes);
1288+
StringBuilder hexHash = new StringBuilder();
1289+
for (byte b : hashBytes) {
1290+
hexHash.append(String.format("%02x", b));
1291+
}
1292+
1293+
UsersBatchResponse res = userService.createBatch(Arrays.asList(BatchUserRequest.builder().loginId(loginId)
1294+
.email(email).verifiedEmail(true).phone(phone).verifiedPhone(true).displayName(name)
1295+
.hashedPassword(BatchUserPasswordHashed.builder()
1296+
.sha(BatchUserPasswordSha.builder()
1297+
.type("sha256")
1298+
.hash(hexHash.toString())
1299+
.salt(hexSalt.toString())
1300+
.build())
1301+
.build())
1302+
.build()));
1303+
assertNotNull(res);
1304+
assertNotNull(res.getCreatedUsers());
1305+
assertEquals(1, res.getCreatedUsers().size());
1306+
assertTrue(res.getFailedUsers() == null || res.getFailedUsers().isEmpty());
1307+
AuthenticationInfo authInfo = passwordService.signIn(loginId, password);
1308+
assertNotNull(authInfo);
1309+
assertNotNull(authInfo.getUser());
1310+
assertEquals(email, authInfo.getUser().getEmail());
1311+
assertEquals(name, authInfo.getUser().getName());
1312+
userService.delete(loginId);
1313+
}
1314+
12651315
@RetryingTest(value = 3, suspendForMs = 30000, onExceptions = RateLimitExceededException.class)
12661316
void testFunctionalSetActivePassword() {
12671317
String loginId = TestUtils.getRandomName("u-");

0 commit comments

Comments
 (0)