June 15, 2019
Stackcheats is a cheat-blog platform where developers and technical writers can create & write tech-cheats by owning user accounts. More importantly, Stackcheats has been using the WSO2 Identity Server as its identity and access management tool to manage user registrations and management tasks.
A tech-developer named “Athiththan” have been requested to develop a custom component to validate the password against a list of defective passwords when users trying to update (renew).
WSO2 Identity Server (5.3.0 ≤ onwards) now supports to handle published events using an integrated event framework by extending `AbstractEventHandler`
So, Athiththan chose to develop the custom component as an event-handler listening to different password-update events to trigger and to validate the given password. We can use the following custom maven archetype to generate boilerplate to extend and implement custom event-handlers for WSO2 Identity Server.
The AbstractEventHandler contains a method named handleEvent() which gets triggered whenever a pre-registered event is made upon the Identity Server. So, for this custom implementation, he will be using the following two publish events …
PRE_UPDATE_CREDENTIAL
PRE_UPDATE_CREDENTIAL_BY_ADMIN
@Override | |
public void handleEvent(Event event) throws IdentityEventException { | |
if (log.isDebugEnabled()) { | |
log.debug("handleEvent() invoked"); | |
} | |
if (IdentityEventConstants.Event.PRE_UPDATE_CREDENTIAL.equals(event.getEventName()) | |
|| IdentityEventConstants.Event.PRE_UPDATE_CREDENTIAL_BY_ADMIN.equals(event.getEventName())) { | |
Object credential = event.getEventProperties().get(IdentityEventConstants.EventProperty.CREDENTIAL); | |
if (!DefaultDefectivePasswordValidator.getInstance().validate(credential)) { | |
if (log.isDebugEnabled()) { | |
log.debug("given password is defective"); | |
} | |
throw Utils.handleEventException( | |
DefectivePasswordValidatorConstants.ErrorMessages.ERROR_CODE_CRACKED_PASSWORD_VALIDATION, null); | |
} | |
} | |
} |
Given below is the implementation to validate the given password against a list of defective passwords. The given implementation reads all the defective passwords from a text file named passwords.txt which is placed inside the /<IS_HOME>/deployments/server/defective
folder.
For testing purposes, the given implementation can be modified to work with pre-defined list of defective passwords using ArrayList.
public class DefaultDefectivePasswordValidator implements DefectivePasswordValidator { | |
private static List<String> crackedPasswords = new ArrayList<>(); | |
private static DefaultDefectivePasswordValidator dPasswordValidator = new DefaultDefectivePasswordValidator(); | |
private static final Logger log = LoggerFactory.getLogger(DefaultDefectivePasswordValidator.class); | |
private DefaultDefectivePasswordValidator() { | |
} | |
public static DefaultDefectivePasswordValidator getInstance() { | |
return dPasswordValidator; | |
} | |
/** | |
* initialize defective password values from the given text file | |
*/ | |
@Override | |
public void initValues() { | |
crackedPasswords = new ArrayList<>(); | |
try { | |
crackedPasswords = Files.readAllLines(Paths.get(DefectivePasswordValidatorConstants.PASSWORD_FILE_PATH), | |
StandardCharsets.UTF_8); | |
} catch (IOException e) { | |
log.error("Exception occured while reading and initializing values from " | |
+ DefectivePasswordValidatorConstants.PASSWORD_FILE_NAME, e); | |
} | |
} | |
/** | |
* validate method | |
*/ | |
@Override | |
public boolean validate(Object credential) { | |
return !crackedPasswords.contains((String) credential); | |
} | |
} |
The custom event-handler has to be registered as a service component (OSGi) with the Identity Server components to work flawlessly. In order to register the custom implementation as a service component, he wrote a ServiceComponent class containing both activate and deactivate methods to register it with the Bundle Context.
@Activate | |
protected void activate(ComponentContext context) { | |
try { | |
context.getBundleContext().registerService(AbstractEventHandler.class.getName(), | |
new DefectivePasswordValidatorEventHandler(), null); | |
// initialize all defective passwords from the text file | |
DefaultDefectivePasswordValidator.getInstance().initValues(); | |
// initialize watchservice on /defective directory | |
initializeWatchService(); | |
} catch (Throwable e) { | |
log.error("Error occured while initializing service component", e); | |
} | |
} | |
@Deactivate | |
protected void deactivate(ComponentContext context) { } |
Create a file called passwords.txt and add all defective-passwords (cracked passwords) at each line. These defined cracked passwords are the values, will be used to validate the entered password.
Create a folder named defective inside the <IS_HOME>/repository/deployment/server directory and place the above created passwords.txt file in it.
Navigate to <IS_HOME>/repository/conf/identity directory and open the identity-event.properties file and add the following lines at the bottom to subscribe to the published events.
Please update the digit value according to your
identity-event.properties
file (last used value + 1)The given
module.name
value is the same value which configured in thegetName()
method inDefectivePasswordValidatorEventHandler
class
module.name.13=defectivePasswordValidator | |
defectivePasswordValidator.subscription.1=PRE_UPDATE_CREDENTIAL | |
defectivePasswordValidator.subscription.2=PRE_UPDATE_CREDENTIAL_BY_ADMIN |
You can clone or download the custom event-handler implementation project done by Athiththan from GitHub and build it using the following command …
mvn clean package
After a successful build, copy the defective-password-validator-1.0.0.jar
artifact and place it inside the <IS_HOME>/repository/components/dropins
folder.
Start your WSO2 Identity Server by navigating to the <IS_HOME>/bin
folder and executing the following command …
sh wso2server.sh
After server startup, navigate to https://<ipaddress>:9443/dashboard
and log in using admin
as both username and password. Click on the “View Details” button on the “Change Password” section and type your current password and enter the new password as one of the defective passwords and try on.
Defective password validation using WSO2 Event Handlers extension