public void verifyIdentity()

in extensions/guacamole-auth-totp/src/main/java/org/apache/guacamole/auth/totp/user/UserVerificationService.java [314:433]


    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");

    }