package org.apereo.cas.authentication.adaptive; import org.apache.commons.lang3.StringUtils; import org.apereo.cas.authentication.adaptive.geo.GeoLocationRequest; import org.apereo.cas.authentication.adaptive.geo.GeoLocationResponse; import org.apereo.cas.authentication.adaptive.geo.GeoLocationService; import org.apereo.cas.configuration.model.core.authentication.AdaptiveAuthenticationProperties; import org.apereo.inspektr.common.web.ClientInfo; import org.apereo.inspektr.common.web.ClientInfoHolder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.regex.Pattern; /** * This is {@link DefaultAdaptiveAuthenticationPolicy}. * * @author Misagh Moayyed * @since 5.0.0 */ public class DefaultAdaptiveAuthenticationPolicy implements AdaptiveAuthenticationPolicy { private static final Logger LOGGER = LoggerFactory.getLogger(DefaultAdaptiveAuthenticationPolicy.class); private GeoLocationService geoLocationService; private AdaptiveAuthenticationProperties adaptiveAuthenticationProperties; public void setGeoLocationService(final GeoLocationService geoLocationService) { this.geoLocationService = geoLocationService; } public void setAdaptiveAuthenticationProperties(final AdaptiveAuthenticationProperties a) { this.adaptiveAuthenticationProperties = a; } @Override public boolean apply(final String userAgent, final GeoLocationRequest location) { final ClientInfo clientInfo = ClientInfoHolder.getClientInfo(); if (clientInfo == null || StringUtils.isBlank(userAgent)) { LOGGER.warn("No client IP or user-agent was provided. Skipping adaptive authentication policy..."); return true; } final String clientIp = clientInfo.getClientIpAddress(); LOGGER.debug("Located client IP address as [{}]", clientIp); if (isClientIpAddressRejected(clientIp)) { LOGGER.warn("Client IP [{}] is rejected for authentication", clientIp); return false; } if (isUserAgentRejected(userAgent)) { LOGGER.warn("User agent [{}] is rejected for authentication", userAgent); return false; } LOGGER.debug("User agent [{}] is authorized to proceed", userAgent); if (this.geoLocationService != null && location != null && StringUtils.isNotBlank(clientIp) && StringUtils.isNotBlank(this.adaptiveAuthenticationProperties.getRejectCountries())) { final GeoLocationResponse loc = this.geoLocationService.locate(clientIp, location); if (loc != null) { LOGGER.debug("Determined geolocation to be [{}]", loc); if (isGeoLocationCountryRejected(loc)) { LOGGER.warn("Client [{}] is rejected for authentication", clientIp); return false; } } else { LOGGER.info("Could not determine geolocation for [{}]", clientIp); } } LOGGER.debug("Adaptive authentication policy has authorized client [{}] to proceed.", clientIp); return true; } private boolean isClientIpAddressRejected(final String clientIp) { return StringUtils.isNotBlank(this.adaptiveAuthenticationProperties.getRejectIpAddresses()) && Pattern.compile(this.adaptiveAuthenticationProperties.getRejectIpAddresses()).matcher(clientIp).find(); } private boolean isGeoLocationCountryRejected(final GeoLocationResponse finalLoc) { return StringUtils.isNotBlank(this.adaptiveAuthenticationProperties.getRejectCountries()) && Pattern.compile(this.adaptiveAuthenticationProperties.getRejectCountries()).matcher(finalLoc.build()).find(); } private boolean isUserAgentRejected(final String userAgent) { return StringUtils.isNotBlank(this.adaptiveAuthenticationProperties.getRejectBrowsers()) && Pattern.compile(this.adaptiveAuthenticationProperties.getRejectBrowsers()).matcher(userAgent).find(); } }