Writing SecurityEnvironmentHandlers

The signing and encryption operations require private-keys and certificates. An application can obtain such information in various ways, such as looking up a keystore with an alias, using the default key-pairs available with the container, looking up a truststore with an alias, etc. Similarly if an application wants to send a username-password in a UsernameToken, it can choose to obtain the username-password pair in various ways, such as reading from a file, prompting the user on the console, using a popup window, etc. The authentication of the username-password on the receiving application can similarly be done by plugging into existing authentication infrastructure, using a proprietary username-password database, etc.

To support these possibilities, XWS-Security defines a set of CallBack classes and requires the application to define a CallBackHandler to handle these callbacks. The xwss:SecurityEnvironmentHandler element is a compulsory child element that needs to be specified. The value of this element is the class name of a Java class that implements the javax.security.auth.callback.CallbackHandler interface and handles the set of callbacks defined by XWS-Security. There are a set of callbacks that are mandatory and every CallbackHandler needs to implement them. A few callbacks are optional and can be used to supply some fine-grained property information to the XWS-Security run-time.

When using the XWS-Security APIs for securing both JAX-RPC applications and stand-alone applications that make use of SAAJ APIs only for their SOAP messaging, you have the option of either implementing a CallbackHandler or implementing the com.sun.xml.wss.SecurityEnvironment interface. Once implemented, the appropriate instance of the CallbackHandler or SecurityEnvironment interface implementation needs to be set into an instance of com.sun.xml.wss.ProcessingContext. For example code uses the XWS-Security APIs, refer to XWS-Security APIs Sample Application. The SecurityEnvironment interface is evolving and is subject to refinement in a later release.

Because information such as private keys and certificates for signing and encryption can be obtained in various ways (looking up a keystore with an alias, using the default key-pairs available with the container, looking up a truststore with an alias, etc.), every callback defines a set of Request inner classes and a callback can be initialized with any of its request inner classes. A tagging Request interface is also defined within the callback to tag all Request classes. For example, the XWS-Security configuration schema defines an xwss:X509Token element containing an optional attribute certificateAlias. When the xwss:X509Token element embedded inside a xwss:Sign element has a certificateAlias attribute specified as shown in the following code snippet, the XWS-Security run-time would invoke the SecurityEnvironmentHandler of the application with a SignatureKeyCallback object to obtain the private-key required for the signing operation.

<xwss:Sign>
    <xwss:X509Token certificateAlias="xws-security-client"/>
</xwss:Sign> 

The SignatureKeyCallback will be initialized by XWS-Security run-time with an AliasPrivKeyCertRequest in the following manner:

SignatureKeyCallback sigKeyCallback = new 
SignatureKeyCallback(new
   SignatureKeyCallback.AliasPrivKeyCertRequest(alias)); 

The application's SecurityEnvironmentHandler implementation then needs to handle the SignatureKeyCallback and use the alias to locate and set the private-key and X.509 certificate pair on the AliasPrivKeyCertRequest. The following code shows how this callback is handled in the handle() method of SecurityEnvironmentHandler shipped with the simple sample.

} else if (callbacks[i] instanceof SignatureKeyCallback) {
   SignatureKeyCallback cb = 
(SignatureKeyCallback)callbacks[i];

       if (cb.getRequest() instanceof 
SignatureKeyCallback.AliasPrivKeyCertRequest) {
         SignatureKeyCallback.AliasPrivKeyCertRequest request 
=
            (SignatureKeyCallback.AliasPrivKeyCertRequest) 
cb.getRequest();
         String alias = request.getAlias();
         if (keyStore == null)
            initKeyStore();
            try {
               X509Certificate cert = (X509Certificate) 
keyStore.getCertificate(alias);
               request.setX509Certificate(cert);
               // Assuming key passwords same as the keystore 
password
               PrivateKey privKey =
                  (PrivateKey) keyStore.getKey(alias, 
keyStorePassword.toCharArray());
               request.setPrivateKey(privKey);
            } catch (Exception e) {
                  throw new IOException(e.getMessage());
               } 
               } else {
                     throw  new 
UnsupportedCallbackException(null, "Unsupported Callback 
                        Type Encountered");
               }
            } 

This handler uses a keystore to locate the private key and certificate pair, and sets it using AliasPrivKeyCertRequest.

As shown in the sample code, the SecurityEnvironmentHandler should throw an UnsupportedCallbackException whenever it cannot handle a Callback or a particular Request type of a Callback.

The type of Request with which the Callback is initialized often depends on the information specified in the security configuration file of the application. For example if the xwss:X509Token specified under an xwss:Sign element did not contain the certificateAlias attribute, XWS-Security would invoke the application's SecurityEnvironmentHandler with SignatureKeyCallback.DefaultPrivKeyCertRequest to try and obtain the default private-key and certificate pair. If the SecurityEnvironmentHandler does not handle this request and throws an UnsupportedCallbackException, the signature operation would fail.

For more information, read the API documentation for callbacks from the <JWSDP_HOME>/xws-security/docs/api/com/sun/xml/wss/impl/callback/package-summary.html. This documentation includes the list of mandatory and optional callbacks and the details of the Callback classes and supported methods. Table 4-41 provides a brief summary of all the mandatory Callback classes and their associated Request types.

Table 4-41 Summary of Callback classes and their Request types 
Callback
Description
  Request Inner Classes Defined
  Methods in the Request Classes
Signature
Key
Callback
Used by XWS-Security run-time to obtain the private key to be used for signing the corresponding X.509 certificate. There are two ways in which an application can supply the private-key and certificate information.
1. Lookup a keystore using an alias.
2. Obtain the default private-key and certificate from the container/environment in which the application is running.
3. Obtain the private key and certificate given the public key. This kind of request is used in scenarios where the public key appears as a KeyValue under a ds:KeyInfo and needs to be used for signing.
 
Accordingly, there are three Request inner classes with which the SignatureKeyCallback can be initialized.
1. AliasPrivKeyCertRequest: A Callback initialized with this request should be handled if the private key to be used for signing is mapped to an alias.
2. DefaultPrivKeyCertRequest: A Callback initialized with this request should be handled if there's some default private key to be used for signing.
3. PublicKeyBasedPrivateKeyCertRequest: A callback initialized with this request should be handled if the private key to be used for signing is to be retrieved given the public key.
The following four methods are present in all Request Classes of this Callback:
public void setPrivateKey(
   PrivateKey privateKey)
public PrivateKey getPrivateKey()
 
public void setX509Certificate(
   X509Certificate certificate)
public X509Certificate
   getX509Certificate()
Signature
Verification
Key
Callback
Obtains the certificate required for signature verification. There are currently two situations in which XWS-Security would require this Callback to resolve the certificate:
1. When the signature to be verified references the key using an X.509 SubjectKeyIdentifier. For example, when the sender specifies the attribute xwss:keyReferenceType="Identifier" on the xwss:X509Token child of the xwss:Sign element.
2. When the signature to be verified references the key using an X.509 IssuerSerialNumber. For example, when the sender specifies the attribute xwss:keyReferenceType="IssuerSerialNumber" on the xwss:X509Token child of the xwss:Sign element.
3. When ds:KeyInfo contains a key value, use the public key to obtain the X.509 certificate.
 
Accordingly, there are three Request inner classes with which a SignatureVerificationKeyCallback can be initialized.
Note: Additional Requests may be defined in a future release.
1. X509SubjectKeyIdentifierBasedRequest: Request for an X.509 certificate whose X.509 SubjectKeyIdentifier value is given.
2. X509IssuerSerialBasedRequest: Request for an X.509 certificate whose issuer name and serial number values are given.
3. PublicKeyBasedRequest: Request for an X.509 certificate for a given public key.
The following two methods are present in all the Request classes of this Callback:
 
public void setX509Certificate(
   X509Certificate certificate)
public X509Certificate
   getX509Certificate()
Encryption
Key
Callback
Obtains the certificate for key-encryption or a symmetric-key for data encryption. The three situations for which XWS-Security would require this Callback for performing encryption:
1. When the xwss:Encrypt element contains an xwss:X509Token child with certificateAlias attribute set to an alias. The certificateAlias indicates that a random symmetric key is used for encryption of the specified message part and the certificate is then used to encrypt the random symmetric-key to be sent along with the message.
2. When the xwss:Encrypt element contains an xwss:X509Token child with no certificateAlias attribute set on it. XWS-Security tries to obtain a default certificate from the Callback to be used for encrypting the random symmetric key.
3. When the xwss:Encrypt element contains an xwss:SymmetricKey child specifying the keyAlias attribute. This alias indicates that a symmetric key corresponding to this alias needs to be located and used for encryption of the specified message part.
4. When an X.509 certificate needs to be obtained for a given public key.
The following are the Request inner classes with which an EncryptionKeyCallback can be initialized.
1. AliasX509CertificateRequest: A Callback initialized with this request should be handled if the X.509 certificate to be used for encryption is mapped to an alias.
2. DefaultX509CertificateRequest: A Callback initialized with this request should be handled if there's a default X.509 certificate to be used for encryption.
3. AliasSymmetricKeyRequest: A Callback initialized with this request should be handled if the symmetric key to be used for encryption is mapped to an alias.
4. PublicKeyBasedRequest: Request for an X.509 certificate for a given public key.
The following two methods are present in the AliasX509CertificateRequest and DefaultX509CertificateRequest Request classes of this Callback:
 
public void setX509Certificate(
   X509Certificate certificate)
public X509Certificate
   getX509Certificate()
 
The following methods are present in the AliasSymmetricKeyRequest class of this Callback:
 
public void setSymmetricKey(
   javax.crypto.SecretKey
      symmetricKey)
public javax.crypto.SecretKey
   getSymmetricKey()
Decryption
Key
Callback
Obtains the symmetric key to be used for decrypting the encrypted data or obtaining the private-key for decrypting the encrypted random symmetric key that was sent with the message (along with the encrypted data).
There are currently four situations in which XWS-Security will require this Callback to perform decryption.
1. When the EncryptedKey references the key (used for encrypting the symmetric key) using an X.509 SubjectKeyIdentifier. For example, when the sender specifies the attribute keyReferenceType="Identifier" on the xwss:X509Token child of the xwss:Encrypt element.
2. When the EncryptedKey references the key (used for encrypting the symmetric key) using an X.509 IssuerSerialNumber. For example, when the sender specifies the attribute keyReferenceType="IssuerSerialNumber" on the xwss:x509Token child of xwss:Encrypt element.
 
1. X509SubjectKeyIdentifierBasedRequest: Request for a private-key when the X.509 SubjectKeyIdentifier value for a corresponding X.509 certificate is given.
2. X509IssuerSerialBasedRequest: Request for a private key when the issuer name and serial number values for a corresponding X.509 certificate are given.
3. X509CertificateBasedRequest: Request for a private key when a corresponding X.509 certificate is given.
 
The following two methods are present in the X509SubjectKeyIdentifierBasedRequest, X509IssuerSerialBasedRequest, and X509CertificateBasedRequest Request classes of this Callback:
 
public void setPrivateKey(
   PrivateKey privateKey)
public PrivateKey
   getPrivateKey()
 
 
Decryption
Key
Callback (continued)
3. When the EncryptedKey contains a wsse:Direct reference to the key used for encrypting the symmetric key. This means the X.509 certificate is present as a wsse:BinarySecurityToken in the message. For example, when the sender specifies the attribute keyReferenceType="Direct" on the xwss:x509Token child of xwss:Encrypt element.
4. When the EncryptedData contains a ds:keyName reference to the symmetric key that was used for encryption. For example, when the sender specifies the xwss:SymmetricKey child of xwss:Encrypt and specifies the keyAlias attribute on it.
5. When the EncryptedKey contains a ds:KeyInfo with a key value child.
Accordingly, there are five Request classes with which a DecryptionKeyCallback can be initialized.
4. AliasSymmetricKeyRequest: A Callback initialized with this request should be handled if the symmetric key to be used for decryption is mapped to some alias.
5. PublicKeyBasedPrivateKeyRequest: Request for a private key given the public key.
The following methods are present in the AliasSymmetricKeyRequest class of this
Callback:
 
public void setSymmetricKey(
   javax.crypto.SecretKey
      symmetricKey)
public javax.crypto.SecretKey
   getSymmetricKey()
 
Password
Validation
Callback
Username-Password validation. A validator that implements the PasswordValidator interface should be set on the callback by the callback handler.
There are currently two situations in which XWS-Security will require this Callback to perform username-password validation:
1. When the receiver gets a UsernameToken with plain-text user name and password.
2. When the receiver gets a UsernameToken with a digested password (as specified in the WSS UsernameToken Profile).
Accordingly there are two Request classes with which the PasswordValidationCallback can be initialized.
Note: A validator for WSS Digested Username-Password is provided as part of this callback, with classname PasswordValidationCallback.DigestPasswordValidator.
This class implements WSS digest password validation. The method for computing password digest is described in http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0.pdf.
For more information, see the ServerSecurityEnvironmentHandler in <JWSDP_HOME>/xws-security/samples/jaas-sample/src/com/sun/xml/wss/sample.
1. PlainTextPasswordRequest: Represents a validation request when the password in the username token is in plain text.
2. DigestPasswordRequest: Represents a validation request when the password in the username token is in digested form.
 
The following methods are present in the PlainTextPasswordRequest:
public String getUsername()
public String getPassword()
 
The following methods are present in the DigestPasswordRequest:
public void setPassword(String password)
 
This method must be invoked by the CallbackHandler while handling a Callback initialized with DigestPasswordRequest to set the plain-text password on the Callback.
 
public java.lang.String
   getPassword()
public java.lang.String
   getUsername()
public java.lang.String getDigest()
public java.lang.String getNonce()
public java.lang.String getCreated()
 
Username
Callback
To supply the user name for the UsernameToken at run-time. It contains the following two methods:
public void setUsername(
String username)
public String getUsername()
 
Refer to the ClientSecurityEnvironmentHandler of the
jaas-sample located in
<JWSDP_HOME>/xws-security/samples/jaas-sample/src/com/sun/xml/wss/sample for more details on using the UsernameCallback.
 
 
PasswordCallback
To supply the password for the username token at run-time. It contains the following two methods:
 
public void setPassword(String
   password)
public String getPassword()
Refer to the ClientSecurityEnvironmentHandler of the jaas-sample located in
<JWSDP_HOME>/xws-security/samples/jaas-sample/src/com/sun/xml/wss/sample for more details on using the PasswordCallback.
 
 
Property
Callback
Optional callback to specify the values of properties configurable with XWS-Security run-time.
Refer to the API documentation at <JWSDP_HOME>/xws-security/docs/api/com/sun/xml/wss/impl/callback/PropertyCallback.html for a list of configurable properties and methods supported by this callback.
 
This callback has been deprecated and disabled in this release. To get similar functionality, use the maxClockSkew and timestampFreshnessLimit attributes on <RequireTimestamp>, or the maxClockSkew, timestampFreshnessLimit, and maxNonceAge attributes on <RequireUsernameToken>.
Prefix
Namespace
Mapping
Callback
Optional callback to register any prefix versus namespace-uri mappings that the developer wants to make use of in the security configuration (while specifying Targets as xpaths).
Refer to the API documentation at <JWSDP_HOME>/xws-security/docs/api/com/sun/xml/wss/impl/callback/PrefixNamespaceMappingCallback.html for more details.
 
The PrefixNamespaceMappingCallback has been deprecated and disabled in this release. When specifying XPath expressions for targets in XWS-Security configuration files, you are required to make use of the elongated syntax of the form
local-name()="Body" and namespace-uri()="http://schemas.xmlsoap.org/soap/envelope/", etc., if the prefix involved is anything other than the following:
1. The prefix of the SOAP envelope in the message.
2. One of the following prefixes:
SOAP-ENV, env, S11 to mean http://schemas.xmlsoap.org/soap/envelope/.
3. Prefix ds to mean http://www.w3.org/2000/09/xmldsig#
4. Prefix xenc to mean http://www.w3.org/2001/04/xmlenc#
5. Prefix wsse to mean http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd
6. Prefix wsu to mean http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd
7.Prefix wsu to mean http://docs.oasis-open.org/wss/2004/01/oasis-200401-ws s-wssecurity-utility-1.0.xsd
 
The use of XPath expressions is discouraged in XWS-Security EA 2.0 because it impacts performance. Users are advised to make use of fragment URI's and QNames to identify targets of signature and encryption.
Certificate
Validation
Callback
This callback is intended for X.509 certificate validation. A validator that implements the CertificateValidator interface should be set on the callback by the callback handler.
Currently this callback is invoked by the XWS-Security runtime whenever an X.509 certificate is present in an incoming message in the form of a BinarySecurityToken.
 
 
Dynamic
Policy
Callback
This callback is intended for dynamic policy resolution. DynamicPolicyCallback is made by the XWS runtime to allow the application and/or handler to decide the incoming and/or outgoing SecurityPolicy at runtime.
 
When the SecurityPolicy set on the callback is a DynamicSecurityPolicy, the CallbackHandler is expected to set a com.sun.xml.wss.impl.configuration.MessagePolicy instance as the resolved policy. The MessagePolicy instance can contain policies generated by the PolicyGenerator obtained from the DynamicSecurityPolicy.
 
 

The following code snippet shows the handle() method skeleton for an application's SecurityEnvironmentHandler that handles all the mandatory Callbacks (except UsernameCallback and PasswordCallback) and associated Requests defined by XWS-Security. A particular application may choose to throw an UnsupportedCallbackException for any of the Callbacks or its Requests that it cannot handle. The UsernameCallback and PasswordCallback are useful for obtaining a username-password pair at run-time and are explained later in this section.


Note: In this release of XWS-Security, users will have to ensure that the SecurityEnvironmentHandler implementation they supply is thread safe.

public  class SecurityEnvironmentHandler implements 
CallbackHandler {

   public void handle(Callback[] callbacks) throws IOException,
      UnsupportedCallbackException {
    
      for (int i=0; i < callbacks.length; i++) {
    
         if (callbacks[i] instanceof 
PasswordValidationCallback) {
            PasswordValidationCallback cb = 
(PasswordValidationCallback) callbacks[i];
             if (cb.getRequest() instanceof
               PasswordValidationCallback.PlainTextPasswordReq
uest) {
               // setValidator for plain-text password 
validation on callback cb
               } else if (cb.getRequest() instanceof
                     PasswordValidationCallback.DigestPassword
Request) {
                        PasswordValidationCallback.DigestPassw
ordRequest request =
                           (PasswordValidationCallback.DigestP
asswordRequest) cb.getRequest();
                        // set plaintext password on  request
                        // setValidator for digest password 
validation on cb

               } else {
                     // throw unsupported;
                  }
    
               } else if (callbacks[i] instanceof 
SignatureVerificationKeyCallback) {
                     SignatureVerificationKeyCallback cb =
                        (SignatureVerificationKeyCallback)call
backs[i];
    
                     if (cb.getRequest() instanceof
                       SignatureVerificationKeyCallback.X509Su
bjectKeyIdentifierBasedRequest) {
                       // subject keyid request
                       SignatureVerificationKeyCallback.X509Su
bjectKeyIdentifierBasedRequest 
                          request =
                       (SignatureVerificationKeyCallback.X509S
ubjectKeyIdentifierBasedRequest)
                           cb.getRequest();
                       // locate and setX509Certificate on the 
request   
                        } else if (cb.getRequest() instanceof
                           SignatureVerificationKeyCallback.X5
09IssuerSerialBasedRequest) {
                        // issuer serial request
                        SignatureVerificationKeyCallback.X509I
ssuerSerialBasedRequest request =
                           (SignatureVerificationKeyCallback.X
509IssuerSerialBasedRequest)
                           cb.getRequest();
                        // locate and setX509Certificate on the 
request

                     } else  {
                        // throw unsupported;
                        }
    
                     } else if (callbacks[i] instanceof 
SignatureKeyCallback) {
                           SignatureKeyCallback cb = 
(SignatureKeyCallback)callbacks[i];
                          if (cb.getRequest() instanceof
                             SignatureKeyCallback.DefaultPrivK
eyCertRequest) {
                             // default priv key cert req
                             
SignatureKeyCallback.DefaultPrivKeyCertRequest request =
                             
   (SignatureKeyCallback.DefaultPrivKeyCertRequest) 
cb.getRequest();
                             // locate and set default 
privateKey and X509Certificate on request  
                       } else if (cb.getRequest() instanceof
                             
SignatureKeyCallback.AliasPrivKeyCertRequest) {
                                // Alias priv key cert req
                             
   SignatureKeyCallback.AliasPrivKeyCertRequest request =
                             
      (SignatureKeyCallback.AliasPrivKeyCertRequest) 
cb.getRequest();
                                // locate and set default 
privateKey and X509Certificate on request
                   
                       } else {
                          // throw unsupported;
                          }
    
                       } else if (callbacks[i] instanceof 
DecryptionKeyCallback) {
                          DecryptionKeyCallback cb = 
(DecryptionKeyCallback)callbacks[i];
    
                          if (cb.getRequest() instanceof 
                             DecryptionKeyCallback.X509Subject
KeyIdentifierBasedRequest) {
                                //ski  request
                             DecryptionKeyCallback.X509Subject
KeyIdentifierBasedRequest request =
                                (DecryptionKeyCallback.X509Sub
jectKeyIdentifierBasedRequest)
                          cb.getRequest();
                          // locate and set the privateKey on 
the request   

                       } else if (cb.getRequest() instanceof
                             DecryptionKeyCallback.X509IssuerS
erialBasedRequest) {
                                // issuer serial request
                                DecryptionKeyCallback.X509Issu
erSerialBasedRequest request =
                                   (DecryptionKeyCallback.X509
IssuerSerialBasedRequest)
                                      cb.getRequest();
                                // locate and set the 
privateKey on the request   
                       } else if (cb.getRequest() instanceof
                             DecryptionKeyCallback.X509Certifi
cateBasedRequest) {
                                // X509 cert request
                                DecryptionKeyCallback.X509Cert
ificateBasedRequest request =
                                  (DecryptionKeyCallback.X509C
ertificateBasedRequest)
                                      cb.getRequest();
                                // locate and set private key 
on the request
                       } else if (cb.getRequest() instanceof
                             DecryptionKeyCallback.AliasSymmet
ricKeyRequest) {
                                DecryptionKeyCallback.AliasSym
metricKeyRequest request =
                                   (DecryptionKeyCallback.Alia
sSymmetricKeyRequest)
                                      cb.getRequest();
                                // locate and set symmetric key 
on request
   
                       } else  {
                          // throw unsupported;
                          }
    
                       } else if (callbacks[i] instanceof 
EncryptionKeyCallback) {
                             EncryptionKeyCallback cb = 
(EncryptionKeyCallback)callbacks[i];
                             if (cb.getRequest() instanceof
                                EncryptionKeyCallback.AliasX50
9CertificateRequest) {
                                EncryptionKeyCallback.AliasX50
9CertificateRequest request =
                                   (EncryptionKeyCallback.Alia
sX509CertificateRequest)
                                      cb.getRequest();
                                // locate and set certificate 
on request   
                       } else if (cb.getRequest() instanceof
                              EncryptionKeyCallback.AliasSymme
tricKeyRequest) {
                                 EncryptionKeyCallback.AliasSy
mmetricKeyRequest request =
                                    (EncryptionKeyCallback.Ali
asSymmetricKeyRequest)
                                       cb.getRequest();
                                 // locate and set symmetric 
key on request
   
                       } else {
                          // throw unsupported;
                          }
    
                       } else if (callbacks[i] instanceof 
CertificateValidationCallback) {
                             CertificateValidationCallback cb 
=
                                (CertificateValidationCallback
)callbacks[i];
                             // set an X509 Certificate 
Validator on the callback
                       } else {
                          // throw unsupported;
                          }
            }
      }
} 

An application can also choose not to handle certain callbacks if it knows that the particular application will never require those callbacks. For example if the security application only deals with signing the requests and does not deal with encryption or username tokens, its handle() method only needs to worry about SignatureKeyCallback (with its associated Requests) and SignatureVerificationKeyCallback (with its associated Requests). It can then throw an UnsupportedCallbackException for any other callback. The following code shows the handle() method skeleton for such an application:

public  class SecurityEnvironmentHandler implements 
CallbackHandler {

   public void handle(Callback[] callbacks) throws IOException,
      UnsupportedCallbackException {

         for (int i=0; i < callbacks.length; i++) {
            if (callbacks[i] instanceof 
SignatureVerificationKeyCallback) {
                  (SignatureVerificationKeyCallback)callbacks[
i];
    
                  if (cb.getRequest() instanceof
                     SignatureVerificationKeyCallback.X509Subj
ectKeyIdentifierBasedRequest) {
                     // subject keyid request
                     SignatureVerificationKeyCallback.X509Subj
ectKeyIdentifierBasedRequest 
                         request =
                         (SignatureVerificationKeyCallback.X50
9SubjectKeyIdentifierBasedRequest)
                            cb.getRequest();
                     // locate and setX509Certificate on the 
request   
                  } else if (cb.getRequest() instanceof
                        SignatureVerificationKeyCallback.X509I
ssuerSerialBasedRequest) {
                        // issuer serial request
                        SignatureVerificationKeyCallback.X509I
ssuerSerialBasedRequest request =
                           (SignatureVerificationKeyCallback.X
509IssuerSerialBasedRequest)
                              cb.getRequest();
                     // locate and setX509Certificate on the 
request

                  } else  {
                     // throw unsupported;
                      }

                  } else if (callbacks[i] instanceof 
SignatureKeyCallback) {
                        SignatureKeyCallback cb = 
(SignatureKeyCallback)callbacks[i];
                        if (cb.getRequest() instanceof
                           SignatureKeyCallback.DefaultPrivKey
CertRequest) {
                        // default priv key cert req
                        SignatureKeyCallback.DefaultPrivKeyCer
tRequest request =
                           (SignatureKeyCallback.DefaultPrivKe
yCertRequest) cb.getRequest();
                        // locate and set default privateKey 
and X509Certificate on request  
                  } else if (cb.getRequest() instanceof
                        SignatureKeyCallback.AliasPrivKeyCertR
equest) {
                        // Alias priv key cert req
                        SignatureKeyCallback.AliasPrivKeyCertR
equest request =
                           (SignatureKeyCallback.AliasPrivKeyC
ertRequest) cb.getRequest();
                        // locate and set default privateKey 
and X509Certificate on request
                   
                  } else {
                     //  throw unsupported;
                     }

                  } else {
                     // throw unsupported;
                    }
               }
         }
} 

Similarly, an application dealing only with UsernameToken but not signature or encryption requirements can simply throw UnsupportedCallbackException for all non-username related callbacks.

The SecurityEnvironmentHandler implementation for the simple sample is located in the directory <JWSDP_HOME>/xws-security/samples/simple/src/com/sun/xml/wss/sample. The simple sample uses the same SecurityEnvironmentHandler for both the client and server side.

The jaas-sample requires a different set of callbacks to be handled on the client and server side. The CallbackHandlers for the jaas-sample are located in the directory <JWSDP_HOME>/xws-security/samples/jaas-sample/src/com/sun/xml/wss/sample. The two CallbackHandlers defined for the jaas-sample are:

Using the SubjectAccessor API

XWS-Security applications might require access to the authenticated subject of the sender from within the SEI implementation methods. The SubjectAccessor API contains a single method:

public static Subject getRequesterSubject(Object context)
   throws XWSSecurityException
public static Subject getRequesterSubject() 

The getRequesterSubject(Object context) method returns the Subject if one is available or else it returns NULL. The context argument to be passed into this method should either be a ServletEndpointContext, which is available with the SEI implementation class, or a com.sun.xml.wss.ProcessingContext. For an example on how the SubjectAccessor is used to obtain the authenticated sender subject, refer to the PingImpl.java class in the jaas-sample located at <JWSDP_HOME>/xws-security/samples/jaas-sample/server/src/sample. The API for SubjectAccessor viewed from <JWSDP_HOME>/xws-security/docs/api/com/sun/xml/wss/SubjectAccessor.html.

The getRequesterSubject() method returns the requester subject from the context if available, and returns null if not available. This method should be used by the receiver response processing to access the subject of the requester. This method will work only for the Synchronous Request-Response Message Exchange Pattern (SRRMEP). For an example that uses this method, see Dynamic Response Sample Application.