diff --git a/cas-mfa-duo/src/main/groovy/net/unicon/cas/mfa/authentication/duo/DuoMultiFactorWebflowConfigurer.java b/cas-mfa-duo/src/main/groovy/net/unicon/cas/mfa/authentication/duo/DuoMultiFactorWebflowConfigurer.java index 2cb6526..76a544a 100644 --- a/cas-mfa-duo/src/main/groovy/net/unicon/cas/mfa/authentication/duo/DuoMultiFactorWebflowConfigurer.java +++ b/cas-mfa-duo/src/main/groovy/net/unicon/cas/mfa/authentication/duo/DuoMultiFactorWebflowConfigurer.java @@ -2,13 +2,10 @@ import org.jasig.cas.authentication.principal.AbstractPersonDirectoryCredentialsToPrincipalResolver; import org.jasig.cas.authentication.principal.Credentials; -import org.jasig.cas.authentication.principal.CredentialsToPrincipalResolver; -import org.jasig.cas.authentication.principal.Principal; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; import org.springframework.web.context.WebApplicationContext; @@ -30,6 +27,7 @@ public class DuoMultiFactorWebflowConfigurer implements InitializingBean { @PostConstruct + @Override public void afterPropertiesSet() throws Exception { try { final List resolvers = this.context.getBean("mfaCredentialsToPrincipalResolvers", List.class); diff --git a/cas-mfa-java/src/main/java/net/unicon/cas/mfa/authentication/CasMultiFactorAuthenticationManager.java b/cas-mfa-java/src/main/java/net/unicon/cas/mfa/authentication/CasMultiFactorAuthenticationManager.java new file mode 100644 index 0000000..587c53a --- /dev/null +++ b/cas-mfa-java/src/main/java/net/unicon/cas/mfa/authentication/CasMultiFactorAuthenticationManager.java @@ -0,0 +1,96 @@ +package net.unicon.cas.mfa.authentication; + +import org.jasig.cas.authentication.AbstractAuthentication; +import org.jasig.cas.authentication.Authentication; +import org.jasig.cas.authentication.AuthenticationManager; +import org.jasig.cas.authentication.AuthenticationManagerImpl; +import org.jasig.cas.authentication.AuthenticationMetaDataPopulator; +import org.jasig.cas.authentication.ImmutableAuthentication; +import org.jasig.cas.authentication.handler.AuthenticationException; +import org.jasig.cas.authentication.handler.AuthenticationHandler; +import org.jasig.cas.authentication.principal.Credentials; +import org.jasig.cas.authentication.principal.CredentialsToPrincipalResolver; +import org.jasig.cas.authentication.principal.Principal; + +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * This is {@link CasMultiFactorAuthenticationManager} that delegates to the CAS authentication + * manager and runs post-authn processes on the final object based on MFA requirements. + * + * @author Misagh Moayyed + */ +public class CasMultiFactorAuthenticationManager implements AuthenticationManager { + private AuthenticationManager delegate; + private List authenticationHandlers = new ArrayList<>(); + private List credentialsToPrincipalResolvers = new ArrayList<>(); + private List authenticationMetaDataPopulators = new ArrayList<>(); + + public void setAuthenticationHandlers(final List authenticationHandlers) { + this.authenticationHandlers = authenticationHandlers; + } + + public final void setAuthenticationMetaDataPopulators(final List authenticationMetaDataPopulators) { + this.authenticationMetaDataPopulators = authenticationMetaDataPopulators; + } + + public void setCredentialsToPrincipalResolvers(final List credentialsToPrincipalResolvers) { + this.credentialsToPrincipalResolvers = credentialsToPrincipalResolvers; + } + + public void setDelegate(final AuthenticationManager delegate) { + this.delegate = delegate; + } + + @Override + public Authentication authenticate(final Credentials credentials) throws AuthenticationException { + final AuthenticationManagerImpl authImpl = new AuthenticationManagerImpl(); + authImpl.setAuthenticationHandlers(this.authenticationHandlers); + authImpl.setCredentialsToPrincipalResolvers(this.credentialsToPrincipalResolvers); + authImpl.setAuthenticationMetaDataPopulators(this.authenticationMetaDataPopulators); + + Authentication authentication = null; + if (!this.authenticationHandlers.isEmpty()) { + authentication = authImpl.authenticate(credentials); + } else { + authentication = this.delegate.authenticate(credentials); + } + + MutableAuthentication authNMutable = new MutableAuthentication(authentication.getPrincipal(), + authentication.getAttributes(), authentication.getAuthenticatedDate()); + for (final AuthenticationMetaDataPopulator authenticationMetaDataPopulator : this.authenticationMetaDataPopulators) { + final Authentication modified = authenticationMetaDataPopulator.populateAttributes(authNMutable, credentials); + authNMutable = new MutableAuthentication(modified.getPrincipal(), + modified.getAttributes(), modified.getAuthenticatedDate()); + } + return new ImmutableAuthentication(authNMutable.getPrincipal(), + authNMutable.getAttributes()); + + } + + private final class MutableAuthentication extends AbstractAuthentication { + private static final long serialVersionUID = 8051060297683763397L; + + private final Date authenticatedDate; + + /** + * Instantiates a new Mutable authentication. + * + * @param principal the principal + * @param attributes the attributes + * @param date the date + */ + public MutableAuthentication(final Principal principal, final Map attributes, final Date date) { + super(principal, new HashMap(attributes)); + this.authenticatedDate = date; + } + + public Date getAuthenticatedDate() { + return this.authenticatedDate; + } + } +} diff --git a/cas-mfa-web/src/main/webapp/WEB-INF/cas-servlet-override-context.xml b/cas-mfa-web/src/main/webapp/WEB-INF/cas-servlet-override-context.xml index 8673f96..4ef4c6e 100644 --- a/cas-mfa-web/src/main/webapp/WEB-INF/cas-servlet-override-context.xml +++ b/cas-mfa-web/src/main/webapp/WEB-INF/cas-servlet-override-context.xml @@ -65,18 +65,19 @@ p:persistentIdGenerator-ref="persistentIdGenerator" p:authenticationManager-ref="mfaAuthenticationManager"/> - + - + - + + diff --git a/pom.xml b/pom.xml index 3e2682e..080ecf3 100644 --- a/pom.xml +++ b/pom.xml @@ -557,8 +557,8 @@ 2.3.4-01 2.9.0-01 - 1.6 - 1.6 + 1.7 + 1.7 UTF-8 UTF-8