cxf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From conflue...@apache.org
Subject [CONF] Apache CXF Documentation > JAX-RS SAML
Date Thu, 03 Nov 2011 17:30:00 GMT
<html>
<head>
    <base href="https://cwiki.apache.org/confluence">
            <link rel="stylesheet" href="/confluence/s/2042/9/1/_/styles/combined.css?spaceKey=CXF20DOC&amp;forWysiwyg=true"
type="text/css">
    </head>
<body style="background: white;" bgcolor="white" class="email-body">
<div id="pageContent">
<div id="notificationFormat">
<div class="wiki-content">
<div class="email">
    <h2><a href="https://cwiki.apache.org/confluence/display/CXF20DOC/JAX-RS+SAML">JAX-RS
SAML</a></h2>
    <h4>Page <b>edited</b> by             <a href="https://cwiki.apache.org/confluence/display/~sergey_beryozkin">Sergey
Beryozkin</a>
    </h4>
        <br/>
                         <h4>Changes (4)</h4>
                                 
    
<div id="page-diffs">
                    <table class="diff" cellpadding="0" cellspacing="0">
    
            <tr><td class="diff-snipped" >...<br></td></tr>
            <tr><td class="diff-unchanged" >All of the SAML output interceptors
depend on a &quot;ws-security.saml-callback-handler&quot; property linking to a custom
javax.security.auth.callback.Callback implementation which in its handle(Callbacks) method
provides the information which is needed to create a SAML assertion to a org.apache.ws.security.saml.ext.SAMLCallback
Callback instance, for example, see this [custom implementation|http://svn.apache.org/repos/asf/cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/saml/SamlCallbackHandler.java].
<br> <br></td></tr>
            <tr><td class="diff-changed-lines" >More involved cases with SAML
assertions being created by identity providers will be supported, <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">possibly</span>
with the help of CXF <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">STSClient.</span>
<span class="diff-added-words"style="background-color: #dfd;">(WS) STSClient when needed.</span>
<br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">
<br>h1. SAML Assertion Validation <br></td></tr>
            <tr><td class="diff-unchanged" > <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">When
SAML assertions are received on the server side, they are validated to make sure that the
enveloped signatures are correct. SubjectConfirmation methods (sender-vouches, holder-of-key,
bearer) are also checked.  <br>The validation can be delegated to STS if needed. By
default, server side SAML handlers have a &quot;samlValidator&quot; property set to
an instance of org.apache.ws.security.validate.SamlAssertionValidator which does a thorough
validation of the assertion. If needed org.apache.cxf.ws.security.trust.STSSamlAssertionValidator
can be set instead which will use STS to validate the assertion. <br>Custom validators
extending WSS4J SamlAssertionValidator and doing the additional application-specific validation
can be registered if needed. <br></td></tr>
            <tr><td class="diff-unchanged" > <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">Note
the fact that the default validation relies a lot on the code heavily utilized by the WS-Security
implementation should be of no concern - it is an example of the integration on its own in
order to get the validation done. For example, WS-* STS are heavily used in the enterprise
today and it simply makes a complete sense to rely on it to validate a SAML assertion if it
is possible. <br> <br>SubjectConfirmation sender-vouches and holder-of-key methods
can be easily validated with enveloped SAML assertions given that the embedded SAML signatures
and key info can be checked against the signature used to sign the envelope or a custom payload
like Book. <br> <br>At the moment these methods can not be properly validated
when the assertion is provided in a header or in the form, the additional signature signing
the encoded SAML token will be needed - this will be supported in due time. Use &quot;bearer&quot;
in those cases. <br> <br></td></tr>
            <tr><td class="diff-unchanged" >h1. SAML Authorization <br></td></tr>
    
            </table>
    </div>                            <h4>Full Content</h4>
                    <div class="notificationGreySide">
        <p><span style="font-size:2em;font-weight:bold"> JAX-RS: SAML </span></p>


<div>
<ul>
    <li><a href='#JAX-RSSAML-Introduction'>Introduction</a></li>
    <li><a href='#JAX-RSSAML-Mavendependencies'>Maven dependencies</a></li>
    <li><a href='#JAX-RSSAML-EnvelopedSAMLassertions'>Enveloped SAML assertions</a></li>
    <li><a href='#JAX-RSSAML-SAMLassertionsinAuthorizationheader'>SAML assertions
in Authorization header</a></li>
    <li><a href='#JAX-RSSAML-SAMLassertionsasFormvalues'>SAML assertions as Form
values</a></li>
    <li><a href='#JAX-RSSAML-CreatingSAMLAssertions'>Creating SAML Assertions</a></li>
    <li><a href='#JAX-RSSAML-SAMLAssertionValidation'>SAML Assertion Validation</a></li>
    <li><a href='#JAX-RSSAML-SAMLAuthorization'>SAML Authorization</a></li>
</ul></div>

<h1><a name="JAX-RSSAML-Introduction"></a>Introduction</h1>

<p>CXF 2.5.0 introduces an initial support for working with <a href="http://en.wikipedia.org/wiki/SAML_2.0"
class="external-link" rel="nofollow">SAML2</a> assertions. So far the main focus
has been put on making sure SAML assertions can be included in HTTP requests targeted at application
endpoints: embedded inside XML payloads or passed as encoded HTTP header or form values. Support
for advanced SAML features such as Web Browser SSO Profile will be coming in due time.</p>

<h1><a name="JAX-RSSAML-Mavendependencies"></a>Maven dependencies</h1>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-xml">
<span class="code-tag">&lt;dependency&gt;</span>
  <span class="code-tag">&lt;groupId&gt;</span>org.apache.cxf<span
class="code-tag">&lt;/groupId&gt;</span>
  <span class="code-tag">&lt;artifactId&gt;</span>cxf-rt-rs-security-xml<span
class="code-tag">&lt;/artifactId&gt;</span>
  <span class="code-tag">&lt;version&gt;</span>2.5.0<span class="code-tag">&lt;/version&gt;</span>
<span class="code-tag">&lt;/dependency&gt;</span>
</pre>
</div></div>

<p>This module depends on CXF WS-Security and Apache WSS4J modules, due to them containing
a lot of useful utility code.<br/>
We will see in time if it will make sense to exclude such dependencies or not. </p>

<h1><a name="JAX-RSSAML-EnvelopedSAMLassertions"></a>Enveloped SAML assertions</h1>

<p>Payload:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-xml">
<span class="code-tag">&lt;env:Envelope <span class="code-keyword">xmlns:env</span>=<span
class="code-quote">"http://org.apache.cxf/rs/env"</span>&gt;</span>

<span class="code-tag">&lt;Book ID=<span class="code-quote">"67ca6441-0c4e-4430-af0e-9463ce9226aa"</span>&gt;</span>
  <span class="code-tag">&lt;id&gt;</span>125<span class="code-tag">&lt;/id&gt;</span>
  <span class="code-tag">&lt;name&gt;</span>CXF<span class="code-tag">&lt;/name&gt;</span>
<span class="code-tag">&lt;/Book&gt;</span>
<span class="code-tag">&lt;ds:Signature <span class="code-keyword">xmlns:ds</span>=<span
class="code-quote">"http://www.w3.org/2000/09/xmldsig#"</span>&gt;</span>
  <span class="code-tag"><span class="code-comment">&lt;!-- Book signature,
omitted for brewity --&gt;</span></span>
<span class="code-tag">&lt;/ds:Signature&gt;</span>

<span class="code-tag"><span class="code-comment">&lt;!-- SAML assertion with
an enveloped signature --&gt;</span></span> 
<span class="code-tag">&lt;saml2:Assertion <span class="code-keyword">xmlns:saml2</span>=<span
class="code-quote">"urn:oasis:names:tc:SAML:2.0:assertion"</span> <span class="code-keyword">xmlns:xs</span>=<span
class="code-quote">"http://www.w3.org/2001/XMLSchema"</span> <span class="code-keyword">xmlns:xsi</span>=<span
class="code-quote">"http://www.w3.org/2001/XMLSchema-instance"</span> ID=<span
class="code-quote">"_62D574706635C0B9F413203247720501"</span> IssueInstant=<span
class="code-quote">"2011-11-03T12:52:52.050Z"</span> Version=<span class="code-quote">"2.0"</span>
xsi:type=<span class="code-quote">"saml2:AssertionType"</span>&gt;</span>

<span class="code-tag">&lt;saml2:Issuer&gt;</span>https://idp.example.org/SAML2<span
class="code-tag">&lt;/saml2:Issuer&gt;</span>

<span class="code-tag">&lt;ds:Signature <span class="code-keyword">xmlns:ds</span>=<span
class="code-quote">"http://www.w3.org/2000/09/xmldsig#"</span>&gt;</span>
   <span class="code-tag">&lt;ds:SignedInfo&gt;</span>
    <span class="code-tag">&lt;ds:CanonicalizationMethod Algorithm=<span class="code-quote">"http://www.w3.org/2001/10/xml-exc-c14n#"</span>/&gt;</span>
    <span class="code-tag">&lt;ds:SignatureMethod Algorithm=<span class="code-quote">"http://www.w3.org/2000/09/xmldsig#rsa-sha1"</span>/&gt;</span>
    <span class="code-tag">&lt;ds:Reference URI=<span class="code-quote">"#_62D574706635C0B9F413203247720501"</span>&gt;</span>
      <span class="code-tag">&lt;ds:Transforms&gt;</span>
       <span class="code-tag">&lt;ds:Transform Algorithm=<span class="code-quote">"http://www.w3.org/2000/09/xmldsig#enveloped-signature"</span>/&gt;</span>
       <span class="code-tag">&lt;ds:Transform Algorithm=<span class="code-quote">"http://www.w3.org/2001/10/xml-exc-c14n#"</span>&gt;</span>
         <span class="code-tag">&lt;ec:InclusiveNamespaces <span class="code-keyword">xmlns:ec</span>=<span
class="code-quote">"http://www.w3.org/2001/10/xml-exc-c14n#"</span> PrefixList=<span
class="code-quote">"xs"</span>/&gt;</span>
       <span class="code-tag">&lt;/ds:Transform&gt;</span>
      <span class="code-tag">&lt;/ds:Transforms&gt;</span>
      <span class="code-tag">&lt;ds:DigestMethod Algorithm=<span class="code-quote">"http://www.w3.org/2000/09/xmldsig#sha1"</span>/&gt;</span>
      <span class="code-tag">&lt;ds:DigestValue&gt;</span>IDD9nFocVm/7FpUbiGI3ZvpY2ps=<span
class="code-tag">&lt;/ds:DigestValue&gt;</span>
    <span class="code-tag">&lt;/ds:Reference&gt;</span>
   <span class="code-tag">&lt;/ds:SignedInfo&gt;</span>
   <span class="code-tag">&lt;ds:SignatureValue&gt;</span>JA2I7u/SmNsXGgWNdrLSovkipiM3JmGHsmpoP0EeIOwPwnLMx0WvV0C3xNGNiT1jOBe2uv8+WchtPoppGTC2JTJVX/t8PmKQCYZo4kVJo6Nmsjbn5kp7ejWuOYynvrUheQeTLU8e5CQmuS6L4VYaMVV2ETtb0VvpKjoQKHOC+co=<span
class="code-tag">&lt;/ds:SignatureValue&gt;</span>
   <span class="code-tag">&lt;ds:KeyInfo&gt;</span>
    <span class="code-tag">&lt;ds:X509Data&gt;</span>
     <span class="code-tag">&lt;ds:X509Certificate&gt;</span><span
class="code-tag"><span class="code-comment">&lt;!-- Omitted for brewity --&gt;</span></span>
<span class="code-tag">&lt;/ds:X509Certificate&gt;</span>
    <span class="code-tag">&lt;/ds:X509Data&gt;</span>
   <span class="code-tag">&lt;/ds:KeyInfo&gt;</span>
 <span class="code-tag">&lt;/ds:Signature&gt;</span>

 <span class="code-tag">&lt;saml2:Subject&gt;</span>
   <span class="code-tag">&lt;saml2:NameID Format=<span class="code-quote">"urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"</span>
NameQualifier=<span class="code-quote">"www.mock-sts.com"</span>&gt;</span>uid=sts-client,o=mock-sts.com<span
class="code-tag">&lt;/saml2:NameID&gt;</span>
   <span class="code-tag">&lt;saml2:SubjectConfirmation Method=<span class="code-quote">"urn:oasis:names:tc:SAML:2.0:cm:sender-vouches"</span>/&gt;</span>
 <span class="code-tag">&lt;/saml2:Subject&gt;</span>

 <span class="code-tag">&lt;saml2:Conditions NotBefore=<span class="code-quote">"2011-11-03T12:52:52.063Z"</span>
NotOnOrAfter=<span class="code-quote">"2011-11-03T12:52:52.063Z"</span>&gt;</span>
  <span class="code-tag">&lt;saml2:AudienceRestriction&gt;</span>
   <span class="code-tag">&lt;saml2:Audience&gt;</span>https://sp.example.com/SAML2<span
class="code-tag">&lt;/saml2:Audience&gt;</span>
  <span class="code-tag">&lt;/saml2:AudienceRestriction&gt;</span>
 <span class="code-tag">&lt;/saml2:Conditions&gt;</span>
 <span class="code-tag">&lt;saml2:AuthnStatement AuthnInstant=<span class="code-quote">"2011-11-03T12:52:51.981Z"</span>
SessionIndex=<span class="code-quote">"123456"</span>&gt;</span>
    <span class="code-tag">&lt;saml2:AuthnContext&gt;</span><span class="code-tag">&lt;saml2:AuthnContextClassRef/&gt;</span><span
class="code-tag">&lt;/saml2:AuthnContext&gt;</span>
 <span class="code-tag">&lt;/saml2:AuthnStatement&gt;</span>

 <span class="code-tag">&lt;saml2:AttributeStatement&gt;</span>
    &lt;saml2:Attribute FriendlyName=<span class="code-quote">"subject-role"</span>

                     Name=<span class="code-quote">"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/role"</span>

                     NameFormat=<span class="code-quote">"http://schemas.xmlsoap.org/ws/2005/05/identity/claims"</span>&gt;
       <span class="code-tag">&lt;saml2:AttributeValue xsi:type=<span class="code-quote">"xs:string"</span>&gt;</span>user<span
class="code-tag">&lt;/saml2:AttributeValue&gt;</span>
    <span class="code-tag">&lt;/saml2:Attribute&gt;</span>
    &lt;saml2:Attribute Name=<span class="code-quote">"http://claims/authentication"</span>

                     NameFormat=<span class="code-quote">"http://claims/authentication-format"</span>&gt;
       <span class="code-tag">&lt;saml2:AttributeValue xsi:type=<span class="code-quote">"xs:string"</span>&gt;</span>password<span
class="code-tag">&lt;/saml2:AttributeValue&gt;</span>
    <span class="code-tag">&lt;/saml2:Attribute&gt;</span>
 <span class="code-tag">&lt;/saml2:AttributeStatement&gt;</span>
<span class="code-tag">&lt;/saml2:Assertion&gt;</span>
<span class="code-tag">&lt;/env:Envelope&gt;</span>
</pre>
</div></div>

<p>Note that Book and SAML assertion are individually signed but the envelope wrapper
itself is not.</p>


<p>Here is another payload showing the whole enveloped signed including Book and SAML
Assertion, this time only a single signature will be available:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-xml">
<span class="code-tag">&lt;env:Envelope <span class="code-keyword">xmlns:env</span>=<span
class="code-quote">"http://org.apache.cxf/rs/env"</span> ID=<span class="code-quote">"e795cdd1-c19d-4a5c-8d86-e8a781af4787"</span>&gt;</span>

<span class="code-tag">&lt;saml2:Assertion <span class="code-keyword">xmlns:saml2</span>=<span
class="code-quote">"urn:oasis:names:tc:SAML:2.0:assertion"</span> <span class="code-keyword">xmlns:xsi</span>=<span
class="code-quote">"http://www.w3.org/2001/XMLSchema-instance"</span> ID=<span
class="code-quote">"_C76E3D5BBEE4C4D87913203281641141"</span> IssueInstant=<span
class="code-quote">"2011-11-03T13:49:24.114Z"</span> Version=<span class="code-quote">"2.0"</span>
xsi:type=<span class="code-quote">"saml2:AssertionType"</span>&gt;</span>
<span class="code-tag">&lt;saml2:Issuer&gt;</span>https://idp.example.org/SAML2<span
class="code-tag">&lt;/saml2:Issuer&gt;</span>
<span class="code-tag">&lt;saml2:Subject&gt;</span>
<span class="code-tag">&lt;saml2:NameID Format=<span class="code-quote">"urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"</span>
NameQualifier=<span class="code-quote">"www.mock-sts.com"</span>&gt;</span>uid=sts-client,o=mock-sts.com<span
class="code-tag">&lt;/saml2:NameID&gt;</span>
<span class="code-tag">&lt;saml2:SubjectConfirmation Method=<span class="code-quote">"urn:oasis:names:tc:SAML:2.0:cm:sender-vouches"</span>/&gt;</span>
<span class="code-tag">&lt;/saml2:Subject&gt;</span>
<span class="code-tag">&lt;saml2:Conditions NotBefore=<span class="code-quote">"2011-11-03T13:49:24.127Z"</span>
NotOnOrAfter=<span class="code-quote">"2011-11-03T13:49:24.127Z"</span>&gt;</span>
<span class="code-tag">&lt;saml2:AudienceRestriction&gt;</span>
<span class="code-tag">&lt;saml2:Audience&gt;</span>https://sp.example.com/SAML2<span
class="code-tag">&lt;/saml2:Audience&gt;</span>
<span class="code-tag">&lt;/saml2:AudienceRestriction&gt;</span>
<span class="code-tag">&lt;/saml2:Conditions&gt;</span>
<span class="code-tag">&lt;saml2:AuthnStatement AuthnInstant=<span class="code-quote">"2011-11-03T13:49:24.044Z"</span>
SessionIndex=<span class="code-quote">"123456"</span>&gt;</span>
<span class="code-tag">&lt;saml2:AuthnContext&gt;</span>
<span class="code-tag">&lt;saml2:AuthnContextClassRef/&gt;</span>
<span class="code-tag">&lt;/saml2:AuthnContext&gt;</span>
<span class="code-tag">&lt;/saml2:AuthnStatement&gt;</span>
<span class="code-tag">&lt;saml2:AttributeStatement&gt;</span>
<span class="code-tag">&lt;saml2:Attribute FriendlyName=<span class="code-quote">"subject-role"</span>
Name=<span class="code-quote">"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/role"</span>
NameFormat=<span class="code-quote">"http://schemas.xmlsoap.org/ws/2005/05/identity/claims"</span>&gt;</span>
<span class="code-tag">&lt;saml2:AttributeValue <span class="code-keyword">xmlns:xs</span>=<span
class="code-quote">"http://www.w3.org/2001/XMLSchema"</span> xsi:type=<span class="code-quote">"xs:string"</span>&gt;</span>user<span
class="code-tag">&lt;/saml2:AttributeValue&gt;</span>
<span class="code-tag">&lt;/saml2:Attribute&gt;</span>
<span class="code-tag">&lt;saml2:Attribute Name=<span class="code-quote">"http://claims/authentication"</span>
NameFormat=<span class="code-quote">"http://claims/authentication-format"</span>&gt;</span>
<span class="code-tag">&lt;saml2:AttributeValue <span class="code-keyword">xmlns:xs</span>=<span
class="code-quote">"http://www.w3.org/2001/XMLSchema"</span> xsi:type=<span class="code-quote">"xs:string"</span>&gt;</span>password<span
class="code-tag">&lt;/saml2:AttributeValue&gt;</span>
<span class="code-tag">&lt;/saml2:Attribute&gt;</span>
<span class="code-tag">&lt;/saml2:AttributeStatement&gt;</span>
<span class="code-tag">&lt;/saml2:Assertion&gt;</span>

<span class="code-tag">&lt;Book&gt;</span>
<span class="code-tag">&lt;id&gt;</span>125<span class="code-tag">&lt;/id&gt;</span>
<span class="code-tag">&lt;name&gt;</span>CXF<span class="code-tag">&lt;/name&gt;</span>
<span class="code-tag">&lt;/Book&gt;</span>

<span class="code-tag">&lt;ds:Signature <span class="code-keyword">xmlns:ds</span>=<span
class="code-quote">"http://www.w3.org/2000/09/xmldsig#"</span>&gt;</span><span
class="code-tag">&lt;ds:SignedInfo&gt;</span><span class="code-tag">&lt;ds:CanonicalizationMethod
Algorithm=<span class="code-quote">"http://www.w3.org/TR/2001/REC-xml-c14n-20010315"</span>/&gt;</span><span
class="code-tag">&lt;ds:SignatureMethod Algorithm=<span class="code-quote">"http://www.w3.org/2000/09/xmldsig#rsa-sha1"</span>/&gt;</span><span
class="code-tag">&lt;ds:Reference URI=<span class="code-quote">"#e795cdd1-c19d-4a5c-8d86-e8a781af4787"</span>&gt;</span><span
class="code-tag">&lt;ds:Transforms&gt;</span><span class="code-tag">&lt;ds:Transform
Algorithm=<span class="code-quote">"http://www.w3.org/2000/09/xmldsig#enveloped-signature"</span>/&gt;</span><span
class="code-tag">&lt;ds:Transform Algorithm=<span class="code-quote">"http://www.w3.org/2001/10/xml-exc-c14n#"</span>/&gt;</span><span
class="code-tag">&lt;/ds:Transforms&gt;</span><span class="code-tag">&lt;ds:DigestMethod
Algorithm=<span class="code-quote">"http://www.w3.org/2000/09/xmldsig#sha1"</span>/&gt;</span><span
class="code-tag">&lt;ds:DigestValue&gt;</span>GR1pHd2JpxYiCzl6ouCmTZjq/AA=<span
class="code-tag">&lt;/ds:DigestValue&gt;</span><span class="code-tag">&lt;/ds:Reference&gt;</span><span
class="code-tag">&lt;/ds:SignedInfo&gt;</span><span class="code-tag">&lt;ds:SignatureValue&gt;</span>C2qUDOFwart2GHFjX6kB3E3z73AMXtRR/6Qjgyp6XP/vTn/Fr2epDNub3q+gNdT0KgjLE2rSynM3QTcpHov9C8l9a8VQquItaalr0XA7BJcxdFMxB7KEATKR9XtrmIEkiw9efM8M83iVux/ufCOWrt0Te2RLz+nRwzyEY49VQOQ=<span
class="code-tag">&lt;/ds:SignatureValue&gt;</span><span class="code-tag">&lt;ds:KeyInfo&gt;</span><span
class="code-tag">&lt;ds:X509Data&gt;</span><span class="code-tag">&lt;ds:X509Certificate&gt;</span><span
class="code-tag"><span class="code-comment">&lt;!-- Omitted for brewity --&gt;</span></span><span
class="code-tag">&lt;/ds:X509Certificate&gt;</span><span class="code-tag">&lt;/ds:X509Data&gt;</span><span
class="code-tag">&lt;ds:KeyValue&gt;</span><span class="code-tag">&lt;ds:RSAKeyValue&gt;</span><span
class="code-tag">&lt;ds:Modulus&gt;</span>vu747/VShQ85f16DGSc4Ixh9PVpGguyEqrCsK8q9XHOYX9l9/g5wEC6ZcR2FwfNsoaHcKNPjd5sSTzVtBWmQjfBEfIqwTR7vuihOxyNTwEzVwIJzvo7p8/aYxk+VdBtQxq4UweIcf/iFkUbM1cZ1oiXRQzciRBi+C1BQCQE0qzs=<span
class="code-tag">&lt;/ds:Modulus&gt;</span><span class="code-tag">&lt;ds:Exponent&gt;</span>AQAB<span
class="code-tag">&lt;/ds:Exponent&gt;</span><span class="code-tag">&lt;/ds:RSAKeyValue&gt;</span><span
class="code-tag">&lt;/ds:KeyValue&gt;</span><span class="code-tag">&lt;/ds:KeyInfo&gt;</span><span
class="code-tag">&lt;/ds:Signature&gt;</span><span class="code-tag">&lt;/env:Envelope&gt;</span>
</pre>
</div></div>

<p>Server configuration fragment:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-xml">
    <span class="code-tag">&lt;bean id=<span class="code-quote">"serviceBean"</span>
class=<span class="code-quote">"org.apache.cxf.systest.jaxrs.security.BookStore"</span>/&gt;</span>
    <span class="code-tag">&lt;bean id=<span class="code-quote">"samlHandler"</span>
class=<span class="code-quote">"org.apache.cxf.rs.security.saml.SamlEnvelopedInHandler"</span>/&gt;</span>
    
    <span class="code-tag"><span class="code-comment">&lt;!-- only needed
if the detached signature signing the application data is expected --&gt;</span></span>

    <span class="code-tag">&lt;bean id=<span class="code-quote">"xmlSigHandler"</span>
class=<span class="code-quote">"org.apache.cxf.rs.security.xml.XmlSigInHandler"</span>/&gt;</span>
    
    
    &lt;jaxrs:server 
       address=<span class="code-quote">"https://localhost:${testutil.ports.jaxrs-saml}/samlxml"</span>&gt;

       <span class="code-tag">&lt;jaxrs:serviceBeans&gt;</span>
          <span class="code-tag">&lt;ref bean=<span class="code-quote">"serviceBean"</span>/&gt;</span>
       <span class="code-tag">&lt;/jaxrs:serviceBeans&gt;</span>
       <span class="code-tag">&lt;jaxrs:providers&gt;</span>
          <span class="code-tag">&lt;ref bean=<span class="code-quote">"xmlSigHandler"</span>/&gt;</span>
          <span class="code-tag">&lt;ref bean=<span class="code-quote">"samlHandler"</span>/&gt;</span>
       <span class="code-tag">&lt;/jaxrs:providers&gt;</span>
       
       <span class="code-tag">&lt;jaxrs:properties&gt;</span>
           &lt;entry key=<span class="code-quote">"ws-security.signature.properties"</span>

                  value=<span class="code-quote">"org/apache/cxf/systest/jaxrs/security/alice.properties"</span>/&gt;
       <span class="code-tag">&lt;/jaxrs:properties&gt;</span>
        
    <span class="code-tag">&lt;/jaxrs:server&gt;</span>
</pre>
</div></div>

<p>Client code:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
<span class="code-keyword">private</span> WebClient createWebClient(<span class="code-object">String</span>
address, 
                                  <span class="code-object">boolean</span> selfSigned)
{
  JAXRSClientFactoryBean bean = <span class="code-keyword">new</span> JAXRSClientFactoryBean();
  bean.setAddress(address);
  
  Map&lt;<span class="code-object">String</span>, <span class="code-object">Object</span>&gt;
properties = <span class="code-keyword">new</span> HashMap&lt;<span class="code-object">String</span>,
<span class="code-object">Object</span>&gt;();
  properties.put(<span class="code-quote">"ws-security.callback-handler"</span>,

                <span class="code-quote">"org.apache.cxf.systest.jaxrs.security.saml.KeystorePasswordCallback"</span>);
  properties.put(<span class="code-quote">"ws-security.saml-callback-handler"</span>,

                 <span class="code-quote">"org.apache.cxf.systest.jaxrs.security.saml.SamlCallbackHandler"</span>);
  properties.put(<span class="code-quote">"ws-security.signature.username"</span>,
<span class="code-quote">"alice"</span>);
  properties.put(<span class="code-quote">"ws-security.signature.properties"</span>,

                 <span class="code-quote">"org/apache/cxf/systest/jaxrs/security/alice.properties"</span>);
  <span class="code-keyword">if</span> (selfSigned) {
     properties.put(<span class="code-quote">"ws-security.self-sign-saml-assertion"</span>,
<span class="code-quote">"<span class="code-keyword">true</span>"</span>);
  }
  bean.setProperties(properties);
        
  bean.getOutInterceptors().add(<span class="code-keyword">new</span> SamlEnvelopedOutInterceptor(!selfSigned));
  XmlSigOutInterceptor xmlSig = <span class="code-keyword">new</span> XmlSigOutInterceptor();
  <span class="code-keyword">if</span> (selfSigned) {
      xmlSig.setStyle(XmlSigOutInterceptor.DETACHED_SIG);
  }
  <span class="code-keyword">return</span> bean.createWebClient();
}
</pre>
</div></div>

<p>In the above code, the "ws-security.self-sign-saml-assertion" property, if set to
true, will require SamlEnvelopedOutInterceptor to get a SAML assertion self-signed, by adding
an enveloped signature to it. When we also need to sign the application payload such as Book
we need to make sure that a detached XML signature for Book is created. When the whole envelope
is signed then SamlEnvelopedOutInterceptor needs to be placed before XmlSigOutInterceptor
hence the "new SamlEnvelopedOutInterceptor(!selfSigned)" constructor is invoked.</p>

<h1><a name="JAX-RSSAML-SAMLassertionsinAuthorizationheader"></a>SAML assertions
in Authorization header</h1>

<p>Logging output:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
Address: https:<span class="code-comment">//localhost:9000/samlheader/bookstore/books/123
</span>Http-Method: GET
Headers: {Accept=[application/xml], Authorization=[SAML eJydV1mTokgQfu9fYTCPrs2htGKMHVEcKq2gKOLxsoFQAsqhFAjNr99CW1ud7t2ZjdAwMisr68s7/YnMwGfaACEYJ14UVmSxQ/z9wjUlBrRYiWZZiWVYlqPrDFVnmhTbwL80UZERSqEcosQMkw7BUDRdwx+qrtP1dp1qs41nLLciKgaMEVaLRZ4popIHfojapyc7RBqH7chEHmqHZgBRO7HaU6AM21iybV7wXO7kqEO4SbJvk2SWZc9Z/TmKHZKhKJpcKMOp5cLA/JT1/lu45p3AWxDfQl47ed/DDvHgDB0zidefZ+7J4vi11IuwYs/eP8PcDPY+PGkvoTM/yTvZnzZqTz0nNJM0hh/g7O8MoUiKI7GMjTznB3G9C2053EQnUjDDKPQs0/cKs4SnwMSN7ArwnSj2Ejf41miaKhXXYG7VLLoR/iDIe2i/qegOYYzMGnJN+kPXBG5gDLE7K7OJ3CF+/HcKna7psRmiTRQH6J78MywwPEI/2kO7hi4mfcD6fYVfeOn1J7Tacmj5KfKOUC2TdG9aEFXGMdx4+dBDOPVzdEk7aP1RAMhbeA/k2Rui50CU/J/g3ATmrMQw/RS+Lod0s8c74oavDxsCSoueGs8H4zUQlp0TgFvhE+Ma1jP5kJDXBDrfABTXCxR7+UJ5clXM0XjN8LG9MQxG57bTMfB9rUkaXUNKJgsRzKl+f8R2q0qr/sLB+Ub3oGEPhrIMJTegkBOM+0E4nbCLjVXYXO6MHXYhDLMWtGjKtRtNGtirfrioTvXhhnM2zalRXdXDlVVPg2Oe0Sp4Ge/eWgdRiXQwOiZWtZEfjtSwm1aH46xzNecGf2nSAL5fzVuwFCeaiXklhLItbHAFJvBVkWWhtxUEsBw5IJN54MjS1Jg4QAcq7+wO7s7rcRnFA23WBSIolImSSdpSNDRtIGV71+p1t2Zvlq7rb+GTomWZ4JwOh1Km+uvAysUtUHhHNXig6PxcbawC1VX4xkLUrUwRpUzRAf7F326EeUoD8/KRDoonRdcylY4ypZB0hZd6gJ5JgqsMlgveXTKuPwy491UhKQqIzme5Iq7mbKhojUwEJxBYveGue/72aaULfFg8miR1ARjxWw1kznKHgUvgmDYbOLhTV2uxG/pF7E2thpy73NjY95z0XTrEAnoatA7coj9aLjifIx02k4SXlTVhutlGRZHZtwbqeGuzaKoXRsLPA2274aWNfMj0SfOYeu4of1f1TCqMTH4rno5Rc98izWW+qxo2n2j5oTHLoGxtSK+7m60V2lrRkbeYaIXlTXivKtC8JmgSdSiQADIJAFNpKuIuk3FQnowJNeX5KOvJ8lzfcbMFtRrPfE6b7TjJmKmz6YwbLWhDn+hgVgalP5EkUQdDx/HRmlGxr9yjVdcyUVu+PQ2ilYxJtfQTrwGx9I87zHZBtbVHg6ThhGtv1ysMSnf203nPmufzAQZYtBKZCV/cLmCP9Nbo981Gj3ty64gKc43RYVbACblrOoFjMEhutOqqEy/7gR4MB6bIzwuT2YN0lYqu1m/1gOS+mbtuMuDH1aokcLGq7ldP4eHQz/P6Yc0kc4Y9TBK+EIMBx9COw42VKFCsZnqYaOfqeMz4K/NcE+RttdxV02ViTtP1FlrJhSwbqCxWuri/mcn3459+pk8cz65tTqLtNER7aGEY0CYqpRYtxTMQk3GHKJtgEFm7GkrQsxUFxGvq2R1M1Czfg2HyV9S5Pb4M6DOWB6BCFG688sVyDzq33X/fUqygjWBow7h2jFK8VaBTX<span
class="code-comment">//SeKzb9krFqKJGCQ+xafCbvYl+wXsTFhqFoxhsktLKb+Uu6kFqe2WbnuD2HXtW+dDj0XVzQZ+LC/bI/eJyFX5k3CkmH236fCtxw2mCsyXAvq+cyH9dEvFOgI2dQlQuiTJ2Zd4haKbeYF+IO534qQTmyVc8wcfLIp5T5A3m2xvkV9CuihJs1TpN4PcnlW6MPWD772XO4BXxHNdaHPnwnI3XgYxOiyV6xlMYt7P9aTJnqBzOLIk/no3Ve8k7afmmFyDyU8OlJP6XHuIXxKdpdrPV5njlxkehg4sDb7ZXj9zJv/7C/tUTd9Z+WGFiv5Z4LPO8rn9hz5eSH8X9R+j3ONJZFNu/b8Ej59cwY1CFiLtLmYCfmXvhdIgyKXENBh7ubfCmvq9/El7/AXoseyE=],
...}</span>
</pre>
</div></div>

<p>Note that the Authorization header has an encoded SAML Assertion as its value. The
original SAML assertion has been optionally compressed using a deflated encoding and then
base64-encoded. This encoded value can be signed itself - but it is not currently possible.</p>

<p>Server configuration is similar to the one from the Enveloped SAML Assertions section,
the only difference is that a SAML handler needs to be replaced:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-xml">
    <span class="code-tag">&lt;bean id=<span class="code-quote">"serviceBean"</span>
class=<span class="code-quote">"org.apache.cxf.systest.jaxrs.security.BookStore"</span>/&gt;</span>
    <span class="code-tag">&lt;bean id=<span class="code-quote">"samlHandler"</span>
class=<span class="code-quote">"org.apache.cxf.rs.security.saml.SamlHeaderInHandler"</span>/&gt;</span>
    
    <span class="code-tag"><span class="code-comment">&lt;!-- same as in the
Enveloped SAML Assertions section --&gt;</span></span> 
</pre>
</div></div>

<p>Client code:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
<span class="code-keyword">private</span> WebClient createWebClient(<span class="code-object">String</span>
address, 
                                  <span class="code-object">boolean</span> selfSigned)
{
  JAXRSClientFactoryBean bean = <span class="code-keyword">new</span> JAXRSClientFactoryBean();
  bean.setAddress(address);
  
  Map&lt;<span class="code-object">String</span>, <span class="code-object">Object</span>&gt;
properties = <span class="code-keyword">new</span> HashMap&lt;<span class="code-object">String</span>,
<span class="code-object">Object</span>&gt;();
  properties.put(<span class="code-quote">"ws-security.callback-handler"</span>,

                <span class="code-quote">"org.apache.cxf.systest.jaxrs.security.saml.KeystorePasswordCallback"</span>);
  properties.put(<span class="code-quote">"ws-security.saml-callback-handler"</span>,

                 <span class="code-quote">"org.apache.cxf.systest.jaxrs.security.saml.SamlCallbackHandler"</span>);
  properties.put(<span class="code-quote">"ws-security.signature.username"</span>,
<span class="code-quote">"alice"</span>);
  properties.put(<span class="code-quote">"ws-security.signature.properties"</span>,

                 <span class="code-quote">"org/apache/cxf/systest/jaxrs/security/alice.properties"</span>);
  <span class="code-keyword">if</span> (selfSigned) {
     properties.put(<span class="code-quote">"ws-security.self-sign-saml-assertion"</span>,
<span class="code-quote">"<span class="code-keyword">true</span>"</span>);
  }
  bean.setProperties(properties);
        
  bean.getOutInterceptors().add(<span class="code-keyword">new</span> SamlHeaderOutInterceptor());
  
  <span class="code-keyword">return</span> bean.createWebClient();
}
</pre>
</div></div>


<h1><a name="JAX-RSSAML-SAMLassertionsasFormvalues"></a>SAML assertions
as Form values</h1>

<p>Logging output:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
Address: https:<span class="code-comment">//localhost:9000/samlform/bookstore/books
</span>Encoding: ISO-8859-1
Http-Method: POST
Content-Type: application/x-www-form-urlencoded
Headers: {Accept=[application/xml], Cache-Control=[no-cache], connection=[keep-alive], Content-Length=[2206],
content-type=[application/x-www-form-urlencoded], Host=[localhost:9000], Pragma=[no-cache],
User-Agent=[Apache CXF ${project.version}]}
Payload: name=CXF&amp;id=125&amp;SAMLToken=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
</pre>
</div></div>

<p>Note that only form 'name' and 'id' fields will remain after the SAML handler processes
a SAML assertion encoded in the SAMLToken form field. The original SAML assertion has been
optionally compressed using a deflated encoding and then base64-encoded. This encoded value
can be signed - but it is not currently possible.</p>

<p>Server configuration is similar to the one from the Enveloped SAML Assertions section,
the only difference is that a SAML handler needs to be replaced:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-xml">
    <span class="code-tag">&lt;bean id=<span class="code-quote">"serviceBean"</span>
class=<span class="code-quote">"org.apache.cxf.systest.jaxrs.security.BookStore"</span>/&gt;</span>
    <span class="code-tag">&lt;bean id=<span class="code-quote">"samlHandler"</span>
class=<span class="code-quote">"org.apache.cxf.rs.security.saml.SamlFormInHandler"</span>/&gt;</span>
    
    <span class="code-tag"><span class="code-comment">&lt;!-- same as in the
Enveloped SAML Assertions section --&gt;</span></span> 
</pre>
</div></div>

<p>The client code is the same as in the SAML assertions in Authorization header section
except than an instance of SamlFormOutInterceptor has to be registered: </p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
bean.getOutInterceptors().add(<span class="code-keyword">new</span> SamlFormOutInterceptor());
</pre>
</div></div>

<h1><a name="JAX-RSSAML-CreatingSAMLAssertions"></a>Creating SAML Assertions</h1>

<p>If you use CXF JAX-RS client API to experiment with SAML then all you need to do
is to register an appropriate out interceptor as shown in the above code fragments. The interceptor
will ensure that a SAML assertion is created and added inside the XML envelope, as a form
or HTTP header value.<br/>
All of the SAML output interceptors depend on a "ws-security.saml-callback-handler" property
linking to a custom javax.security.auth.callback.Callback implementation which in its handle(Callbacks)
method provides the information which is needed to create a SAML assertion to a org.apache.ws.security.saml.ext.SAMLCallback
Callback instance, for example, see this <a href="http://svn.apache.org/repos/asf/cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/saml/SamlCallbackHandler.java"
class="external-link" rel="nofollow">custom implementation</a>.</p>

<p>More involved cases with SAML assertions being created by identity providers will
be supported, with the help of CXF (WS) STSClient when needed.</p>

<h1><a name="JAX-RSSAML-SAMLAssertionValidation"></a>SAML Assertion Validation</h1>

<p>When SAML assertions are received on the server side, they are validated to make
sure that the enveloped signatures are correct. SubjectConfirmation methods (sender-vouches,
holder-of-key, bearer) are also checked. <br/>
The validation can be delegated to STS if needed. By default, server side SAML handlers have
a "samlValidator" property set to an instance of org.apache.ws.security.validate.SamlAssertionValidator
which does a thorough validation of the assertion. If needed org.apache.cxf.ws.security.trust.STSSamlAssertionValidator
can be set instead which will use STS to validate the assertion.<br/>
Custom validators extending WSS4J SamlAssertionValidator and doing the additional application-specific
validation can be registered if needed.</p>

<p>Note the fact that the default validation relies a lot on the code heavily utilized
by the WS-Security implementation should be of no concern - it is an example of the integration
on its own in order to get the validation done. For example, WS-* STS are heavily used in
the enterprise today and it simply makes a complete sense to rely on it to validate a SAML
assertion if it is possible.</p>

<p>SubjectConfirmation sender-vouches and holder-of-key methods can be easily validated
with enveloped SAML assertions given that the embedded SAML signatures and key info can be
checked against the signature used to sign the envelope or a custom payload like Book.</p>

<p>At the moment these methods can not be properly validated when the assertion is provided
in a header or in the form, the additional signature signing the encoded SAML token will be
needed - this will be supported in due time. Use "bearer" in those cases.</p>

<h1><a name="JAX-RSSAML-SAMLAuthorization"></a>SAML Authorization</h1>
    </div>
        <div id="commentsSection" class="wiki-content pageSection">
        <div style="float: right;">
            <a href="https://cwiki.apache.org/confluence/users/viewnotifications.action"
class="grey">Change Notification Preferences</a>
        </div>
        <a href="https://cwiki.apache.org/confluence/display/CXF20DOC/JAX-RS+SAML">View
Online</a>
        |
        <a href="https://cwiki.apache.org/confluence/pages/diffpagesbyversion.action?pageId=27830327&revisedVersion=7&originalVersion=6">View
Changes</a>
                |
        <a href="https://cwiki.apache.org/confluence/display/CXF20DOC/JAX-RS+SAML?showComments=true&amp;showCommentArea=true#addcomment">Add
Comment</a>
            </div>
</div>
</div>
</div>
</div>
</body>
</html>

Mime
View raw message