/*
* Atricore IDBus
*
* Copyright (c) 2009, Atricore Inc.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.atricore.idbus.capabilities.sso.main.claims.producers;
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.claims.SSOClaimsMediator;
import org.atricore.idbus.capabilities.sso.main.claims.SSOCredentialClaimsRequest;
import org.atricore.idbus.capabilities.sso.main.claims.SSOCredentialClaimsResponse;
import org.atricore.idbus.capabilities.sso.main.common.plans.SSOPlanningConstants;
import org.atricore.idbus.capabilities.sso.main.common.producers.SSOProducer;
import org.atricore.idbus.capabilities.sso.support.SAMLR2Constants;
import org.atricore.idbus.capabilities.sso.support.SAMLR2MessagingConstants;
import org.atricore.idbus.capabilities.sso.support.auth.AuthnCtxClass;
import org.atricore.idbus.capabilities.sso.support.binding.SSOBinding;
import org.atricore.idbus.kernel.main.authn.Constants;
import org.atricore.idbus.kernel.main.federation.metadata.EndpointDescriptor;
import org.atricore.idbus.kernel.main.federation.metadata.EndpointDescriptorImpl;
import org.atricore.idbus.kernel.main.mediation.Channel;
import org.atricore.idbus.kernel.main.mediation.MediationMessageImpl;
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.claim.*;
import org.atricore.idbus.kernel.main.mediation.endpoint.IdentityMediationEndpoint;
import org.oasis_open.docs.wss._2004._01.oasis_200401_wss_wssecurity_secext_1_0.AttributedString;
import org.oasis_open.docs.wss._2004._01.oasis_200401_wss_wssecurity_secext_1_0.UsernameTokenType;
import javax.xml.namespace.QName;
import java.io.IOException;
/**
* @author <a href="mailto:sgonzalez@atricore.org">Sebastian Gonzalez Oyuela</a>
* @version $Id$
*/
public class UsernamePasswordClaimsProducer extends SSOProducer
implements SAMLR2Constants, SAMLR2MessagingConstants, SSOPlanningConstants {
private static final Log logger = LogFactory.getLog( UsernamePasswordClaimsProducer.class );
public UsernamePasswordClaimsProducer( AbstractCamelEndpoint<CamelMediationExchange> endpoint ) throws Exception {
super( endpoint );
}
@Override
protected void doProcess ( CamelMediationExchange exchange) throws Exception {
if (logger.isDebugEnabled())
logger.debug("Collecting Password claims");
CamelMediationMessage in = (CamelMediationMessage) exchange.getIn();
// -------------------------------------------------------------------------
// Collect claims
// -------------------------------------------------------------------------
if (logger.isDebugEnabled())
logger.debug("Starting to collect password claims");
SSOCredentialClaimsRequest claimsRequest = (SSOCredentialClaimsRequest) in.getMessage().getContent();
if (logger.isDebugEnabled())
logger.debug("Storing claims request as local variable, id:" + claimsRequest.getId());
in.getMessage().getState().setLocalVariable("urn:org:atricore:idbus:credential-claims-request", claimsRequest);
doProcessClaimsRequest(exchange, claimsRequest);
}
@Override
protected void doProcessResponse(CamelMediationExchange exchange) throws Exception {
// -------------------------------------------------------------------------
// Process collected claims
// -------------------------------------------------------------------------
if (logger.isDebugEnabled())
logger.debug("Received username/password claims");
CamelMediationMessage in = (CamelMediationMessage) exchange.getIn();
CredentialClaimsResponse credentialClaimsResponse = (CredentialClaimsResponse) in.getMessage().getContent();
CredentialClaimsRequest credentialClaimsRequest = (CredentialClaimsRequest) in.getMessage().getState().getLocalVariable("urn:org:atricore:idbus:credential-claims-request");
if (credentialClaimsRequest == null)
throw new IllegalStateException("Claims request not found!");
if (logger.isDebugEnabled())
logger.debug("Recovered claims request from local variable, id:" + credentialClaimsRequest.getId());
doProcessReceivedClaims(exchange, credentialClaimsRequest, credentialClaimsResponse.getClaimSet());
}
protected void doProcessClaimsRequest(CamelMediationExchange exchange, CredentialClaimsRequest credentialClaimsRequest) throws IOException {
SSOClaimsMediator mediator = (SSOClaimsMediator)channel.getIdentityMediator();
CamelMediationMessage in = (CamelMediationMessage) exchange.getIn();
EndpointDescriptor ed = new EndpointDescriptorImpl(
"BasicAuthnLoginForm",
"BasicAuthnLoginForm",
SSOBinding.SSO_ARTIFACT.getValue(),
mediator.getBasicAuthnUILocation(),
null);
CamelMediationMessage out = (CamelMediationMessage) exchange.getOut();
out.setMessage(
new MediationMessageImpl(credentialClaimsRequest.getId(),
credentialClaimsRequest,
"ClaimsRequest",
null,
ed,
in.getMessage().getState())
);
exchange.setOut(out);
}
protected void doProcessReceivedClaims(CamelMediationExchange exchange,
CredentialClaimsRequest credentialClaimsRequest,
ClaimSet receivedClaims) throws Exception {
CamelMediationMessage in = (CamelMediationMessage) exchange.getIn();
SSOClaimsMediator mediator = ((SSOClaimsMediator) channel.getIdentityMediator());
// This is the binding we're using to send the response
SSOBinding binding = SSOBinding.SSO_ARTIFACT;
Channel issuer = credentialClaimsRequest.getIssuerChannel();
IdentityMediationEndpoint claimsProcessingEndpoint = null;
// Look for an endpoint to send the response
for (IdentityMediationEndpoint endpoint : issuer.getEndpoints()) {
if (endpoint.getType().equals(credentialClaimsRequest.getIssuerEndpoint().getType()) &&
endpoint.getBinding().equals(binding.getValue())) {
claimsProcessingEndpoint = endpoint;
break;
}
}
if (claimsProcessingEndpoint == null) {
throw new SSOException("No endpoint supporting " + binding + " of type " +
credentialClaimsRequest.getIssuerEndpoint().getType() + " found in channel " + credentialClaimsRequest.getIssuerChannel().getName());
}
EndpointDescriptor ed = mediator.resolveEndpoint(credentialClaimsRequest.getIssuerChannel(),
claimsProcessingEndpoint);
String password = null;
String username = null;
boolean rememberMe = false;
// Addapt received simple claims to SAMLR Required token
for (Claim c : receivedClaims.getClaims()) {
if (c instanceof CredentialClaim) {
CredentialClaim credentialClaim = (CredentialClaim) c;
if (credentialClaim.getQualifier().equalsIgnoreCase("username"))
username = (String) c.getValue();
if (credentialClaim.getQualifier().equalsIgnoreCase("password"))
password = (String) c.getValue();
} else if (c instanceof UserClaim) {
UserClaim userClaim = (UserClaim) c;
if (userClaim.getName().equalsIgnoreCase("rememberMe"))
rememberMe = (Boolean) userClaim.getValue();
}
}
AuthnCtxClass authnCtxClass = null;
if (mediator.getBasicAuthnCtxClass() != null) {
if (logger.isDebugEnabled())
logger.debug("Using configured Basic Authentication Context class: " + mediator.getBasicAuthnCtxClass());
authnCtxClass = AuthnCtxClass.asEnum(mediator.getBasicAuthnCtxClass());
} else {
if (logger.isDebugEnabled())
logger.debug("Using default Basic Authentication Context class: " + AuthnCtxClass.PASSWORD_AUTHN_CTX);
authnCtxClass = AuthnCtxClass.PASSWORD_AUTHN_CTX;
}
// Build a SAMLR2 Compatible Security token
UsernameTokenType usernameToken = new UsernameTokenType ();
AttributedString usernameString = new AttributedString();
usernameString.setValue( username );
usernameToken.setUsername( usernameString );
usernameToken.getOtherAttributes().put(new QName(Constants.PASSWORD_NS), password );
usernameToken.getOtherAttributes().put(new QName(authnCtxClass.getValue()), "TRUE");
usernameToken.getOtherAttributes().put(new QName(Constants.REMEMBERME_NS), rememberMe ? "TRUE" : "FALSE");
CredentialClaim credentialClaim = new CredentialClaimImpl(authnCtxClass.getValue(), usernameToken);
ClaimSet claims = new ClaimSetImpl();
claims.addClaim(credentialClaim);
SSOCredentialClaimsResponse claimsResponse = new SSOCredentialClaimsResponse(credentialClaimsRequest.getId() /* TODO : Generate new ID !*/,
channel, credentialClaimsRequest.getId(), claims, credentialClaimsRequest.getRelayState());
CamelMediationMessage out = (CamelMediationMessage) exchange.getOut();
out.setMessage(new MediationMessageImpl(claimsResponse.getId(),
claimsResponse,
"ClaimsResponse",
null,
ed,
in.getMessage().getState()));
exchange.setOut(out);
}
}