Search in sources :

Example 1 with TwoFactorAuth

use of com.zimbra.cs.account.auth.twofactor.TwoFactorAuth in project zm-mailbox by Zimbra.

the class AuthMechanism method doTwoFactorAuth.

/**
     * @param acct
     * @param password
     * @param authCtxt
     * @throws ServiceException
     * @throws AuthFailedServiceException
     */
public static boolean doTwoFactorAuth(Account acct, String password, Map<String, Object> authCtxt) throws ServiceException, AuthFailedServiceException {
    TwoFactorAuth twoFactorManager = TwoFactorAuth.getFactory().getTwoFactorAuth(acct);
    AppSpecificPasswords appPasswords = TwoFactorAuth.getFactory().getAppSpecificPasswords(acct);
    boolean authDone = false;
    if (twoFactorManager.twoFactorAuthRequired() && authCtxt != null) {
        //if two-factor auth is enabled, check non-http protocols against app-specific passwords
        Protocol proto = (Protocol) authCtxt.get("proto");
        switch(proto) {
            case soap:
            case http_basic:
                break;
            default:
                if (appPasswords.isEnabled()) {
                    appPasswords.authenticate(password);
                    authDone = true;
                } else {
                    throw AuthFailedServiceException.AUTH_FAILED(acct.getName(), namePassedIn(authCtxt), "invalid password");
                }
        }
    }
    return authDone;
}
Also used : TwoFactorAuth(com.zimbra.cs.account.auth.twofactor.TwoFactorAuth) Protocol(com.zimbra.cs.account.auth.AuthContext.Protocol) AppSpecificPasswords(com.zimbra.cs.account.auth.twofactor.AppSpecificPasswords)

Example 2 with TwoFactorAuth

use of com.zimbra.cs.account.auth.twofactor.TwoFactorAuth in project zm-mailbox by Zimbra.

the class Auth method handle.

@Override
public Element handle(Element request, Map<String, Object> context) throws ServiceException {
    ZimbraSoapContext zsc = getZimbraSoapContext(context);
    Provisioning prov = Provisioning.getInstance();
    // Look up the specified account.  It is optional in the <authToken> case.
    String acctValuePassedIn = null, acctValue = null, acctByStr = null;
    AccountBy acctBy = null;
    Account acct = null;
    Element acctEl = request.getOptionalElement(AccountConstants.E_ACCOUNT);
    boolean csrfSupport = request.getAttributeBool(AccountConstants.A_CSRF_SUPPORT, false);
    if (acctEl != null) {
        acctValuePassedIn = acctEl.getText();
        acctValue = acctValuePassedIn;
        acctByStr = acctEl.getAttribute(AccountConstants.A_BY, AccountBy.name.name());
        acctBy = AccountBy.fromString(acctByStr);
        if (acctBy == AccountBy.name) {
            Element virtualHostEl = request.getOptionalElement(AccountConstants.E_VIRTUAL_HOST);
            String virtualHost = virtualHostEl == null ? null : virtualHostEl.getText().toLowerCase();
            if (virtualHost != null && acctValue.indexOf('@') == -1) {
                Domain d = prov.get(Key.DomainBy.virtualHostname, virtualHost);
                if (d != null)
                    acctValue = acctValue + "@" + d.getName();
            }
        }
        acct = prov.get(acctBy, acctValue);
    }
    TrustedDeviceToken trustedToken = null;
    if (acct != null) {
        TrustedDevices trustedDeviceManager = TwoFactorAuth.getFactory().getTrustedDevices(acct);
        if (trustedDeviceManager != null) {
            trustedToken = trustedDeviceManager.getTokenFromRequest(request, context);
            if (trustedToken != null && trustedToken.isExpired()) {
                TrustedDevice device = trustedDeviceManager.getTrustedDeviceByTrustedToken(trustedToken);
                if (device != null) {
                    device.revoke();
                }
            }
        }
    }
    String password = request.getAttribute(AccountConstants.E_PASSWORD, null);
    boolean generateDeviceId = request.getAttributeBool(AccountConstants.A_GENERATE_DEVICE_ID, false);
    String twoFactorCode = request.getAttribute(AccountConstants.E_TWO_FACTOR_CODE, null);
    String newDeviceId = generateDeviceId ? UUIDUtil.generateUUID() : null;
    Element authTokenEl = request.getOptionalElement(AccountConstants.E_AUTH_TOKEN);
    if (authTokenEl != null) {
        boolean verifyAccount = authTokenEl.getAttributeBool(AccountConstants.A_VERIFY_ACCOUNT, false);
        if (verifyAccount && acctEl == null) {
            throw ServiceException.INVALID_REQUEST("missing required element: " + AccountConstants.E_ACCOUNT, null);
        }
        try {
            AuthToken at = AuthProvider.getAuthToken(authTokenEl, acct);
            addAccountToLogContextByAuthToken(prov, at);
            // so the account will show in log context
            if (!checkPasswordSecurity(context))
                throw ServiceException.INVALID_REQUEST("clear text password is not allowed", null);
            AuthToken.Usage usage = at.getUsage();
            if (usage != Usage.AUTH && usage != Usage.TWO_FACTOR_AUTH) {
                throw AuthFailedServiceException.AUTH_FAILED("invalid auth token");
            }
            Account authTokenAcct = AuthProvider.validateAuthToken(prov, at, false, usage);
            if (verifyAccount) {
                // can treat the auth token as an opaque string.
                if (acct == null || !acct.getId().equalsIgnoreCase(authTokenAcct.getId())) {
                    throw new AuthTokenException("auth token doesn't match the named account");
                }
            }
            if (usage == Usage.AUTH) {
                ServletRequest httpReq = (ServletRequest) context.get(SoapServlet.SERVLET_REQUEST);
                httpReq.setAttribute(CsrfFilter.AUTH_TOKEN, at);
                if (csrfSupport && !at.isCsrfTokenEnabled()) {
                    // handle case where auth token was originally generated with csrf support
                    // and now client sends the same auth token but saying csrfSupport is turned off
                    // in that case do not disable CSRF check for this authToken.
                    at.setCsrfTokenEnabled(csrfSupport);
                }
                return doResponse(request, at, zsc, context, authTokenAcct, csrfSupport, trustedToken, newDeviceId);
            } else {
                acct = authTokenAcct;
            }
        } catch (AuthTokenException e) {
            throw ServiceException.AUTH_REQUIRED();
        }
    }
    if (!checkPasswordSecurity(context)) {
        throw ServiceException.INVALID_REQUEST("clear text password is not allowed", null);
    }
    Element preAuthEl = request.getOptionalElement(AccountConstants.E_PREAUTH);
    String deviceId = request.getAttribute(AccountConstants.E_DEVICE_ID, null);
    long expires = 0;
    Map<String, Object> authCtxt = new HashMap<String, Object>();
    authCtxt.put(AuthContext.AC_ORIGINATING_CLIENT_IP, context.get(SoapEngine.ORIG_REQUEST_IP));
    authCtxt.put(AuthContext.AC_REMOTE_IP, context.get(SoapEngine.SOAP_REQUEST_IP));
    authCtxt.put(AuthContext.AC_ACCOUNT_NAME_PASSEDIN, acctValuePassedIn);
    authCtxt.put(AuthContext.AC_USER_AGENT, zsc.getUserAgent());
    boolean acctAutoProvisioned = false;
    if (acct == null) {
        // try LAZY auto provision if it is enabled
        if (acctBy == AccountBy.name || acctBy == AccountBy.krb5Principal) {
            try {
                if (acctBy == AccountBy.name) {
                    EmailAddress email = new EmailAddress(acctValue, false);
                    String domainName = email.getDomain();
                    Domain domain = domainName == null ? null : prov.get(Key.DomainBy.name, domainName);
                    if (password != null) {
                        acct = prov.autoProvAccountLazy(domain, acctValuePassedIn, password, null);
                    } else if (preAuthEl != null) {
                        long timestamp = preAuthEl.getAttributeLong(AccountConstants.A_TIMESTAMP);
                        expires = preAuthEl.getAttributeLong(AccountConstants.A_EXPIRES, 0);
                        String preAuth = preAuthEl.getTextTrim();
                        prov.preAuthAccount(domain, acctValue, acctByStr, timestamp, expires, preAuth, authCtxt);
                        acct = prov.autoProvAccountLazy(domain, acctValuePassedIn, null, AutoProvAuthMech.PREAUTH);
                    }
                } else {
                    if (password != null) {
                        Domain domain = Krb5Principal.getDomainByKrb5Principal(acctValuePassedIn);
                        if (domain != null) {
                            acct = prov.autoProvAccountLazy(domain, acctValuePassedIn, password, null);
                        }
                    }
                }
                if (acct != null) {
                    acctAutoProvisioned = true;
                }
            } catch (AuthFailedServiceException e) {
                ZimbraLog.account.debug("auth failed, unable to auto provisioing acct " + acctValue, e);
            } catch (ServiceException e) {
                ZimbraLog.account.info("unable to auto provisioing acct " + acctValue, e);
            }
        }
    }
    if (acct == null) {
        // try ZMG Proxy auto provision if it is enabled
        if (acctBy == AccountBy.name && password != null) {
            Pair<Account, Boolean> result = null;
            try {
                result = prov.autoProvZMGProxyAccount(acctValuePassedIn, password);
            } catch (AuthFailedServiceException e) {
            // Most likely in error with user creds
            } catch (ServiceException e) {
                ZimbraLog.account.info("unable to auto provision acct " + acctValuePassedIn, e);
            }
            if (result != null) {
                acct = result.getFirst();
                acctAutoProvisioned = result.getSecond();
            }
        }
    }
    if (acct == null) {
        throw AuthFailedServiceException.AUTH_FAILED(acctValue, acctValuePassedIn, "account not found");
    }
    AccountUtil.addAccountToLogContext(prov, acct.getId(), ZimbraLog.C_NAME, ZimbraLog.C_ID, null);
    Boolean registerTrustedDevice = false;
    TwoFactorAuth twoFactorManager = TwoFactorAuth.getFactory().getTwoFactorAuth(acct);
    if (twoFactorManager.twoFactorAuthEnabled()) {
        registerTrustedDevice = trustedToken == null && request.getAttributeBool(AccountConstants.A_TRUSTED_DEVICE, false);
    }
    // if account was auto provisioned, we had already authenticated the principal
    if (!acctAutoProvisioned) {
        boolean trustedDeviceOverride = false;
        if (trustedToken != null && acct.isFeatureTrustedDevicesEnabled()) {
            if (trustedToken.isExpired()) {
                ZimbraLog.account.debug("trusted token is expired");
                registerTrustedDevice = false;
            } else {
                Map<String, Object> attrs = getTrustedDeviceAttrs(zsc, deviceId);
                try {
                    verifyTrustedDevice(acct, trustedToken, attrs);
                    trustedDeviceOverride = true;
                } catch (AuthFailedServiceException e) {
                    ZimbraLog.account.info("trusted device not verified");
                }
            }
        }
        boolean usingTwoFactorAuth = acct != null && twoFactorManager.twoFactorAuthRequired() && !trustedDeviceOverride;
        boolean twoFactorAuthWithToken = usingTwoFactorAuth && authTokenEl != null;
        if (password != null || twoFactorAuthWithToken) {
            // authentication logic can be reached with either a password, or a 2FA auth token
            if (usingTwoFactorAuth && twoFactorCode == null && password != null) {
                int mtaAuthPort = acct.getServer().getMtaAuthPort();
                boolean supportsAppSpecificPaswords = acct.isFeatureAppSpecificPasswordsEnabled() && zsc.getPort() == mtaAuthPort;
                if (supportsAppSpecificPaswords && password != null) {
                    // if we are here, it means we are authenticating SMTP,
                    // so app-specific passwords are accepted. Other protocols (pop, imap)
                    // doesn't touch this code, so their authentication happens in ZimbraAuth.
                    AppSpecificPasswords appPasswords = TwoFactorAuth.getFactory().getAppSpecificPasswords(acct, acctValuePassedIn);
                    appPasswords.authenticate(password);
                } else {
                    prov.authAccount(acct, password, AuthContext.Protocol.soap, authCtxt);
                    return needTwoFactorAuth(acct, twoFactorManager, zsc);
                }
            } else {
                if (password != null) {
                    prov.authAccount(acct, password, AuthContext.Protocol.soap, authCtxt);
                } else {
                    // it's ok to not have a password if the client is using a 2FA auth token for the 2nd step of 2FA
                    if (!twoFactorAuthWithToken) {
                        throw ServiceException.AUTH_REQUIRED();
                    }
                }
                if (usingTwoFactorAuth) {
                    // check that 2FA has been enabled, in case the client is passing in a twoFactorCode prior to setting up 2FA
                    if (!twoFactorManager.twoFactorAuthEnabled()) {
                        throw AccountServiceException.TWO_FACTOR_SETUP_REQUIRED();
                    }
                    AuthToken twoFactorToken = null;
                    if (password == null) {
                        try {
                            twoFactorToken = AuthProvider.getAuthToken(authTokenEl, acct);
                            Account twoFactorTokenAcct = AuthProvider.validateAuthToken(prov, twoFactorToken, false, Usage.TWO_FACTOR_AUTH);
                            boolean verifyAccount = authTokenEl.getAttributeBool(AccountConstants.A_VERIFY_ACCOUNT, false);
                            if (verifyAccount && !twoFactorTokenAcct.getId().equalsIgnoreCase(acct.getId())) {
                                throw new AuthTokenException("two-factor auth token doesn't match the named account");
                            }
                        } catch (AuthTokenException e) {
                            throw AuthFailedServiceException.AUTH_FAILED("bad auth token");
                        }
                    }
                    TwoFactorAuth manager = TwoFactorAuth.getFactory().getTwoFactorAuth(acct);
                    if (twoFactorCode != null) {
                        manager.authenticate(twoFactorCode);
                    } else {
                        throw AuthFailedServiceException.AUTH_FAILED("no two-factor code provided");
                    }
                    if (twoFactorToken != null) {
                        try {
                            twoFactorToken.deRegister();
                        } catch (AuthTokenException e) {
                            throw ServiceException.FAILURE("cannot de-register two-factor auth token", e);
                        }
                    }
                }
            }
        } else if (preAuthEl != null) {
            long timestamp = preAuthEl.getAttributeLong(AccountConstants.A_TIMESTAMP);
            expires = preAuthEl.getAttributeLong(AccountConstants.A_EXPIRES, 0);
            String preAuth = preAuthEl.getTextTrim();
            prov.preAuthAccount(acct, acctValue, acctByStr, timestamp, expires, preAuth, authCtxt);
        } else {
            throw ServiceException.INVALID_REQUEST("must specify " + AccountConstants.E_PASSWORD, null);
        }
    }
    AuthToken at = expires == 0 ? AuthProvider.getAuthToken(acct) : AuthProvider.getAuthToken(acct, expires);
    if (registerTrustedDevice && (trustedToken == null || trustedToken.isExpired())) {
        //generate a new trusted device token if there is no existing one or if the current one is no longer valid
        Map<String, Object> attrs = getTrustedDeviceAttrs(zsc, newDeviceId == null ? deviceId : newDeviceId);
        TrustedDevices trustedDeviceManager = TwoFactorAuth.getFactory().getTrustedDevices(acct);
        trustedToken = trustedDeviceManager.registerTrustedDevice(attrs);
    }
    ServletRequest httpReq = (ServletRequest) context.get(SoapServlet.SERVLET_REQUEST);
    // For CSRF filter so that token generation can happen
    if (csrfSupport && !at.isCsrfTokenEnabled()) {
        // handle case where auth token was originally generated with csrf support
        // and now client sends the same auth token but saying csrfSupport is turned off
        // in that case do not disable CSRF check for this authToken.
        at.setCsrfTokenEnabled(csrfSupport);
    }
    httpReq.setAttribute(CsrfFilter.AUTH_TOKEN, at);
    return doResponse(request, at, zsc, context, acct, csrfSupport, trustedToken, newDeviceId);
}
Also used : Account(com.zimbra.cs.account.Account) HttpServletRequest(javax.servlet.http.HttpServletRequest) ServletRequest(javax.servlet.ServletRequest) AuthFailedServiceException(com.zimbra.cs.account.AccountServiceException.AuthFailedServiceException) TrustedDeviceToken(com.zimbra.cs.account.TrustedDeviceToken) HashMap(java.util.HashMap) Element(com.zimbra.common.soap.Element) Provisioning(com.zimbra.cs.account.Provisioning) AccountBy(com.zimbra.common.account.Key.AccountBy) TwoFactorAuth(com.zimbra.cs.account.auth.twofactor.TwoFactorAuth) Usage(com.zimbra.cs.account.AuthToken.Usage) AppSpecificPasswords(com.zimbra.cs.account.auth.twofactor.AppSpecificPasswords) EmailAddress(com.zimbra.cs.account.names.NameUtil.EmailAddress) AccountServiceException(com.zimbra.cs.account.AccountServiceException) ServiceException(com.zimbra.common.service.ServiceException) AuthFailedServiceException(com.zimbra.cs.account.AccountServiceException.AuthFailedServiceException) ZimbraSoapContext(com.zimbra.soap.ZimbraSoapContext) AuthTokenException(com.zimbra.cs.account.AuthTokenException) TrustedDevice(com.zimbra.cs.account.TrustedDevice) AuthToken(com.zimbra.cs.account.AuthToken) Domain(com.zimbra.cs.account.Domain) TrustedDevices(com.zimbra.cs.account.auth.twofactor.TrustedDevices)

Example 3 with TwoFactorAuth

use of com.zimbra.cs.account.auth.twofactor.TwoFactorAuth in project zm-mailbox by Zimbra.

the class Auth method handle.

@Override
public Element handle(Element request, Map<String, Object> context) throws ServiceException {
    ZimbraSoapContext zsc = getZimbraSoapContext(context);
    AuthToken at = null;
    Account acct = null;
    Provisioning prov = Provisioning.getInstance();
    boolean csrfSupport = request.getAttributeBool(AccountConstants.A_CSRF_SUPPORT, false);
    String name = request.getAttribute(AdminConstants.E_NAME, null);
    Element acctEl = request.getOptionalElement(AccountConstants.E_ACCOUNT);
    //only perform auth-token authentication if other credentials are not provided
    if (name == null && acctEl == null) {
        //get an auth token from cookie
        at = zsc.getAuthToken();
        if (at == null) {
            //if auth token is not in the cookie check for auth token in SOAP
            Element authTokenEl = request.getOptionalElement(AdminConstants.E_AUTH_TOKEN);
            if (authTokenEl != null) {
                try {
                    at = AuthProvider.getAuthToken(request, new HashMap<String, Object>());
                } catch (AuthTokenException e) {
                    throw ServiceException.AUTH_REQUIRED();
                }
            }
        }
        if (at == null) {
            //neither login credentials nor valid auth token could be retrieved
            throw ServiceException.AUTH_REQUIRED();
        }
        com.zimbra.cs.service.account.Auth.addAccountToLogContextByAuthToken(prov, at);
        if (at.isExpired())
            throw ServiceException.AUTH_EXPIRED();
        if (!at.isRegistered())
            throw ServiceException.AUTH_EXPIRED("authtoken is invalid");
        // make sure that the authenticated account is active and has not been deleted/disabled since the last request
        acct = prov.get(AccountBy.id, at.getAccountId(), at);
        if (acct == null || !acct.getAccountStatus(prov).equals(Provisioning.ACCOUNT_STATUS_ACTIVE))
            throw ServiceException.AUTH_EXPIRED();
        // make sure the authenticated account is an admin account
        checkAdmin(acct);
    } else {
        /*
             * only one of
             *     <name>...</name>
             * or
             *     <account by="name|id|foreignPrincipal">...</account>
             * can/must be specified
             */
        if (name != null && acctEl != null)
            throw ServiceException.INVALID_REQUEST("only one of <name> or <account> can be specified", null);
        if (name == null && acctEl == null)
            throw ServiceException.INVALID_REQUEST("missing <name> or <account>", null);
        String password = request.getAttribute(AdminConstants.E_PASSWORD);
        String twoFactorCode = request.getAttribute(AccountConstants.E_TWO_FACTOR_CODE, null);
        Element virtualHostEl = request.getOptionalElement(AccountConstants.E_VIRTUAL_HOST);
        String virtualHost = virtualHostEl == null ? null : virtualHostEl.getText().toLowerCase();
        String valuePassedIn;
        AccountBy by;
        String value;
        if (name != null) {
            valuePassedIn = name;
            by = AccountBy.name;
        } else {
            valuePassedIn = acctEl.getText();
            String byStr = acctEl.getAttribute(AccountConstants.A_BY, AccountBy.name.name());
            by = AccountBy.fromString(byStr);
        }
        value = valuePassedIn;
        try {
            if (by == AccountBy.name && value.indexOf("@") == -1) {
                // first try to get by adminName, which resolves the account under cn=admins,cn=zimbra
                // and does not need a domain
                acct = prov.get(AccountBy.adminName, value, zsc.getAuthToken());
                // not found, try applying virtual host name
                if (acct == null) {
                    if (virtualHost != null) {
                        Domain d = prov.get(Key.DomainBy.virtualHostname, virtualHost);
                        if (d != null)
                            value = value + "@" + d.getName();
                    }
                }
            }
            if (acct == null)
                acct = prov.get(by, value);
            if (acct == null)
                throw AuthFailedServiceException.AUTH_FAILED(value, valuePassedIn, "account not found");
            AccountUtil.addAccountToLogContext(prov, acct.getId(), ZimbraLog.C_NAME, ZimbraLog.C_ID, null);
            ZimbraLog.security.info(ZimbraLog.encodeAttrs(new String[] { "cmd", "AdminAuth", "account", value }));
            Map<String, Object> authCtxt = new HashMap<String, Object>();
            authCtxt.put(AuthContext.AC_ORIGINATING_CLIENT_IP, context.get(SoapEngine.ORIG_REQUEST_IP));
            authCtxt.put(AuthContext.AC_REMOTE_IP, context.get(SoapEngine.SOAP_REQUEST_IP));
            authCtxt.put(AuthContext.AC_ACCOUNT_NAME_PASSEDIN, valuePassedIn);
            authCtxt.put(AuthContext.AC_USER_AGENT, zsc.getUserAgent());
            authCtxt.put(AuthContext.AC_AS_ADMIN, Boolean.TRUE);
            prov.authAccount(acct, password, AuthContext.Protocol.soap, authCtxt);
            TwoFactorAuth twoFactorAuth = TwoFactorAuth.getFactory().getTwoFactorAuth(acct);
            boolean usingTwoFactorAuth = twoFactorAuth.twoFactorAuthEnabled();
            if (usingTwoFactorAuth) {
                if (twoFactorCode != null) {
                    twoFactorAuth.authenticate(twoFactorCode);
                }
            }
            checkAdmin(acct);
            AuthMech authedByMech = (AuthMech) authCtxt.get(AuthContext.AC_AUTHED_BY_MECH);
            at = AuthProvider.getAuthToken(acct, true, authedByMech);
        } catch (ServiceException se) {
            ZimbraLog.security.warn(ZimbraLog.encodeAttrs(new String[] { "cmd", "AdminAuth", "account", value, "error", se.getMessage() }));
            throw se;
        }
    }
    if (at != null) {
        at.setCsrfTokenEnabled(csrfSupport);
    }
    ServletRequest httpReq = (ServletRequest) context.get(SoapServlet.SERVLET_REQUEST);
    httpReq.setAttribute(CsrfFilter.AUTH_TOKEN, at);
    return doResponse(request, at, zsc, context, acct, csrfSupport);
}
Also used : Account(com.zimbra.cs.account.Account) HttpServletRequest(javax.servlet.http.HttpServletRequest) ServletRequest(javax.servlet.ServletRequest) HashMap(java.util.HashMap) Element(com.zimbra.common.soap.Element) Provisioning(com.zimbra.cs.account.Provisioning) AccountBy(com.zimbra.common.account.Key.AccountBy) AuthMech(com.zimbra.cs.account.auth.AuthMechanism.AuthMech) ServiceException(com.zimbra.common.service.ServiceException) AuthFailedServiceException(com.zimbra.cs.account.AccountServiceException.AuthFailedServiceException) ZimbraSoapContext(com.zimbra.soap.ZimbraSoapContext) TwoFactorAuth(com.zimbra.cs.account.auth.twofactor.TwoFactorAuth) AuthTokenException(com.zimbra.cs.account.AuthTokenException) AuthToken(com.zimbra.cs.account.AuthToken) Domain(com.zimbra.cs.account.Domain)

Aggregations

TwoFactorAuth (com.zimbra.cs.account.auth.twofactor.TwoFactorAuth)3 AccountBy (com.zimbra.common.account.Key.AccountBy)2 ServiceException (com.zimbra.common.service.ServiceException)2 Element (com.zimbra.common.soap.Element)2 Account (com.zimbra.cs.account.Account)2 AuthFailedServiceException (com.zimbra.cs.account.AccountServiceException.AuthFailedServiceException)2 AuthToken (com.zimbra.cs.account.AuthToken)2 AuthTokenException (com.zimbra.cs.account.AuthTokenException)2 Domain (com.zimbra.cs.account.Domain)2 Provisioning (com.zimbra.cs.account.Provisioning)2 AppSpecificPasswords (com.zimbra.cs.account.auth.twofactor.AppSpecificPasswords)2 ZimbraSoapContext (com.zimbra.soap.ZimbraSoapContext)2 HashMap (java.util.HashMap)2 ServletRequest (javax.servlet.ServletRequest)2 HttpServletRequest (javax.servlet.http.HttpServletRequest)2 AccountServiceException (com.zimbra.cs.account.AccountServiceException)1 Usage (com.zimbra.cs.account.AuthToken.Usage)1 TrustedDevice (com.zimbra.cs.account.TrustedDevice)1 TrustedDeviceToken (com.zimbra.cs.account.TrustedDeviceToken)1 Protocol (com.zimbra.cs.account.auth.AuthContext.Protocol)1