use of password.pwm.util.operations.otp.PasscodeGenerator in project pwm by pwm-project.
the class OtpService method validateToken.
public boolean validateToken(final SessionLabel sessionLabel, final UserIdentity userIdentity, final OTPUserRecord otpUserRecord, final String userInput, final boolean allowRecoveryCodes) throws PwmOperationalException, PwmUnrecoverableException {
boolean otpCorrect = false;
try {
final Base32 base32 = new Base32();
final byte[] rawSecret = base32.decode(otpUserRecord.getSecret());
final Mac mac = Mac.getInstance("HMACSHA1");
mac.init(new SecretKeySpec(rawSecret, ""));
final PasscodeGenerator generator = new PasscodeGenerator(mac, settings.getOtpTokenLength(), settings.getTotpIntervalSeconds());
switch(otpUserRecord.getType()) {
case TOTP:
otpCorrect = generator.verifyTimeoutCode(userInput, settings.getTotpPastIntervals(), settings.getTotpFutureIntervals());
break;
default:
throw new UnsupportedOperationException("OTP type not supported: " + otpUserRecord.getType());
}
} catch (Exception e) {
LOGGER.error(sessionLabel, "error checking otp secret: " + e.getMessage());
}
if (!otpCorrect && allowRecoveryCodes && otpUserRecord.getRecoveryCodes() != null && otpUserRecord.getRecoveryInfo() != null) {
final OTPUserRecord.RecoveryInfo recoveryInfo = otpUserRecord.getRecoveryInfo();
final String userHashedInput = doRecoveryHash(userInput, recoveryInfo);
for (final OTPUserRecord.RecoveryCode code : otpUserRecord.getRecoveryCodes()) {
if (code.getHashCode().equals(userInput) || code.getHashCode().equals(userHashedInput)) {
if (code.isUsed()) {
throw new PwmOperationalException(PwmError.ERROR_OTP_RECOVERY_USED, "recovery code has been previously used");
}
code.setUsed(true);
try {
pwmApplication.getOtpService().writeOTPUserConfiguration(null, userIdentity, otpUserRecord);
} catch (ChaiUnavailableException e) {
throw new PwmUnrecoverableException(new ErrorInformation(PwmError.ERROR_WRITING_OTP_SECRET, e.getMessage()));
}
otpCorrect = true;
}
}
}
return otpCorrect;
}
Aggregations