package net.unicon.idp.externalauth;
import net.shibboleth.idp.attribute.IdPAttribute;
import net.shibboleth.idp.attribute.StringAttributeValue;
import net.shibboleth.idp.authn.ExternalAuthentication;
import net.shibboleth.idp.authn.principal.IdPAttributePrincipal;
import net.shibboleth.idp.authn.principal.UsernamePrincipal;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.jasig.cas.client.authentication.AttributePrincipal;
import org.jasig.cas.client.validation.Assertion;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.security.auth.Subject;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Simple translation of the principal name from the CAS assertion to the string value used by Shib
*
* @author chasegawa@unicon.net
* @author jgasper@unicon.net
*/
public class AuthenticatedNameTranslator implements CasToShibTranslator {
private Logger logger = LoggerFactory.getLogger(ShibcasAuthServlet.class);
@Override
public void doTranslation(final HttpServletRequest request, final HttpServletResponse response,
final Assertion assertion) {
if (assertion == null || assertion.getPrincipal() == null) {
logger.error("No valid assertion or principal could be found to translate");
return;
}
AttributePrincipal casPrincipal = assertion.getPrincipal();
logger.debug("principalName found and being passed on: {}", casPrincipal.getName());
// Pass authenticated principal back to IdP to finish its part of authentication request processing
Collection<IdPAttributePrincipal> assertionAttributes = produceIdpAttributePrincipal(assertion.getAttributes());
Collection<IdPAttributePrincipal> principalAttributes = produceIdpAttributePrincipal(casPrincipal.getAttributes());
if (!assertionAttributes.isEmpty() || !principalAttributes.isEmpty()) {
logger.debug("Found attributes from CAS. Processing...");
Set<Principal> principals = new HashSet<>();
principals.addAll(assertionAttributes);
principals.addAll(principalAttributes);
principals.add(new UsernamePrincipal(casPrincipal.getName()));
request.setAttribute(ExternalAuthentication.SUBJECT_KEY, new Subject(false, principals,
Collections.emptySet(), Collections.emptySet()));
logger.info("Created an IdP subject instance with principals containing attributes for {} ", casPrincipal.getName());
} else {
logger.debug("No attributes released from CAS. Creating an IdP principal for {}", casPrincipal.getName());
request.setAttribute(ExternalAuthentication.PRINCIPAL_NAME_KEY, casPrincipal.getName());
}
}
@Override
public int hashCode() {
return HashCodeBuilder.reflectionHashCode(this);
}
@Override
public boolean equals(final Object that) {
return EqualsBuilder.reflectionEquals(this, that);
}
private Collection<IdPAttributePrincipal> produceIdpAttributePrincipal(Map<String, Object> casAttributes) {
Set<IdPAttributePrincipal> principals = new HashSet<>();
for (final Map.Entry<String, Object> entry : casAttributes.entrySet()) {
IdPAttribute attr = new IdPAttribute(entry.getKey());
List<StringAttributeValue> attributeValues = new ArrayList<>();
if (entry.getValue() instanceof Collection) {
for (final Object value : (Collection) entry.getValue()) {
attributeValues.add(new StringAttributeValue(value.toString()));
}
} else {
attributeValues.add(new StringAttributeValue(entry.getValue().toString()));
}
if (!attributeValues.isEmpty()) {
attr.setValues(attributeValues);
logger.debug("Added attribute {} with values {}", entry.getKey(), entry.getValue());
principals.add(new IdPAttributePrincipal(attr));
} else {
logger.warn("Skipped attribute {} since it contains no values", entry.getKey());
}
}
return principals;
}
}