Search in sources :

Example 1 with DuoWebException

use of com.duosecurity.duoweb.DuoWebException in project cas by apereo.

the class BaseDuoSecurityAuthenticationService method getUserAccount.

@Override
public DuoSecurityUserAccount getUserAccount(final String username) {
    if (!properties.isAccountStatusEnabled()) {
        LOGGER.debug("Checking Duo Security for user's [{}] account status is disabled", username);
        val account = new DuoSecurityUserAccount(username);
        account.setStatus(DuoSecurityUserAccountStatus.AUTH);
        return account;
    }
    val userAccountCachedMap = userAccountCache.asMap();
    if (userAccountCachedMap.containsKey(username)) {
        val account = userAccountCachedMap.get(username);
        LOGGER.debug("Found cached duo user account [{}]", account);
        return account;
    }
    val account = new DuoSecurityUserAccount(username);
    account.setStatus(DuoSecurityUserAccountStatus.AUTH);
    try {
        val userRequest = buildHttpPostUserPreAuthRequest(username);
        signHttpUserPreAuthRequest(userRequest);
        LOGGER.debug("Contacting Duo to inquire about username [{}]", username);
        val userResponse = getHttpResponse(userRequest);
        val jsonResponse = URLDecoder.decode(userResponse, StandardCharsets.UTF_8.name());
        LOGGER.debug("Received Duo response [{}]", jsonResponse);
        val result = MAPPER.readTree(jsonResponse);
        if (!result.has(RESULT_KEY_STAT)) {
            LOGGER.warn("Duo response was received in unknown format: [{}]", jsonResponse);
            throw new DuoWebException("Invalid response format received from Duo");
        }
        if (result.get(RESULT_KEY_STAT).asText().equalsIgnoreCase("OK")) {
            val response = result.get(RESULT_KEY_RESPONSE);
            val authResult = response.get(RESULT_KEY_RESULT).asText().toUpperCase();
            val status = DuoSecurityUserAccountStatus.valueOf(authResult);
            account.setStatus(status);
            account.setMessage(response.get(RESULT_KEY_STATUS_MESSAGE).asText());
            if (status == DuoSecurityUserAccountStatus.ENROLL) {
                val enrollUrl = response.get(RESULT_KEY_ENROLL_PORTAL_URL).asText();
                account.setEnrollPortalUrl(enrollUrl);
            }
        } else {
            val code = result.get(RESULT_KEY_CODE).asInt();
            if (code > RESULT_CODE_ERROR_THRESHOLD) {
                LOGGER.warn("Duo returned a failure response with code: [{}]. Duo will be considered unavailable", result.get(RESULT_KEY_MESSAGE));
                throw new DuoWebException("Duo returned code 500: " + result.get(RESULT_KEY_MESSAGE));
            }
            LOGGER.warn("Duo returned an Invalid response with message [{}] and detail [{}] " + "when determining user account. This maybe a configuration error in the admin request and Duo will " + "still be considered available.", result.hasNonNull(RESULT_KEY_MESSAGE) ? result.get(RESULT_KEY_MESSAGE).asText() : StringUtils.EMPTY, result.hasNonNull(RESULT_KEY_MESSAGE_DETAIL) ? result.get(RESULT_KEY_MESSAGE_DETAIL).asText() : StringUtils.EMPTY);
        }
    } catch (final Exception e) {
        LOGGER.warn("Reaching Duo has failed with error: [{}]", e.getMessage(), e);
        account.setStatus(DuoSecurityUserAccountStatus.UNAVAILABLE);
    }
    userAccountCachedMap.put(account.getUsername(), account);
    LOGGER.debug("Fetched and cached duo user account [{}]", account);
    return account;
}
Also used : lombok.val(lombok.val) DuoSecurityUserAccount(org.apereo.cas.adaptors.duo.DuoSecurityUserAccount) DuoWebException(com.duosecurity.duoweb.DuoWebException) DuoWebException(com.duosecurity.duoweb.DuoWebException)

Aggregations

DuoWebException (com.duosecurity.duoweb.DuoWebException)1 lombok.val (lombok.val)1 DuoSecurityUserAccount (org.apereo.cas.adaptors.duo.DuoSecurityUserAccount)1