blob: edf2f585ddb93544a32de1e5000b9a9c603f2e0d [file] [log] [blame]
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" lang="en"><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/><link rel="stylesheet" href="../.resources/report.css" type="text/css"/><link rel="shortcut icon" href="../.resources/report.gif" type="image/gif"/><title>SAMLTokenValidator.java</title><link rel="stylesheet" href="../.resources/prettify.css" type="text/css"/><script type="text/javascript" src="../.resources/prettify.js"></script></head><body onload="window['PR_TAB_WIDTH']=4;prettyPrint()"><div class="breadcrumb" id="breadcrumb"><span class="right"><a href="../.sessions.html" class="el_session">Sessions</a></span><a href="../index.html" class="el_report">Coverage Report</a> &gt; <a href="index.html" class="el_package">org.apache.rahas.impl</a> &gt; <span class="el_source">SAMLTokenValidator.java</span></div><h1>SAMLTokenValidator.java</h1><pre class="source lang-java linenums">package org.apache.rahas.impl;
import java.security.PublicKey;
import java.security.cert.X509Certificate;
import javax.xml.namespace.QName;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.soap.SOAPEnvelope;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.description.Parameter;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.rahas.RahasConstants;
import org.apache.rahas.RahasData;
import org.apache.rahas.Token;
import org.apache.rahas.TokenStorage;
import org.apache.rahas.TokenValidator;
import org.apache.rahas.TrustException;
import org.apache.rahas.TrustUtil;
import org.apache.rahas.impl.util.CommonUtil;
import org.apache.rahas.impl.util.SAMLUtils;
import org.apache.ws.security.components.crypto.Crypto;
import org.apache.ws.security.components.crypto.CryptoFactory;
import org.opensaml.saml1.core.Assertion;
import org.opensaml.xml.signature.SignatureValidator;
import org.opensaml.xml.validation.ValidationException;
import org.w3c.dom.Element;
/**
* Implementation of a SAML Token Validator for the Security Token Service.
*/
@SuppressWarnings({&quot;UnusedDeclaration&quot;})
<span class="nc" id="L34">public class SAMLTokenValidator implements TokenValidator {</span>
<span class="nc" id="L36"> Log log = LogFactory.getLog(SAMLTokenValidator.class);</span>
private String configFile;
private OMElement configElement;
private String configParamName;
/**
* Returns a SOAPEnvelope with the result of the validation.
*
* @param data
* the RahasData object, containing information about the
* request.
*/
public SOAPEnvelope validate(RahasData data) throws TrustException {
// retrieve the message context
<span class="nc" id="L51"> MessageContext inMsgCtx = data.getInMessageContext();</span>
// retrieve the list of tokens from the message context
<span class="nc" id="L54"> TokenStorage tkStorage = TrustUtil.getTokenStore(inMsgCtx);</span>
// Create envelope
<span class="nc" id="L57"> SOAPEnvelope env = TrustUtil.createSOAPEnvelope(inMsgCtx</span>
.getEnvelope().getNamespace().getNamespaceURI());
// Create RSTR element, with respective version
OMElement rstrElem;
<span class="nc" id="L62"> int wstVersion = data.getVersion();</span>
<span class="nc bnc" id="L63" title="All 2 branches missed."> if (RahasConstants.VERSION_05_02 == wstVersion) {</span>
<span class="nc" id="L64"> rstrElem = TrustUtil.createRequestSecurityTokenResponseElement(</span>
wstVersion, env.getBody());
} else {
<span class="nc" id="L67"> OMElement rstrcElem = TrustUtil</span>
.createRequestSecurityTokenResponseCollectionElement(
wstVersion, env.getBody());
<span class="nc" id="L70"> rstrElem = TrustUtil.createRequestSecurityTokenResponseElement(</span>
wstVersion, rstrcElem);
}
// Create TokenType element, set to RSTR/Status
<span class="nc" id="L75"> TrustUtil.createTokenTypeElement(wstVersion, rstrElem).setText(</span>
TrustUtil.getWSTNamespace(wstVersion)
+ RahasConstants.TOK_TYPE_STATUS);
// Create Status element
<span class="nc" id="L80"> OMElement statusElement = createMessageElement(wstVersion,</span>
rstrElem, RahasConstants.LocalNames.STATUS);
// Obtain the token
<span class="nc" id="L84"> Token tk = tkStorage.getToken(data.getTokenId());</span>
// create the crypto object
<span class="nc" id="L87"> PublicKey issuerPBKey = getIssuerPublicKey(inMsgCtx);</span>
<span class="nc" id="L89"> boolean valid = isValid(tk, issuerPBKey);</span>
String validityCode;
<span class="nc bnc" id="L92" title="All 2 branches missed."> if (valid) {</span>
<span class="nc" id="L93"> validityCode = RahasConstants.STATUS_CODE_VALID;</span>
} else {
<span class="nc" id="L95"> validityCode = RahasConstants.STATUS_CODE_INVALID;</span>
}
// Create Code element (inside Status) and set it to the
// correspondent value
<span class="nc" id="L100"> createMessageElement(wstVersion, statusElement,</span>
RahasConstants.LocalNames.CODE).setText(
TrustUtil.getWSTNamespace(wstVersion) + validityCode);
<span class="nc" id="L104"> return env;</span>
}
/**
* Checks whether the token is valid or not, by verifying the issuer's own
* signature. If it has been signed by the token issuer, then it is a valid
* token.
*
* @param token
* the token to validate.
* @param issuerPBKey Public key which should be used during validation.
* @return true if the token has been signed by the issuer.
*/
private boolean isValid(Token token, PublicKey issuerPBKey) {
// extract SAMLAssertion object from token
<span class="nc" id="L119"> OMElement assertionOMElement = token.getToken();</span>
Assertion samlAssertion;
try {
<span class="nc" id="L123"> samlAssertion = SAMLUtils.buildAssertion((Element) assertionOMElement);</span>
<span class="nc" id="L125"> log.info(&quot;Verifying token validity...&quot;);</span>
// check if the token has been signed by the issuer.
<span class="nc" id="L128"> SignatureValidator validator = new SignatureValidator(samlAssertion.getSignature().getSigningCredential());</span>
<span class="nc" id="L129"> validator.validate(samlAssertion.getSignature());</span>
<span class="nc" id="L131"> } catch (ValidationException e) {</span>
<span class="nc" id="L132"> log.error(&quot;Signature verification failed on SAML token.&quot;, e);</span>
<span class="nc" id="L133"> return false;</span>
<span class="nc" id="L134"> }</span>
// if there was no exception, then the token is valid
<span class="nc" id="L137"> return true;</span>
}
//here we basically reuse the SAMLTokenIssuer config
// to create the crypto object, so we can load the issuer's certificates
private PublicKey getIssuerPublicKey(MessageContext inMsgCtx) {
<span class="nc" id="L143"> PublicKey issuerPBKey = null;</span>
<span class="nc" id="L144"> SAMLTokenIssuerConfig config = null;</span>
try {
<span class="nc bnc" id="L147" title="All 2 branches missed."> if (configElement != null) {</span>
<span class="nc" id="L148"> config = new SAMLTokenIssuerConfig(</span>
configElement
.getFirstChildWithName(SAMLTokenIssuerConfig.SAML_ISSUER_CONFIG));
}
// Look for the file
<span class="nc bnc" id="L154" title="All 4 branches missed."> if ((config == null) &amp;&amp; (configFile != null)) {</span>
<span class="nc" id="L155"> config = new SAMLTokenIssuerConfig(configFile);</span>
}
// Look for the param
<span class="nc bnc" id="L159" title="All 4 branches missed."> if ((config == null) &amp;&amp; (configParamName != null)) {</span>
<span class="nc" id="L160"> Parameter param = inMsgCtx.getParameter(configParamName);</span>
<span class="nc bnc" id="L161" title="All 4 branches missed."> if ((param != null) &amp;&amp; (param.getParameterElement() != null)) {</span>
<span class="nc" id="L162"> config = new SAMLTokenIssuerConfig(param</span>
.getParameterElement().getFirstChildWithName(
SAMLTokenIssuerConfig.SAML_ISSUER_CONFIG));
} else {
<span class="nc" id="L166"> throw new TrustException(&quot;expectedParameterMissing&quot;,</span>
new String[] { configParamName });
}
}
<span class="nc bnc" id="L171" title="All 2 branches missed."> if (config == null) {</span>
<span class="nc" id="L172"> throw new TrustException(&quot;configurationIsNull&quot;);</span>
}
Crypto crypto;
<span class="nc bnc" id="L176" title="All 2 branches missed."> if (config.cryptoElement != null) { // crypto props</span>
// defined as
// elements
<span class="nc" id="L179"> crypto = CryptoFactory.getInstance(TrustUtil</span>
.toProperties(config.cryptoElement), inMsgCtx
.getAxisService().getClassLoader());
} else { // crypto props defined in a properties file
<span class="nc" id="L183"> crypto = CryptoFactory.getInstance(config.cryptoPropertiesFile,</span>
inMsgCtx.getAxisService().getClassLoader());
}
<span class="nc" id="L187"> X509Certificate issuerCert = CommonUtil.getCertificateByAlias(crypto,config.getIssuerKeyAlias());</span>
<span class="nc" id="L189"> issuerPBKey = issuerCert.getPublicKey();</span>
<span class="nc" id="L191"> } catch (Exception e) {</span>
<span class="nc" id="L192"> log.error(&quot;Could not retrieve issuer public key&quot;, e);</span>
<span class="nc" id="L193"> }</span>
<span class="nc" id="L194"> return issuerPBKey;</span>
}
private static OMElement createMessageElement(int version,
OMElement parent, String elementName) throws TrustException {
<span class="nc" id="L200"> return createOMElement(parent, TrustUtil.getWSTNamespace(version),</span>
elementName, RahasConstants.WST_PREFIX);
}
private static OMElement createOMElement(OMElement parent, String ns,
String ln, String prefix) {
<span class="nc" id="L206"> return parent.getOMFactory().createOMElement(new QName(ns, ln, prefix),</span>
parent);
}
// ========================================================================
/**
* Set the configuration file of this TokenValidator. &lt;p/&gt; This is the text
* value of the &amp;lt;configuration-file&amp;gt; element of the
* token-dispatcher-configuration
*
* @param configFile configuration file to be used.
*/
public void setConfigurationFile(String configFile) {
<span class="nc" id="L220"> this.configFile = configFile;</span>
<span class="nc" id="L221"> }</span>
/**
* Set the name of the configuration parameter. &lt;p/&gt; If this is used then
* there must be a &lt;code&gt;org.apache.axis2.description.Parameter&lt;/code&gt;
* object available in the via the messageContext when the
* &lt;code&gt;TokenValidator&lt;/code&gt; is called.
*
* @param configParamName Parameter name.
* @see org.apache.axis2.description.Parameter
*/
public void setConfigurationParamName(String configParamName) {
<span class="nc" id="L233"> this.configParamName = configParamName;</span>
<span class="nc" id="L234"> }</span>
public void setConfigurationElement(OMElement configElement) {
<span class="nc" id="L237"> this.configElement = configElement;</span>
<span class="nc" id="L238"> }</span>
}
</pre><div class="footer"><span class="right">Created with <a href="http://www.eclemma.org/jacoco">JaCoCo</a> 0.6.1.201212231917</span></div></body></html>