public void verifyIdentity(UserContext context,
            AuthenticatedUser authenticatedUser) throws GuacamoleException {

        // Pull the original HTTP request used to authenticate
        Credentials credentials = authenticatedUser.getCredentials();
        
        // Get the current client address
        IPAddress clientAddr = new IPAddressString(credentials.getRemoteAddress()).getAddress();

        // Ignore anonymous users
        if (authenticatedUser.getIdentifier().equals(AuthenticatedUser.ANONYMOUS_IDENTIFIER))
            return;
        
        // Pull address lists to check from configuration. Note that the enforce
        // list will override the bypass list, which means that, if the client
        // address happens to be in both lists, Duo MFA will be enforced.
        List<IPAddress> bypassAddresses = confService.getBypassHosts();
        List<IPAddress> enforceAddresses = confService.getEnforceHosts();
        
        // Check the bypass list for the client address, and set the enforce
        // flag to the opposite.
        boolean enforceHost = !(IPAddressListProperty.addressListContains(bypassAddresses, clientAddr));
        
        // Only continue processing if the list is not empty
        if (!enforceAddresses.isEmpty()) {
            
            // If client address is not available or invalid, MFA will
            // be enforced.
            if (clientAddr == null || !clientAddr.isIPAddress())
                enforceHost = true;
            
            // Check the enforce list and set the flag if the client address
            // is found in the list.
            else
                enforceHost = IPAddressListProperty.addressListContains(enforceAddresses, clientAddr);
        }
            
        // If the enforce flag is not true, bypass TOTP MFA.
        if (!enforceHost)
            return;
        
        // Ignore anonymous users
        String username = authenticatedUser.getIdentifier();
        if (username.equals(AuthenticatedUser.ANONYMOUS_IDENTIFIER))
            return;

        // Check if TOTP has been disabled for this user
        if (totpDisabled(context, authenticatedUser))
            return;
        
        // Ignore users which do not have an associated key
        UserTOTPKey key = getKey(context, username);
        if (key == null)
            return;

        // Retrieve TOTP from request
        String code = credentials.getParameter(AuthenticationCodeField.PARAMETER_NAME);

        // If no TOTP provided, request one
        if (code == null) {

            AuthenticationCodeField field = codeFieldProvider.get();

            // If the user hasn't completed enrollment, request that they do
            if (!key.isConfirmed()) {
                
                // If the key has not yet been confirmed, generate a new one.
                key = generateKey(context, username);
                
                field.exposeKey(key);
                throw new TranslatableGuacamoleInsufficientCredentialsException(
                        "TOTP enrollment must be completed before "
                        + "authentication can continue",
                        "TOTP.INFO_ENROLL_REQUIRED", new CredentialsInfo(
                            Collections.<Field>singletonList(field)
                        ));
            }

            // Otherwise simply request the user's authentication code
            throw new TranslatableGuacamoleInsufficientCredentialsException(
                    "A TOTP authentication code is required before login can "
                    + "continue", "TOTP.INFO_CODE_REQUIRED", new CredentialsInfo(
                        Collections.<Field>singletonList(field)
                    ));

        }

        try {

            // Get generator based on user's key and provided configuration
            TOTPGenerator totp = new TOTPGenerator(key.getSecret(),
                    confService.getMode(), confService.getDigits(),
                    TOTPGenerator.DEFAULT_START_TIME, confService.getPeriod());

            // Verify provided TOTP against value produced by generator
            if ((code.equals(totp.generate()) || code.equals(totp.previous()))
                    && codeService.useCode(username, code)) {

                // Record key as confirmed, if it hasn't already been so recorded
                if (!key.isConfirmed()) {
                    key.setConfirmed(true);
                    setKey(context, key);
                }

                // User has been verified
                return;

            }

        }
        catch (InvalidKeyException e) {
            logger.warn("User \"{}\" is associated with an invalid TOTP key.", username);
            logger.debug("TOTP key is not valid.", e);
        }

        // Provided code is not valid
        throw new TranslatableGuacamoleClientException("Provided TOTP code "
                + "is not valid.", "TOTP.INFO_VERIFICATION_FAILED");

    }
Verifies the identity of the given user using TOTP. If a authentication
code from the user's TOTP device has not already been provided, a code is
requested in the form of additional expected credentials. Any provided
code is cryptographically verified. If no code is present, or the
received code is invalid, an exception is thrown.

@param context
    The UserContext provided for the user by another authentication
    extension.

@param authenticatedUser
    The user whose identity should be verified using TOTP.

@throws GuacamoleException
    If required TOTP-specific configuration options are missing or
    malformed, or if the user's identity cannot be verified.
extensions/guacamole-auth-totp/src/main/java/org/apache/guacamole/auth/totp/user/UserVerificationService.java