From dcf568ed64405d7c10c80d7b6448beed881d3b17 Mon Sep 17 00:00:00 2001 From: karthik-tarento Date: Wed, 11 Sep 2024 10:37:11 +0530 Subject: [PATCH 1/3] Added debug logs --- keycloak/sms-provider/pom.xml | 4 ++++ .../login/PasswordAndOtpAuthenticator.java | 17 +++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/keycloak/sms-provider/pom.xml b/keycloak/sms-provider/pom.xml index 5a62df19..2711bb52 100644 --- a/keycloak/sms-provider/pom.xml +++ b/keycloak/sms-provider/pom.xml @@ -121,5 +121,9 @@ + + org.springframework.security + spring-security-core + diff --git a/keycloak/sms-provider/src/main/java/org/sunbird/keycloak/login/PasswordAndOtpAuthenticator.java b/keycloak/sms-provider/src/main/java/org/sunbird/keycloak/login/PasswordAndOtpAuthenticator.java index 132073a6..817bc4df 100644 --- a/keycloak/sms-provider/src/main/java/org/sunbird/keycloak/login/PasswordAndOtpAuthenticator.java +++ b/keycloak/sms-provider/src/main/java/org/sunbird/keycloak/login/PasswordAndOtpAuthenticator.java @@ -61,6 +61,8 @@ public class PasswordAndOtpAuthenticator extends AbstractUsernameFormAuthenticat Logger logger = Logger.getLogger(PasswordAndOtpAuthenticator.class); private static final SecureRandom random = new SecureRandom(); + private Pbkdf2PasswordEncoder passwordEncoder = new Pbkdf2PasswordEncoder(); + private enum CODE_STATUS { VALID, INVALID, EXPIRED @@ -670,6 +672,9 @@ public boolean validatePassword(AuthenticationFlowContext context, UserModel use List credentials = new LinkedList<>(); credentials.add(UserCredentialModel.password(decryptedPassword)); + boolean isValid = validateHashedPassword(context, user, decryptedPassword); + logger.info(String.format("PasswordAndOtpAuthenticator::validateHashedPassword returns : %s", isValid)); + if (decryptedPassword != null && !decryptedPassword.isEmpty() && context.getSession().userCredentialManager().isValid(context.getRealm(), user, credentials)) { return true; @@ -695,4 +700,16 @@ private String decryptPassword(String encryptedPassword, String secretKey, Strin throw new RuntimeException("Error while decrypting password", e); } } + + private boolean validateHashedPassword(AuthenticationFlowContext context, UserModel user, String clientHashedPassword) { + // Fetch the stored password from Keycloak + CredentialModel storedCredential = context.getSession().userCredentialManager().getStoredCredentialById(context.getRealm(), user, CredentialModel.PASSWORD); + + // The password stored in Keycloak is hashed with PBKDF2 + String storedPasswordHash = storedCredential.getValue(); + logger.info(String.format("PasswordAndOtpAuthenticator::validateHashedPassword storedPasswordHash : %s", storedPasswordHash)); + + // Compare the PBKDF2-hashed password from client with Keycloak's stored PBKDF2 hash + return passwordEncoder.matches(clientHashedPassword, storedPasswordHash); + } } From e44ca84c078fcf64ecec9b745003baa25acafea1 Mon Sep 17 00:00:00 2001 From: karthik-tarento Date: Wed, 11 Sep 2024 12:57:43 +0530 Subject: [PATCH 2/3] Added logs --- keycloak/sms-provider/pom.xml | 1 + .../sunbird/keycloak/login/PasswordAndOtpAuthenticator.java | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/keycloak/sms-provider/pom.xml b/keycloak/sms-provider/pom.xml index 2711bb52..0e446ad9 100644 --- a/keycloak/sms-provider/pom.xml +++ b/keycloak/sms-provider/pom.xml @@ -124,6 +124,7 @@ org.springframework.security spring-security-core + 5.5.0 diff --git a/keycloak/sms-provider/src/main/java/org/sunbird/keycloak/login/PasswordAndOtpAuthenticator.java b/keycloak/sms-provider/src/main/java/org/sunbird/keycloak/login/PasswordAndOtpAuthenticator.java index 817bc4df..7f4d5935 100644 --- a/keycloak/sms-provider/src/main/java/org/sunbird/keycloak/login/PasswordAndOtpAuthenticator.java +++ b/keycloak/sms-provider/src/main/java/org/sunbird/keycloak/login/PasswordAndOtpAuthenticator.java @@ -45,6 +45,7 @@ import org.keycloak.services.ServicesLogger; import org.keycloak.services.managers.AuthenticationManager; import org.keycloak.services.messages.Messages; +import org.springframework.security.crypto.password.Pbkdf2PasswordEncoder; import org.sunbird.keycloak.resetcredential.sms.KeycloakSmsAuthenticatorConstants; import org.sunbird.keycloak.resetcredential.sms.KeycloakSmsAuthenticatorUtil; import org.sunbird.keycloak.utils.Constants; @@ -702,6 +703,7 @@ private String decryptPassword(String encryptedPassword, String secretKey, Strin } private boolean validateHashedPassword(AuthenticationFlowContext context, UserModel user, String clientHashedPassword) { + try { // Fetch the stored password from Keycloak CredentialModel storedCredential = context.getSession().userCredentialManager().getStoredCredentialById(context.getRealm(), user, CredentialModel.PASSWORD); @@ -711,5 +713,9 @@ private boolean validateHashedPassword(AuthenticationFlowContext context, UserMo // Compare the PBKDF2-hashed password from client with Keycloak's stored PBKDF2 hash return passwordEncoder.matches(clientHashedPassword, storedPasswordHash); + } catch (Exception e){ + logger.error("Failed to validateHashedPassword. Exception: ", e); + } + return false; } } From 896ebec9b6f96e3c7f33ccae5f148af83e52cc46 Mon Sep 17 00:00:00 2001 From: karthik-tarento Date: Thu, 12 Sep 2024 10:44:34 +0530 Subject: [PATCH 3/3] Added more logs to validate password --- .../login/PasswordAndOtpAuthenticator.java | 44 ++++++++++++++----- 1 file changed, 33 insertions(+), 11 deletions(-) diff --git a/keycloak/sms-provider/src/main/java/org/sunbird/keycloak/login/PasswordAndOtpAuthenticator.java b/keycloak/sms-provider/src/main/java/org/sunbird/keycloak/login/PasswordAndOtpAuthenticator.java index 7f4d5935..c7168fdc 100644 --- a/keycloak/sms-provider/src/main/java/org/sunbird/keycloak/login/PasswordAndOtpAuthenticator.java +++ b/keycloak/sms-provider/src/main/java/org/sunbird/keycloak/login/PasswordAndOtpAuthenticator.java @@ -702,18 +702,40 @@ private String decryptPassword(String encryptedPassword, String secretKey, Strin } } - private boolean validateHashedPassword(AuthenticationFlowContext context, UserModel user, String clientHashedPassword) { + private boolean validateHashedPassword(AuthenticationFlowContext context, UserModel user, + String clientHashedPassword) { try { - // Fetch the stored password from Keycloak - CredentialModel storedCredential = context.getSession().userCredentialManager().getStoredCredentialById(context.getRealm(), user, CredentialModel.PASSWORD); - - // The password stored in Keycloak is hashed with PBKDF2 - String storedPasswordHash = storedCredential.getValue(); - logger.info(String.format("PasswordAndOtpAuthenticator::validateHashedPassword storedPasswordHash : %s", storedPasswordHash)); - - // Compare the PBKDF2-hashed password from client with Keycloak's stored PBKDF2 hash - return passwordEncoder.matches(clientHashedPassword, storedPasswordHash); - } catch (Exception e){ + + // Fetch the stored password credential + List credentials = context.getSession().userCredentialManager() + .getStoredCredentialsByType(context.getRealm(), user, CredentialModel.PASSWORD); + + if (!credentials.isEmpty()) { + CredentialModel storedCredential = credentials.get(0); + logger.info(String.format( + "PasswordAndOtpAuthenticator::validateHashedPassword storedPasswordHash from list : %s", + storedCredential.getValue())); + } else { + logger.info(String.format("PasswordAndOtpAuthenticator::validateHashedPassword null value from type")); + } + + // Fetch the stored password from Keycloak + CredentialModel storedCredential = context.getSession().userCredentialManager() + .getStoredCredentialById(context.getRealm(), user, CredentialModel.PASSWORD); + + // The password stored in Keycloak is hashed with PBKDF2 + if (storedCredential != null) { + String storedPasswordHash = storedCredential.getValue(); + logger.info(String.format("PasswordAndOtpAuthenticator::validateHashedPassword storedPasswordHash : %s", + storedPasswordHash)); + // Compare the PBKDF2-hashed password from client with Keycloak's stored PBKDF2 + // hash + return passwordEncoder.matches(clientHashedPassword, storedPasswordHash); + } else { + logger.info(String.format("PasswordAndOtpAuthenticator::validateHashedPassword null value from id")); + } + + } catch (Exception e) { logger.error("Failed to validateHashedPassword. Exception: ", e); } return false;