Dieser Inhalt ist in der von Ihnen ausgewählten Sprache nicht verfügbar.
Appendix A. Reference Material
A.1. JAX-RS/RESTEasy Annotations
Annotation | Usage |
---|---|
Cache |
Set response |
ClientInterceptor | Identifies an interceptor as a client-side interceptor. |
ContentEncoding |
Meta annotation that specifies a |
Context |
Allows you to specify instances of |
CookieParam | Allows you to specify the value of a cookie or object representation of an HTTP request cookie into the method invocation. |
DecorateTypes |
Must be placed on a |
Decorator | Meta-annotation to be placed on another annotation that triggers decoration. |
DefaultValue |
Can be combined with the other |
DELETE |
An annotation that signifies that the method responds to HTTP |
DoNotUseJAXBProvider |
Put this on a class or parameter when you do not want the JAXB |
Encoded |
Can be used on a class, method, or param. By default, inject |
Form | This can be used as a value object for incoming/outgoing request/responses. |
Formatted | Format XML output with indentations and newlines. This is a JAXB Decorator. |
GET |
An annotation that signifies that the method responds to HTTP |
IgnoreMediaTypes | Placed on a type, method, parameter, or field to tell JAXRS not to use JAXB provider for a certain media type |
ImageWriterParams |
An annotation that a resource class can use to pass parameters to the |
Mapped |
A |
MultipartForm | This can be used as a value object for incoming/outgoing request/responses of the multipart/form-data MIME type. |
NoCache |
Set |
NoJackson | Placed on class, parameter, field or method when you do not want the Jackson provider to be triggered. |
PartType |
Must be used in conjunction with Multipart providers when writing out a List or Map as a |
Path | This must exist either in the class or resource method. If it exists in both, the relative path to the resource method is a concatenation of the class and method. |
PathParam | Allows you to map variable URI path fragments into a method call. |
POST |
An annotation that signifies that the method responds to HTTP |
Priority | An annotation to indicate what order a class should be used. Uses an integer parameter with a lower value signifying a higher priority. |
Provider | Marks a class to be discoverable as a provider by JAX-RS runtime during a provider scanning phase. |
PUT |
An annotation that signifies that the method responds to HTTP |
QueryParam | Allows you to map URI query string parameter or URL form encoded parameter to the method invocation. |
ServerInterceptor | Identifies an interceptor as a server-side interceptor. |
StringParameterUnmarshallerBinder |
Meta-annotation to be placed on another annotation that triggers a |
Stylesheet | Specifies an XML stylesheet header. |
Wrapped | Put this on a method or parameter when you want to marshal or unmarshal a collection or array of JAXB objects. |
WrappedMap | Put this on a method or parameter when you want to marshal or unmarshal a map of JAXB objects. |
XmlHeader | Sets an XML header for the returned document. |
XmlNsMap |
A |
XopWithMultipartRelated | This annotation can be used to process/produce incoming/outgoing XOP messages (packaged as multipart/related) to/from JAXB annotated objects. |
A.2. RESTEasy Configuration Parameters
Option Name | Default Value | Description |
---|---|---|
resteasy.servlet.mapping.prefix | No default |
If the URL-pattern for the Resteasy servlet-mapping is not |
resteasy.scan | false |
Automatically scan |
resteasy.scan.providers | false |
Scan for |
resteasy.scan.resources | false | Scan for JAX-RS resource classes. |
resteasy.providers | no default |
A comma delimited list of fully qualified |
resteasy.use.builtin.providers | true |
Whether or not to register default, built-in |
resteasy.resources | No default | A comma delimited list of fully qualified JAX-RS resource class names you want to register. |
resteasy.jndi.resources | No default | A comma delimited list of JNDI names which reference objects you want to register as JAX-RS resources. |
javax.ws.rs.Application | No default |
Fully qualified name of |
resteasy.media.type.mappings | No default |
Replaces the need for an |
resteasy.language.mappings | No default |
Replaces the need for an |
resteasy.document.expand.entity.references | false |
Whether to expand external entities or replace them with an empty string. In JBoss EAP, this parameter defaults to |
resteasy.document.secure.processing.feature | true |
Impose security constraints in processing |
resteasy.document.secure.disableDTDs | true |
Prohibit DTDs in |
resteasy.wider.request.matching | true | Turn off class-level expression filtering as defined in the JAX-RS specification and instead match based on the full expression of each JAX-RS method. |
resteasy.use.container.form.params | true |
Use the |
resteasy.add.charset | true |
If a resource method returns a |
These parameters are configured in the WEB-INF/web.xml
file.
In a Servlet 3.0 container, the resteasy.scan.*
configurations in the web.xml
file are ignored, and all JAX-RS annotated components will be automatically scanned.
For example, javax.ws.rs.Application
parameter is configured within init-param
of the servlet configuration:
<servlet> <servlet-name>Resteasy</servlet-name> <servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class> <init-param> <param-name>javax.ws.rs.Application</param-name> <param-value>org.jboss.resteasy.utils.TestApplication</param-value> </init-param> </servlet>
For example, resteasy.document.expand.entity.references
is configured within context-param
:
<context-param> <param-name>resteasy.document.expand.entity.references</param-name> <param-value>true</param-value> </context-param>
Changing the default values of the following RESTEasy parameters may cause RESTEasy applications to be potentially vulnerable against XXE attacks:
- resteasy.document.expand.entity.references
- resteasy.document.secure.processing.feature
- resteasy.document.secure.disableDTDs
A.3. RESTEasy JavaScript API Parameters
Property | Default Value | Description |
---|---|---|
$entity |
The entity to send as a | |
$contentType |
The MIME type of the body entity sent as the | |
$accepts | */* |
The accepted MIME types sent as the |
$callback |
Set to a function ( | |
$apiURL | Set to the base URI of the JAX-RS endpoint, not including the last slash. | |
$username | If username and password are set, they will be used for credentials for the request. | |
$password | If username and password are set, they will be used for credentials for the request. |
A.4. REST.Request Class Members
Member | Description |
---|---|
execute(callback) | Executes the request with all the information set in the current object. The value is passed to the optional argument callback, not returned. |
setAccepts(acceptHeader) |
Sets the |
setCredentials(username, password) | Sets the request credentials. |
setEntity(entity) | Sets the request entity. |
setContentType(contentTypeHeader) |
Sets the |
setURI(uri) | Sets the request URI. This should be an absolute URI. |
setMethod(method) |
Sets the request method. Defaults to |
setAsync(async) |
Controls whether the request should be asynchronous. Defaults to |
addCookie(name, value) | Sets the given cookie in the current document when executing the request. This will be persistent in the browser. |
addQueryParameter(name, value) | Adds a query parameter to the URI query part. |
addMatrixParameter(name, value) | Adds a matrix parameter (path parameter) to the last path segment of the request URI. |
addHeader(name, value) | Adds a request header. |
addForm(name, value) | Adds a form. |
addFormParameter(name, value) | Adds a form parameter. |
A.5. RESTEasy Asynchronous Job Service Configuration Parameters
The table below details the configurable context-params
for the Asynchronous Job Service. These parameters can be configured in the web.xml
file.
Parameter | Description |
---|---|
resteasy.async.job.service.max.job.results |
Number of job results that can be held in the memory at any one time. Default value is |
resteasy.async.job.service.max.wait |
Maximum wait time on a job when a client is querying for it. Default value is |
resteasy.async.job.service.thread.pool.size |
Thread pool size of the background threads that run the job. Default value is |
resteasy.async.job.service.base.path |
Sets the base path for the job URIs. Default value is |
<web-app> <context-param> <param-name>resteasy.async.job.service.enabled</param-name> <param-value>true</param-value> </context-param> <context-param> <param-name>resteasy.async.job.service.max.job.results</param-name> <param-value>100</param-value> </context-param> <context-param> <param-name>resteasy.async.job.service.max.wait</param-name> <param-value>300000</param-value> </context-param> <context-param> <param-name>resteasy.async.job.service.thread.pool.size</param-name> <param-value>100</param-value> </context-param> <context-param> <param-name>resteasy.async.job.service.base.path</param-name> <param-value>/asynch/jobs</param-value> </context-param> <listener> <listener-class> org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap </listener-class> </listener> <servlet> <servlet-name>Resteasy</servlet-name> <servlet-class> org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher </servlet-class> </servlet> <servlet-mapping> <servlet-name>Resteasy</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping> </web-app>
A.6. JAX-WS Tools
wsconsume
wsconsume
is a command-line tool provided with JBoss EAP that consumes a WSDL and produces portable JAX-WS service and client artifacts.
Usage
The wsconsume
tool is located in the EAP_HOME/bin
directory and uses the following syntax.
EAP_HOME/bin/wsconsume.sh [options] <wsdl-url>
Use the wsconsume.bat
script for Windows.
Example usage:
Generate Java class files from the
Example.wsdl
WSDL fileEAP_HOME/bin/wsconsume.sh Example.wsdl
Generate Java source and class files from the
Example.wsdl
WSDL fileEAP_HOME/bin/wsconsume.sh -k Example.wsdl
Generate Java source and class files in the
my.org
package from theExample.wsdl
WSDL fileEAP_HOME/bin/wsconsume.sh -k -p my.org Example.wsdl
Generate Java source and class files using multiple binding files
EAP_HOME/bin/wsconsume.sh -k -b schema-binding1.xsd -b schema-binding2.xsd Example.wsdl
Use the --help
argument or see the below table for a listing of all available wsconsume
options.
Option | Description |
---|---|
-a, --additionalHeaders | Enable processing of implicit SOAP headers. |
-b, --binding=<file> | One or more JAX-WS or JAXB binding files. |
-c --catalog=<file> | Oasis XML Catalog file for entity resolution. |
-d --encoding=<charset> | The charset encoding to use for generated sources. |
-e, --extension | Enable SOAP 1.2 binding extension. |
-h, --help | Show this help message. |
-j --clientjar=<name> | Create a jar file of the generated artifacts for calling the web. service |
-k, --keep | Keep/Generate Java source. |
-l, --load-consumer | Load the consumer and exit (debug utility). |
-n, --nocompile | Do not compile generated sources. |
-o, --output=<directory> | The directory to put generated artifacts. |
-p --package=<name> | The target package for generated source. |
-q, --quiet | Be somewhat more quiet. |
-s, --source=<directory> | The directory to put Java source. |
-t, --target=<2.1|2.2> | The JAX-WS specification target. |
-v, --verbose | Show full exception stack traces. |
-w --wsdlLocation=<loc> |
Value to use for |
wsprovide
wsprovide
is a command-line tool provided with JBoss EAP that generates portable JAX-WS artifacts for a service endpoint implementation. It also has the option to generate a WSDL file.
Usage
The wsprovide
tool is located in the EAP_HOME/bin
directory and uses the following syntax.
EAP_HOME/bin/wsprovide.sh [options] <endpoint class name>
Use the wsprovide.bat
script for Windows.
Example usage:
Generate wrapper classes for portable artifacts in the
output
directory.EAP_HOME/bin/wsprovide.sh -o output my.package.MyEndpoint
Generate wrapper classes and WSDL in the
output
directory.EAP_HOME/bin/wsprovide.sh -o output -w my.package.MyEndpoint
Generate wrapper classes in the
output
directory for an endpoint that references other JARs.EAP_HOME/bin/wsprovide.sh -o output -c myapplication1.jar:myapplication2.jar my.org.MyEndpoint
Use the --help
argument or see the below table for a listing of all available wsprovide
options.
Option | Description |
---|---|
-a, --address=<address> | The generated port soap:address in WSDL. |
-c, --classpath=<path> | The classpath that contains the endpoint. |
-e, --extension | Enable SOAP 1.2 binding extension. |
-h, --help | Show this help message. |
-k, --keep | Keep/Generate Java source. |
-l, --load-provider | Load the provider and exit (debug utility). |
-o, --output=<directory> | The directory to put generated artifacts. |
-q, --quiet | Be somewhat more quiet. |
-r, --resource=<directory> | The directory to put resource artifacts. |
-s, --source=<directory> | The directory to put Java source. |
-t, --show-traces | Show full exception stack traces. |
-w, --wsdl | Enable WSDL file generation. |
A.7. JAX-WS Common API Reference
Several JAX-WS development concepts are shared between web service endpoints and clients. These include the handler framework, message context, and fault handling.
Handler Framework
The handler framework is implemented by a JAX-WS protocol binding in the runtime of the client and the endpoint, which is the server component. Proxies and Dispatch
instances, known collectively as binding providers, each use protocol bindings to bind their abstract functionality to specific protocols.
Client and server-side handlers are organized into an ordered list known as a handler chain. The handlers within a handler chain are invoked each time a message is sent or received. Inbound messages are processed by handlers before the binding provider processes them. Outbound messages are processed by handlers after the binding provider processes them.
Handlers are invoked with a message context which provides methods to access and modify inbound and outbound messages and to manage a set of properties. Message context properties facilitate communication between individual handlers, as well as between handlers and client and service implementations. Different types of handlers are invoked with different types of message contexts.
- Logical Handler
-
Logical handlers only operate on message context properties and message payloads. Logical handlers are protocol-independent and cannot affect protocol-specific parts of a message. Logical handlers implement interface
javax.xml.ws.handler.LogicalHandler
. - Protocol Handler
-
Protocol handlers operate on message context properties and protocol-specific messages. Protocol handlers are specific to a particular protocol and may access and change protocol-specific aspects of a message. Protocol handlers implement any interface derived from
javax.xml.ws.handler.Handler
, exceptjavax.xml.ws.handler.LogicalHandler
. - Service Endpoint Handler
On a service endpoint, handlers are defined using the
@HandlerChain
annotation. The location of the handler chain file can be either an absolutejava.net.URL
inexternalForm
or a relative path from the source file or class file.@WebService @HandlerChain(file = "jaxws-server-source-handlers.xml") public class SOAPEndpointSourceImpl { ... }
- Service Client Handler
On a JAX-WS client, handlers are defined either by using the
@HandlerChain
annotation, as in service endpoints, or dynamically, using the JAX-WS API.Service service = Service.create(wsdlURL, serviceName); Endpoint port = (Endpoint)service.getPort(Endpoint.class); BindingProvider bindingProvider = (BindingProvider)port; List<Handler> handlerChain = new ArrayList<Handler>(); handlerChain.add(new LogHandler()); handlerChain.add(new AuthorizationHandler()); handlerChain.add(new RoutingHandler()); bindingProvider.getBinding().setHandlerChain(handlerChain);
The call to the
setHandlerChain
method is required.
Message Context
The MessageContext
interface is the super interface for all JAX-WS message contexts. It extends Map<String,Object>
with additional methods and constants to manage a set of properties that enable handlers in a handler chain to share processing related state. For example, a handler may use the put
method to insert a property into the message context. One or more other handlers in the handler chain may subsequently obtain the message using the get
method.
Properties are scoped as either APPLICATION
or HANDLER
. All properties are available to all handlers for an instance of a message exchange pattern (MEP) of a particular endpoint. For instance, if a logical handler puts a property into the message context, that property is also available to any protocol handlers in the chain during the execution of an MEP instance.
An asynchronous Message Exchange Pattern (MEP) allows for sending and receiving messages asynchronously at the HTTP connection level. You can enable it by setting additional properties in the request context.
Properties scoped at the APPLICATION
level are also made available to client applications and service endpoint implementations. The defaultscope
for a property is HANDLER
.
Logical and SOAP messages use different contexts.
- Logical Message Context
-
When logical handlers are invoked, they receive a message context of type
LogicalMessageContext
.LogicalMessageContext
extendsMessageContext
with methods which obtain and modify the message payload. It does not provide access to the protocol-specific aspects of a message. A protocol binding defines which components of a message are available through a logical message context. A logical handler deployed in a SOAP binding can access the contents of the SOAP body but not the SOAP headers. On the other hand, the XML/HTTP binding defines that a logical handler can access the entire XML payload of a message. - SOAP Message Context
-
When SOAP handlers are invoked, they receive a
SOAPMessageContext
.SOAPMessageContext
extendsMessageContext
with methods which obtain and modify the SOAP message payload.
Fault Handling
An application may throw a SOAPFaultException
or an application-specific user exception. In the case of the latter, the required fault wrapper beans are generated at runtime if they are not already part of the deployment.
public void throwSoapFaultException() { SOAPFactory factory = SOAPFactory.newInstance(); SOAPFault fault = factory.createFault("this is a fault string!", new QName("http://foo", "FooCode")); fault.setFaultActor("mr.actor"); fault.addDetail().addChildElement("test"); throw new SOAPFaultException(fault); }
public void throwApplicationException() throws UserException { throw new UserException("validation", 123, "Some validation error"); }
JAX-WS Annotations
The annotations available by the JAX-WS API are defined in JSR-224. These annotations are in the javax.xml.ws
package.
The annotations available by the JWS API are defined in JSR-181. These annotations are in the javax.jws
package.
A.8. Advanced WS-Trust Scenarios
A.8.1. Scenario: SAML Holder-Of-Key Assertion Scenario
WS-Trust helps in managing software security tokens. A SAML assertion is a type of security token. In the Holder-Of-Key method, 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 SAML token.
Implementation of this scenario requires the following:
-
SAML tokens with a Holder-Of-Key subject confirmation method must be protected so the token cannot be snooped. In most cases, a Holder-Of-Key token combined with HTTPS is sufficient to prevent getting possession of the token. This means the security policy uses a
sp:TransportBinding
andsp:HttpsToken
. -
A Holder-Of-Key token has no encryption or signing keys associated with it, therefore a
sp:IssuedToken
ofSymmetricKey
orPublicKey
keyType should be used with asp:SignedEndorsingSupportingTokens
.
A.8.1.1. Web Service Provider
This section lists the web service elements for the SAML Holder-Of-Key scenario. The components include:
A.8.1.1.1. Web Service Provider WSDL
The Web Service Provider is a contract-first endpoint. All WS-trust and security policies for it are declared in the HolderOfKeyService.wsdl
WSDL. For this scenario, a ws-requester
is required to provide a SAML 2.0 token of SymmetricKey
keyType, issued from a designated STS. The STS address 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 following listing:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <definitions targetNamespace="http://www.jboss.org/jbossws/ws-extensions/holderofkeywssecuritypolicy" name="HolderOfKeyService" xmlns:tns="http://www.jboss.org/jbossws/ws-extensions/holderofkeywssecuritypolicy" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:wsp="http://www.w3.org/ns/ws-policy" xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsaws="http://www.w3.org/2005/08/addressing" xmlns:wsx="http://schemas.xmlsoap.org/ws/2004/09/mex" xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702" xmlns:t="http://docs.oasis-open.org/ws-sx/ws-trust/200512"> <types> <xsd:schema> <xsd:import namespace="http://www.jboss.org/jbossws/ws-extensions/holderofkeywssecuritypolicy" schemaLocation="HolderOfKeyService_schema1.xsd"/> </xsd:schema> </types> <message name="sayHello"> <part name="parameters" element="tns:sayHello"/> </message> <message name="sayHelloResponse"> <part name="parameters" element="tns:sayHelloResponse"/> </message> <portType name="HolderOfKeyIface"> <operation name="sayHello"> <input message="tns:sayHello"/> <output message="tns:sayHelloResponse"/> </operation> </portType> <!-- The wsp:PolicyReference binds the security requirements on all the endpoints. The wsp:Policy wsu:Id="#TransportSAML2HolderOfKeyPolicy" element is defined later in this file. --> <binding name="HolderOfKeyServicePortBinding" type="tns:HolderOfKeyIface"> <wsp:PolicyReference URI="#TransportSAML2HolderOfKeyPolicy" /> <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/> <operation name="sayHello"> <soap:operation soapAction=""/> <input> <soap:body use="literal"/> </input> <output> <soap:body use="literal"/> </output> </operation> </binding> <!-- The soap:address has been defined to use JBoss's https port, 8443. This is set in conjunction with the sp:TransportBinding policy for https. --> <service name="HolderOfKeyService"> <port name="HolderOfKeyServicePort" binding="tns:HolderOfKeyServicePortBinding"> <soap:address location="https://@jboss.bind.address@:8443/jaxws-samples-wsse-policy-trust-holderofkey/HolderOfKeyService"/> </port> </service> <wsp:Policy wsu:Id="TransportSAML2HolderOfKeyPolicy"> <wsp:ExactlyOne> <wsp:All> <!-- The wsam:Addressing element, indicates that the endpoints of this web service MUST conform to the WS-Addressing specification. The attribute wsp:Optional="false" enforces this assertion. --> <wsam:Addressing wsp:Optional="false"> <wsp:Policy /> </wsam:Addressing> <!-- The sp:TransportBinding element indicates that security is provided by the message exchange transport medium, https. WS-Security policy specification defines the sp:HttpsToken for use in exchanging messages transmitted over HTTPS. --> <sp:TransportBinding xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702"> <wsp:Policy> <sp:TransportToken> <wsp:Policy> <sp:HttpsToken> <wsp:Policy/> </sp:HttpsToken> </wsp:Policy> </sp:TransportToken> <!-- The sp:AlgorithmSuite element, requires the TripleDes algorithm suite be used in performing cryptographic operations. --> <sp:AlgorithmSuite> <wsp:Policy> <sp:TripleDes /> </wsp:Policy> </sp:AlgorithmSuite> <!-- The sp:Layout element, indicates the layout rules to apply when adding items to the security header. The sp:Lax sub-element indicates items are added to the security header in any order that conforms to WSS: SOAP Message Security. --> <sp:Layout> <wsp:Policy> <sp:Lax /> </wsp:Policy> </sp:Layout> <sp:IncludeTimestamp /> </wsp:Policy> </sp:TransportBinding> <!-- The sp:SignedEndorsingSupportingTokens, when transport level security level is used there will be no message signature and the signature generated by the supporting token will sign the Timestamp. --> <sp:SignedEndorsingSupportingTokens xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702"> <wsp:Policy> <!-- The sp:IssuedToken element asserts that a SAML 2.0 security token of type Bearer is expected from the STS. The sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient"> attribute instructs the runtime to include the initiator's public key with every message sent to the recipient. The sp:RequestSecurityTokenTemplate element directs that all of the children of this element will be copied directly into the body of the RequestSecurityToken (RST) message that is sent to the STS when the initiator asks the STS to issue a token. --> <sp:IssuedToken sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient"> <sp:RequestSecurityTokenTemplate> <t:TokenType>http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0</t:TokenType> <!-- KeyType of "SymmetricKey", the client must prove to the WS service that it possesses a particular symmetric session key. --> <t:KeyType>http://docs.oasis-open.org/ws-sx/ws-trust/200512/SymmetricKey</t:KeyType> </sp:RequestSecurityTokenTemplate> <wsp:Policy> <sp:RequireInternalReference /> </wsp:Policy> <!-- The sp:Issuer element defines the STS's address and endpoint information This information is used by the STSClient. --> <sp:Issuer> <wsaws:Address>http://@jboss.bind.address@:8080/jaxws-samples-wsse-policy-trust-sts-holderofkey/SecurityTokenService</wsaws:Address> <wsaws:Metadata xmlns:wsdli="http://www.w3.org/2006/01/wsdl-instance" wsdli:wsdlLocation="http://@jboss.bind.address@:8080/jaxws-samples-wsse-policy-trust-sts-holderofkey/SecurityTokenService?wsdl"> <wsaw:ServiceName xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" xmlns:stsns="http://docs.oasis-open.org/ws-sx/ws-trust/200512/" EndpointName="UT_Port">stsns:SecurityTokenService</wsaw:ServiceName> </wsaws:Metadata> </sp:Issuer> </sp:IssuedToken> </wsp:Policy> </sp:SignedEndorsingSupportingTokens> <!-- The sp:Wss11 element declares WSS: SOAP Message Security 1.1 options to be supported by the STS. These particular elements generally refer to how keys are referenced within the SOAP envelope. These are normally handled by Apache CXF. --> <sp:Wss11> <wsp:Policy> <sp:MustSupportRefIssuerSerial /> <sp:MustSupportRefThumbprint /> <sp:MustSupportRefEncryptedKey /> </wsp:Policy> </sp:Wss11> <!-- The sp:Trust13 element declares controls for WS-Trust 1.3 options. They are policy assertions related to exchanges specifically with client and server challenges and entropy behaviors. Again these are normally handled by Apache CXF. --> <sp:Trust13> <wsp:Policy> <sp:MustSupportIssuedTokens /> <sp:RequireClientEntropy /> <sp:RequireServerEntropy /> </wsp:Policy> </sp:Trust13> </wsp:All> </wsp:ExactlyOne> </wsp:Policy> </definitions>
A.8.1.1.2. SSL Configuration
This web service uses HTTPS, therefore the JBoss EAP server must be configured to provide SSL/TLS support in the undertow
subsystem. There are two components for SSL/TLS configuration:
- Create a certificate keystore.
-
Declare an SSL connector in the
undertow
subsystem of the JBoss EAP server configuration file.
The following is an example of an SSL/TLS connector declaration:
<subsystem xmlns="urn:jboss:domain:web:1.4" default-virtual-server="default-host" native="false"> ..... <connector name="jbws-https-connector" protocol="HTTP/1.1" scheme="https" socket-binding="https" secure="true" enabled="true"> <ssl key-alias="tomcat" password="changeit" certificate-key-file="/myJbossHome/security/test.keystore" verify-client="false"/> </connector> ...
Red Hat recommends that SSLv2, SSLv3, and TLSv1.0 be explicitly disabled in favor of TLSv1.1 or TLSv1.2 in all affected packages.
A.8.1.1.3. Web Service Provider Interface
The web service provider interface HolderOfKeyIface
class is a simple web service definition.
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(); }
A.8.1.1.4. Web Service Provider Implementation
The web service provider implementation HolderOfKeyImpl
class 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 Apache CXF runtime. These annotations come from the Apache WSS4J project, which provides a Java implementation of the primary WS-Security standards for web services. These annotations programmatically add properties to the endpoint. With plain Apache CXF, these properties are often set using the <jaxws:properties>
element on the <jaxws:endpoint>
element in the Spring configuration. 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 asserted by the WSDL for this service. The WSS4J configuration information provided by HolderOfKeyImpl
is for Crypto’s Merlin implementation.
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.
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!"; } }
A.8.1.1.5. Crypto Properties and Keystore Files
WSS4J’s Crypto implementation is loaded and configured using a Java properties file that contains Crypto configuration data. The file contains implementation-specific properties such as a keystore location, password, default alias and so on. This application uses the Merlin implementation. The serviceKeystore.properties
file contains this information.
The servicestore.jks
file is a Java KeyStore (JKS) repository. It contains self-signed certificates for myservicekey
and mystskey
.
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
A.8.1.1.6. Default MANIFEST.MF
This application requires access to JBossWS and Apache CXF APIs provided in the org.jboss.ws.cxf.jbossws-cxf-client
module. The dependency statement directs the server to provide them at deployment.
Manifest-Version: 1.0 Dependencies: org.jboss.ws.cxf.jbossws-cxf-client
A.8.2. Scenario: SAML Bearer Assertion
WS-Trust manages software security tokens. A SAML assertion is a type of security token. In the SAML Bearer scenario, the service provider automatically trusts that the incoming SOAP request came from the subject defined in the SAML token after the service verifies the token’s signature.
Implementation of this scenario has the following requirements.
-
SAML tokens with a
Bearer
subject confirmation method must be protected so the token can not be snooped. In most cases, a bearer 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 asp:TransportBinding
andsp:HttpsToken
. -
A bearer token has no encryption or signing keys associated with it, therefore a
sp:IssuedToken
ofbearer
keyType should be used with asp:SupportingToken
or asp:SignedSupportingTokens
.
A.8.2.1. Web Service Provider
This section examines the web service elements for the SAML Bearer scenario. The components include:
A.8.2.1.1. Bearer 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 BearerService.wsdl
WSDL. For this scenario, a ws-requester
is required to provide a SAML 2.0 Bearer token issued from a designated STS. The address of the STS is provided in the WSDL. HTTPS, a TransportBinding
and HttpsToken
policy are used to protect the SOAP body of messages that are sent between ws-requester
and ws-provider
. The security settings details are provided as comments in the following listing.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <definitions targetNamespace="http://www.jboss.org/jbossws/ws-extensions/bearerwssecuritypolicy" name="BearerService" xmlns:tns="http://www.jboss.org/jbossws/ws-extensions/bearerwssecuritypolicy" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:wsp="http://www.w3.org/ns/ws-policy" xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsaws="http://www.w3.org/2005/08/addressing" xmlns:wsx="http://schemas.xmlsoap.org/ws/2004/09/mex" xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702" xmlns:t="http://docs.oasis-open.org/ws-sx/ws-trust/200512"> <types> <xsd:schema> <xsd:import namespace="http://www.jboss.org/jbossws/ws-extensions/bearerwssecuritypolicy" schemaLocation="BearerService_schema1.xsd"/> </xsd:schema> </types> <message name="sayHello"> <part name="parameters" element="tns:sayHello"/> </message> <message name="sayHelloResponse"> <part name="parameters" element="tns:sayHelloResponse"/> </message> <portType name="BearerIface"> <operation name="sayHello"> <input message="tns:sayHello"/> <output message="tns:sayHelloResponse"/> </operation> </portType> <!-- The wsp:PolicyReference binds the security requirments on all the endpoints. The wsp:Policy wsu:Id="#TransportSAML2BearerPolicy" element is defined later in this file. --> <binding name="BearerServicePortBinding" type="tns:BearerIface"> <wsp:PolicyReference URI="#TransportSAML2BearerPolicy" /> <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/> <operation name="sayHello"> <soap:operation soapAction=""/> <input> <soap:body use="literal"/> </input> <output> <soap:body use="literal"/> </output> </operation> </binding> <!-- The soap:address has been defined to use JBoss's https port, 8443. This is set in conjunction with the sp:TransportBinding policy for https. --> <service name="BearerService"> <port name="BearerServicePort" binding="tns:BearerServicePortBinding"> <soap:address location="https://@jboss.bind.address@:8443/jaxws-samples-wsse-policy-trust-bearer/BearerService"/> </port> </service> <wsp:Policy wsu:Id="TransportSAML2BearerPolicy"> <wsp:ExactlyOne> <wsp:All> <!-- The wsam:Addressing element, indicates that the endpoints of this web service MUST conform to the WS-Addressing specification. The attribute wsp:Optional="false" enforces this assertion. --> <wsam:Addressing wsp:Optional="false"> <wsp:Policy /> </wsam:Addressing> <!-- The sp:TransportBinding element indicates that security is provided by the message exchange transport medium, https. WS-Security policy specification defines the sp:HttpsToken for use in exchanging messages transmitted over HTTPS. --> <sp:TransportBinding xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702"> <wsp:Policy> <sp:TransportToken> <wsp:Policy> <sp:HttpsToken> <wsp:Policy/> </sp:HttpsToken> </wsp:Policy> </sp:TransportToken> <!-- The sp:AlgorithmSuite element, requires the TripleDes algorithm suite be used in performing cryptographic operations. --> <sp:AlgorithmSuite> <wsp:Policy> <sp:TripleDes /> </wsp:Policy> </sp:AlgorithmSuite> <!-- The sp:Layout element, indicates the layout rules to apply when adding items to the security header. The sp:Lax sub-element indicates items are added to the security header in any order that conforms to WSS: SOAP Message Security. --> <sp:Layout> <wsp:Policy> <sp:Lax /> </wsp:Policy> </sp:Layout> <sp:IncludeTimestamp /> </wsp:Policy> </sp:TransportBinding> <!-- The sp:SignedSupportingTokens element causes the supporting tokens to be signed using the primary token that is used to sign the message. --> <sp:SignedSupportingTokens xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702"> <wsp:Policy> <!-- The sp:IssuedToken element asserts that a SAML 2.0 security token of type Bearer is expected from the STS. The sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient"> attribute instructs the runtime to include the initiator's public key with every message sent to the recipient. The sp:RequestSecurityTokenTemplate element directs that all of the children of this element will be copied directly into the body of the RequestSecurityToken (RST) message that is sent to the STS when the initiator asks the STS to issue a token. --> <sp:IssuedToken sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient"> <sp:RequestSecurityTokenTemplate> <t:TokenType>http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0</t:TokenType> <t:KeyType>http://docs.oasis-open.org/ws-sx/ws-trust/200512/Bearer</t:KeyType> </sp:RequestSecurityTokenTemplate> <wsp:Policy> <sp:RequireInternalReference /> </wsp:Policy> <!-- The sp:Issuer element defines the STS's address and endpoint information This information is used by the STSClient. --> <sp:Issuer> <wsaws:Address>http://@jboss.bind.address@:8080/jaxws-samples-wsse-policy-trust-sts-bearer/SecurityTokenService</wsaws:Address> <wsaws:Metadata xmlns:wsdli="http://www.w3.org/2006/01/wsdl-instance" wsdli:wsdlLocation="http://@jboss.bind.address@:8080/jaxws-samples-wsse-policy-trust-sts-bearer/SecurityTokenService?wsdl"> <wsaw:ServiceName xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" xmlns:stsns="http://docs.oasis-open.org/ws-sx/ws-trust/200512/" EndpointName="UT_Port">stsns:SecurityTokenService</wsaw:ServiceName> </wsaws:Metadata> </sp:Issuer> </sp:IssuedToken> </wsp:Policy> </sp:SignedSupportingTokens> <!-- The sp:Wss11 element declares WSS: SOAP Message Security 1.1 options to be supported by the STS. These particular elements generally refer to how keys are referenced within the SOAP envelope. These are normally handled by Apache CXF. --> <sp:Wss11> <wsp:Policy> <sp:MustSupportRefIssuerSerial /> <sp:MustSupportRefThumbprint /> <sp:MustSupportRefEncryptedKey /> </wsp:Policy> </sp:Wss11> <!-- The sp:Trust13 element declares controls for WS-Trust 1.3 options. They are policy assertions related to exchanges specifically with client and server challenges and entropy behaviors. Again these are normally handled by Apache CXF. --> <sp:Trust13> <wsp:Policy> <sp:MustSupportIssuedTokens /> <sp:RequireClientEntropy /> <sp:RequireServerEntropy /> </wsp:Policy> </sp:Trust13> </wsp:All> </wsp:ExactlyOne> </wsp:Policy> </definitions>
A.8.2.1.2. SSL Configuration
This web service is using HTTPS, therefore the JBoss EAP server must be configured to provide SSL support in the undertow
subsystem. There are two components to SSL configuration:
- Create a certificate keystore.
-
Declare an SSL connector in the
undertow
subsystem of the JBoss EAP server configuration file.
Here is an example of an SSL connector declaration:
<subsystem xmlns="urn:jboss:domain:web:1.4" default-virtual-server="default-host" native="false"> ..... <connector name="jbws-https-connector" protocol="HTTP/1.1" scheme="https" socket-binding="https" secure="true" enabled="true"> <ssl key-alias="tomcat" password="changeit" certificate-key-file="/myJbossHome/security/test.keystore" verify-client="false"/> </connector> ...
Red Hat recommends that SSLv2, SSLv3, and TLSv1.0 be explicitly disabled in favor of TLSv1.1 or TLSv1.2 in all affected packages.
A.8.2.1.3. Bearer Web Service Providers Interface
The BearerIface
Bearer Web Service Provider Interface class is a simple web service definition.
package org.jboss.test.ws.jaxws.samples.wsse.policy.trust.bearer; import javax.jws.WebMethod; import javax.jws.WebService; @WebService ( targetNamespace = "http://www.jboss.org/jbossws/ws-extensions/bearerwssecuritypolicy" ) public interface BearerIface { @WebMethod String sayHello(); }
A.8.2.1.4. Bearer Web Service Providers Implementation
The BearerImpl
Web Service Provider Implementation class 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 Apache CXF runtime. These annotations come from the 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 using the <jaxws:properties>
element on the <jaxws:endpoint>
element in the Spring configuration. 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 asserted by the WSDL for this service. The WSS4J configuration information being provided by BearerImpl
is for Crypto’s Merlin implementation.
Because the web service provider automatically trusts that the incoming SOAP request that came from the subject defined in the SAML token, it is not required for a Crypto CallbackHandler
class or a signature username, unlike in prior examples. However, in order to verify the message signature, the Java properties file that contains the (Merlin) Crypto configuration information is still required.
package org.jboss.test.ws.jaxws.samples.wsse.policy.trust.bearer; import org.apache.cxf.annotations.EndpointProperties; import org.apache.cxf.annotations.EndpointProperty; import javax.jws.WebService; @WebService ( portName = "BearerServicePort", serviceName = "BearerService", wsdlLocation = "WEB-INF/wsdl/BearerService.wsdl", targetNamespace = "http://www.jboss.org/jbossws/ws-extensions/bearerwssecuritypolicy", endpointInterface = "org.jboss.test.ws.jaxws.samples.wsse.policy.trust.bearer.BearerIface" ) @EndpointProperties(value = { @EndpointProperty(key = "ws-security.signature.properties", value = "serviceKeystore.properties") }) public class BearerImpl implements BearerIface { public String sayHello() { return "Bearer WS-Trust Hello World!"; } }
A.8.2.1.5. Crypto Properties and Keystore Files
WSS4J’s Crypto implementation is loaded and configured using a Java properties file that contains Crypto configuration data. The file contains implementation-specific properties such as a keystore location, password, default alias and so on. This application is using the Merlin implementation. The serviceKeystore.properties
file contains this information.
The servicestore.jks
file 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
A.8.2.1.6. Default MANIFEST.MF
When deployed, this application requires access to the JBossWS and Apache 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 Dependencies: org.jboss.ws.cxf.jbossws-cxf-client
A.8.2.2. Bearer Security Token Service
This section lists the crucial elements in providing the Security Token Service functionality for providing a SAML Bearer token. The components include:
A.8.2.2.1. Security Domain
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 EAP server configuration file.
For this scenario the domain needs to contain user alice
, password clarinet
, and role friend
. Refer to the following listings 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.
<security-domain name="JBossWS-trust-sts"> <authentication> <login-module code="UsersRoles" flag="required"> <module-option name="usersProperties" value="/SOME_PATH/jbossws-users.properties"/> <module-option name="unauthenticatedIdentity" value="anonymous"/> <module-option name="rolesProperties" value="/SOME_PATH/jbossws-roles.properties"/> </login-module> </authentication> </security-domain>
Example: .jboss-web.xml
File
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE jboss-web PUBLIC "-//JBoss//DTD Web Application 2.4//EN" "> <jboss-web> <security-domain>java:/jaas/JBossWS-trust-sts</security-domain> </jboss-web>
Example: .jbossws-users.properties
File
# A sample users.properties file for use with the UsersRolesLoginModule alice=clarinet
Example: jbossws-roles.properties
File
# A sample roles.properties file for use with the UsersRolesLoginModule alice=friend
A.8.2.2.2. STS WSDL
<?xml version="1.0" encoding="UTF-8"?> <wsdl:definitions targetNamespace="http://docs.oasis-open.org/ws-sx/ws-trust/200512/" xmlns:tns="http://docs.oasis-open.org/ws-sx/ws-trust/200512/" xmlns:wstrust="http://docs.oasis-open.org/ws-sx/ws-trust/200512/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsap10="http://www.w3.org/2006/05/addressing/wsdl" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsp="http://www.w3.org/ns/ws-policy" xmlns:wst="http://docs.oasis-open.org/ws-sx/ws-trust/200512" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata"> <wsdl:types> <xs:schema elementFormDefault="qualified" targetNamespace='http://docs.oasis-open.org/ws-sx/ws-trust/200512'> <xs:element name='RequestSecurityToken' type='wst:AbstractRequestSecurityTokenType'/> <xs:element name='RequestSecurityTokenResponse' type='wst:AbstractRequestSecurityTokenType'/> <xs:complexType name='AbstractRequestSecurityTokenType'> <xs:sequence> <xs:any namespace='##any' processContents='lax' minOccurs='0' maxOccurs='unbounded'/> </xs:sequence> <xs:attribute name='Context' type='xs:anyURI' use='optional'/> <xs:anyAttribute namespace='##other' processContents='lax'/> </xs:complexType> <xs:element name='RequestSecurityTokenCollection' type='wst:RequestSecurityTokenCollectionType'/> <xs:complexType name='RequestSecurityTokenCollectionType'> <xs:sequence> <xs:element name='RequestSecurityToken' type='wst:AbstractRequestSecurityTokenType' minOccurs='2' maxOccurs='unbounded'/> </xs:sequence> </xs:complexType> <xs:element name='RequestSecurityTokenResponseCollection' type='wst:RequestSecurityTokenResponseCollectionType'/> <xs:complexType name='RequestSecurityTokenResponseCollectionType'> <xs:sequence> <xs:element ref='wst:RequestSecurityTokenResponse' minOccurs='1' maxOccurs='unbounded'/> </xs:sequence> <xs:anyAttribute namespace='##other' processContents='lax'/> </xs:complexType> </xs:schema> </wsdl:types> <!-- WS-Trust defines the following GEDs --> <wsdl:message name="RequestSecurityTokenMsg"> <wsdl:part name="request" element="wst:RequestSecurityToken"/> </wsdl:message> <wsdl:message name="RequestSecurityTokenResponseMsg"> <wsdl:part name="response" element="wst:RequestSecurityTokenResponse"/> </wsdl:message> <wsdl:message name="RequestSecurityTokenCollectionMsg"> <wsdl:part name="requestCollection" element="wst:RequestSecurityTokenCollection"/> </wsdl:message> <wsdl:message name="RequestSecurityTokenResponseCollectionMsg"> <wsdl:part name="responseCollection" element="wst:RequestSecurityTokenResponseCollection"/> </wsdl:message> <!-- This portType an example of a Requestor (or other) endpoint that Accepts SOAP-based challenges from a Security Token Service --> <wsdl:portType name="WSSecurityRequestor"> <wsdl:operation name="Challenge"> <wsdl:input message="tns:RequestSecurityTokenResponseMsg"/> <wsdl:output message="tns:RequestSecurityTokenResponseMsg"/> </wsdl:operation> </wsdl:portType> <!-- This portType is an example of an STS supporting full protocol --> <!-- The wsdl:portType and data types are XML elements defined by the WS_Trust specification. The wsdl:portType defines the endpoints supported in the STS implementation. This WSDL defines all operations that an STS implementation can support. --> <wsdl:portType name="STS"> <wsdl:operation name="Cancel"> <wsdl:input wsam:Action="http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/Cancel" message="tns:RequestSecurityTokenMsg"/> <wsdl:output wsam:Action="http://docs.oasis-open.org/ws-sx/ws-trust/200512/RSTR/CancelFinal" message="tns:RequestSecurityTokenResponseMsg"/> </wsdl:operation> <wsdl:operation name="Issue"> <wsdl:input wsam:Action="http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/Issue" message="tns:RequestSecurityTokenMsg"/> <wsdl:output wsam:Action="http://docs.oasis-open.org/ws-sx/ws-trust/200512/RSTRC/IssueFinal" message="tns:RequestSecurityTokenResponseCollectionMsg"/> </wsdl:operation> <wsdl:operation name="Renew"> <wsdl:input wsam:Action="http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/Renew" message="tns:RequestSecurityTokenMsg"/> <wsdl:output wsam:Action="http://docs.oasis-open.org/ws-sx/ws-trust/200512/RSTR/RenewFinal" message="tns:RequestSecurityTokenResponseMsg"/> </wsdl:operation> <wsdl:operation name="Validate"> <wsdl:input wsam:Action="http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/Validate" message="tns:RequestSecurityTokenMsg"/> <wsdl:output wsam:Action="http://docs.oasis-open.org/ws-sx/ws-trust/200512/RSTR/ValidateFinal" message="tns:RequestSecurityTokenResponseMsg"/> </wsdl:operation> <wsdl:operation name="KeyExchangeToken"> <wsdl:input wsam:Action="http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/KET" message="tns:RequestSecurityTokenMsg"/> <wsdl:output wsam:Action="http://docs.oasis-open.org/ws-sx/ws-trust/200512/RSTR/KETFinal" message="tns:RequestSecurityTokenResponseMsg"/> </wsdl:operation> <wsdl:operation name="RequestCollection"> <wsdl:input message="tns:RequestSecurityTokenCollectionMsg"/> <wsdl:output message="tns:RequestSecurityTokenResponseCollectionMsg"/> </wsdl:operation> </wsdl:portType> <!-- This portType is an example of an endpoint that accepts Unsolicited RequestSecurityTokenResponse messages --> <wsdl:portType name="SecurityTokenResponseService"> <wsdl:operation name="RequestSecurityTokenResponse"> <wsdl:input message="tns:RequestSecurityTokenResponseMsg"/> </wsdl:operation> </wsdl:portType> <!-- The wsp:PolicyReference binds the security requirments on all the STS endpoints. The wsp:Policy wsu:Id="UT_policy" element is later in this file. --> <wsdl:binding name="UT_Binding" type="wstrust:STS"> <wsp:PolicyReference URI="#UT_policy"/> <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/> <wsdl:operation name="Issue"> <soap:operation soapAction="http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/Issue"/> <wsdl:input> <wsp:PolicyReference URI="#Input_policy"/> <soap:body use="literal"/> </wsdl:input> <wsdl:output> <wsp:PolicyReference URI="#Output_policy"/> <soap:body use="literal"/> </wsdl:output> </wsdl:operation> <wsdl:operation name="Validate"> <soap:operation soapAction="http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/Validate"/> <wsdl:input> <wsp:PolicyReference URI="#Input_policy"/> <soap:body use="literal"/> </wsdl:input> <wsdl:output> <wsp:PolicyReference URI="#Output_policy"/> <soap:body use="literal"/> </wsdl:output> </wsdl:operation> <wsdl:operation name="Cancel"> <soap:operation soapAction="http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/Cancel"/> <wsdl:input> <soap:body use="literal"/> </wsdl:input> <wsdl:output> <soap:body use="literal"/> </wsdl:output> </wsdl:operation> <wsdl:operation name="Renew"> <soap:operation soapAction="http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/Renew"/> <wsdl:input> <soap:body use="literal"/> </wsdl:input> <wsdl:output> <soap:body use="literal"/> </wsdl:output> </wsdl:operation> <wsdl:operation name="KeyExchangeToken"> <soap:operation soapAction="http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/KeyExchangeToken"/> <wsdl:input> <soap:body use="literal"/> </wsdl:input> <wsdl:output> <soap:body use="literal"/> </wsdl:output> </wsdl:operation> <wsdl:operation name="RequestCollection"> <soap:operation soapAction="http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/RequestCollection"/> <wsdl:input> <soap:body use="literal"/> </wsdl:input> <wsdl:output> <soap:body use="literal"/> </wsdl:output> </wsdl:operation> </wsdl:binding> <wsdl:service name="SecurityTokenService"> <wsdl:port name="UT_Port" binding="tns:UT_Binding"> <soap:address location="http://localhost:8080/SecurityTokenService/UT"/> </wsdl:port> </wsdl:service> <wsp:Policy wsu:Id="UT_policy"> <wsp:ExactlyOne> <wsp:All> <!-- The sp:UsingAddressing element, indicates that the endpoints of this web service conforms to the WS-Addressing specification. More detail can be found here: [http://www.w3.org/TR/2006/CR-ws-addr-wsdl-20060529] --> <wsap10:UsingAddressing/> <!-- The sp:SymmetricBinding element indicates that security is provided at the SOAP layer and any initiator must authenticate itself by providing WSS UsernameToken credentials. --> <sp:SymmetricBinding xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702"> <wsp:Policy> <!-- In a symmetric binding, the keys used for encrypting and signing in both directions are derived from a single key, the one specified by the sp:ProtectionToken element. The sp:X509Token sub-element declares this key to be a X.509 certificate and the IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/Never" attribute adds the requirement that the token MUST NOT be included in any messages sent between the initiator and the recipient; rather, an external reference to the token should be used. Lastly the WssX509V3Token10 sub-element declares that the Username token presented by the initiator should be compliant with Web Services Security UsernameToken Profile 1.0 specification. [ http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0.pdf ] --> <sp:ProtectionToken> <wsp:Policy> <sp:X509Token sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/Never"> <wsp:Policy> <sp:RequireDerivedKeys/> <sp:RequireThumbprintReference/> <sp:WssX509V3Token10/> </wsp:Policy> </sp:X509Token> </wsp:Policy> </sp:ProtectionToken> <!-- The sp:AlgorithmSuite element, requires the Basic256 algorithm suite be used in performing cryptographic operations. --> <sp:AlgorithmSuite> <wsp:Policy> <sp:Basic256/> </wsp:Policy> </sp:AlgorithmSuite> <!-- The sp:Layout element, indicates the layout rules to apply when adding items to the security header. The sp:Lax sub-element indicates items are added to the security header in any order that conforms to WSS: SOAP Message Security. --> <sp:Layout> <wsp:Policy> <sp:Lax/> </wsp:Policy> </sp:Layout> <sp:IncludeTimestamp/> <sp:EncryptSignature/> <sp:OnlySignEntireHeadersAndBody/> </wsp:Policy> </sp:SymmetricBinding> <!-- The sp:SignedSupportingTokens element declares that the security header of messages must contain a sp:UsernameToken and the token must be signed. The attribute IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient" on sp:UsernameToken indicates that the token MUST be included in all messages sent from initiator to the recipient and that the token MUST NOT be included in messages sent from the recipient to the initiator. And finally the element sp:WssUsernameToken10 is a policy assertion indicating the Username token should be as defined in Web Services Security UsernameToken Profile 1.0 --> <sp:SignedSupportingTokens xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702"> <wsp:Policy> <sp:UsernameToken sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient"> <wsp:Policy> <sp:WssUsernameToken10/> </wsp:Policy> </sp:UsernameToken> </wsp:Policy> </sp:SignedSupportingTokens> <!-- The sp:Wss11 element declares WSS: SOAP Message Security 1.1 options to be supported by the STS. These particular elements generally refer to how keys are referenced within the SOAP envelope. These are normally handled by Apache CXF. --> <sp:Wss11 xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702"> <wsp:Policy> <sp:MustSupportRefKeyIdentifier/> <sp:MustSupportRefIssuerSerial/> <sp:MustSupportRefThumbprint/> <sp:MustSupportRefEncryptedKey/> </wsp:Policy> </sp:Wss11> <!-- The sp:Trust13 element declares controls for WS-Trust 1.3 options. They are policy assertions related to exchanges specifically with client and server challenges and entropy behaviors. Again these are normally handled by Apache CXF. --> <sp:Trust13 xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702"> <wsp:Policy> <sp:MustSupportIssuedTokens/> <sp:RequireClientEntropy/> <sp:RequireServerEntropy/> </wsp:Policy> </sp:Trust13> </wsp:All> </wsp:ExactlyOne> </wsp:Policy> <wsp:Policy wsu:Id="Input_policy"> <wsp:ExactlyOne> <wsp:All> <sp:SignedParts xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702"> <sp:Body/> <sp:Header Name="To" Namespace="http://www.w3.org/2005/08/addressing"/> <sp:Header Name="From" Namespace="http://www.w3.org/2005/08/addressing"/> <sp:Header Name="FaultTo" Namespace="http://www.w3.org/2005/08/addressing"/> <sp:Header Name="ReplyTo" Namespace="http://www.w3.org/2005/08/addressing"/> <sp:Header Name="MessageID" Namespace="http://www.w3.org/2005/08/addressing"/> <sp:Header Name="RelatesTo" Namespace="http://www.w3.org/2005/08/addressing"/> <sp:Header Name="Action" Namespace="http://www.w3.org/2005/08/addressing"/> </sp:SignedParts> </wsp:All> </wsp:ExactlyOne> </wsp:Policy> <wsp:Policy wsu:Id="Output_policy"> <wsp:ExactlyOne> <wsp:All> <sp:SignedParts xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702"> <sp:Body/> <sp:Header Name="To" Namespace="http://www.w3.org/2005/08/addressing"/> <sp:Header Name="From" Namespace="http://www.w3.org/2005/08/addressing"/> <sp:Header Name="FaultTo" Namespace="http://www.w3.org/2005/08/addressing"/> <sp:Header Name="ReplyTo" Namespace="http://www.w3.org/2005/08/addressing"/> <sp:Header Name="MessageID" Namespace="http://www.w3.org/2005/08/addressing"/> <sp:Header Name="RelatesTo" Namespace="http://www.w3.org/2005/08/addressing"/> <sp:Header Name="Action" Namespace="http://www.w3.org/2005/08/addressing"/> </sp:SignedParts> </wsp:All> </wsp:ExactlyOne> </wsp:Policy> </wsdl:definitions>
A.8.2.2.3. STS 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 and its components are configurable or replaceable. There are optional features that are enabled by implementing and configuring plugins. You can customize your own STS by extending from SecurityTokenServiceProvider
and overriding the default settings.
The SampleSTSBearer
STS implementation class is a POJO that extends from SecurityTokenServiceProvider
.
The SampleSTSBearer
class is defined with a WebServiceProvider
annotation and not a WebService
annotation. This annotation defines the service as a Provider
-based endpoint, it supports a messaging-oriented approach to web services. In particular, it signals that the exchanged messages will be XML documents. SecurityTokenServiceProvider
is an implementation of the javax.xml.ws.Provider
interface. In comparison the WebService
annotation defines a service endpoint interface-based endpoint, which supports message exchange using SOAP envelopes.
As done in the BearerImpl
class, the WSS4J annotations EndpointProperties
and EndpointProperty
provide endpoint configuration for the Apache CXF runtime. The first EndpointProperty
statement in the listing is declaring the user’s name to use for the message signature. It is used as the alias name in the keystore to get the user’s certificate and private key for signature. The next two EndpointProperty
statements declare the Java properties file that contains the (Merlin) Crypto configuration information. In this case both for signing and encrypting the messages. WSS4J reads this file and required information for message handling. The last EndpointProperty
statement declares the STSBearerCallbackHandler
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, token validation, and their static properties.
StaticSTSProperties
is used to set select properties for configuring resources in STS. This may seem like 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 are 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
default behavior and performing SAML token processing. Apache CXF provides an implementation of a SAMLTokenProvider
, which can be used rather than creating one.
package org.jboss.test.ws.jaxws.samples.wsse.policy.trust.stsbearer; 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; @WebServiceProvider(serviceName = "SecurityTokenService", portName = "UT_Port", targetNamespace = "http://docs.oasis-open.org/ws-sx/ws-trust/200512/", wsdlLocation = "WEB-INF/wsdl/bearer-ws-trust-1.4-service.wsdl") //dependency on org.apache.cxf module or on module that exports org.apache.cxf (e.g. org.jboss.ws.cxf.jbossws-cxf-client) is needed, otherwise Apache CXF annotations are ignored @EndpointProperties(value = { @EndpointProperty(key = "ws-security.signature.username", value = "mystskey"), @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.stsbearer.STSBearerCallbackHandler") }) public class SampleSTSBearer extends SecurityTokenServiceProvider { public SampleSTSBearer() throws Exception { super(); StaticSTSProperties props = new StaticSTSProperties(); props.setSignatureCryptoProperties("stsKeystore.properties"); props.setSignatureUsername("mystskey"); props.setCallbackHandlerClass(STSBearerCallbackHandler.class.getName()); props.setEncryptionCryptoProperties("stsKeystore.properties"); props.setEncryptionUsername("myservicekey"); props.setIssuer("DoubleItSTSIssuer"); List<ServiceMBean> services = new LinkedList<ServiceMBean>(); StaticService service = new StaticService(); service.setEndpoints(Arrays.asList( "https://localhost:(\\d)*/jaxws-samples-wsse-policy-trust-bearer/BearerService", "https://\\[::1\\]:(\\d)*/jaxws-samples-wsse-policy-trust-bearer/BearerService", "https://\\[0:0:0:0:0:0:0:1\\]:(\\d)*/jaxws-samples-wsse-policy-trust-bearer/BearerService" )); services.add(service); TokenIssueOperation issueOperation = new TokenIssueOperation(); issueOperation.getTokenProviders().add(new SAMLTokenProvider()); issueOperation.setServices(services); issueOperation.setStsProperties(props); this.setIssueOperation(issueOperation); } }
A.8.2.2.4. STSBearerCallbackHandler Class
STSBearerCallbackHandler
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 Apache CXF to retrieve the password of the user name to use for the message signature.
package org.jboss.test.ws.jaxws.samples.wsse.policy.trust.stsbearer; import org.jboss.wsf.stack.cxf.extensions.security.PasswordCallbackHandler; import java.util.HashMap; import java.util.Map; public class STSBearerCallbackHandler extends PasswordCallbackHandler { public STSBearerCallbackHandler() { super(getInitMap()); } private static Map<String, String> getInitMap() { Map<String, String> passwords = new HashMap<String, String>(); passwords.put("mystskey", "stskpass"); passwords.put("alice", "clarinet"); return passwords; } }
A.8.2.2.5. Crypto Properties and Keystore Files
WSS4J’s Crypto implementation is loaded and configured using a Java properties file that contains Crypto configuration data. The file contains implementation-specific properties such as a keystore location, password, default alias and so on. This application is using the Merlin implementation. The stsKeystore.properties
file contains this information.
The servicestore.jks
file 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
A.8.2.2.6. Default MANIFEST.MF
This application requires access to the JBossWS and Apache CXF APIs provided in the org.jboss.ws.cxf.jbossws-cxf-client
module. The org.jboss.ws.cxf.sts
module is also needed to build the STS configuration in the SampleSTS
constructor. The dependency statement directs the server to provide them at deployment.
Manifest-Version: 1.0 Dependencies: org.jboss.ws.cxf.jbossws-cxf-client,org.jboss.ws.cxf.sts
A.8.2.3. Web Service Requester
This section provides the details of crucial elements in calling a web service that implements endpoint security as described in the SAML Bearer scenario. The components that will be discussed include:
A.8.2.3.1. 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 required for message generation. In addition, the STSClient
that communicates with the STS is configured with similar values.
The key strings ending with a .it
suffix flags these settings as belonging to the STSClient
. The internal Apache 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 Apache CXF code uses this object and does 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.
String serviceURL = "https://" + getServerHost() + ":8443/jaxws-samples-wsse-policy-trust-bearer/BearerService"; final QName serviceName = new QName("http://www.jboss.org/jbossws/ws-extensions/bearerwssecuritypolicy", "BearerService"); Service service = Service.create(new URL(serviceURL + "?wsdl"), serviceName); BearerIface proxy = (BearerIface) service.getPort(BearerIface.class); Map<String, Object> 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();
A.8.2.3.2. 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 Apache CXF to retrieve the password of the user name to use for the message signature.
The user alice
and password have been provided here. This information is not in the (JKS) keystore but provided in the security domain. It is declared in jbossws-users.properties
file.
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; } } } } }
A.8.2.3.3. Crypto Properties and Keystore Files
WSS4J’s Crypto implementation is loaded and configured using a Java properties file that contains Crypto configuration data. The file contains implementation-specific properties such as a keystore location, password, default alias and so on. This application is using the Merlin implementation. The clientKeystore.properties
file contains this information.
The clientstore.jks
file 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
A.8.3. Scenario: OnBehalfOf WS-Trust
The OnBehalfOf
feature is used in scenarios that use the proxy pattern. In such scenarios, the client cannot access the STS directly, instead it communicates through a proxy gateway. The proxy gateway authenticates the caller and puts information about the caller into the OnBehalfOf
element of the RequestSecurityToken
(RST) sent to the real STS for processing. The resulting token contains only claims related to the client of the proxy, making the proxy completely transparent to the receiver of the issued token.
OnBehalfOf
is nothing more than a new sub-element in the RST. It provides additional information about the original caller when a token is negotiated with the STS. The OnBehalfOf
element usually takes the form of a token with identity claims such as name, role, and authorization code, for the client to access the service.
The OnBehalfOf
scenario is an extension of the basic WS-Trust scenario. In this example the OnBehalfOf
service calls the ws-service
on behalf of a user. There are only a couple of additions to the basic scenario’s code. An OnBehalfOf
web service provider and callback handler have been added. The OnBehalfOf
web services' WSDL imposes the same security policies as the ws-provider
. UsernameTokenCallbackHandler
is a utility shared with ActAs
. It generates the content for the OnBehalfOf
element. Lastly, there are code additions in the STS that both OnBehalfOf
and ActAs
share in common.
A.8.3.1. Web Service Provider
This section provides the web service elements from the basic WS-Trust scenario that have been updated to address the requirements of the OnBehalfOf
example. The components include:
A.8.3.1.1. Web Service Provider WSDL
The OnBehalfOf
web service provider’s WSDL is a clone of the ws-provider’s
WSDL. The wsp:Policy
section is the same. There are updates to the service endpoint, targetNamespace
, portType
, binding
name, and service
.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <definitions targetNamespace="http://www.jboss.org/jbossws/ws-extensions/onbehalfofwssecuritypolicy" name="OnBehalfOfService" xmlns:tns="http://www.jboss.org/jbossws/ws-extensions/onbehalfofwssecuritypolicy" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:wsp="http://www.w3.org/ns/ws-policy" xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsaws="http://www.w3.org/2005/08/addressing" xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702" xmlns:t="http://docs.oasis-open.org/ws-sx/ws-trust/200512"> <types> <xsd:schema> <xsd:import namespace="http://www.jboss.org/jbossws/ws-extensions/onbehalfofwssecuritypolicy" schemaLocation="OnBehalfOfService_schema1.xsd"/> </xsd:schema> </types> <message name="sayHello"> <part name="parameters" element="tns:sayHello"/> </message> <message name="sayHelloResponse"> <part name="parameters" element="tns:sayHelloResponse"/> </message> <portType name="OnBehalfOfServiceIface"> <operation name="sayHello"> <input message="tns:sayHello"/> <output message="tns:sayHelloResponse"/> </operation> </portType> <binding name="OnBehalfOfServicePortBinding" type="tns:OnBehalfOfServiceIface"> <wsp:PolicyReference URI="#AsymmetricSAML2Policy" /> <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/> <operation name="sayHello"> <soap:operation soapAction=""/> <input> <soap:body use="literal"/> <wsp:PolicyReference URI="#Input_Policy" /> </input> <output> <soap:body use="literal"/> <wsp:PolicyReference URI="#Output_Policy" /> </output> </operation> </binding> <service name="OnBehalfOfService"> <port name="OnBehalfOfServicePort" binding="tns:OnBehalfOfServicePortBinding"> <soap:address location="http://@jboss.bind.address@:8080/jaxws-samples-wsse-policy-trust-onbehalfof/OnBehalfOfService"/> </port> </service> </definitions>
A.8.3.1.2. Web Service Provider Interface
The OnBehalfOfServiceIface
web service provider interface class is a simple web service definition.
package org.jboss.test.ws.jaxws.samples.wsse.policy.trust.onbehalfof; import javax.jws.WebMethod; import javax.jws.WebService; @WebService ( targetNamespace = "http://www.jboss.org/jbossws/ws-extensions/onbehalfofwssecuritypolicy" ) public interface OnBehalfOfServiceIface { @WebMethod String sayHello(); }
A.8.3.1.3. Web Service Provider Implementation
The OnBehalfOfServiceImpl
web service provider implementation class is a simple POJO. It uses the standard WebService
annotation to define the service endpoint and two Apache WSS4J annotations, EndpointProperties
and EndpointProperty
used for configuring the endpoint for the Apache CXF runtime. The WSS4J configuration information provided is for WSS4J’s Crypto Merlin implementation.
OnBehalfOfServiceImpl
calls the ServiceImpl
acting on behalf of the user. The setupService
method performs the required configuration setup.
package org.jboss.test.ws.jaxws.samples.wsse.policy.trust.onbehalfof; import org.apache.cxf.Bus; import org.apache.cxf.BusFactory; import org.apache.cxf.annotations.EndpointProperties; import org.apache.cxf.annotations.EndpointProperty; import org.apache.cxf.ws.security.SecurityConstants; import org.apache.cxf.ws.security.trust.STSClient; import org.jboss.test.ws.jaxws.samples.wsse.policy.trust.service.ServiceIface; import org.jboss.test.ws.jaxws.samples.wsse.policy.trust.shared.WSTrustAppUtils; import javax.jws.WebService; import javax.xml.namespace.QName; import javax.xml.ws.BindingProvider; import javax.xml.ws.Service; import java.net.*; import java.util.Map; @WebService ( portName = "OnBehalfOfServicePort", serviceName = "OnBehalfOfService", wsdlLocation = "WEB-INF/wsdl/OnBehalfOfService.wsdl", targetNamespace = "http://www.jboss.org/jbossws/ws-extensions/onbehalfofwssecuritypolicy", endpointInterface = "org.jboss.test.ws.jaxws.samples.wsse.policy.trust.onbehalfof.OnBehalfOfServiceIface" ) @EndpointProperties(value = { @EndpointProperty(key = "ws-security.signature.username", value = "myactaskey"), @EndpointProperty(key = "ws-security.signature.properties", value = "actasKeystore.properties"), @EndpointProperty(key = "ws-security.encryption.properties", value = "actasKeystore.properties"), @EndpointProperty(key = "ws-security.callback-handler", value = "org.jboss.test.ws.jaxws.samples.wsse.policy.trust.onbehalfof.OnBehalfOfCallbackHandler") }) public class OnBehalfOfServiceImpl implements OnBehalfOfServiceIface { public String sayHello() { try { ServiceIface proxy = setupService(); return "OnBehalfOf " + proxy.sayHello(); } catch (MalformedURLException e) { e.printStackTrace(); } return null; } /** * * @return * @throws MalformedURLException */ private ServiceIface setupService()throws MalformedURLException { ServiceIface proxy = null; Bus bus = BusFactory.newInstance().createBus(); try { BusFactory.setThreadDefaultBus(bus); final String serviceURL = "http://" + WSTrustAppUtils.getServerHost() + ":8080/jaxws-samples-wsse-policy-trust/SecurityService"; final QName serviceName = new QName("http://www.jboss.org/jbossws/ws-extensions/wssecuritypolicy", "SecurityService"); final URL wsdlURL = new URL(serviceURL + "?wsdl"); Service service = Service.create(wsdlURL, serviceName); proxy = (ServiceIface) service.getPort(ServiceIface.class); Map<String, Object> ctx = ((BindingProvider) proxy).getRequestContext(); ctx.put(SecurityConstants.CALLBACK_HANDLER, new OnBehalfOfCallbackHandler()); ctx.put(SecurityConstants.SIGNATURE_PROPERTIES, Thread.currentThread().getContextClassLoader().getResource( "actasKeystore.properties" )); ctx.put(SecurityConstants.SIGNATURE_USERNAME, "myactaskey" ); ctx.put(SecurityConstants.ENCRYPT_PROPERTIES, Thread.currentThread().getContextClassLoader().getResource( "../../META-INF/clientKeystore.properties" )); ctx.put(SecurityConstants.ENCRYPT_USERNAME, "myservicekey"); STSClient stsClient = new STSClient(bus); Map<String, Object> props = stsClient.getProperties(); props.put(SecurityConstants.USERNAME, "bob"); props.put(SecurityConstants.ENCRYPT_USERNAME, "mystskey"); props.put(SecurityConstants.STS_TOKEN_USERNAME, "myactaskey" ); props.put(SecurityConstants.STS_TOKEN_PROPERTIES, Thread.currentThread().getContextClassLoader().getResource( "actasKeystore.properties" )); props.put(SecurityConstants.STS_TOKEN_USE_CERT_FOR_KEYINFO, "true"); ctx.put(SecurityConstants.STS_CLIENT, stsClient); } finally { bus.shutdown(true); } return proxy; } }
A.8.3.1.4. OnBehalfOfCallbackHandler Class
The OnBehalfOfCallbackHandler
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 Apache CXF to retrieve the password of the user name to use for the message signature. This class has been updated to return the passwords for this service, myactaskey
and the OnBehalfOf
user, alice
.
package org.jboss.test.ws.jaxws.samples.wsse.policy.trust.onbehalfof; import org.jboss.wsf.stack.cxf.extensions.security.PasswordCallbackHandler; import java.util.HashMap; import java.util.Map; public class OnBehalfOfCallbackHandler extends PasswordCallbackHandler { public OnBehalfOfCallbackHandler() { super(getInitMap()); } private static Map<String, String> getInitMap() { Map<String, String> passwords = new HashMap<String, String>(); passwords.put("myactaskey", "aspass"); passwords.put("alice", "clarinet"); passwords.put("bob", "trombone"); return passwords; } }
A.8.3.2. Web Service Requester
This section provides details of the ws-requester
elements from the basic WS-Trust scenario that have been updated to address the requirements of the OnBehalfOf
example. The component is:
A.8.3.2.1. OnBehalfOf Web Service Requester Implementation Class
The OnBehalfOf
ws-requester
, the client, uses standard procedures for creating a reference to the web service in the first four lines. To address the endpoint security requirements, the web service’s request context is configured using the BindingProvider
. Information needed in the message generation is provided through it. The OnBehalfOf
user, alice
, is declared in this section and the callbackHandler
, UsernameTokenCallbackHandler
is provided to the STSClient
for generation of the contents for the OnBehalfOf
message element. In this example an STSClient
object is created and provided to the proxy’s request context. The alternative is to provide keys tagged with the .it
suffix as done in the Basic Scenario client. The use of OnBehalfOf
is configured by the stsClient.setOnBehalfOf
call method. The alternative is to use the key SecurityConstants.STS_TOKEN_ON_BEHALF_OF
and a value in the properties map.
final QName serviceName = new QName("http://www.jboss.org/jbossws/ws-extensions/onbehalfofwssecuritypolicy", "OnBehalfOfService"); final URL wsdlURL = new URL(serviceURL + "?wsdl"); Service service = Service.create(wsdlURL, serviceName); OnBehalfOfServiceIface proxy = (OnBehalfOfServiceIface) service.getPort(OnBehalfOfServiceIface.class); Bus bus = BusFactory.newInstance().createBus(); try { BusFactory.setThreadDefaultBus(bus); Map<String, Object> ctx = proxy.getRequestContext(); ctx.put(SecurityConstants.CALLBACK_HANDLER, new ClientCallbackHandler()); ctx.put(SecurityConstants.ENCRYPT_PROPERTIES, Thread.currentThread().getContextClassLoader().getResource( "META-INF/clientKeystore.properties")); ctx.put(SecurityConstants.ENCRYPT_USERNAME, "myactaskey"); ctx.put(SecurityConstants.SIGNATURE_PROPERTIES, Thread.currentThread().getContextClassLoader().getResource( "META-INF/clientKeystore.properties")); ctx.put(SecurityConstants.SIGNATURE_USERNAME, "myclientkey"); // user and password OnBehalfOf user // UsernameTokenCallbackHandler will extract this information when called ctx.put(SecurityConstants.USERNAME,"alice"); ctx.put(SecurityConstants.PASSWORD, "clarinet"); STSClient stsClient = new STSClient(bus); // Providing the STSClient the mechanism to create the claims contents for OnBehalfOf stsClient.setOnBehalfOf(new UsernameTokenCallbackHandler()); Map<String, Object> props = stsClient.getProperties(); props.put(SecurityConstants.CALLBACK_HANDLER, new ClientCallbackHandler()); props.put(SecurityConstants.ENCRYPT_PROPERTIES, Thread.currentThread().getContextClassLoader().getResource( "META-INF/clientKeystore.properties")); props.put(SecurityConstants.ENCRYPT_USERNAME, "mystskey"); props.put(SecurityConstants.STS_TOKEN_USERNAME, "myclientkey"); props.put(SecurityConstants.STS_TOKEN_PROPERTIES, Thread.currentThread().getContextClassLoader().getResource( "META-INF/clientKeystore.properties")); props.put(SecurityConstants.STS_TOKEN_USE_CERT_FOR_KEYINFO, "true"); ctx.put(SecurityConstants.STS_CLIENT, stsClient); } finally { bus.shutdown(true); } proxy.sayHello();
A.8.4. Scenario: ActAs WS-Trust
The ActAs
feature is used in scenarios that require composite delegation. It is commonly used in multi-tiered systems where an application calls a service on behalf of a logged in user, or a service calls another service on behalf of the original caller.
ActAs
is nothing more than a new sub-element in the RequestSecurityToken
(RST). It provides additional information about the original caller when a token is negotiated with the STS. The ActAs
element usually takes the form of a token with identity claims such as name, role, and authorization code, for the client to access the service.
The ActAs
scenario is an extension of the basic WS-Trust scenario. In this example the ActAs
service calls the ws-service
on behalf of a user. There are only a couple of additions to the basic scenario’s code. An ActAs
web service provider and callback handler have been added. The ActAs
web services' WSDL imposes the same security policies as the ws-provider
. UsernameTokenCallbackHandler
is a new utility that generates the content for the ActAs
element. Lastly, there are a couple of code additions in the STS to support the ActAs
request.
A.8.4.1. Web Service Provider
This section provides details about the web service elements from the basic WS-Trust scenario that have been changed to address the needs of the ActAs
example. The components include:
A.8.4.1.1. Web Service Provider WSDL
The ActAs
web service provider’s WSDL is a clone of the ws-provider’s
WSDL. The wsp:Policy
section is the same. There are changes to the service endpoint, targetNamespace
, portType
, binding
name, and service
.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <definitions targetNamespace="http://www.jboss.org/jbossws/ws-extensions/actaswssecuritypolicy" name="ActAsService" xmlns:tns="http://www.jboss.org/jbossws/ws-extensions/actaswssecuritypolicy" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:wsp="http://www.w3.org/ns/ws-policy" xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsaws="http://www.w3.org/2005/08/addressing" xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702" xmlns:t="http://docs.oasis-open.org/ws-sx/ws-trust/200512"> <types> <xsd:schema> <xsd:import namespace="http://www.jboss.org/jbossws/ws-extensions/actaswssecuritypolicy" schemaLocation="ActAsService_schema1.xsd"/> </xsd:schema> </types> <message name="sayHello"> <part name="parameters" element="tns:sayHello"/> </message> <message name="sayHelloResponse"> <part name="parameters" element="tns:sayHelloResponse"/> </message> <portType name="ActAsServiceIface"> <operation name="sayHello"> <input message="tns:sayHello"/> <output message="tns:sayHelloResponse"/> </operation> </portType> <binding name="ActAsServicePortBinding" type="tns:ActAsServiceIface"> <wsp:PolicyReference URI="#AsymmetricSAML2Policy" /> <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/> <operation name="sayHello"> <soap:operation soapAction=""/> <input> <soap:body use="literal"/> <wsp:PolicyReference URI="#Input_Policy" /> </input> <output> <soap:body use="literal"/> <wsp:PolicyReference URI="#Output_Policy" /> </output> </operation> </binding> <service name="ActAsService"> <port name="ActAsServicePort" binding="tns:ActAsServicePortBinding"> <soap:address location="http://@jboss.bind.address@:8080/jaxws-samples-wsse-policy-trust-actas/ActAsService"/> </port> </service> </definitions>
A.8.4.1.2. Web Service Provider Interface
The ActAsServiceIface
web service provider interface class is a simple web service definition.
package org.jboss.test.ws.jaxws.samples.wsse.policy.trust.actas; import javax.jws.WebMethod; import javax.jws.WebService; @WebService ( targetNamespace = "http://www.jboss.org/jbossws/ws-extensions/actaswssecuritypolicy" ) public interface ActAsServiceIface { @WebMethod String sayHello(); }
A.8.4.1.3. Web Service Provider Implementation
The ActAsServiceImpl
web service provider implementation class is a simple POJO. It uses the standard WebService
annotation to define the service endpoint and two Apache WSS4J annotations, EndpointProperties
, and EndpointProperty
, used for configuring the endpoint for the Apache CXF runtime. The WSS4J configuration information provided is for WSS4J’s Crypto Merlin implementation.
ActAsServiceImpl
is calling ServiceImpl
acting on behalf of the user. The setupService
method performs the required configuration setup.
package org.jboss.test.ws.jaxws.samples.wsse.policy.trust.actas; import org.apache.cxf.Bus; import org.apache.cxf.BusFactory; import org.apache.cxf.annotations.EndpointProperties; import org.apache.cxf.annotations.EndpointProperty; import org.apache.cxf.ws.security.SecurityConstants; import org.apache.cxf.ws.security.trust.STSClient; import org.jboss.test.ws.jaxws.samples.wsse.policy.trust.service.ServiceIface; import org.jboss.test.ws.jaxws.samples.wsse.policy.trust.shared.WSTrustAppUtils; import javax.jws.WebService; import javax.xml.namespace.QName; import javax.xml.ws.BindingProvider; import javax.xml.ws.Service; import java.net.MalformedURLException; import java.net.URL; import java.util.Map; @WebService ( portName = "ActAsServicePort", serviceName = "ActAsService", wsdlLocation = "WEB-INF/wsdl/ActAsService.wsdl", targetNamespace = "http://www.jboss.org/jbossws/ws-extensions/actaswssecuritypolicy", endpointInterface = "org.jboss.test.ws.jaxws.samples.wsse.policy.trust.actas.ActAsServiceIface" ) @EndpointProperties(value = { @EndpointProperty(key = "ws-security.signature.username", value = "myactaskey"), @EndpointProperty(key = "ws-security.signature.properties", value = "actasKeystore.properties"), @EndpointProperty(key = "ws-security.encryption.properties", value = "actasKeystore.properties"), @EndpointProperty(key = "ws-security.callback-handler", value = "org.jboss.test.ws.jaxws.samples.wsse.policy.trust.actas.ActAsCallbackHandler") }) public class ActAsServiceImpl implements ActAsServiceIface { public String sayHello() { try { ServiceIface proxy = setupService(); return "ActAs " + proxy.sayHello(); } catch (MalformedURLException e) { e.printStackTrace(); } return null; } private ServiceIface setupService()throws MalformedURLException { ServiceIface proxy = null; Bus bus = BusFactory.newInstance().createBus(); try { BusFactory.setThreadDefaultBus(bus); final String serviceURL = "http://" + WSTrustAppUtils.getServerHost() + ":8080/jaxws-samples-wsse-policy-trust/SecurityService"; final QName serviceName = new QName("http://www.jboss.org/jbossws/ws-extensions/wssecuritypolicy", "SecurityService"); final URL wsdlURL = new URL(serviceURL + "?wsdl"); Service service = Service.create(wsdlURL, serviceName); proxy = (ServiceIface) service.getPort(ServiceIface.class); Map<String, Object> ctx = ((BindingProvider) proxy).getRequestContext(); ctx.put(SecurityConstants.CALLBACK_HANDLER, new ActAsCallbackHandler()); ctx.put(SecurityConstants.SIGNATURE_PROPERTIES, Thread.currentThread().getContextClassLoader().getResource("actasKeystore.properties" )); ctx.put(SecurityConstants.SIGNATURE_USERNAME, "myactaskey" ); ctx.put(SecurityConstants.ENCRYPT_PROPERTIES, Thread.currentThread().getContextClassLoader().getResource("../../META-INF/clientKeystore.properties" )); ctx.put(SecurityConstants.ENCRYPT_USERNAME, "myservicekey"); STSClient stsClient = new STSClient(bus); Map<String, Object> props = stsClient.getProperties(); props.put(SecurityConstants.USERNAME, "alice"); props.put(SecurityConstants.ENCRYPT_USERNAME, "mystskey"); props.put(SecurityConstants.STS_TOKEN_USERNAME, "myactaskey" ); props.put(SecurityConstants.STS_TOKEN_PROPERTIES, Thread.currentThread().getContextClassLoader().getResource("actasKeystore.properties" )); props.put(SecurityConstants.STS_TOKEN_USE_CERT_FOR_KEYINFO, "true"); ctx.put(SecurityConstants.STS_CLIENT, stsClient); } finally { bus.shutdown(true); } return proxy; } }
A.8.4.1.4. ActAsCallbackHandler Class
ActAsCallbackHandler
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 Apache CXF to retrieve the password of the user name to use for the message signature. This class has been updated to return the passwords for this service, myactaskey
and the ActAs
user, alice
.
package org.jboss.test.ws.jaxws.samples.wsse.policy.trust.actas; import org.jboss.wsf.stack.cxf.extensions.security.PasswordCallbackHandler; import java.util.HashMap; import java.util.Map; public class ActAsCallbackHandler extends PasswordCallbackHandler { public ActAsCallbackHandler() { super(getInitMap()); } private static Map<String, String> getInitMap() { Map<String, String> passwords = new HashMap<String, String>(); passwords.put("myactaskey", "aspass"); passwords.put("alice", "clarinet"); return passwords; } }
A.8.4.1.5. UsernameTokenCallbackHandler
The ActAs
and OnBeholdOf
sub-elements of the RequestSecurityToken
have to be defined as WSSE UsernameTokens
. This utility generates the properly formatted element.
package org.jboss.test.ws.jaxws.samples.wsse.policy.trust.shared; import org.apache.cxf.helpers.DOMUtils; import org.apache.cxf.message.Message; import org.apache.cxf.ws.security.SecurityConstants; import org.apache.cxf.ws.security.trust.delegation.DelegationCallback; import org.apache.ws.security.WSConstants; import org.apache.ws.security.message.token.UsernameToken; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.Element; import org.w3c.dom.ls.DOMImplementationLS; import org.w3c.dom.ls.LSSerializer; import javax.security.auth.callback.Callback; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.UnsupportedCallbackException; import java.io.IOException; import java.util.Map; /** * A utility to provide the 3 different input parameter types for jaxws property * "ws-security.sts.token.act-as" and "ws-security.sts.token.on-behalf-of". * This implementation obtains a username and password via the jaxws property * "ws-security.username" and "ws-security.password" respectively, as defined * in SecurityConstants. It creates a wss UsernameToken to be used as the * delegation token. */ public class UsernameTokenCallbackHandler implements CallbackHandler { public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { for (int i = 0; i < callbacks.length; i++) { if (callbacks[i] instanceof DelegationCallback) { DelegationCallback callback = (DelegationCallback) callbacks[i]; Message message = callback.getCurrentMessage(); String username = (String)message.getContextualProperty(SecurityConstants.USERNAME); String password = (String)message.getContextualProperty(SecurityConstants.PASSWORD); if (username != null) { Node contentNode = message.getContent(Node.class); Document doc = null; if (contentNode != null) { doc = contentNode.getOwnerDocument(); } else { doc = DOMUtils.createDocument(); } UsernameToken usernameToken = createWSSEUsernameToken(username,password, doc); callback.setToken(usernameToken.getElement()); } } else { throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback"); } } } /** * Provide UsernameToken as a string. * @param ctx * @return */ public String getUsernameTokenString(Map<String, Object> ctx){ Document doc = DOMUtils.createDocument(); String result = null; String username = (String)ctx.get(SecurityConstants.USERNAME); String password = (String)ctx.get(SecurityConstants.PASSWORD); if (username != null) { UsernameToken usernameToken = createWSSEUsernameToken(username,password, doc); result = toString(usernameToken.getElement().getFirstChild().getParentNode()); } return result; } /** * * @param username * @param password * @return */ public String getUsernameTokenString(String username, String password){ Document doc = DOMUtils.createDocument(); String result = null; if (username != null) { UsernameToken usernameToken = createWSSEUsernameToken(username,password, doc); result = toString(usernameToken.getElement().getFirstChild().getParentNode()); } return result; } /** * Provide UsernameToken as a DOM Element. * @param ctx * @return */ public Element getUsernameTokenElement(Map<String, Object> ctx){ Document doc = DOMUtils.createDocument(); Element result = null; UsernameToken usernameToken = null; String username = (String)ctx.get(SecurityConstants.USERNAME); String password = (String)ctx.get(SecurityConstants.PASSWORD); if (username != null) { usernameToken = createWSSEUsernameToken(username,password, doc); result = usernameToken.getElement(); } return result; } /** * * @param username * @param password * @return */ public Element getUsernameTokenElement(String username, String password){ Document doc = DOMUtils.createDocument(); Element result = null; UsernameToken usernameToken = null; if (username != null) { usernameToken = createWSSEUsernameToken(username,password, doc); result = usernameToken.getElement(); } return result; } private UsernameToken createWSSEUsernameToken(String username, String password, Document doc) { UsernameToken usernameToken = new UsernameToken(true, doc, (password == null)? null: WSConstants.PASSWORD_TEXT); usernameToken.setName(username); usernameToken.addWSUNamespace(); usernameToken.addWSSENamespace(); usernameToken.setID("id-" + username); if (password != null){ usernameToken.setPassword(password); } return usernameToken; } private String toString(Node node) { String str = null; if (node != null) { DOMImplementationLS lsImpl = (DOMImplementationLS) node.getOwnerDocument().getImplementation().getFeature("LS", "3.0"); LSSerializer serializer = lsImpl.createLSSerializer(); serializer.getDomConfig().setParameter("xml-declaration", false); //by default its true, so set it to false to get String without xml-declaration str = serializer.writeToString(node); } return str; } }
A.8.4.1.6. Crypto properties and keystore files
The ActAs
service must provide its own credentials. The requisite actasKeystore.properties
properties file and actasstore.jks
keystore are created.
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=aapass org.apache.ws.security.crypto.merlin.keystore.alias=myactaskey org.apache.ws.security.crypto.merlin.keystore.file=actasstore.jks
A.8.4.1.7. Default MANIFEST.MF
This application requires access to the JBossWS and Apache CXF APIs provided in the org.jboss.ws.cxf.jbossws-cxf-client
module. The org.jboss.ws.cxf.sts
module is also needed in handling the ActAs
and OnBehalfOf
extensions. The dependency statement directs the server to provide them at deployment.
Manifest-Version: 1.0 Dependencies: org.jboss.ws.cxf.jbossws-cxf-client, org.jboss.ws.cxf.sts
A.8.4.2. Security Token Service
This section provides the details of the STS elements from the basic WS-Trust scenario that have been changed to address the needs of the ActAs
example. The components include:
A.8.4.2.1. STS Implementation Class
The declaration of the set of allowed token recipients by address has been extended to accept ActAs
addresses and OnBehalfOf
addresses. The addresses are specified as reg-ex patterns.
The TokenIssueOperation
requires the UsernameTokenValidator
class to be provided to validate the contents of the OnBehalfOf
, and the UsernameTokenDelegationHandler
class to be provided to process the token delegation request of the ActAs
on OnBehalfOf
user.
package org.jboss.test.ws.jaxws.samples.wsse.policy.trust.sts; import java.util.Arrays; import java.util.LinkedList; import java.util.List; import javax.xml.ws.WebServiceProvider; import org.apache.cxf.annotations.EndpointProperties; import org.apache.cxf.annotations.EndpointProperty; import org.apache.cxf.interceptor.InInterceptors; import org.apache.cxf.sts.StaticSTSProperties; import org.apache.cxf.sts.operation.TokenIssueOperation; import org.apache.cxf.sts.operation.TokenValidateOperation; import org.apache.cxf.sts.service.ServiceMBean; import org.apache.cxf.sts.service.StaticService; import org.apache.cxf.sts.token.delegation.UsernameTokenDelegationHandler; import org.apache.cxf.sts.token.provider.SAMLTokenProvider; import org.apache.cxf.sts.token.validator.SAMLTokenValidator; import org.apache.cxf.sts.token.validator.UsernameTokenValidator; import org.apache.cxf.ws.security.sts.provider.SecurityTokenServiceProvider; @WebServiceProvider(serviceName = "SecurityTokenService", portName = "UT_Port", targetNamespace = "http://docs.oasis-open.org/ws-sx/ws-trust/200512/", wsdlLocation = "WEB-INF/wsdl/ws-trust-1.4-service.wsdl") //dependency on org.apache.cxf module or on module that exports org.apache.cxf (e.g. org.jboss.ws.cxf.jbossws-cxf-client) is needed, otherwise Apache CXF annotations are ignored @EndpointProperties(value = { @EndpointProperty(key = "ws-security.signature.username", value = "mystskey"), @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.sts.STSCallbackHandler"), @EndpointProperty(key = "ws-security.validate.token", value = "false") //to let the JAAS integration deal with validation through the interceptor below }) @InInterceptors(interceptors = {"org.jboss.wsf.stack.cxf.security.authentication.SubjectCreatingPolicyInterceptor"}) public class SampleSTS extends SecurityTokenServiceProvider { public SampleSTS() throws Exception { super(); StaticSTSProperties props = new StaticSTSProperties(); props.setSignatureCryptoProperties("stsKeystore.properties"); props.setSignatureUsername("mystskey"); props.setCallbackHandlerClass(STSCallbackHandler.class.getName()); props.setIssuer("DoubleItSTSIssuer"); List<ServiceMBean> services = new LinkedList<ServiceMBean>(); StaticService service = new StaticService(); service.setEndpoints(Arrays.asList( "http://localhost:(\\d)*/jaxws-samples-wsse-policy-trust/SecurityService", "http://\\[::1\\]:(\\d)*/jaxws-samples-wsse-policy-trust/SecurityService", "http://\\[0:0:0:0:0:0:0:1\\]:(\\d)*/jaxws-samples-wsse-policy-trust/SecurityService", "http://localhost:(\\d)*/jaxws-samples-wsse-policy-trust-actas/ActAsService", "http://\\[::1\\]:(\\d)*/jaxws-samples-wsse-policy-trust-actas/ActAsService", "http://\\[0:0:0:0:0:0:0:1\\]:(\\d)*/jaxws-samples-wsse-policy-trust-actas/ActAsService", "http://localhost:(\\d)*/jaxws-samples-wsse-policy-trust-onbehalfof/OnBehalfOfService", "http://\\[::1\\]:(\\d)*/jaxws-samples-wsse-policy-trust-onbehalfof/OnBehalfOfService", "http://\\[0:0:0:0:0:0:0:1\\]:(\\d)*/jaxws-samples-wsse-policy-trust-onbehalfof/OnBehalfOfService" )); services.add(service); TokenIssueOperation issueOperation = new TokenIssueOperation(); issueOperation.setServices(services); issueOperation.getTokenProviders().add(new SAMLTokenProvider()); // required for OnBehalfOf issueOperation.getTokenValidators().add(new UsernameTokenValidator()); // added for OnBehalfOf and ActAs issueOperation.getDelegationHandlers().add(new UsernameTokenDelegationHandler()); issueOperation.setStsProperties(props); TokenValidateOperation validateOperation = new TokenValidateOperation(); validateOperation.getTokenValidators().add(new SAMLTokenValidator()); validateOperation.setStsProperties(props); this.setIssueOperation(issueOperation); this.setValidateOperation(validateOperation); } }
A.8.4.2.2. STSCallbackHandler Class
The user, alice
, and corresponding password was required to be added for the ActAs
example.
package org.jboss.test.ws.jaxws.samples.wsse.policy.trust.sts; import java.util.HashMap; import java.util.Map; import org.jboss.wsf.stack.cxf.extensions.security.PasswordCallbackHandler; public class STSCallbackHandler extends PasswordCallbackHandler { public STSCallbackHandler() { super(getInitMap()); } private static Map<String, String> getInitMap() { Map<String, String> passwords = new HashMap<String, String>(); passwords.put("mystskey", "stskpass"); passwords.put("alice", "clarinet"); return passwords; } }
A.8.4.2.3. Web Service Requester
This section provides the details of the ws-requester
elements from the basic WS-Trust scenario that have been changed to address the requirements of the ActAs
example. The component is:
A.8.4.2.4. Web Service Requester Implementation Class
The ActAs
ws-requester
, the client, uses standard procedures for creating a reference to the web service in the first four lines. To address the endpoint security requirements, the web service’s request context is configured using BindingProvider
to provide information required for message generation. The ActAs
user, myactaskey
, is declared in this section and UsernameTokenCallbackHandler
is used to provide the contents of the ActAs
element to the STSClient
. In this example an STSClient
object is created and provided to the proxy’s request context. The alternative is to provide keys tagged with the .it
suffix as was done in the Basic Scenario client. The use of ActAs
is configured through the properties map using the SecurityConstants.STS_TOKEN_ACT_AS
key. The alternative is to use the STSClient.setActAs
method.
final QName serviceName = new QName("http://www.jboss.org/jbossws/ws-extensions/actaswssecuritypolicy", "ActAsService"); final URL wsdlURL = new URL(serviceURL + "?wsdl"); Service service = Service.create(wsdlURL, serviceName); ActAsServiceIface proxy = (ActAsServiceIface) service.getPort(ActAsServiceIface.class); Bus bus = BusFactory.newInstance().createBus(); try { BusFactory.setThreadDefaultBus(bus); Map<String, Object> ctx = proxy.getRequestContext(); ctx.put(SecurityConstants.CALLBACK_HANDLER, new ClientCallbackHandler()); ctx.put(SecurityConstants.ENCRYPT_PROPERTIES, Thread.currentThread().getContextClassLoader().getResource( "META-INF/clientKeystore.properties")); ctx.put(SecurityConstants.ENCRYPT_USERNAME, "myactaskey"); ctx.put(SecurityConstants.SIGNATURE_PROPERTIES, Thread.currentThread().getContextClassLoader().getResource( "META-INF/clientKeystore.properties")); ctx.put(SecurityConstants.SIGNATURE_USERNAME, "myclientkey"); // Generate the ActAs element contents and pass to the STSClient as a string UsernameTokenCallbackHandler ch = new UsernameTokenCallbackHandler(); String str = ch.getUsernameTokenString("alice","clarinet"); ctx.put(SecurityConstants.STS_TOKEN_ACT_AS, str); STSClient stsClient = new STSClient(bus); Map<String, Object> props = stsClient.getProperties(); props.put(SecurityConstants.USERNAME, "bob"); props.put(SecurityConstants.CALLBACK_HANDLER, new ClientCallbackHandler()); props.put(SecurityConstants.ENCRYPT_PROPERTIES, Thread.currentThread().getContextClassLoader().getResource( "META-INF/clientKeystore.properties")); props.put(SecurityConstants.ENCRYPT_USERNAME, "mystskey"); props.put(SecurityConstants.STS_TOKEN_USERNAME, "myclientkey"); props.put(SecurityConstants.STS_TOKEN_PROPERTIES, Thread.currentThread().getContextClassLoader().getResource( "META-INF/clientKeystore.properties")); props.put(SecurityConstants.STS_TOKEN_USE_CERT_FOR_KEYINFO, "true"); ctx.put(SecurityConstants.STS_CLIENT, stsClient); } finally { bus.shutdown(true); } proxy.sayHello();
Revised on 2018-10-11 12:32:52 UTC