Search in sources :

Example 1 with PasscodeGenerator

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;
}
Also used : ChaiUnavailableException(com.novell.ldapchai.exception.ChaiUnavailableException) PwmUnrecoverableException(password.pwm.error.PwmUnrecoverableException) Mac(javax.crypto.Mac) PasscodeGenerator(password.pwm.util.operations.otp.PasscodeGenerator) PwmUnrecoverableException(password.pwm.error.PwmUnrecoverableException) PwmException(password.pwm.error.PwmException) PwmOperationalException(password.pwm.error.PwmOperationalException) IOException(java.io.IOException) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) ChaiUnavailableException(com.novell.ldapchai.exception.ChaiUnavailableException) PwmOperationalException(password.pwm.error.PwmOperationalException) ErrorInformation(password.pwm.error.ErrorInformation) SecretKeySpec(javax.crypto.spec.SecretKeySpec) Base32(org.apache.commons.codec.binary.Base32) OTPUserRecord(password.pwm.util.operations.otp.OTPUserRecord)

Aggregations

ChaiUnavailableException (com.novell.ldapchai.exception.ChaiUnavailableException)1 IOException (java.io.IOException)1 NoSuchAlgorithmException (java.security.NoSuchAlgorithmException)1 Mac (javax.crypto.Mac)1 SecretKeySpec (javax.crypto.spec.SecretKeySpec)1 Base32 (org.apache.commons.codec.binary.Base32)1 ErrorInformation (password.pwm.error.ErrorInformation)1 PwmException (password.pwm.error.PwmException)1 PwmOperationalException (password.pwm.error.PwmOperationalException)1 PwmUnrecoverableException (password.pwm.error.PwmUnrecoverableException)1 OTPUserRecord (password.pwm.util.operations.otp.OTPUserRecord)1 PasscodeGenerator (password.pwm.util.operations.otp.PasscodeGenerator)1