|
Download
FAQ History |
|
API
Search Feedback |
Writing SecurityEnvironmentHandlers for XWS-Security Applications
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
CallBackclasses and requires the application to define aCallBackHandlerto handle these callbacks. Thexwss:SecurityEnvironmentHandlerelement 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 thejavax.security.auth.callback.CallbackHandlerinterface and handles the set of callbacks defined by XWS-Security. There are a set of callbacks that are mandatory and everyCallbackHandlerneeds 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.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
Requestinner classes and a callback can be initialized with any of its request inner classes. A taggingRequestinterface is also defined within the callback to tag allRequestclasses. For example, the XWS-Security configuration schema defines anxwss:X509Tokenelement containing an optional attributecertificateAlias. When thexwss:X509Tokenelement embedded inside axwss:Signelement has acertificateAliasattribute specified as shown in the following code snippet, the XWS-Security run-time would invoke theSecurityEnvironmentHandlerof the application with aSignatureKeyCallbackobject to obtain the private-key required for the signing operation.The
SignatureKeyCallbackwill be initialized by XWS-Security run-time with anAliasPrivKeyCertRequestin the following manner:SignatureKeyCallback sigKeyCallback = new SignatureKeyCallback(new SignatureKeyCallback.AliasPrivKeyCertRequest(alias));The application's
SecurityEnvironmentHandlerimplementation then needs to handle theSignatureKeyCallbackand use the alias to locate and set the private-key and X.509 certificate pair on theAliasPrivKeyCertRequest. The following code shows how this callback is handled in thehandle()method ofSecurityEnvironmentHandlershipped with thesimplesample.} 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
SecurityEnvironmentHandlershould throw anUnsupportedCallbackExceptionwhenever it cannot handle aCallbackor a particularRequesttype of aCallback.The type of
Requestwith which theCallbackis initialized often depends on the information specified in the security configuration file of the application. For example if thexwss:X509Tokenspecified under anxwss:Signelement did not contain thecertificateAliasattribute, XWS-Security would invoke the application'sSecurityEnvironmentHandlerwithSignatureKeyCallback.DefaultPrivKeyCertRequestto try and obtain the default private-key and certificate pair. If theSecurityEnvironmentHandlerdoes not handle this request and throws anUnsupportedCallbackException, 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 theCallbackclasses and supported methods. Table 3-24 provides a brief summary of all the mandatoryCallbackclasses and their associatedRequesttypes.
Table 3-24 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.Accordingly, there are twoRequestinner classes with which theSignatureKeyCallbackcan be initialized. 1.AliasPrivKeyCertRequest: ACallbackinitialized with this request should be handled if the private key to be used for signing is mapped to an alias.2.DefaultPrivKeyCertRequest: ACallbackinitialized with this request should be handled if there's some default private key to be used for signing. The following four methods are present in allRequestClasses of thisCallback: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.509SubjectKeyIdentifier. For example, when the sender specifies the attributexwss:keyReferenceType="Identifier"on thexwss:X509Tokenchild of thexwss:Signelement.2. When the signature to be verified references the key using an X.509IssuerSerialNumber. For example, when the sender specifies the attributexwss:keyReferenceType="IssuerSerialNumber"on thexwss:X509Tokenchild of thexwss:Signelement.Accordingly, there are twoRequestinner classes with which aSignatureVerificationKeyCallbackcan be initialized.Note: AdditionalRequestsmay be defined in a future release. 1.X509SubjectKeyIdentifierBasedRequest: Request for an X.509 certificate whose X.509SubjectKeyIdentifiervalue is given.2.X509IssuerSerialBasedRequest: Request for an X.509 certificate whose issuer name and serial number values are given. The following two methods are present in all theRequestclasses of thisCallback:public void setX509Certificate(
X509Certificate certificate)public X509Certificate
getX509Certificate() Encryption
Key
Callback Obtains the certificate for key-encryption or a symmetric-key for data encryption. There are currently three situations in which XWS-Security would require thisCallbackfor performing encryption:1. When thexwss:Encryptelement contains anxwss:X509Tokenchild withcertificateAliasattribute set to an alias. ThecertificateAliasindicates 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 thexwss:Encryptelement contains anxwss:X509Tokenchild with nocertificateAliasattribute set on it. XWS-Security tries to obtain a default certificate from theCallbackto be used for encrypting the random symmetric key.3. When thexwss:Encryptelement contains anxwss:SymmetricKeychild specifying thekeyAliasattribute. This alias indicates that a symmetric key corresponding to this alias needs to be located and used for encryption of the specified message part.Accordingly, there are threeRequestinner classes with which anEncryptionKeyCallbackcan be initialized. 1.AliasX509CertificateRequest: ACallbackinitialized with this request should be handled if the X.509 certificate to be used for encryption is mapped to an alias.2.DefaultX509CertificateRequest: ACallbackinitialized with this request should be handled if there's a default X.509 certificate to be used for encryption.3.AliasSymmetricKeyRequest: ACallbackinitialized with this request should be handled if the symmetric key to be used for encryption is mapped to an alias. The following two methods are present in theAliasX509CertificateRequestandDefaultX509CertificateRequest Requestclasses of thisCallback:public void setX509Certificate(
X509Certificate certificate)
public X509Certificate
getX509Certificate()The following methods are present in theAliasSymmetricKeyRequestclass of thisCallback: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 thisCallbackto perform decryption.1. When theEncryptedKeyreferences the key (used for encrypting the symmetric key) using an X.509SubjectKeyIdentifier. For example, when the sender specifies the attributekeyReferenceType="Identifier"on thexwss:X509Tokenchild of thexwss:Encryptelement.2. When theEncryptedKeyreferences the key (used for encrypting the symmetric key) using an X.509IssuerSerialNumber. For example, when the sender specifies the attributekeyReferenceType="IssuerSerialNumber"on thexwss:x509Tokenchild ofxwss:Encryptelement. 1.X509SubjectKeyIdentifierBasedRequest: Request for a private-key when the X.509SubjectKeyIdentifiervalue 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 theX509SubjectKeyIdentifierBasedRequest,X509IssuerSerialBasedRequest, andX509CertificateBasedRequestRequestclasses of thisCallback:public void setPrivateKey(
PrivateKey privateKey)
public PrivateKey
getPrivateKey() Decryption
Key
Callback (continued) 3. When theEncryptedKeycontains awsse:Directreference to the key used for encrypting the symmetric key. This means the X.509 certificate is present as awsse:BinarySecurityTokenin the message. For example, when the sender specifies the attributekeyReferenceType="Direct"on thexwss:x509Tokenchild ofxwss:Encryptelement.4. When theEncryptedDatacontains ads:keyNamereference to the symmetric key that was used for encryption. For example, when the sender specifies thexwss:SymmetricKeychild ofxwss:Encryptand specifies thekeyAliasattribute on it.Accordingly, there are fourRequestclasses with which aDecryptionKeyCallbackcan be initialized. 4.AliasSymmetricKeyRequest: ACallbackinitialized with this request should be handled if the symmetric key to be used for decryption is mapped to some alias. The following methods are present in theAliasSymmetricKeyRequestclass of thisCallback:public void setSymmetricKey(
javax.crypto.SecretKey
symmetricKey)
public javax.crypto.SecretKey
getSymmetricKey() Password
Validation
Callback Username-Password validation. A validator that implements thePasswordValidatorinterface should be set on the callback by the callback handler.There are currently two situations in which XWS-Security will require thisCallbackto perform username-password validation:1. When the receiver gets aUsernameTokenwith plain-text user name and password.2. When the receiver gets aUsernameTokenwith a digested password (as specified in the WSS UsernameToken Profile).Accordingly there are two Request classes with which thePasswordValidationCallbackcan be initialized.Note: A validator for WSS Digested Username-Password is provided as part of this callback, with classnamePasswordValidationCallback.DigestPasswordValidator.This class implements WSS digest password validation. The method for computing password digest is described inhttp://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0.pdf.For more information, see theServerSecurityEnvironmentHandlerin <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 thePlainTextPasswordRequest:public String getUsername()public String getPassword()The following methods are present in theDigestPasswordRequest:public void setPassword(String password)This method must be invoked by theCallbackHandlerwhile handling aCallbackinitialized withDigestPasswordRequestto set the plain-text password on theCallback.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 theUsernameTokenat run-time. It contains the following two methods:public void setUsername(String username)public String getUsername()Refer to theClientSecurityEnvironmentHandlerof thejaas-samplesample located in<JWSDP_HOME>/xws-security/samples/jaas-sample/src/com/sun/xml/wss/samplefor more details on using theUsernameCallback. 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 theClientSecurityEnvironmentHandlerof thejaas-samplesample located in<JWSDP_HOME>/xws-security/samples/jaas-sample/src/com/sun/xml/wss/samplefor more details on using thePasswordCallback. 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.htmlfor a list of configurable properties methods supported by this callback. 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 specifyingTargetsasxpaths).Refer to the API documentation at<JWSDP_HOME>/xws-security/docs/api/com/sun/xml/wss/impl/callback/PrefixNamespaceMappingCallback.htmlfor more details.
The following code snippet shows the
handle()method skeleton for an application'sSecurityEnvironmentHandlerthat handles all the mandatoryCallbacks(exceptUsernameCallbackandPasswordCallback) and associatedRequestsdefined by XWS-Security. A particular application may choose to throw anUnsupportedCallbackExceptionfor any of theCallbacksor itsRequeststhat it cannot handle. TheUsernameCallbackandPasswordCallbackare 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
SecurityEnvironmentHandlerimplementation 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.PlainTextPasswor dRequest) { // setValidator for plain-text password validation on callback cb } else if (cb.getRequest() instanceof PasswordValidationCallback.DigestPasswor dRequest) { PasswordValidationCallback.DigestPasswordRequest request = (PasswordValidationCallback.DigestPasswordRequest) 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)callbacks [i]; if (cb.getRequest() instanceof SignatureVerificationKeyCallback.X509Subjec tKeyIdentifierBasedRequest) { // subject keyid request SignatureVerificationKeyCallback.X509SubjectKeyIdentifierBased Request request = (SignatureVerificationKeyCallback.X509SubjectKeyIdentifierBase dRequest) cb.getRequest(); // locate and setX509Certificate on the request } else if (cb.getRequest() instanceof SignatureVerificationKeyCallback.X509Iss uerSerialBasedRequest) { // issuer serial request SignatureVerificationKeyCallback.X509IssuerSerialBasedRequest request = (SignatureVerificationKeyCallback.X509IssuerSerialBasedRequest ) 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.DefaultPrivKeyCertRequest) { // 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.X509SubjectKeyIdentif ierBasedRequest) { //ski request DecryptionKeyCallback.X509SubjectKeyIdentifierBasedRequest request = (DecryptionKeyCallback.X509SubjectKeyIdentifierBasedRequest) cb.getRequest(); // locate and set the privateKey on the request } else if (cb.getRequest() instanceof DecryptionKeyCallback.X509IssuerSerialBas edRequest) { // issuer serial request DecryptionKeyCallback.X509IssuerSerialBasedRequest request = (DecryptionKeyCallback.X509IssuerSerialBasedRequest) cb.getRequest(); // locate and set the privateKey on the request } else if (cb.getRequest() instanceof DecryptionKeyCallback.X509CertificateBas edRequest) { // X509 cert request DecryptionKeyCallback.X509CertificateBasedRequest request = (DecryptionKeyCallback.X509CertificateBasedRequest) cb.getRequest(); // locate and set private key on the request } else if (cb.getRequest() instanceof DecryptionKeyCallback.AliasSymmetricKeyR equest) { DecryptionKeyCallback.AliasSymmetricKeyRequest request = (DecryptionKeyCallback.AliasSymmetricKeyRequest) 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.AliasX509CertificateRequest) { EncryptionKeyCallback.AliasX509CertificateRequest request = (EncryptionKeyCallback.AliasX509CertificateRequest) cb.getRequest(); // locate and set certificate on request } else if (cb.getRequest() instanceof EncryptionKeyCallback.AliasSymmetricKeyRe quest) { EncryptionKeyCallback.AliasSymmetricKeyRequest request = (EncryptionKeyCallback.AliasSymmetricKeyRequest) 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 aboutSignatureKeyCallback(with its associatedRequests) andSignatureVerificationKeyCallback(with its associatedRequests). It can then throw anUnsupportedCallbackExceptionfor any other callback. The following code shows thehandle()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 cb = (SignatureVerificationKeyCallback)callbacks [i]; if (cb.getRequest() instanceof SignatureVerificationKeyCallback.X509Subjec tKeyIdentifierBasedRequest) { // subject keyid request SignatureVerificationKeyCallback.X509SubjectKeyIdentifierBased Request request = (SignatureVerificationKeyCallback.X509SubjectKeyIdentifierBase dRequest) cb.getRequest(); // locate and setX509Certificate on the request } else if (cb.getRequest() instanceof SignatureVerificationKeyCallback.X509Issu erSerialBasedRequest) { // issuer serial request SignatureVerificationKeyCallback.X509IssuerSerialBasedRequest request = (SignatureVerificationKeyCallback.X509IssuerSerialBasedRequest ) 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.DefaultPrivKeyCertRequest) { // 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 { // throw unsupported; } } } }Similarly, an application dealing only with
UsernameTokenbut not signature or encryption requirements can simply throwUnsupportedCallbackExceptionfor all non-username related callbacks.The
SecurityEnvironmentHandlerimplementation for thesimplesample is located in the directory<JWSDP_HOME>/xws-security/samples/simple/src/com/sun/xml/wss/sample. Thesimplesample uses the sameSecurityEnvironmentHandlerfor both the client and server side.The
jaas-samplesample requires a different set of callbacks to be handled on the client and server side. TheCallbackHandlersfor thejaas-samplesample are located in the directory<JWSDP_HOME>/xws-security/samples/jaas-sample/src/com/sun/xml/wss/sample. The twoCallbackHandlersdefined for thejaas-sampleare:
- A
ClientSecurityEnvironmentHandlerthat handles only theUsernameCallbackandPasswordCallbackfor retrieving the username and password to be sent in a WSSUsernameToken.- A
ServerSecurityEnvironmentHandlerthat handles only thePasswordValidationCallbackto validate the username-password pair that it received in the WSSUsernameToken.Using the SubjectAccessor API
XWS-Security applications might require access to the authenticated subject of the sender from within the SEI implementation methods. The
SubjectAccessorAPI contains a single method:This method returns the
Subjectif one is available or else it returnsNULL. The context argument to be passed into this method is theServletEndpointContextwhich is available with the SEI implementation class. For an example on how theSubjectAccessoris used to obtain the authenticated sender subject, refer to thePingImpl.javaclass in thejaas-samplesample located at<JWSDP_HOME>/xws-security/samples/jaas-sample/server/src/sample. The API forSubjectAccessorviewed from<JWSDP_HOME>/xws-security/docs/api/com/sun/xml/wss/SubjectAccessor.html.
|
Download
FAQ History |
|
API
Search Feedback |
All of the material in The Java(TM) Web Services Tutorial is copyright-protected and may not be published in other works without express written permission from Sun Microsystems.