@Override
    public GoogleAuthenticatorToken validate(final Authentication authentication,
                                             final GoogleAuthenticatorTokenCredential tokenCredential) throws Throwable {

        if (!StringUtils.isNumeric(tokenCredential.getToken())) {
            throw new PreventedException("Invalid non-numeric OTP format specified.");
        }

        val uid = authentication.getPrincipal().getId();
        val otp = Integer.parseInt(tokenCredential.getToken());
        LOGGER.trace("Received OTP [{}] assigned to account [{}]", otp, tokenCredential.getAccountId());

        LOGGER.trace("Received principal id [{}]. Attempting to locate account in credential repository...", uid);
        val accounts = credentialRepository.get(uid);
        if (accounts == null || accounts.isEmpty()) {
            throw new AccountNotFoundException(uid + " cannot be found in the registry");
        }

        if (accounts.size() > 1 && tokenCredential.getAccountId() == null) {
            throw new PreventedException("Account identifier must be specified if multiple accounts are registered for " + uid);
        }
        LOGGER.trace("Attempting to locate OTP token [{}] in token repository for [{}]...", otp, uid);
        if (this.tokenRepository.exists(uid, otp)) {
            throw new AccountExpiredException(uid + " cannot reuse OTP " + otp + " as it may be expired/invalid");
        }

        LOGGER.debug("Attempting to authorize OTP token [{}]...", otp);
        val result = getAuthorizedAccountForToken(tokenCredential, accounts)
            .or(() -> getAuthorizedScratchCodeForToken(tokenCredential, authentication, accounts));
        return result
            .map(acct -> new GoogleAuthenticatorToken(otp, uid))
            .orElse(null);
    }
This is {@link GoogleAuthenticatorOneTimeTokenCredentialValidator}.

@author Misagh Moayyed
@since 6.3.0
support/cas-server-support-gauth-core/src/main/java/org/apereo/cas/gauth/credential/GoogleAuthenticatorOneTimeTokenCredentialValidator.java