[[SAML_Holder-Of-Key_Assertion_Scenario]]
= SAML Holder-Of-Key Assertion Scenario
WS-Trust deals with managing software security tokens. A SAML assertion
is a type of security token. In the Holder-Of-Key method, the STS
creates a SAML token containing the client's public key and signs the
SAML token with its private key. The client includes the SAML token and
signs the outgoing soap envelope to the web service with its private
key. The web service validates the SOAP message and the SAML token.
Implementation of this scenario has the following requirements.
* SAML tokens with a Holder-Of-Key subject confirmation method must be
protected so the token can not be snooped. In most cases, a
Holder-Of-Key token combined with HTTPS is sufficient to prevent "a man
in the middle" getting possession of the token. This means a security
policy that uses a sp:TransportBinding and sp:HttpsToken.
* A Holder-Of-Key token has no encryption or signing keys associated
with it, therefore a sp:IssuedToken of SymmetricKey or PublicKey keyType
should be used with a sp:SignedEndorsingSupportingTokens.
== Web service Provider
This section examines the web service elements for the SAML
Holder-Of-Key scenario. The components are
* Web service provider's WSDL
* SSL configuration
* Web service provider's Interface and Implementation classes.
* Crypto properties and keystore files
* MANIFEST.MF
=== Web service provider WSDL
The web service provider is a contract-first endpoint. All the WS-trust
and security policies for it are declared in the WSDL,
HolderOfKeyService.wsdl. For this scenario a ws-requester is required to
present a SAML 2.0 token of SymmetricKey keyType, issued from a designed
STS. The address of the STS is provided in the WSDL. A transport binding
policy is used. The token is declared to be signed and endorsed,
sp:SignedEndorsingSupportingTokens. A detailed explanation of the
security settings are provided in the comments in the listing below.
[source,xml]
----
http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0http://docs.oasis-open.org/ws-sx/ws-trust/200512/SymmetricKeyhttp://@jboss.bind.address@:8080/jaxws-samples-wsse-policy-trust-sts-holderofkey/SecurityTokenServicestsns:SecurityTokenService
----
[[ssl-configuration]]
=== SSL configuration
https://docs.jboss.org/author/display/JBWS/WS-Trust+and+STS#WS-TrustandSTS-SSLconfiguration
This web service is using https, therefore the JBoss server must be
configured to provide SSL support in the Web subsystem. There are 2
components to SSL configuration.
* create a certificate keystore
* declare an SSL connector in the Web subsystem of the JBoss server
configuration file.
Follow the directions in the, " _Using the pure Java implementation
supplied by JSSE_" section in the link:#[SSL Setup
Guide|../../../../../../../../../../display/WFLY8/SSL+setup+guide|||\].
Here is an example of an SSL connector declaration.
[source, java]
----
.....
...
----
[[web-service-interface]]
=== Web service Interface
The web service provider interface class, HolderOfKeyIface, is a simple
straight forward web service definition.
[source, java]
----
package org.jboss.test.ws.jaxws.samples.wsse.policy.trust.holderofkey;
import javax.jws.WebMethod;
import javax.jws.WebService;
@WebService
(
targetNamespace = "http://www.jboss.org/jbossws/ws-extensions/holderofkeywssecuritypolicy"
)
public interface HolderOfKeyIface {
@WebMethod
String sayHello();
}
----
[[web-service-implementation]]
=== Web service Implementation
The web service provider implementation class, HolderOfKeyImpl, is a
simple POJO. It uses the standard WebService annotation to define the
service endpoint. In addition there are two Apache CXF annotations,
EndpointProperties and EndpointProperty used for configuring the
endpoint for the CXF runtime. These annotations come from the
https://ws.apache.org/wss4j/[Apache WSS4J project], which provides a
Java implementation of the primary WS-Security standards for Web
Services. These annotations are programmatically adding properties to
the endpoint. With plain Apache CXF, these properties are often set via
the element on the element in the
Spring config; these annotations allow the properties to be configured
in the code.
WSS4J uses the Crypto interface to get keys and certificates for
signature creation/verification, as is asserted by the WSDL for this
service. The WSS4J configuration information being provided by
HolderOfKeyImpl is for Crypto's Merlin implementation. More information
will be provided about this in the keystore section.
The first EndpointProperty statement in the listing disables ensurance
of compliance with the Basic Security Profile 1.1. The next
EndpointProperty statements declares the Java properties file that
contains the (Merlin) crypto configuration information. The last
EndpointProperty statement declares the STSHolderOfKeyCallbackHandler
implementation class. It is used to obtain the user's password for the
certificates in the keystore file.
[source, java]
----
package org.jboss.test.ws.jaxws.samples.wsse.policy.trust.holderofkey;
import org.apache.cxf.annotations.EndpointProperties;
import org.apache.cxf.annotations.EndpointProperty;
import javax.jws.WebService;
@WebService
(
portName = "HolderOfKeyServicePort",
serviceName = "HolderOfKeyService",
wsdlLocation = "WEB-INF/wsdl/HolderOfKeyService.wsdl",
targetNamespace = "http://www.jboss.org/jbossws/ws-extensions/holderofkeywssecuritypolicy",
endpointInterface = "org.jboss.test.ws.jaxws.samples.wsse.policy.trust.holderofkey.HolderOfKeyIface"
)
@EndpointProperties(value = {
@EndpointProperty(key = "ws-security.is-bsp-compliant", value = "false"),
@EndpointProperty(key = "ws-security.signature.properties", value = "serviceKeystore.properties"),
@EndpointProperty(key = "ws-security.callback-handler", value = "org.jboss.test.ws.jaxws.samples.wsse.policy.trust.holderofkey.HolderOfKeyCallbackHandler")
})
public class HolderOfKeyImpl implements HolderOfKeyIface
{
public String sayHello()
{
return "Holder-Of-Key WS-Trust Hello World!";
}
}
----
[[crypto-properties-and-keystore-files]]
=== Crypto properties and keystore files
WSS4J's Crypto implementation is loaded and configured via a Java
properties file that contains Crypto configuration data. The file
contains implementation-specific properties such as a keystore location,
password, default alias and the like. This application is using the
Merlin implementation. File serviceKeystore.properties contains this
information.
File servicestore.jks, is a Java KeyStore (JKS) repository. It contains
self signed certificates for myservicekey and mystskey. _Self signed
certificates are not appropriate for production use._
....
org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin
org.apache.ws.security.crypto.merlin.keystore.type=jks
org.apache.ws.security.crypto.merlin.keystore.password=sspass
org.apache.ws.security.crypto.merlin.keystore.alias=myservicekey
org.apache.ws.security.crypto.merlin.keystore.file=servicestore.jks
....
[[manifest.mf]]
=== MANIFEST.MF
https://docs.jboss.org/author/display/JBWS/WS-Trust+and+STS#WS-TrustandSTS-MANIFEST.MF
When deployed on WildFly this application requires access to the JBossWs
and CXF APIs provided in module org.jboss.ws.cxf.jbossws-cxf-client. The
dependency statement directs the server to provide them at deployment.
....
Manifest-Version:1.0
Ant-Version: Apache Ant1.8.2
Created-By:1.7.0_25-b15 (Oracle Corporation)
Dependencies: org.jboss.ws.cxf.jbossws-cxf-client
....
[[security-token-service]]
== Security Token Service
This section examines the crucial elements in providing the Security
Token Service functionality for providing a SAML Holder-Of-Key token.
The components that will be discussed are.
* Security Domain
* STS's WSDL
* STS's implementation class
* STSBearerCallbackHandler
* Crypto properties and keystore files
* MANIFEST.MF
[[security-domain]]
=== Security Domain
The STS requires a JBoss security domain be configured. The
jboss-web.xml descriptor declares a named security
domain,"JBossWS-trust-sts" to be used by this service for
authentication. This security domain requires two properties files and
the addition of a security-domain declaration in the JBoss server
configuration file.
For this scenario the domain needs to contain user _alice_, password
_clarinet_, and role _friend_. See the listings below for
jbossws-users.properties and jbossws-roles.properties. In addition the
following XML must be added to the JBoss security subsystem in the
server configuration file. Replace " *SOME_PATH*" with appropriate
information.
[source,xml]
----
----
jboss-web.xml
[source,xml]
----
----
[[stss-implementation-class]]
=== STS's implementation class
The Apache CXF's STS, SecurityTokenServiceProvider, is a web service
provider that is compliant with the protocols and functionality defined
by the WS-Trust specification. It has a modular architecture. Many of
its components are configurable or replaceable and there are many
optional features that are enabled by implementing and configuring
plug-ins. Users can customize their own STS by extending from
SecurityTokenServiceProvider and overriding the default settings.
Extensive information about the CXF's STS configurable and pluggable
components can be found
http://coheigea.blogspot.com/2011/11/apache-cxf-sts-documentation-part-viii_10.html[here].
This STS implementation class, SampleSTSHolderOfKey, is a POJO that
extends from SecurityTokenServiceProvider. Note that the class is
defined with a WebServiceProvider annotation and not a WebService
annotation. This annotation defines the service as a Provider-based
endpoint, meaning it supports a more messaging-oriented approach to Web
services. In particular, it signals that the exchanged messages will be
XML documents of some type. SecurityTokenServiceProvider is an
implementation of the javax.xml.ws.Provider interface. In comparison the
WebService annotation defines a (service endpoint interface) SEI-based
endpoint which supports message exchange via SOAP envelopes.
As was done in the HolderOfKeyImpl class, the WSS4J annotations
EndpointProperties and EndpointProperty are providing endpoint
configuration for the CXF runtime. The first EndpointProperty statements
declares the Java properties file that contains the (Merlin) crypto
configuration information. WSS4J reads this file and extra required
information for message handling. The last EndpointProperty statement
declares the STSHolderOfKeyCallbackHandler implementation class. It is
used to obtain the user's password for the certificates in the keystore
file.
In this implementation we are customizing the operations of token
issuance and their static properties.
StaticSTSProperties is used to set select properties for configuring
resources in the STS. You may think this is a duplication of the
settings made with the WSS4J annotations. The values are the same but
the underlaying structures being set are different, thus this
information must be declared in both places.
The setIssuer setting is important because it uniquely identifies the
issuing STS. The issuer string is embedded in issued tokens and, when
validating tokens, the STS checks the issuer string value. Consequently,
it is important to use the issuer string in a consistent way, so that
the STS can recognize the tokens that it has issued.
The setEndpoints call allows the declaration of a set of allowed token
recipients by address. The addresses are specified as reg-ex patterns.
TokenIssueOperation has a modular structure. This allows custom
behaviors to be injected into the processing of messages. In this case
we are overriding the SecurityTokenServiceProvider's default behavior
and performing SAML token processing. CXF provides an implementation of
a SAMLTokenProvider which we are using rather than writing our own.
Learn more about the SAMLTokenProvider
http://coheigea.blogspot.it/2011/10/apache-cxf-sts-documentation-part-iv.html[here].
[source, java]
----
package org.jboss.test.ws.jaxws.samples.wsse.policy.trust.stsholderofkey;
import org.apache.cxf.annotations.EndpointProperties;
import org.apache.cxf.annotations.EndpointProperty;
import org.apache.cxf.sts.StaticSTSProperties;
import org.apache.cxf.sts.operation.TokenIssueOperation;
import org.apache.cxf.sts.service.ServiceMBean;
import org.apache.cxf.sts.service.StaticService;
import org.apache.cxf.sts.token.provider.SAMLTokenProvider;
import org.apache.cxf.ws.security.sts.provider.SecurityTokenServiceProvider;
import javax.xml.ws.WebServiceProvider;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
/**
* User: rsearls
* Date: 3/14/14
*/
@WebServiceProvider(serviceName = "SecurityTokenService",
portName = "UT_Port",
targetNamespace = "http://docs.oasis-open.org/ws-sx/ws-trust/200512/",
wsdlLocation = "WEB-INF/wsdl/holderofkey-ws-trust-1.4-service.wsdl")
//be sure to have dependency on org.apache.cxf module when on AS7, otherwise Apache CXF annotations are ignored
@EndpointProperties(value = {
@EndpointProperty(key = "ws-security.signature.properties", value = "stsKeystore.properties"),
@EndpointProperty(key = "ws-security.callback-handler", value = "org.jboss.test.ws.jaxws.samples.wsse.policy.trust.stsholderofkey.STSHolderOfKeyCallbackHandler")
})
public class SampleSTSHolderOfKey extends SecurityTokenServiceProvider
{
public SampleSTSHolderOfKey() throws Exception
{
super();
StaticSTSProperties props = new StaticSTSProperties();
props.setSignatureCryptoProperties("stsKeystore.properties");
props.setSignatureUsername("mystskey");
props.setCallbackHandlerClass(STSHolderOfKeyCallbackHandler.class.getName());
props.setEncryptionCryptoProperties("stsKeystore.properties");
props.setEncryptionUsername("myservicekey");
props.setIssuer("DoubleItSTSIssuer");
List services = new LinkedList();
StaticService service = new StaticService();
service.setEndpoints(Arrays.asList(
"https://localhost:(\\d)*/jaxws-samples-wsse-policy-trust-holderofkey/HolderOfKeyService",
"https://\\[::1\\]:(\\d)*/jaxws-samples-wsse-policy-trust-holderofkey/HolderOfKeyService",
"https://\\[0:0:0:0:0:0:0:1\\]:(\\d)*/jaxws-samples-wsse-policy-trust-holderofkey/HolderOfKeyService"
));
services.add(service);
TokenIssueOperation issueOperation = new TokenIssueOperation();
issueOperation.getTokenProviders().add(new SAMLTokenProvider());
issueOperation.setServices(services);
issueOperation.setStsProperties(props);
this.setIssueOperation(issueOperation);
}
}
----
[[holderofkeycallbackhandler]]
=== HolderOfKeyCallbackHandler
STSHolderOfKeyCallbackHandler is a callback handler for the WSS4J Crypto
API. It is used to obtain the password for the private key in the
keystore. This class enables CXF to retrieve the password of the user
name to use for the message signature.
[source, java]
----
package org.jboss.test.ws.jaxws.samples.wsse.policy.trust.stsholderofkey;
import org.jboss.wsf.stack.cxf.extensions.security.PasswordCallbackHandler;
import java.util.HashMap;
import java.util.Map;
/**
* User: rsearls
* Date: 3/19/14
*/
public class STSHolderOfKeyCallbackHandler extends PasswordCallbackHandler
{
public STSHolderOfKeyCallbackHandler()
{
super(getInitMap());
}
private static Map getInitMap()
{
Map passwords = new HashMap();
passwords.put("mystskey", "stskpass");
passwords.put("alice", "clarinet");
return passwords;
}
}
----
[[crypto-properties-and-keystore-files-1]]
=== Crypto properties and keystore files
WSS4J's Crypto implementation is loaded and configured via a Java
properties file that contains Crypto configuration data. The file
contains implementation-specific properties such as a keystore location,
password, default alias and the like. This application is using the
Merlin implementation. File stsKeystore.properties contains this
information.
File servicestore.jks, is a Java KeyStore (JKS) repository. It contains
self signed certificates for myservicekey and mystskey. _Self signed
certificates are not appropriate for production use._
....
org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin
org.apache.ws.security.crypto.merlin.keystore.type=jks
org.apache.ws.security.crypto.merlin.keystore.password=stsspass
org.apache.ws.security.crypto.merlin.keystore.file=stsstore.jks
....
[[manifest.mf-1]]
=== MANIFEST.MF
When deployed on WildFly, this application requires access to the
JBossWs and CXF APIs provided in modules
org.jboss.ws.cxf.jbossws-cxf-client and org.apache.cxf. The Apache CXF
internals, org.apache.cxf.impl, are needed to build the STS
configuration in the SampleSTSHolderOfKey constructor. The dependency
statement directs the server to provide them at deployment.
....
Manifest-Version:1.0
Ant-Version: Apache Ant1.8.2
Created-By:1.7.0_25-b15 (Oracle Corporation)
Dependencies: org.jboss.ws.cxf.jbossws-cxf-client,org.apache.cxf.impl
....
[[web-service-requester]]
== Web service requester
This section examines the crucial elements in calling a web service that
implements endpoint security as described in the SAML Holder-Of-Key
scenario. The components that will be discussed are.
* web service requester's implementation
* ClientCallbackHandler
* Crypto properties and keystore files
[[web-service-requester-implementation]]
=== Web service requester Implementation
The ws-requester, the client, uses standard procedures for creating a
reference to the web service. To address the endpoint security
requirements, the web service's "Request Context" is configured with the
information needed in message generation. In addition, the STSClient
that communicates with the STS is configured with similar values. Note
the key strings ending with a ".it" suffix. This suffix flags these
settings as belonging to the STSClient. The internal CXF code assigns
this information to the STSClient that is auto-generated for this
service call.
There is an alternate method of setting up the STSCLient. The user may
provide their own instance of the STSClient. The CXF code will use this
object and not auto-generate one. When providing the STSClient in this
way, the user must provide a org.apache.cxf.Bus for it and the
configuration keys must not have the ".it" suffix. This is used in the
ActAs and OnBehalfOf examples.
[source, java]
----
String serviceURL = "https://" + getServerHost() + ":8443/jaxws-samples-wsse-policy-trust-holderofkey/HolderOfKeyService";
final QName serviceName = new QName("http://www.jboss.org/jbossws/ws-extensions/holderofkeywssecuritypolicy", "HolderOfKeyService");
final URL wsdlURL = new URL(serviceURL + "?wsdl");
Service service = Service.create(wsdlURL, serviceName);
HolderOfKeyIface proxy = (HolderOfKeyIface) service.getPort(HolderOfKeyIface.class);
Map ctx = ((BindingProvider)proxy).getRequestContext();
// set the security related configuration information for the service "request"
ctx.put(SecurityConstants.CALLBACK_HANDLER, new ClientCallbackHandler());
ctx.put(SecurityConstants.SIGNATURE_PROPERTIES,
Thread.currentThread().getContextClassLoader().getResource(
"META-INF/clientKeystore.properties"));
ctx.put(SecurityConstants.ENCRYPT_PROPERTIES,
Thread.currentThread().getContextClassLoader().getResource(
"META-INF/clientKeystore.properties"));
ctx.put(SecurityConstants.SIGNATURE_USERNAME, "myclientkey");
ctx.put(SecurityConstants.ENCRYPT_USERNAME, "myservicekey");
//-- Configuration settings that will be transfered to the STSClient
// "alice" is the name provided for the WSS Username. Her password will
// be retreived from the ClientCallbackHander by the STSClient.
ctx.put(SecurityConstants.USERNAME + ".it", "alice");
ctx.put(SecurityConstants.CALLBACK_HANDLER + ".it", new ClientCallbackHandler());
ctx.put(SecurityConstants.ENCRYPT_PROPERTIES + ".it",
Thread.currentThread().getContextClassLoader().getResource(
"META-INF/clientKeystore.properties"));
ctx.put(SecurityConstants.ENCRYPT_USERNAME + ".it", "mystskey");
ctx.put(SecurityConstants.STS_TOKEN_USERNAME + ".it", "myclientkey");
ctx.put(SecurityConstants.STS_TOKEN_PROPERTIES + ".it",
Thread.currentThread().getContextClassLoader().getResource(
"META-INF/clientKeystore.properties"));
ctx.put(SecurityConstants.STS_TOKEN_USE_CERT_FOR_KEYINFO + ".it", "true");
proxy.sayHello();
----
[[clientcallbackhandler]]
=== ClientCallbackHandler
ClientCallbackHandler is a callback handler for the WSS4J Crypto API. It
is used to obtain the password for the private key in the keystore. This
class enables CXF to retrieve the password of the user name to use for
the message signature. Note that "alice" and her password have been
provided here. This information is not in the (JKS) keystore but
provided in the WildFly security domain. It was declared in file
jbossws-users.properties.
[source, java]
----
package org.jboss.test.ws.jaxws.samples.wsse.policy.trust.shared;
import java.io.IOException;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import org.apache.ws.security.WSPasswordCallback;
public class ClientCallbackHandler implements CallbackHandler {
public void handle(Callback[] callbacks) throws IOException,
UnsupportedCallbackException {
for (int i = 0; i < callbacks.length; i++) {
if (callbacks[i] instanceof WSPasswordCallback) {
WSPasswordCallback pc = (WSPasswordCallback) callbacks[i];
if ("myclientkey".equals(pc.getIdentifier())) {
pc.setPassword("ckpass");
break;
} else if ("alice".equals(pc.getIdentifier())) {
pc.setPassword("clarinet");
break;
} else if ("bob".equals(pc.getIdentifier())) {
pc.setPassword("trombone");
break;
} else if ("myservicekey".equals(pc.getIdentifier())) { // rls test added for bearer test
pc.setPassword("skpass");
break;
}
}
}
}
}
----
[[crypto-properties-and-keystore-files-2]]
=== Crypto properties and keystore files
WSS4J's Crypto implementation is loaded and configured via a Java
properties file that contains Crypto configuration data. The file
contains implementation-specific properties such as a keystore location,
password, default alias and the like. This application is using the
Merlin implementation. File clientKeystore.properties contains this
information.
File clientstore.jks, is a Java KeyStore (JKS) repository. It contains
self signed certificates for myservicekey and mystskey. _Self signed
certificates are not appropriate for production use._
....
org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin
org.apache.ws.security.crypto.merlin.keystore.type=jks
org.apache.ws.security.crypto.merlin.keystore.password=cspass
org.apache.ws.security.crypto.merlin.keystore.alias=myclientkey
org.apache.ws.security.crypto.merlin.keystore.file=META-INF/clientstore.jks
....