protected Map<String, List<Object>> collectDuoAuthenticationContextAttributes(final Token result) {
        val authContext = result.getAuth_context();
        val attributes = new LinkedHashMap<String, List<Object>>();
        if (authContext != null) {
            collectDuoAttribute(attributes, "duoAuthCtxEventType", CollectionUtils.wrap(authContext.getEvent_type()));
            collectDuoAttribute(attributes, "duoAuthCtxFactor", CollectionUtils.wrap(authContext.getFactor()));
            collectDuoAttribute(attributes, "duoAuthCtxReason", CollectionUtils.wrap(authContext.getReason()));
            collectDuoAttribute(attributes, "duoAuthCtxResult", CollectionUtils.wrap(authContext.getResult()));
            collectDuoAttribute(attributes, "duoAuthCtxTimestamp", CollectionUtils.wrap(authContext.getTimestamp()));
            collectDuoAttribute(attributes, "duoAuthCtxTxId", CollectionUtils.wrap(authContext.getTxid()));
            collectDuoAttribute(attributes, "duoAuthCtxUserKey", CollectionUtils.wrap(authContext.getUser().getKey()));

            val accessDevice = authContext.getAccess_device();
            if (accessDevice != null) {
                if (StringUtils.isNotBlank(accessDevice.getHostname())) {
                    collectDuoAttribute(attributes, "duoAuthCtxAccessDeviceHostname", CollectionUtils.wrap(accessDevice.getHostname()));
                }
                if (StringUtils.isNotBlank(accessDevice.getIp())) {
                    collectDuoAttribute(attributes, "duoAuthCtxAccessDeviceIp", CollectionUtils.wrap(accessDevice.getIp()));
                }
                val accessLocation = accessDevice.getLocation();
                if (accessLocation != null) {
                    collectDuoAttribute(attributes, "duoAuthCtxAccessDeviceLocationCity", CollectionUtils.wrap(accessLocation.getCity()));
                    collectDuoAttribute(attributes, "duoAuthCtxAccessDeviceLocationCountry", CollectionUtils.wrap(accessLocation.getCountry()));
                    collectDuoAttribute(attributes, "duoAuthCtxAccessDeviceLocationState", CollectionUtils.wrap(accessLocation.getState()));
                }
            }

            val application = authContext.getApplication();
            if (application != null) {
                collectDuoAttribute(attributes, "duoAuthCtxApplicationId", CollectionUtils.wrap(application.getName()));
            }

            val authDevice = authContext.getAuth_device();
            if (authDevice != null) {
                collectDuoAttribute(attributes, "duoAuthCtxAuthDeviceHostname", CollectionUtils.wrap(authDevice.getName()));
                collectDuoAttribute(attributes, "duoAuthCtxAuthDeviceIp", CollectionUtils.wrap(authDevice.getIp()));

                val authLocation = authDevice.getLocation();
                if (authLocation != null) {
                    collectDuoAttribute(attributes, "duoAuthCtxAuthDeviceLocationCity", CollectionUtils.wrap(authLocation.getCity()));
                    collectDuoAttribute(attributes, "duoAuthCtxAuthDeviceLocationCountry", CollectionUtils.wrap(authLocation.getCountry()));
                    collectDuoAttribute(attributes, "duoAuthCtxAuthDeviceLocationState", CollectionUtils.wrap(authLocation.getState()));
                }
            }
        }
        return attributes;
    }
An abstraction that encapsulates interaction with
Duo 2fa authentication service via its universal prompt API.

@author Misagh Moayyed
@since 6.3.0
support/cas-server-support-duo-core/src/main/java/org/apereo/cas/adaptors/duo/authn/UniversalPromptDuoSecurityAuthenticationService.java