Skip to content

Commit

Permalink
working on delegated access strategies
Browse files Browse the repository at this point in the history
  • Loading branch information
SavvasMisaghMoayyed committed Nov 30, 2017
1 parent 8e7d211 commit 0c8948b
Show file tree
Hide file tree
Showing 23 changed files with 260 additions and 154 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@
import javax.servlet.http.HttpServletRequest;

/**
* This is {@link ValidationAuthorizer}.
* This is {@link ServiceTicketValidationAuthorizer}.
*
* @author Misagh Moayyed
* @since 5.2.0
*/
@FunctionalInterface
public interface ValidationAuthorizer {
public interface ServiceTicketValidationAuthorizer {

/**
* Is authorized?
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package org.apereo.cas.validation;

/**
* This is {@link ServiceTicketValidationAuthorizerConfigurer}.
*
* @author Misagh Moayyed
* @since 5.2.0
*/
public interface ServiceTicketValidationAuthorizerConfigurer {

/**
* Configure authorizer execution plan.
*
* @param plan the plan
*/
default void configureAuthorizersExecutionPlan(final ServiceTicketValidationAuthorizersExecutionPlan plan) {
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package org.apereo.cas.validation;

import java.util.Collection;

/**
* This is {@link ServiceTicketValidationAuthorizersExecutionPlan}.
*
* @author Misagh Moayyed
* @since 5.2.0
*/
public interface ServiceTicketValidationAuthorizersExecutionPlan {

/**
* Register authorizer.
*
* @param authz the authz
*/
void registerAuthorizer(ServiceTicketValidationAuthorizer authz);

/**
* Gets authorizers.
*
* @return the authorizers
*/
Collection<ServiceTicketValidationAuthorizer> getAuthorizers();
}
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,6 @@ public Map<String, Set<String>> getRejectedAttributes() {
}

@Override
@JsonIgnore
public RegisteredServiceDelegatedAuthenticationPolicy getDelegatedAuthenticationPolicy() {
return delegatedAuthenticationPolicy;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.apereo.cas.services;

import com.fasterxml.jackson.annotation.JsonIgnore;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.commons.lang3.builder.ToStringBuilder;
Expand Down Expand Up @@ -66,6 +67,7 @@ public String toString() {
}

@Override
@JsonIgnore
public boolean isProviderAllowed(final String provider, final RegisteredService registeredService) {
if (this.allowedProviders.isEmpty()) {
LOGGER.warn("Registered service [{}] does not define any authorized/supported delegated authentication providers. "
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package org.apereo.cas.validation;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

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

/**
* This is {@link DefaultServiceTicketValidationAuthorizersExecutionPlan}.
*
* @author Misagh Moayyed
* @since 5.2.0
*/
public class DefaultServiceTicketValidationAuthorizersExecutionPlan implements ServiceTicketValidationAuthorizersExecutionPlan {
private static final Logger LOGGER = LoggerFactory.getLogger(DefaultServiceTicketValidationAuthorizersExecutionPlan.class);

private final List<ServiceTicketValidationAuthorizer> serviceTicketValidationAuthorizers = new ArrayList<>();


@Override
public void registerAuthorizer(final ServiceTicketValidationAuthorizer authz) {
serviceTicketValidationAuthorizers.add(authz);
}

@Override
public Collection<ServiceTicketValidationAuthorizer> getAuthorizers() {
return this.serviceTicketValidationAuthorizers;
}
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,25 @@
package org.apereo.cas.validation.config;

import org.apache.commons.lang3.StringUtils;
import org.apereo.cas.configuration.CasConfigurationProperties;
import org.apereo.cas.validation.Cas10ProtocolValidationSpecification;
import org.apereo.cas.validation.Cas20ProtocolValidationSpecification;
import org.apereo.cas.validation.Cas20WithoutProxyingValidationSpecification;
import org.apereo.cas.validation.CasProtocolValidationSpecification;
import org.apereo.cas.validation.DefaultServiceTicketValidationAuthorizersExecutionPlan;
import org.apereo.cas.validation.ServiceTicketValidationAuthorizerConfigurer;
import org.apereo.cas.validation.ServiceTicketValidationAuthorizersExecutionPlan;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;

import java.util.List;

/**
* This is {@link CasCoreValidationConfiguration}.
*
Expand All @@ -18,8 +28,10 @@
*/
@Configuration("casCoreValidationConfiguration")
@EnableConfigurationProperties(CasConfigurationProperties.class)
public class CasCoreValidationConfiguration {

public class CasCoreValidationConfiguration implements ServiceTicketValidationAuthorizerConfigurer {

private static final Logger LOGGER = LoggerFactory.getLogger(CasCoreValidationConfiguration.class);

@Bean
@Scope(value = "prototype")
public CasProtocolValidationSpecification cas10ProtocolValidationSpecification() {
Expand All @@ -37,4 +49,17 @@ public CasProtocolValidationSpecification cas20ProtocolValidationSpecification()
public CasProtocolValidationSpecification cas20WithoutProxyProtocolValidationSpecification() {
return new Cas20WithoutProxyingValidationSpecification();
}

@Autowired
@Bean
@ConditionalOnMissingBean(name = "serviceValidationAuthorizers")
public ServiceTicketValidationAuthorizersExecutionPlan serviceValidationAuthorizers(final List<ServiceTicketValidationAuthorizerConfigurer> configurers) {
final DefaultServiceTicketValidationAuthorizersExecutionPlan plan = new DefaultServiceTicketValidationAuthorizersExecutionPlan();
configurers.forEach(c -> {
final String name = StringUtils.removePattern(c.getClass().getSimpleName(), "\\$.+");
LOGGER.debug("Configuring service ticket validation authorizer execution plan [{}]", name);
c.configureAuthorizersExecutionPlan(plan);
});
return plan;
}
}
28 changes: 20 additions & 8 deletions gradle.properties
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
#################################################
# Platform metadata for releases, POM generation, etc.
#################################################
group=org.apereo.cas
version=5.3.0-RC1-SNAPSHOT

projectUrl=http://www.apereo.org/cas
projectInceptionYear=2004

Expand All @@ -7,25 +13,31 @@ projectLicenseName=The Apache Software License, Version 2.0
projectLicenseUrl=http://www.apache.org/licenses/LICENSE-2.0.txt
projectLicenseDistribution=repo

projectIssueSystem=Github
projectIssueSystem=GithHub
projectIssueUrl=https://github.com/apereo/cas/issues

sonatypeRepositoryUrl=https://oss.sonatype.org/service/local/staging/deploy/maven2/
sonatypeSnapshotsRepositoryUrl=https://oss.sonatype.org/content/repositories/snapshots/

#################################################################################
# A number of dependency versions are defined in gradle/overrides.gradle file
# in order to fully override component versions that are provided by Spring Boot.
##################################################################################
#################################################
# Localized gradle settings to ensure modules can be loaded/configured as quickly as possible.
#################################################
gradleVersion=4.3.1
org.gradle.configureondemand=true
org.gradle.jvmargs=-Xmx2048m -XX:SoftRefLRUPolicyMSPerMB=0 -noverify

#################################################
# Platform SDK versions for both Java and Kotlin, etc.
#################################################
sourceCompatibility=1.8
targetCompatibility=1.8
group=org.apereo.cas
version=5.3.0-RC1-SNAPSHOT

kotlinVersion=1.1.60
kotlin.incremental=true

#################################################################################
# A number of dependency versions are defined in gradle/overrides.gradle file
# in order to fully override component versions that are provided by Spring Boot.
##################################################################################
aspectjVersion=1.8.12
junitVersion=4.12
mockitoVersion=2.11.0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
import org.apereo.cas.ticket.registry.TicketRegistrySupport;
import org.apereo.cas.util.CollectionUtils;
import org.apereo.cas.validation.CasProtocolValidationSpecification;
import org.apereo.cas.validation.ValidationAuthorizer;
import org.apereo.cas.validation.ServiceTicketValidationAuthorizersExecutionPlan;
import org.apereo.cas.web.AbstractDelegateController;
import org.apereo.cas.web.DelegatingController;
import org.apereo.cas.web.flow.resolver.CasDelegatingWebflowEventResolver;
Expand All @@ -42,7 +42,6 @@
import org.springframework.webflow.execution.Action;

import java.util.Properties;
import java.util.Set;

/**
* This is {@link OpenIdConfiguration}.
Expand Down Expand Up @@ -121,7 +120,7 @@ public class OpenIdConfiguration {

@Autowired
@Qualifier("serviceValidationAuthorizers")
private Set<ValidationAuthorizer> validationAuthorizers;
private ServiceTicketValidationAuthorizersExecutionPlan validationAuthorizers;

@Bean
public AbstractDelegateController smartOpenIdAssociationController() {
Expand Down Expand Up @@ -172,7 +171,8 @@ public OpenIdUserNameExtractor defaultOpenIdUserNameExtractor() {

@Autowired
@Bean
public OpenIdPostUrlHandlerMapping openIdPostUrlHandlerMapping(@Qualifier("argumentExtractor") final ArgumentExtractor argumentExtractor) {
public OpenIdPostUrlHandlerMapping openIdPostUrlHandlerMapping(@Qualifier("argumentExtractor")
final ArgumentExtractor argumentExtractor) {
final OpenIdValidateController c = new OpenIdValidateController(cas20WithoutProxyProtocolValidationSpecification,
authenticationSystemSupport, servicesManager,
centralAuthenticationService, proxy20Handler,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import org.apereo.cas.support.openid.OpenIdProtocolConstants;
import org.apereo.cas.ticket.proxy.ProxyHandler;
import org.apereo.cas.validation.CasProtocolValidationSpecification;
import org.apereo.cas.validation.ValidationAuthorizer;
import org.apereo.cas.validation.ServiceTicketValidationAuthorizersExecutionPlan;
import org.apereo.cas.web.AbstractServiceValidateController;
import org.apereo.cas.web.support.ArgumentExtractor;
import org.openid4java.message.ParameterList;
Expand All @@ -24,7 +24,6 @@
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
* An Openid controller that delegates to its own views on service validates.
Expand All @@ -48,7 +47,7 @@ public OpenIdValidateController(final CasProtocolValidationSpecification validat
final View jsonView, final View successView,
final View failureView, final String authnContextAttribute,
final ServerManager serverManager,
final Set<ValidationAuthorizer> validationAuthorizers) {
final ServiceTicketValidationAuthorizersExecutionPlan validationAuthorizers) {
super(validationSpecification, authenticationSystemSupport, servicesManager,
centralAuthenticationService, proxyHandler,
argumentExtractor, multifactorTriggerSelectionStrategy,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
* @since 3.5.0
*/
public class DelegatedClientAuthenticationAction extends AbstractAction {

/**
* Stop the webflow for pac4j and route to view.
*/
Expand Down Expand Up @@ -113,10 +113,8 @@ protected Event doExecute(final RequestContext context) throws Exception {
final HttpServletResponse response = WebUtils.getHttpServletResponseFromExternalWebflowContext(context);
final HttpSession session = request.getSession();

// web context
final WebContext webContext = Pac4jUtils.getPac4jJ2EContext(request, response);

// get client
final String clientName = request.getParameter(this.clients.getClientNameParameter());
LOGGER.debug("Delegated authentication is handled by client name [{}]", clientName);

Expand All @@ -133,7 +131,6 @@ protected Event doExecute(final RequestContext context) throws Exception {
LOGGER.debug("Retrieve service: [{}]", service);
if (service != null) {
request.setAttribute(CasProtocolConstants.PARAMETER_SERVICE, service.getId());

if (!isDelegatedClientAuthorizedForService(client, service)) {
LOGGER.warn("Delegated client [{}] is not authorized by service [{}]", client, service);
throw new UnauthorizedServiceException(UnauthorizedServiceException.CODE_UNAUTHZ_SERVICE, StringUtils.EMPTY);
Expand Down Expand Up @@ -193,10 +190,8 @@ protected void prepareForLoginPage(final RequestContext context) {
final HttpServletResponse response = WebUtils.getHttpServletResponseFromExternalWebflowContext(context);
final HttpSession session = request.getSession();

// web context
final WebContext webContext = Pac4jUtils.getPac4jJ2EContext(request, response);

// save parameters in web session
final Service service = WebUtils.getService(context);
LOGGER.debug("Save service: [{}]", service);
session.setAttribute(CasProtocolConstants.PARAMETER_SERVICE, service);
Expand Down Expand Up @@ -231,7 +226,8 @@ protected void prepareForLoginPage(final RequestContext context) {
if (!urls.isEmpty()) {
context.getFlowScope().put(PAC4J_URLS, urls);
} else if (response.getStatus() != HttpStatus.UNAUTHORIZED.value()) {
LOGGER.warn("No clients could be determined based on the provided configuration");
LOGGER.warn("No delegated authentication providers could be determined based on the provided configuration. "
+ "Either no clients are configured, or the current access strategy rules prohibit CAS from using authentication providers for this request.");
}
}

Expand Down Expand Up @@ -328,7 +324,7 @@ private boolean isDelegatedClientAuthorizedForService(final Client client, final
LOGGER.debug("Delegated authentication policy for [{}] allows for using client [{}]", registeredService, client);
return true;
}
LOGGER.warn("Delegated authentication policy for [{}] refuses access to client [{}]", registeredService, client);
LOGGER.warn("Delegated authentication policy for [{}] refuses access to client [{}]", registeredService.getServiceId(), client);
return false;
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.apereo.cas.authentication.principal;

import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.apereo.cas.authentication.Credential;
import org.pac4j.core.profile.UserProfile;

Expand Down Expand Up @@ -84,7 +85,7 @@ public void setTypedIdUsed(final boolean typedIdUsed) {

@Override
public String toString() {
return new ToStringBuilder(this)
return new ToStringBuilder(this, ToStringStyle.NO_CLASS_NAME_STYLE)
.append("id", getId())
.toString();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
import org.apereo.cas.support.saml.web.view.Saml10SuccessResponseView;
import org.apereo.cas.ticket.proxy.ProxyHandler;
import org.apereo.cas.validation.CasProtocolValidationSpecification;
import org.apereo.cas.validation.ValidationAuthorizer;
import org.apereo.cas.validation.ServiceTicketValidationAuthorizersExecutionPlan;
import org.apereo.cas.web.support.ArgumentExtractor;
import org.apereo.cas.web.support.DefaultArgumentExtractor;
import org.springframework.beans.factory.annotation.Autowired;
Expand All @@ -31,7 +31,6 @@
import org.springframework.web.servlet.View;

import java.nio.charset.StandardCharsets;
import java.util.Set;

/**
* This is {@link SamlConfiguration} that creates the necessary OpenSAML context and beans.
Expand Down Expand Up @@ -92,7 +91,7 @@ public class SamlConfiguration {

@Autowired
@Qualifier("serviceValidationAuthorizers")
private Set<ValidationAuthorizer> validationAuthorizers;
private ServiceTicketValidationAuthorizersExecutionPlan validationAuthorizers;

@ConditionalOnMissingBean(name = "casSamlServiceSuccessView")
@RefreshScope
Expand Down
Loading

0 comments on commit 0c8948b

Please sign in to comment.