Skip to content

Commit

Permalink
Working on googlemaps geo profiling
Browse files Browse the repository at this point in the history
  • Loading branch information
SavvasMisaghMoayyed committed Aug 9, 2016
1 parent 5befe01 commit 76aa0e0
Show file tree
Hide file tree
Showing 17 changed files with 146 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
import org.apereo.cas.authentication.adaptive.geo.GeoLocationRequest;

/**
* This is {@link AdaptiveAuthenticationStrategy}.
* This is {@link AdaptiveAuthenticationPolicy}.
*
* @author Misagh Moayyed
* @since 5.0.0
*/
public interface AdaptiveAuthenticationStrategy {
public interface AdaptiveAuthenticationPolicy {

/**
* Apply the strategy to figure out whether this authentication attempt can proceed.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package org.apereo.cas.authentication.adaptive;

import org.apereo.cas.authentication.AuthenticationException;
import org.apereo.cas.authentication.HandlerResult;

import java.util.Collections;
import java.util.Map;

/**
* This is {@link UnauthorizedAuthenticationException}.
*
* @author Misagh Moayyed
* @since 5.0.0
*/
public class UnauthorizedAuthenticationException extends AuthenticationException {

public UnauthorizedAuthenticationException(final String message, final Map<String, Class<? extends Exception>> handlerErrors) {
super(message, handlerErrors, Collections.emptyMap());
}

public UnauthorizedAuthenticationException(final Map<String, Class<? extends Exception>> handlerErrors) {
super(handlerErrors);
}

public UnauthorizedAuthenticationException(final Map<String, Class<? extends Exception>> handlerErrors, final Map<String, HandlerResult> handlerSuccesses) {
super(handlerErrors, handlerSuccesses);
}

public UnauthorizedAuthenticationException(final String message, final Map<String, Class<? extends Exception>> handlerErrors, final Map<String, HandlerResult> handlerSuccesses) {
super(message, handlerErrors, handlerSuccesses);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.apereo.cas.authentication.adaptive.geo;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.builder.ToStringBuilder;

/**
* This is {@link GeoLocationRequest}.
Expand Down Expand Up @@ -50,4 +51,14 @@ public boolean isValid() {
return StringUtils.isNotBlank(this.latitude) && StringUtils.isNotBlank(this.longitude)
&& StringUtils.isNotBlank(this.accuracy) && StringUtils.isNotBlank(this.timestamp);
}

@Override
public String toString() {
return new ToStringBuilder(this)
.append("latitude", latitude)
.append("longitude", longitude)
.append("accuracy", accuracy)
.append("timestamp", timestamp)
.toString();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.util.WebUtils;

/**
* This is {@link DefaultAuthenticationTransactionManager}.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@
import org.slf4j.LoggerFactory;

/**
* This is {@link DefaultAdaptiveAuthenticationStrategy}.
* This is {@link DefaultAdaptiveAuthenticationTransactionPolicy}.
*
* @author Misagh Moayyed
* @since 5.0.0
*/
public class DefaultAdaptiveAuthenticationStrategy implements AdaptiveAuthenticationStrategy {
public class DefaultAdaptiveAuthenticationTransactionPolicy implements AdaptiveAuthenticationTransactionPolicy {
protected final Logger logger = LoggerFactory.getLogger(this.getClass());

private GeoLocationService geoLocationService;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@
import org.apereo.cas.authentication.RequiredHandlerAuthenticationPolicy;
import org.apereo.cas.authentication.RequiredHandlerAuthenticationPolicyFactory;
import org.apereo.cas.authentication.SuccessfulHandlerMetaDataPopulator;
import org.apereo.cas.authentication.adaptive.AdaptiveAuthenticationPolicy;
import org.apereo.cas.authentication.adaptive.DefaultAdaptiveAuthenticationPolicy;
import org.apereo.cas.authentication.adaptive.geo.GeoLocationService;
import org.apereo.cas.authentication.handler.support.HttpBasedServiceCredentialsAuthenticationHandler;
import org.apereo.cas.authentication.handler.support.JaasAuthenticationHandler;
import org.apereo.cas.authentication.principal.BasicPrincipalResolver;
Expand Down Expand Up @@ -73,6 +76,10 @@ public class CasCoreAuthenticationConfiguration {
@Autowired
private CasConfigurationProperties casProperties;

@Autowired(required = false)
@Qualifier("geoLocationService")
private GeoLocationService geoLocationService;

@Autowired(required = false)
@Qualifier("acceptPasswordPolicyConfiguration")
private PasswordPolicyConfiguration acceptPasswordPolicyConfiguration;
Expand Down Expand Up @@ -120,7 +127,7 @@ public AuthenticationPolicy defaultAuthenticationPolicy() {

return new AnyAuthenticationPolicy(casProperties.getAuthn().getPolicy().getAny().isTryAll());
}

@Bean
public AuthenticationHandler acceptUsersAuthenticationHandler() {
final Pattern pattern = Pattern.compile("::");
Expand Down Expand Up @@ -152,7 +159,7 @@ public AuthenticationHandler acceptUsersAuthenticationHandler() {
public PrincipalFactory acceptUsersPrincipalFactory() {
return new DefaultPrincipalFactory();
}

@RefreshScope
@Bean
public AuthenticationContextValidator authenticationContextValidator() {
Expand All @@ -175,8 +182,7 @@ public AuthenticationSystemSupport defaultAuthenticationSystemSupport(@Qualifier
@Bean(name = {"defaultAuthenticationTransactionManager", "authenticationTransactionManager"})
public AuthenticationTransactionManager defaultAuthenticationTransactionManager(@Qualifier(BEAN_NAME_HTTP_CLIENT)
final HttpClient httpClient) {
final DefaultAuthenticationTransactionManager r =
new DefaultAuthenticationTransactionManager();
final DefaultAuthenticationTransactionManager r = new DefaultAuthenticationTransactionManager();
r.setAuthenticationManager(authenticationManager(httpClient));
return r;
}
Expand Down Expand Up @@ -224,7 +230,7 @@ public AuthenticationManager authenticationManager(
p.setAuthenticationPolicy(defaultAuthenticationPolicy());
return p;
}

@Bean
public AuthenticationHandlerResolver registeredServiceAuthenticationHandlerResolver() {
final RegisteredServiceAuthenticationHandlerResolver r =
Expand All @@ -242,7 +248,7 @@ public ContextualAuthenticationPolicyFactory requiredHandlerAuthenticationPolicy
public AuthenticationMetaDataPopulator successfulHandlerMetaDataPopulator() {
return new SuccessfulHandlerMetaDataPopulator();
}

@Bean
public AuthenticationMetaDataPopulator rememberMeAuthenticationMetaDataPopulator() {
return new RememberMeAuthenticationMetaDataPopulator();
Expand Down Expand Up @@ -276,7 +282,7 @@ public PrincipalResolver proxyPrincipalResolver() {
p.setPrincipalFactory(proxyPrincipalFactory());
return p;
}

@RefreshScope
@Bean
public AuthenticationHandler jaasAuthenticationHandler() {
Expand Down Expand Up @@ -353,4 +359,13 @@ public HttpClient supportsTrustStoreSslSocketFactoryHttpClient() throws Exceptio
c.setSslSocketFactory(trustStoreSslSocketFactory());
return c.getObject();
}


@Bean
public AdaptiveAuthenticationPolicy adaptiveAuthenticationPolicy() {
final DefaultAdaptiveAuthenticationPolicy p = new DefaultAdaptiveAuthenticationPolicy();
p.setGeoLocationService(this.geoLocationService);
p.setAdaptiveAuthenticationProperties(casProperties.getAuthn().getAdaptive());
return p;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import org.apereo.cas.authentication.AuthenticationException;
import org.apereo.cas.authentication.InvalidLoginLocationException;
import org.apereo.cas.authentication.InvalidLoginTimeException;
import org.apereo.cas.authentication.adaptive.UnauthorizedAuthenticationException;
import org.apereo.cas.services.UnauthorizedServiceForPrincipalException;
import org.apereo.cas.ticket.AbstractTicketException;
import org.apereo.cas.ticket.UnsatisfiedAuthenticationPolicyException;
Expand Down Expand Up @@ -75,6 +76,7 @@ public class AuthenticationExceptionHandler {
DEFAULT_ERROR_LIST.add(javax.security.auth.login.FailedLoginException.class);
DEFAULT_ERROR_LIST.add(UnauthorizedServiceForPrincipalException.class);
DEFAULT_ERROR_LIST.add(UnsatisfiedAuthenticationPolicyException.class);
DEFAULT_ERROR_LIST.add(UnauthorizedAuthenticationException.class);
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
package org.apereo.cas.configuration.model.core.authentication;

import java.util.ArrayList;
import java.util.List;

/**
* This is {@link AdaptiveAuthenticationProperties}.
*
Expand All @@ -11,22 +8,22 @@
*/
public class AdaptiveAuthenticationProperties {

private List<String> rejectCountries = new ArrayList<>();
private List<String> rejectBrowsers = new ArrayList<>();
private String rejectCountries;
private String rejectBrowsers;

public List<String> getRejectCountries() {
public String getRejectCountries() {
return rejectCountries;
}

public void setRejectCountries(final List<String> rejectCountries) {
public void setRejectCountries(final String rejectCountries) {
this.rejectCountries = rejectCountries;
}

public List<String> getRejectBrowsers() {
public String getRejectBrowsers() {
return rejectBrowsers;
}

public void setRejectBrowsers(final List<String> rejectBrowsers) {
public void setRejectBrowsers(final String rejectBrowsers) {
this.rejectBrowsers = rejectBrowsers;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,9 @@
import org.apache.logging.log4j.core.layout.PatternLayout;
import org.apache.logging.log4j.message.Message;
import org.apache.logging.log4j.message.SimpleMessage;
import org.apereo.cas.ticket.TicketGrantingTicket;
import org.apereo.cas.ticket.proxy.ProxyGrantingTicket;
import org.apereo.cas.util.TicketIdSanitizationUtils;
import org.springframework.util.Assert;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
* This is {@link CasAppender}.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,11 @@ same IP address.

## Adaptive Authentication

```properties
# cas.authn.adaptive.rejectCountries=United.+
# cas.authn.adaptive.rejectBrowsers=Gecko.+
```

## GoogleMaps GeoTracking

Used to geo-profile authentication events.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import org.apache.commons.lang3.StringUtils;
import org.apereo.cas.CentralAuthenticationService;
import org.apereo.cas.authentication.AuthenticationSystemSupport;
import org.apereo.cas.authentication.adaptive.AdaptiveAuthenticationPolicy;
import org.apereo.cas.configuration.CasConfigurationProperties;
import org.apereo.cas.services.ServicesManager;
import org.apereo.cas.ticket.registry.TicketRegistrySupport;
Expand Down Expand Up @@ -72,11 +73,14 @@ public class CasSupportActionsConfiguration {
@Autowired
private CasConfigurationProperties casProperties;

@Autowired
@Qualifier("adaptiveAuthenticationPolicy")
private AdaptiveAuthenticationPolicy adaptiveAuthenticationPolicy;

@Autowired
@Qualifier("centralAuthenticationService")
private CentralAuthenticationService centralAuthenticationService;



@Autowired
@Qualifier("defaultAuthenticationSystemSupport")
private AuthenticationSystemSupport authenticationSystemSupport;
Expand All @@ -99,6 +103,7 @@ public Action authenticationViaFormAction() {
final AuthenticationViaFormAction a = new AuthenticationViaFormAction();
a.setInitialAuthenticationAttemptWebflowEventResolver(initialAuthenticationAttemptWebflowEventResolver);
a.setServiceTicketRequestWebflowEventResolver(serviceTicketRequestWebflowEventResolver);
a.setAdaptiveAuthenticationPolicy(this.adaptiveAuthenticationPolicy);
return a;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
package org.apereo.cas.web.flow;

import com.google.common.collect.ImmutableMap;
import org.apereo.cas.authentication.AuthenticationException;
import org.apereo.cas.authentication.adaptive.AdaptiveAuthenticationPolicy;
import org.apereo.cas.authentication.adaptive.UnauthorizedAuthenticationException;
import org.apereo.cas.authentication.adaptive.geo.GeoLocationRequest;
import org.apereo.cas.web.flow.resolver.CasWebflowEventResolver;
import org.apereo.cas.web.support.WebUtils;
import org.springframework.webflow.action.AbstractAction;
import org.springframework.webflow.core.collection.LocalAttributeMap;
import org.springframework.webflow.execution.Event;
import org.springframework.webflow.execution.RequestContext;

import java.util.Collections;
import java.util.Map;

/**
* Action to authenticate credential and retrieve a TicketGrantingTicket for
* those credential. If there is a request for renew, then it also generates
Expand All @@ -19,14 +29,30 @@ public class AuthenticationViaFormAction extends AbstractAction {

private CasWebflowEventResolver initialAuthenticationAttemptWebflowEventResolver;

private AdaptiveAuthenticationPolicy adaptiveAuthenticationPolicy;

@Override
protected Event doExecute(final RequestContext requestContext) throws Exception {
final String agent = WebUtils.getHttpServletRequestUserAgent();
final GeoLocationRequest geoLocation = WebUtils.getHttpServletRequestGeoLocation();

if (!adaptiveAuthenticationPolicy.apply(agent, geoLocation)) {
final String msg = "Authentication policy does not allow this request for " + agent + " and " + geoLocation;
final Map map = ImmutableMap.of(
UnauthorizedAuthenticationException.class.getSimpleName(),
UnauthorizedAuthenticationException.class);
final AuthenticationException error = new AuthenticationException(msg, map, Collections.emptyMap());
return new Event(this, CasWebflowConstants.TRANSITION_ID_AUTHENTICATION_FAILURE,
new LocalAttributeMap(CasWebflowConstants.TRANSITION_ID_ERROR, error));

}

final Event serviceTicketEvent = this.serviceTicketRequestWebflowEventResolver.resolveSingle(requestContext);
if (serviceTicketEvent != null) {
return serviceTicketEvent;
}

return this.initialAuthenticationAttemptWebflowEventResolver.resolveSingle(requestContext);

}

public void setServiceTicketRequestWebflowEventResolver(final CasWebflowEventResolver r) {
Expand All @@ -36,4 +62,8 @@ public void setServiceTicketRequestWebflowEventResolver(final CasWebflowEventRes
public void setInitialAuthenticationAttemptWebflowEventResolver(final CasWebflowEventResolver r) {
this.initialAuthenticationAttemptWebflowEventResolver = r;
}

public void setAdaptiveAuthenticationPolicy(final AdaptiveAuthenticationPolicy a) {
this.adaptiveAuthenticationPolicy = a;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ public GeoLocationResponse locate(final String address) {

@Override
public GeoLocationResponse locate(final double latitude, final double longitude) {
logger.warn("Geolocating an address by latitude/longitude is not supported");
logger.warn("Geolocating an address by latitude/longitude {}/{} is not supported", latitude, longitude);
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -165,10 +165,10 @@ public EndpointHandlerMappingCustomizer mappingCustomizer() {
public void init() {
if (StringUtils.isNotBlank(casProperties.getAuthn().getAccept().getUsers())) {
final String header =
"\nCAS is configured to accept a static list of credentials for authentication. "
+ "While this is generally useful for demo purposes, it is STRONGLY recommended "
+ "that you DISABLE this authentication method (by SETTING 'cas.authn.accept.users' to a blank value "
+ "in your configuration) and switch to a mode that is more suitable for production. \n";
"\nCAS is configured to accept a static list of credentials for authentication.\n"
+ "While this is generally useful for demo purposes, it is STRONGLY recommended\n"
+ "that you DISABLE this authentication method (by SETTING 'cas.authn.accept.users'\n"
+ "to a blank value) and switch to a mode that is more suitable for production. \n";
AsciiArtUtils.printAsciiArt(LOGGER, "STOP!", header);
this.authenticationHandlersResolvers.put(acceptUsersAuthenticationHandler,
personDirectoryPrincipalResolver);
Expand Down
2 changes: 2 additions & 0 deletions cas-server-webapp/src/main/resources/messages.properties
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,8 @@ screen.mustchangepass.heading=You must change your password.
screen.mustchangepass.message=Please <a href="{0}">change your password</a>.
screen.badhours.heading=Your account is forbidden to login at this time.
screen.badhours.message=Please try again later.
screen.authnblocked.heading=Authentication attempt is blocked.
screen.authnblocked.message=Your authentication attempt is untrusted and unauthorized from your current workstation.
screen.badworkstation.heading=You cannot login from this workstation.
screen.badworkstation.message=Please contact the system administrator to regain access.

Expand Down
Loading

0 comments on commit 76aa0e0

Please sign in to comment.