package org.atricore.idbus.capabilities.sso.main.sp.producers;
import oasis.names.tc.saml._2_0.assertion.*;
import oasis.names.tc.saml._2_0.idbus.SecTokenAuthnRequestType;
import oasis.names.tc.saml._2_0.metadata.EndpointType;
import oasis.names.tc.saml._2_0.metadata.EntityDescriptorType;
import oasis.names.tc.saml._2_0.metadata.IDPSSODescriptorType;
import oasis.names.tc.saml._2_0.metadata.RoleDescriptorType;
import oasis.names.tc.saml._2_0.protocol.ResponseType;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.atricore.idbus.capabilities.sso.main.SSOException;
import org.atricore.idbus.capabilities.sso.main.common.producers.SSOProducer;
import org.atricore.idbus.capabilities.sso.main.select.spi.EntitySelectorConstants;
import org.atricore.idbus.capabilities.sso.main.sp.SPSecurityContext;
import org.atricore.idbus.capabilities.sso.main.sp.SSOSPMediator;
import org.atricore.idbus.capabilities.sso.main.sp.plans.AssertIdentityWithSimpleAuthenticationReqToSamlR2AuthnReqPlan;
import org.atricore.idbus.capabilities.sso.support.SAMLR2Constants;
import org.atricore.idbus.capabilities.sso.support.auth.AuthnCtxClass;
import org.atricore.idbus.capabilities.sso.support.binding.SSOBinding;
import org.atricore.idbus.capabilities.sso.support.core.StatusCode;
import org.atricore.idbus.capabilities.sso.support.core.StatusDetails;
import org.atricore.idbus.capabilities.sts.main.SecurityTokenEmissionException;
import org.atricore.idbus.common.sso._1_0.protocol.AssertIdentityWithSimpleAuthenticationRequestType;
import org.atricore.idbus.common.sso._1_0.protocol.RequestAttributeType;
import org.atricore.idbus.common.sso._1_0.protocol.SPAuthnResponseType;
import org.atricore.idbus.kernel.main.authn.SecurityToken;
import org.atricore.idbus.kernel.main.authn.SecurityTokenImpl;
import org.atricore.idbus.kernel.main.federation.*;
import org.atricore.idbus.kernel.main.federation.metadata.CircleOfTrustMemberDescriptor;
import org.atricore.idbus.kernel.main.federation.metadata.EndpointDescriptor;
import org.atricore.idbus.kernel.main.federation.metadata.EndpointDescriptorImpl;
import org.atricore.idbus.kernel.main.federation.metadata.MetadataEntry;
import org.atricore.idbus.kernel.main.mediation.IdentityMediationFault;
import org.atricore.idbus.kernel.main.mediation.MediationMessageImpl;
import org.atricore.idbus.kernel.main.mediation.binding.BindingChannel;
import org.atricore.idbus.kernel.main.mediation.camel.AbstractCamelEndpoint;
import org.atricore.idbus.kernel.main.mediation.camel.component.binding.CamelMediationExchange;
import org.atricore.idbus.kernel.main.mediation.camel.component.binding.CamelMediationMessage;
import org.atricore.idbus.kernel.main.mediation.channel.FederationChannel;
import org.atricore.idbus.kernel.main.mediation.channel.IdPChannel;
import org.atricore.idbus.kernel.main.mediation.provider.FederatedLocalProvider;
import org.atricore.idbus.kernel.main.mediation.provider.FederatedProvider;
import org.atricore.idbus.kernel.main.session.SSOSessionManager;
import org.atricore.idbus.kernel.main.session.exceptions.SSOSessionException;
import org.atricore.idbus.kernel.main.util.UUIDGenerator;
import org.atricore.idbus.kernel.planning.*;
import org.w3._2001._04.xmlenc_.EncryptedType;
import org.w3c.dom.Element;
import javax.security.auth.Subject;
import javax.xml.bind.JAXBElement;
import javax.xml.namespace.QName;
import java.util.List;
import java.util.Set;
/**
* @author <a href="mailto:sgonzalez@atricore.org">Sebastian Gonzalez Oyuela</a>
* @version $Id$
*/
public class AssertIdentityWithSimpleAuthenticationProducer extends SSOProducer {
private UUIDGenerator uuidGenerator = new UUIDGenerator();
private static final Log logger = LogFactory.getLog(AssertIdentityWithSimpleAuthenticationProducer.class);
public AssertIdentityWithSimpleAuthenticationProducer(AbstractCamelEndpoint<CamelMediationExchange> endpoint) throws Exception {
super(endpoint);
}
@Override
protected void doProcess(CamelMediationExchange exchange) throws Exception {
// Store credentials
CamelMediationMessage in = (CamelMediationMessage) exchange.getIn();
Object content = in.getMessage().getContent();
// Check Binding ... we only support SOAP!
SSOBinding b = SSOBinding.asEnum(endpoint.getBinding());
if (!b.equals(SSOBinding.SSO_SOAP)) {
throw new SSOException("Operation does not support " + b.getValue() + " binding!");
}
if (content instanceof AssertIdentityWithSimpleAuthenticationRequestType) {
AssertIdentityWithSimpleAuthenticationRequestType ssoRequest = (AssertIdentityWithSimpleAuthenticationRequestType) content;
// ------------------------------------------------------
// Resolve IDP configuration!
// ------------------------------------------------------
CircleOfTrustMemberDescriptor idp = resolveIdp(exchange);
logger.debug("Using IdP " + idp.getAlias());
FederationChannel idpChannel = resolveIdpChannel(idp);
if (logger.isDebugEnabled())
logger.debug("Using IdP channel " + idpChannel.getName());
EndpointType idpSsoEndpoint = resolveIdpSsoEndpoint(idp);
EndpointDescriptor ed = new EndpointDescriptorImpl(
"IDPSSOEndpoint",
"SingleSignOnService",
idpSsoEndpoint.getBinding(),
idpSsoEndpoint.getLocation(),
idpSsoEndpoint.getResponseLocation());
// Resolve IdP and send SOAP Authn Request
// ---------------------------------------------------------
// Setup CXF Client
// ---------------------------------------------------------
SecTokenAuthnRequestType authnRequest = buildSamlSecTokenAuthnRequetRequest(exchange, idp, ed, idpChannel);
if (logger.isDebugEnabled())
logger.debug("Sending SecTokenAuthnRequest " + authnRequest.getID() +
" to IDP " + idp.getAlias() +
" using endpoint " + ed.getLocation());
ResponseType authnResponse = (ResponseType) channel.getIdentityMediator().sendMessage(authnRequest, ed, channel);
StatusCode status = StatusCode.asEnum(authnResponse.getStatus().getStatusCode().getValue());
StatusCode secStatus = authnResponse.getStatus().getStatusCode().getStatusCode() != null ?
StatusCode.asEnum(authnResponse.getStatus().getStatusCode().getStatusCode().getValue()) : null;
if (logger.isDebugEnabled())
logger.debug("Received status code " + status.getValue() +
(secStatus != null ? "/" + secStatus.getValue() : ""));
// TODO : Validate SP Response!
if (!status.equals(StatusCode.TOP_SUCCESS)) {
throw new SSOException("Unexpected IDP Status Code " + status.getValue() +
(secStatus != null ? "/" + secStatus.getValue() : ""));
}
if (idpChannel.getAccountLinkLifecycle() == null) {
// cannot map subject to local account, terminate
logger.error("No Account Lifecycle configured for Channel [" + idpChannel.getName() + "] " +
" Response [" + authnResponse.getID() + "]");
throw new SSOException("No Account Lifecycle configured for Channel [" + idpChannel.getName() + "] " +
" Response [" + authnResponse.getID() + "]");
}
AccountLinkLifecycle accountLinkLifecycle = idpChannel.getAccountLinkLifecycle();
// ------------------------------------------------------------------
// Build IDP Subject from response
// ------------------------------------------------------------------
Subject idpSubject = buildSubjectFromResponse(authnResponse);
// check if there is an existing account link for the assertion's subject
AccountLink acctLink = null;
/* TODO : For now, only dymanic link is supported!
if (accountLinkLifecycle.persistentForIDPSubjectExists(idpSubject)) {
acctLink = accountLinkLifecycle.findByIDPAccount(idpSubject);
logger.debug("Persistent Account Link Found for Channel [" + idpChannel.getName() + "] " +
"IDP Subject [" + idpSubject + "]" );
} else if (accountLinkLifecycle.transientForIDPSubjectExists(idpSubject)) {
acctLink = accountLinkLifecycle.findByIDPAccount(idpSubject);
logger.debug("Transient Account Link Found for Channel [" + idpChannel.getName() + "] " +
"IDP Subject [" + idpSubject + "]"
);
} else {
// there isn't an account link, therefore emit one using the configured
// account link emitter
AccountLinkEmitter accountLinkEmitter = idpChannel.getAccountLinkEmitter();
logger.debug("Account Link Emitter Found for Channel [" + idpChannel.getName() + "] " +
"IDP Subject [" + idpSubject + "]"
);
if (accountLinkEmitter != null) {
acctLink = accountLinkEmitter.emit(idpSubject);
logger.debug("Emitter Account Link [" + (acctLink != null ? acctLink.getRegion() : "null") + "] [" + idpChannel.getName() + "] " +
"IDP Subject [" + idpSubject + "]"
);
}
} */
// there isn't an account link, therefore emit one using the configured
// account link emitter
AccountLinkEmitter accountLinkEmitter = idpChannel.getAccountLinkEmitter();
logger.debug("Account Link Emitter Found for Channel [" + idpChannel.getName() + "] " +
"IDP Subject [" + idpSubject + "]");
if (accountLinkEmitter != null) {
acctLink = accountLinkEmitter.emit(idpSubject);
logger.debug("Emitter Account Link [" + (acctLink != null ? acctLink.getId() : "null") + "] [" + idpChannel.getName() + "] " +
"IDP Subject [" + idpSubject + "]" );
}
if (acctLink == null) {
logger.error("No Account Link for Channel [" + idpChannel.getName() + "] " +
" Response [" + authnResponse.getID() + "]");
throw new IdentityMediationFault(StatusCode.TOP_REQUESTER.getValue(),
null,
StatusDetails.NO_ACCOUNT_LINK.getValue(),
idpSubject.toString(), null);
}
// ------------------------------------------------------------------
// fetch local account for subject, if any
// ------------------------------------------------------------------
Subject localAccountSubject = accountLinkLifecycle.resolve(acctLink);
logger.debug("Account Link [" + acctLink.getId() + "] resolved to " +
"Local Subject [" + localAccountSubject + "] ");
Subject federatedSubject = localAccountSubject; // if no identity mapping, the local account
// subject is used
// having both idp and local account is now time to apply custom identity mapping rules
if (idpChannel.getIdentityMapper() != null) {
IdentityMapper im = idpChannel.getIdentityMapper();
federatedSubject = im.map(idpSubject, localAccountSubject);
logger.debug("IDP Subject [" + idpSubject + "] mapped to Subject [" + federatedSubject + "] " +
"through Account Link [" + acctLink.getId() + "]" );
}
// ---------------------------------------------------
// Create SP Security context and session!
// ---------------------------------------------------
SPSecurityContext spSecurityCtx = createSPSecurityContext(exchange,
ssoRequest.getReplyTo(),
idp,
(IdPChannel) idpChannel,
acctLink,
federatedSubject,
idpSubject);
// ---------------------------------------------------
// Send SPAuthnResponse
// ---------------------------------------------------
EndpointDescriptor destination = null;
// TODO : Use plan samlr2resposne to spauthnresponse
SPAuthnResponseType ssoResponse = new SPAuthnResponseType();
ssoResponse.setID(authnResponse.getID());
ssoResponse.setIssuer(getProvider().getName());
if (ssoRequest != null) {
ssoResponse.setInReplayTo(ssoRequest.getID());
if (ssoRequest.getReplyTo() != null) {
destination = new EndpointDescriptorImpl("EmbeddedSPAcs",
"AssertionConsumerService",
SSOBinding.SSO_ARTIFACT.getValue(),
ssoRequest.getReplyTo(), null);
}
}
ssoResponse.setSubject(toSubjectType(spSecurityCtx.getSubject()));
ssoResponse.setSessionIndex(spSecurityCtx.getSessionIndex());
CamelMediationMessage out = (CamelMediationMessage) exchange.getOut();
out.setMessage(new MediationMessageImpl(ssoResponse.getID(),
ssoResponse, "SPAuthnResposne", null, destination, in.getMessage().getState()));
exchange.setOut(out);
}
}
protected CircleOfTrustMemberDescriptor resolveIdp(CamelMediationExchange exchange) throws SSOException {
CamelMediationMessage in = (CamelMediationMessage) exchange.getIn();
AssertIdentityWithSimpleAuthenticationRequestType ssoAuthnReq =
(AssertIdentityWithSimpleAuthenticationRequestType) in.getMessage().getContent();
// TODO : The way to resolve the IDP may vary from deployment to deployment, user intervention may be required
String idpAlias = null;
CircleOfTrustMemberDescriptor idp = null;
// --------------------------------------------------------------
// Try with the received IdP alias, if any
// --------------------------------------------------------------
for (int i = 0; i < ssoAuthnReq.getRequestAttribute().size(); i++) {
RequestAttributeType a = ssoAuthnReq.getRequestAttribute().get(i);
// TODO : [ENTITY-SEL] CHECK BASE 64 ENCODING AND ENTITY SELECTOR USAGE!
if (a.getName().equals(EntitySelectorConstants.REQUESTED_IDP_ALIAS_ATTR))
idpAlias = new String(Base64.decodeBase64(a.getValue().getBytes()));
}
if (idpAlias != null) {
if (logger.isDebugEnabled())
logger.debug("Using IdP alias from request attribute " + idpAlias);
idp = getCotManager().lookupMemberByAlias(idpAlias);
if (idp == null) {
throw new SSOException("No IDP found in circle of trust for received alias [" + idpAlias + "], verify your setup.");
}
}
if (idp != null)
return idp;
// --------------------------------------------------------------
// Try with the preferred idp alias, if any
// --------------------------------------------------------------
SSOSPMediator mediator = (SSOSPMediator) channel.getIdentityMediator();
idpAlias = mediator.getPreferredIdpAlias();
if (idpAlias != null) {
if (logger.isDebugEnabled())
logger.debug("Using preferred IdP alias " + idpAlias);
idp = getCotManager().lookupMemberByAlias(idpAlias);
if (idp == null) {
throw new SSOException("No IDP found in circle of trust for preferred alias [" + idpAlias + "], verify your setup.");
}
}
if (idp != null)
return idp;
// --------------------------------------------------------------
// TODO : In the future, we could discover IdPs from COT Manager, based on COT Member role and user intervention
throw new SSOException("Cannot resolve IDP, try to configure a preferred IdP for this SP");
}
protected EndpointType resolveIdpSsoEndpoint(CircleOfTrustMemberDescriptor idp) throws SSOException {
SSOSPMediator mediator = (SSOSPMediator) channel.getIdentityMediator();
MetadataEntry idpMd = idp.getMetadata();
if (idpMd == null || idpMd.getEntry() == null)
throw new SSOException("No metadata descriptor found for IDP " + idp);
if (idpMd.getEntry() instanceof EntityDescriptorType) {
EntityDescriptorType md = (EntityDescriptorType) idpMd.getEntry();
for (RoleDescriptorType role : md.getRoleDescriptorOrIDPSSODescriptorOrSPSSODescriptor()) {
if (role instanceof IDPSSODescriptorType) {
IDPSSODescriptorType idpSsoRole = (IDPSSODescriptorType) role;
EndpointType defaultEndpoint = null;
for (EndpointType idpSsoEndpoint : idpSsoRole.getSingleSignOnService()) {
SSOBinding b = SSOBinding.asEnum(idpSsoEndpoint.getBinding());
if (b.equals(SSOBinding.SAMLR2_SOAP))
defaultEndpoint = idpSsoEndpoint;
}
return defaultEndpoint;
}
}
} else {
throw new SSOException("Unknown metadata descriptor type " + idpMd.getEntry().getClass().getName());
}
logger.debug("No IDP Endpoint supporting binding : " + SSOBinding.SAMLR2_SOAP);
throw new SSOException("IDP does not support preferred binding " + SSOBinding.SAMLR2_SOAP);
}
protected FederationChannel resolveIdpChannel(CircleOfTrustMemberDescriptor idpDescriptor) {
// Resolve IdP channel, then look for the ACS endpoint
BindingChannel bChannel = (BindingChannel) channel;
FederatedLocalProvider sp = bChannel.getFederatedProvider();
FederationChannel idpChannel = sp.getChannel();
for (FederationChannel fChannel : sp.getChannels()) {
FederatedProvider idp = fChannel.getTargetProvider();
for (CircleOfTrustMemberDescriptor member : idp.getMembers()) {
if (member.getAlias().equals(idpDescriptor.getAlias())) {
if (logger.isDebugEnabled())
logger.debug("Selected IdP channel " + fChannel.getName() + " for provider " + idp.getName());
idpChannel = fChannel;
break;
}
}
}
return idpChannel;
}
protected SecTokenAuthnRequestType buildSamlSecTokenAuthnRequetRequest(CamelMediationExchange exchange,
CircleOfTrustMemberDescriptor idp,
EndpointDescriptor ed,
FederationChannel idpChannel) throws SSOException, IdentityPlanningException {
IdentityPlan identityPlan = findIdentityPlanOfType(AssertIdentityWithSimpleAuthenticationReqToSamlR2AuthnReqPlan.class);
IdentityPlanExecutionExchange idPlanExchange = createIdentityPlanExecutionExchange();
// Publish IdP Metadata
idPlanExchange.setProperty(VAR_DESTINATION_COT_MEMBER, idp);
idPlanExchange.setProperty(VAR_DESTINATION_ENDPOINT_DESCRIPTOR, ed);
idPlanExchange.setProperty(VAR_COT_MEMBER, idpChannel.getMember());
idPlanExchange.setProperty(VAR_RESPONSE_CHANNEL, idpChannel);
// Get SPInitiated authn request, if any!
AssertIdentityWithSimpleAuthenticationRequestType assertIdentityWithSimpleAuthReq =
(AssertIdentityWithSimpleAuthenticationRequestType) ((CamelMediationMessage) exchange.getIn()).getMessage().getContent();
// Create in/out artifacts
IdentityArtifact in =
new IdentityArtifactImpl(new QName("urn:org:atricore:idbus:sso:protocol",
"AssertIdentityWithSimpleAuthenticationRequest"), assertIdentityWithSimpleAuthReq);
idPlanExchange.setIn(in);
IdentityArtifact<SecTokenAuthnRequestType> out =
new IdentityArtifactImpl<SecTokenAuthnRequestType>(new QName(SAMLR2Constants.SAML_IDBUS_NS, "SecTokenAuthnRequest"),
new SecTokenAuthnRequestType());
idPlanExchange.setOut(out);
// Prepare execution
identityPlan.prepare(idPlanExchange);
// Perform execution
identityPlan.perform(idPlanExchange);
if (!idPlanExchange.getStatus().equals(IdentityPlanExecutionStatus.SUCCESS)) {
throw new SecurityTokenEmissionException("Identity plan returned : " + idPlanExchange.getStatus());
}
if (idPlanExchange.getOut() == null)
throw new SecurityTokenEmissionException("Plan Exchange OUT must not be null!");
return (SecTokenAuthnRequestType) idPlanExchange.getOut().getContent();
}
/**
* TODO : Duplicated with ACS !
* @param exchange
* @param requester
* @param idp
* @param acctLink
* @param federatedSubject
* @param idpSubject
* @return
* @throws org.atricore.idbus.capabilities.sso.main.SSOException
*/
protected SPSecurityContext createSPSecurityContext(CamelMediationExchange exchange,
String requester,
CircleOfTrustMemberDescriptor idp,
IdPChannel idpChannel,
AccountLink acctLink,
Subject federatedSubject,
Subject idpSubject)
throws SSOException {
if (logger.isDebugEnabled())
logger.debug("Creating new SP Security Context for subject " + federatedSubject);
SSOSessionManager ssoSessionManager = idpChannel.getSessionManager();
CamelMediationMessage in = (CamelMediationMessage) exchange.getIn();
// Get Subject ID (username ?)
SubjectNameID nameId = null;
Set<SubjectNameID> nameIds = federatedSubject.getPrincipals(SubjectNameID.class);
if (nameIds != null) {
for (SubjectNameID i : nameIds) {
if (i.getFormat() == null) {
nameId = i;
break;
}
}
}
if (nameId == null) {
logger.error("No suitable Subject Name Identifier (SubjectNameID) found");
throw new SSOException("No suitable Subject Name Identifier (SubjectNameID) found");
}
// Create a new Security Context
SPSecurityContext secCtx = new SPSecurityContext();
secCtx.setIdpAlias(idp.getAlias());
secCtx.setSubject(federatedSubject);
secCtx.setAccountLink(acctLink);
secCtx.setRequester(requester);
secCtx.setAuthnCtxClass(AuthnCtxClass.PASSWORD_AUTHN_CTX);
SecurityToken<SPSecurityContext> token = new SecurityTokenImpl<SPSecurityContext>(uuidGenerator.generateId(), secCtx);
try {
// Create new SSO Session
String ssoSessionId = ssoSessionManager.initiateSession(nameId.getName(), token);
// Update security context with SSO Session nameId
secCtx.setSessionIndex(ssoSessionId);
// TODO : Use IDP Session information Subject's attributes and update local session: expiration time, etc.
Set<SubjectAuthenticationAttribute> attrs = idpSubject.getPrincipals(SubjectAuthenticationAttribute.class);
String idpSsoSessionId = null;
for (SubjectAuthenticationAttribute attr : attrs) {
// Session index
if (attr.getName().equals(SubjectAuthenticationAttribute.Name.SESSION_INDEX.name())) {
idpSsoSessionId = attr.getValue();
break;
}
}
// SubjectAuthenticationAttribute.Name.SESSION_NOT_ON_OR_AFTER
if (logger.isDebugEnabled())
logger.debug("Created SP security context " + secCtx);
in.getMessage().getState().setLocalVariable(getProvider().getName().toUpperCase() + "_SECURITY_CTX", secCtx);
in.getMessage().getState().getLocalState().addAlternativeId("ssoSessionId", secCtx.getSessionIndex());
in.getMessage().getState().getLocalState().addAlternativeId("idpSsoSessionId", idpSsoSessionId);
return secCtx;
} catch (SSOSessionException e) {
throw new SSOException(e);
}
}
/**
* TODO ! Duplicated with ACS !!!!
* @param response
* @return
*/
private Subject buildSubjectFromResponse(ResponseType response) {
Subject outSubject = new Subject();
if (response.getAssertionOrEncryptedAssertion().size() > 0) {
AssertionType assertion = null;
if (response.getAssertionOrEncryptedAssertion().get(0) instanceof AssertionType) {
assertion = (AssertionType) response.getAssertionOrEncryptedAssertion().get(0);
} else {
throw new RuntimeException("Response should be already decripted!");
}
// store subject identification information
if (assertion.getSubject() != null) {
List subjectContentItems = assertion.getSubject().getContent();
for (Object o: subjectContentItems) {
JAXBElement subjectContent = (JAXBElement) o;
if (subjectContent.getValue() instanceof NameIDType) {
NameIDType nameId = (NameIDType) subjectContent.getValue();
// Create Subject ID Attribute
if (logger.isDebugEnabled()) {
logger.debug("Adding NameID to IDP Subject {"+nameId.getSPNameQualifier()+"}" + nameId.getValue() + ":" + nameId.getFormat());
}
outSubject.getPrincipals().add(
new SubjectNameID(nameId.getValue(),
nameId.getFormat(),
nameId.getNameQualifier(),
nameId.getSPNameQualifier()));
} else if (subjectContent.getValue() instanceof BaseIDAbstractType) {
// TODO : Can we do something with this ?
throw new IllegalArgumentException("Unsupported Subject BaseID type "+ subjectContent.getValue() .getClass().getName());
} else if (subjectContent.getValue() instanceof EncryptedType) {
throw new IllegalArgumentException("Response should be already decripted!");
} else if (subjectContent.getValue() instanceof SubjectConfirmationType) {
// TODO : Store subject confirmation data ?
} else {
logger.error("Unknown subject content type : " + subjectContent.getClass().getName());
}
}
}
// store subject user attributes
List<StatementAbstractType> stmts = assertion.getStatementOrAuthnStatementOrAuthzDecisionStatement();
if (logger.isDebugEnabled())
logger.debug("Found " + stmts.size() + " statements") ;
for (StatementAbstractType stmt : stmts) {
if (logger.isDebugEnabled())
logger.debug("Processing statement " + stmts) ;
if (stmt instanceof AttributeStatementType) {
AttributeStatementType attrStmt = (AttributeStatementType) stmt;
List attrs = attrStmt.getAttributeOrEncryptedAttribute();
if (logger.isDebugEnabled())
logger.debug("Found " + attrs.size() + " attributes in attribute statement") ;
for (Object attrOrEncAttr : attrs) {
if (attrOrEncAttr instanceof AttributeType) {
AttributeType attr = (AttributeType) attrOrEncAttr;
List<Object> attributeValues = attr.getAttributeValue();
if (logger.isDebugEnabled())
logger.debug("Processing attribute " + attr.getName()) ;
for (Object attributeValue : attributeValues) {
if (logger.isDebugEnabled())
logger.debug("Processing attribute value " + attributeValue) ;
if (attributeValue instanceof String ) {
if (logger.isDebugEnabled()) {
logger.debug("Adding Attribute Statement to IDP Subject " +
attr.getName() + ":" +
attr.getNameFormat() + "=" +
attr.getAttributeValue()) ;
}
outSubject.getPrincipals().add(
new SubjectAttribute(
attr.getName(),
(String) attributeValue
)
);
} else if (attributeValue instanceof Element) {
Element e = (Element) attributeValue;
if (logger.isDebugEnabled()) {
logger.debug("Adding Attribute Statement to IDP Subject from DOM Element " +
attr.getName() + ":" +
attr.getNameFormat() + "=" +
e.getTextContent()) ;
}
outSubject.getPrincipals().add(
new SubjectAttribute(
attr.getName(),
e.getTextContent()
)
);
} else {
logger.error("Unknown Attribute Value type " + attributeValue.getClass().getName());
}
}
} else {
// TODO : Decrypt attribute using IDP's encryption key
logger.debug("Unknown attribute type " + attrOrEncAttr);
}
}
}
// store subject authentication attributes
if (stmt instanceof AuthnStatementType) {
AuthnStatementType authnStmt = (AuthnStatementType) stmt;
if (authnStmt.getAuthnContext() != null) {
List<JAXBElement<?>> authnContextItems = authnStmt.getAuthnContext().getContent();
for (JAXBElement<?> authnContext : authnContextItems) {
if (logger.isDebugEnabled()) {
logger.debug("Adding Authentiation Context to IDP Subject " +
authnContext.getValue() + ":" +
SubjectAuthenticationAttribute.Name.AUTHENTICATION_CONTEXT) ;
}
outSubject.getPrincipals().add(
new SubjectAuthenticationAttribute(
SubjectAuthenticationAttribute.Name.AUTHENTICATION_CONTEXT,
(String) authnContext.getValue()
)
);
}
}
if (authnStmt.getAuthnInstant() != null) {
if (logger.isDebugEnabled()) {
logger.debug("Adding Authentiation Attribute to IDP Subject " +
authnStmt.getAuthnInstant().toString() + ":" +
SubjectAuthenticationAttribute.Name.AUTHENTICATION_INSTANT) ;
}
outSubject.getPrincipals().add(
new SubjectAuthenticationAttribute(
SubjectAuthenticationAttribute.Name.AUTHENTICATION_INSTANT,
authnStmt.getAuthnInstant().toString()
)
);
}
if (authnStmt.getSessionIndex() != null) {
if (logger.isDebugEnabled()) {
logger.debug("Adding Authentiation Attribute to IDP Subject " +
authnStmt.getSessionIndex() + ":" +
SubjectAuthenticationAttribute.Name.SESSION_INDEX) ;
}
outSubject.getPrincipals().add(
new SubjectAuthenticationAttribute(
SubjectAuthenticationAttribute.Name.SESSION_INDEX,
authnStmt.getSessionIndex()
)
);
}
if (authnStmt.getSessionNotOnOrAfter() != null) {
if (logger.isDebugEnabled()) {
logger.debug("Adding Authentiation Attribute to IDP Subject " +
authnStmt.getSessionNotOnOrAfter().toString() + ":" +
SubjectAuthenticationAttribute.Name.SESSION_NOT_ON_OR_AFTER) ;
}
outSubject.getPrincipals().add(
new SubjectAuthenticationAttribute(
SubjectAuthenticationAttribute.Name.SESSION_NOT_ON_OR_AFTER,
authnStmt.getSessionNotOnOrAfter().toString()
)
);
}
if (authnStmt.getSubjectLocality() != null && authnStmt.getSubjectLocality().getAddress() != null) {
if (logger.isDebugEnabled()) {
logger.debug("Adding Authentiation Attribute to IDP Subject " +
authnStmt.getSubjectLocality().getAddress() + ":" +
SubjectAuthenticationAttribute.Name.SUBJECT_LOCALITY_ADDRESS) ;
}
outSubject.getPrincipals().add(
new SubjectAuthenticationAttribute(
SubjectAuthenticationAttribute.Name.SUBJECT_LOCALITY_ADDRESS,
authnStmt.getSubjectLocality().getAddress()
)
);
}
if (authnStmt.getSubjectLocality() != null && authnStmt.getSubjectLocality().getDNSName() != null) {
if (logger.isDebugEnabled()) {
logger.debug("Adding Authentiation Attribute to IDP Subject " +
authnStmt.getSubjectLocality().getDNSName() + ":" +
SubjectAuthenticationAttribute.Name.SUBJECT_LOCALITY_DNSNAME) ;
}
outSubject.getPrincipals().add(
new SubjectAuthenticationAttribute(
SubjectAuthenticationAttribute.Name.SUBJECT_LOCALITY_DNSNAME,
authnStmt.getSubjectLocality().getDNSName()
)
);
}
}
// Store subject authorization attributes
if (stmt instanceof AuthzDecisionStatementType) {
AuthzDecisionStatementType authzStmt = (AuthzDecisionStatementType) stmt;
for (ActionType action : authzStmt.getAction()) {
if (action.getNamespace() != null) {
if (logger.isDebugEnabled()) {
logger.debug("Adding Authz Decision Action NS to IDP Subject " +
action.getNamespace() + ":" +
SubjectAuthorizationAttribute.Name.ACTION_NAMESPACE) ;
}
outSubject.getPrincipals().add(
new SubjectAuthorizationAttribute(
SubjectAuthorizationAttribute.Name.ACTION_NAMESPACE,
action.getNamespace()
)
);
}
if (action.getValue() != null) {
if (logger.isDebugEnabled()) {
logger.debug("Adding Authz Decision Action Value to IDP Subject " +
action.getValue() + ":" +
SubjectAuthorizationAttribute.Name.ACTION_VALUE) ;
}
outSubject.getPrincipals().add(
new SubjectAuthorizationAttribute(
SubjectAuthorizationAttribute.Name.ACTION_VALUE,
action.getValue()
)
);
}
}
if (authzStmt.getDecision() != null) {
if (logger.isDebugEnabled()) {
logger.debug("Adding Authz Decision Action to IDP Subject " +
authzStmt.getDecision().value() + ":" +
SubjectAuthorizationAttribute.Name.DECISION) ;
}
outSubject.getPrincipals().add(
new SubjectAuthorizationAttribute(
SubjectAuthorizationAttribute.Name.DECISION,
authzStmt.getDecision().value()
)
);
}
if (authzStmt.getResource() != null) {
if (logger.isDebugEnabled()) {
logger.debug("Adding Authz Decision Action to IDP Subject " +
authzStmt.getResource() + ":" +
SubjectAuthorizationAttribute.Name.RESOURCE) ;
}
outSubject.getPrincipals().add(
new SubjectAuthorizationAttribute(
SubjectAuthorizationAttribute.Name.RESOURCE,
authzStmt.getResource()
)
);
}
// TODO: store evidence
}
}
} else {
logger.warn("No Assertion present within Response [" + response.getID() + "]");
}
if (outSubject != null && logger.isDebugEnabled()) {
logger.debug("IDP Subject:" + outSubject) ;
}
return outSubject;
}
}