SOAP KeyInfo failed to recognise by IIS Server and client is java - java

I am getting following error while consuming .Net Web Service from java Spring
Web Service uses Certificate based authentication.
I tried java(Server) to java(Client) working locally using HTTPS and without https
Even .Net Side Server and client working.
org.springframework.ws.soap.client.SoapFaultClientException: Referenced security token could not be retrieved --->
WSE590: Failed to resolve the following Key Info
<KeyInfo Id="KI-A65A1CE3CB2EB7AE6114286591136763" xmlns="http://www.w3.org/2000/09/xmldsig#">
<wsse:SecurityTokenReference xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<ds:X509Data xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:X509IssuerSerial>
<ds:X509IssuerName>CN=VXX,OU=NXX,O=iXXX,L=Cty,ST=MH,C=IN</ds:X509IssuerName>
<ds:X509SerialNumber>1711043036</ds:X509SerialNumber>
</ds:X509IssuerSerial>
</ds:X509Data>
</wsse:SecurityTokenReference>
</KeyInfo>.
I am using org.springframework.ws.soap.security.wss4j.Wss4jSecurityInterceptor
to intercept request and response.
I don't understand whats happening at .Net side as its developed by other team.
But .Net Team told request is not reached to applcation, IIS server itself not able to process this.
Please find .Net client calling code snippet.
// TODO: Replace with a valid path to your certificate
string certPath = #"C:\mypath\certClient1.cer";
Secured.TSRService objsecserv = new Secured.TSRService();
objsecserv.Url = #"https://xyz/service.asmx";
//objsecserv.Url = #"http://xyz:97/service.asmx";
objsecserv.ClientCertificates.Add(X509Certificate.CreateFromCertFile(certPath));
objsecserv.Timeout = Timeout.Infinite;
string strresult1 = objsecserv.GetCertDetails();
rtxtresult.Text = strresult1;
And Here is my java side code snippet
<bean id="countryWsClSecInterId" class="org.springframework.ws.soap.security.wss4j.Wss4jSecurityInterceptor">
<property name="securementActions" value="Timestamp Signature" /> <!-- Encrypt -->
<!-- Key alias for signature -->
<property name="securementUsername" value="client" />
<property name="securementPassword" value="mypasswd" />
<property name="securementSignatureCrypto" ref="countryCrypto"/>
<property name="securementEncryptionCrypto" ref="countryCrypto"/>
<!-- Key alias for encryption -->
<property name="securementEncryptionUser" value="server"/>
<!-- Validation config -->
<property name="validationActions" value="Signature" />
<property name="validationSignatureCrypto" ref="countryCrypto"/>
</bean>
Please guide me , I searched a lot and made changes according but nothing worked.

Related

This could be due to the fact that the server certificate is not configured properly with HTTP.SYS in the HTTPS case. c#

Maybe this question already has but I think there is a different situation.
I configure all required things from the web config file and install certificates.
I consume java web service in ASP.NET WEB API.
SOAP service was configured mutual authentication. (Two-way SSL)
I have 2 Keystore files. (client.jks and truststore.jks)
My full error: This could be due to the fact that the server certificate is
not configured properly with HTTP.SYS in the HTTPS case.
This could also be caused by a mismatch of the security binding between
the client and the server.'
WebConfig:
<customBinding>
<binding name="MyBinding">
<textMessageEncoding messageVersion="Soap11"/>
<security authenticationMode="MutualCertificate" enableUnsecuredResponse="true" allowSerializedSigningTokenOnReply="true"
messageSecurityVersion="WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10"
includeTimestamp="false">
</security>
<httpsTransport />
</binding>
</customBinding>
<endpoint behaviorConfiguration="ClientCredentialsBehavior" address="https://abc.bank.dm:9193/Money/Money" binding="customBinding" bindingConfiguration="MyBinding" contract="Ref.Port" name="Port">
<identity>
<dns value="test"/>
</identity>
</endpoint>
<behaviors>
<endpointBehaviors>
<behavior name="ClientCredentialsBehavior">
<clientCredentials>
<clientCertificate findValue="2d73n94087857dndyr874ydr"
storeLocation="CurrentUser"
storeName="My"
x509FindType="FindByThumbprint" />
<serviceCertificate>
<defaultCertificate findValue="d346n32d48938w43d943095d"
storeLocation="CurrentUser"
storeName="TrustedPeople"
x509FindType="FindByThumbprint" />
<authentication certificateValidationMode="None" revocationMode="NoCheck"/>
</serviceCertificate>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
Try to specify the same protocol on the client and server. Add the following code in the client:
System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls12;
Here is the reference: TLS 1.2

Multiple AssertionConsumerService in SP with differend 2nd level domains

I am implementing a multitenant application with the spring security saml extention.
I have a Service Provider (SP) for each tenant.
All SPs runs on the same server exposed with SP-specific 2nd level domain:
sp1.myapp.com/myapi/1/
sp1.myapp.com/myapi/2/
In each SP metadata file I have configured the tenant-specific AssertionConsumerService.
When I test the SSO Login, I get a KO on SP side when it gets the response of the Identity Provider (IDP).
On Log side i see only:
ERROR [BaseSAMLMessageDecoder] SAML message intended destination endpoint 'https://sp1.myapp.com/myapi/saml/SSO' did not match the recipient endpoint 'https://default.myapp.com/myapi/saml/SSO'
Where the 'https://default.myapp.com/myapi/saml/SSO' is the URL set as serverName of the load balancer context provider:
<bean id="lbContextProvider" class="org.springframework.security.saml.context.SAMLContextProviderLB" init-method="afterPropertiesSet">
<property name="metadata" ref="metadata" />
<property name="keyManager" ref="keyManager" />
<property name="scheme" value="https" />
<property name="serverName" value="default.myapp.com" />
<property name="contextPath" value="/myapi" />
<property name="serverPort" value="443" />
<property name="includeServerPortInRequestURL" value="true" />
</bean>
Question
In the docs.spring.io/spring-security-saml I see that
Service provider can now define multiple assertion consumer endpoints with same binding
How can I configure it?
Does it conflict with load balancer context provider?
Can I provide multiple AssertionConsumerService with different 2nd level domains without reproduction this conflict?
I already tested:
This question seems to be fixed with the LB, but anyone knows if I can provide multiple serverName to load balancer context provider (maybe with a dynamic pick)?
Disable the checking of the InResponseToField as suggested at ch.13 docs.spring.io/spring-security-saml and for this and this question.
Configure the defaultTargetUrl of the successRedirectHandler (where I am using a custom superclass of org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler) as suggested for this question. In addition this solution is not multitenant.
<bean id="successRedirectHandler" class="org.MySamlAuthenticationSuccessHandler"
init-method="afterPropertiesSet">
<property name="contextPath" value="/myapi" />
<property name="defaultTargetUrl" value="https://default.myapp.com/myapi/saml/SSO"/>
<property name="requireProxyWrapping" value="false"/>
</bean>
Customize SAMLContextProviderLB by extending SamlContextProviderLB.
In custom class, add constructor and initialize with default values.
Override getLocalAndPeerEntity/getLocalEntity/populateLocalEntityId. In each of this method set lbDomain based on domain in requestURL.
above approach worked for me.

Difference between certificates for APNs

Is it any difference between certificates for development and production servers?
If I have my_certificate.p12 and for ApnService provide that information
<bean id="apnsServiceFactory" class="org.apache.camel.component.apns.factory.ApnsServiceFactory">
<property name="feedbackHost" value="feedback.sandbox.push.apple.com" />
<property name="feedbackPort" value="2196" />
<property name="gatewayHost" value="gateway.sandbox.push.apple.com" />
<property name="gatewayPort" value="2195" />
<property name="certificatePath" value="file:etc/my_certificate.p12" />
<property name="certificatePassword" value="111" />
</bean>
would it be equal with that?
<bean id="apnsServiceFactory" class="org.apache.camel.component.apns.factory.ApnsServiceFactory">
<property name="feedbackHost" value="feedback.push.apple.com" />
<property name="feedbackPort" value="2196" />
<property name="gatewayHost" value="gateway.push.apple.com" />
<property name="gatewayPort" value="2195" />
<property name="certificatePath" value="file:etc/my_certificate.p12" />
<property name="certificatePassword" value="111" />
</bean>
I mean, will I be able to get some pushes and feedback with only 1 certificate, or I must have both?
And for test in development, should I use gateway.sandbox.push.apple.com or I can use feedback.push.apple.com ?
While you are in development mode, i mean for the builds installed in device via Xcode or OTA, the notifications must use development certificates and need to use gateway.sandbox.push.apple.com for sending notifications.
But while in production mode, i mean once you have tested everything looks good, and uploaded build to AppStore/TestFlight. So, for those builds, you required to use production/distribution certificates and required to sent via feedback.push.apple.com.
UPDATE:
If you required common way for both development and distribution. Then stop using certificates, instead start using token based APNs keys for the same. You can refer more detail about token based APNs keys over here: https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/establishing_a_token-based_connection_to_apns

Generate web service client secure policy from .wsdl for java

I have been researching how to implement a web service client policies from a .wsdl file.
The policies of the web services implicates a signature and encryption using a .jks file with the necessary keys (asymmetric privateKey for signing, and a symmetric privateKey for encryption). The policy is: username:oracle/wss10_username_token_with_message_protection_service_policy.
I am able to make the .xsd files (request, response and service objects) using the wsimport tool for java (or with cxf or axis2). What i can't resolve is how to make the correct policy.
Is there any way to automatically generate the policies from the .wsdl or do i have to make them by myself
The username:oracle/wss10_username_token_with_message_protection_service_policy is solved with spring ws this way:
<!-- == Ougoing interceptor == -->
<bean id="loginOutgoingWss4jSecurityInterceptor" class="org.springframework.ws.soap.security.wss4j2.Wss4jSecurityInterceptor">
<property name="securementActions" value="Timestamp Signature Encrypt" />
<!-- == Set Outgoing Signature properties == -->
<property name="securementUsername" value="alias"/>
<property name="securementPassword" value="aliasPass"/>
<property name="securementSignatureKeyIdentifier" value="DirectReference"/>
<property name="securementSignatureCrypto" ref="cryptoFactoryBean" />
<property name="securementSignatureParts" value="{Element}{}Body;{Element}{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd}Timestamp;" />
<!-- == Set Outgoing Encryption properties == -->
<property name="securementEncryptionUser" value="alias"/>
<property name="securementEncryptionCrypto" ref="cryptoFactoryBean" />
<property name="securementEncryptionKeyIdentifier" value="DirectReference"/>
<property name="securementEncryptionParts" value="{Content}{}Body;" />
</bean>
<!-- == Incoming interceptor == -->
<bean id="loginIncomingWss4jSecurityInterceptor" class="org.springframework.ws.soap.security.wss4j2.Wss4jSecurityInterceptor">
<property name="validationActions" value="Timestamp Signature Encrypt" />
<!-- == Set Validations Response, This validate signature and decrypts response == -->
<property name="validateResponse" value="true" />
<!-- The lower operation validation. Less time consume-->
<property name="validateRequest" value="false" />
<property name="enableSignatureConfirmation" value="false"/>
<!-- == Set Incoming Signature/Decryption keystore == -->
<property name="validationDecryptionCrypto" ref="cryptoFactoryBean" />
<property name="validationSignatureCrypto" ref="cryptoFactoryBean" />
<!-- Sets the {#link org.apache.ws.security.WSPasswordCallback} handler to use when validating messages -->
<property name="validationCallbackHandler">
<bean class="org.springframework.ws.soap.security.wss4j2.callback.KeyStoreCallbackHandler">
<property name="privateKeyPassword" value="aliasPass"/>
</bean>
</property>
</bean>
If you are using policies in WS-SecurityPolicy (1.1 or later) in your wsdl, no need to generate policies nor make them on client side with Apache CXF. With WS-SecurityPolicy, CXF's security runtime is policy driven.
1) You follow CXF's WSDL-first approach to generate the client code, using either wsdl2java command-line tool or Maven cxf-codegen-plugin (wsdl2java goal). This is described in CXF doc's How to develop a client.
2) Following CXF's doc on WS-SecurityPolicy usage, you configure the client security properties for the wsdl port you want to use, either using JAX-WS API (on the client's RequestContext) or Spring XML configuration. For the list of possible properties, there are the generic XML security ones and WS-Security-specific ones. Example with Spring XML for UsernameToken policy (from Glen Mazza's blog samples ):
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd">
<jaxws:client name="{http://www.example.org/contract/DoubleIt}DoubleItPort" createdFromAPI="true">
<!-- Use this for the UsernameToken Symmetric Binding w/X.509 for secret key derivation -->
<jaxws:properties>
<entry key="ws-security.username" value="alice"/>
<entry key="ws-security.callback-handler" value="client.ClientPasswordCallback"/>
<entry key="ws-security.encryption.properties" value="clientKeystore.properties"/>
<entry key="ws-security.encryption.username" value="myservicekey"/>
</jaxws:properties>
<!-- Use this for the UsernameToken Symmetric Binding w/UT password for secret key derivation -->
<!--jaxws:properties>
<entry key="ws-security.username" value="alice"/>
<entry key="ws-security.callback-handler" value="client.ClientPasswordCallback"/>
</jaxws:properties-->
</jaxws:client>
</beans>
Put this in /cxf.xml on the class path. Warning: the example is using a CallbackHandler subclass (client.ClientPasswordCallback in this example) to provide the password. So you'll need to provide your own implementation.
3) Back to CXF doc's How to develop a client - last part - in the application code, initialize the client using JAX-WS API with arguments: a) the location of the WSDL (URL) having the WS-SecurityPolicy policies (you already have that, as far as I understand); b) service and port's QNames to be used by the client, as defined in the WSDL:
final Service service = Service.create(wsdlLocation, SERVICE_QNAME);
final DoubleItPortType transportPort = service.getPort(PORT_QNAME, DoubleItPortType.class);
4) Make sure you have cxf-rt-ws-policy and cxf-rt-ws-security modules on the classpath at runtime to enable WS-SecurityPolicy support.

What is proper way to add encryption/decryption in spring-ws (wss4j)?

I have deployed 2 web apps, one representing web service and other representing ws client. When using SIGNING and TIMESTAMP-ing, everything works fine, client stamps message(but i think that he doesn't override the default 300s ttl), signs the message with his x509 cert, and sends it to ws. He, in the other hand, recives message and is able to valiadate timestamp and certificate/signature against clients trusted cert in his keystore.
Problem arises when i add Encrypt operation to my configuration. Client seems to be able to encrypt the message, but ws seems not to be intrested in decrypting the message. He just sees that there is no endpoint mapping for
[SaajSoapMessage {http://www.w3.org/2001/04/xmlenc#}EncryptedData]
and throws
WebServiceTransportException: Not Found [404] exception.
SO can someone explain what I need to do in order to achieve timestamping,signing with x509 and encryption, again with x509?
part of server app-context:
<bean id="wss4jSecurityInterceptor" class="org.springframework.ws.soap.security.wss4j.Wss4jSecurityInterceptor">
<!-- valiadation -->
<property name="validationActions" value="Timestamp Signature Encrypt"/>
<property name="enableSignatureConfirmation" value="true"/>
<property name="validationSignatureCrypto">
<ref bean="keystore"/>
</property>
<property name="validationDecryptionCrypto">
<ref bean="keystore"/>
</property>
<property name="validationCallbackHandler">
<bean class="org.springframework.ws.soap.security.wss4j.callback.KeyStoreCallbackHandler">
<property name="privateKeyPassword" value="password"/>
</bean>
</property>
<!-- timestamp options -->
<property name="timestampStrict" value="true"/>
<property name="timeToLive" value="30"/>
<property name="timestampPrecisionInMilliseconds" value="true"/>
<!-- signing and encryption -->
<property name="securementActions" value="Timestamp Signature Encrypt"/>
<property name="securementUsername" value="wsserver"/>
<property name="securementPassword" value="password"/>
<property name="securementSignatureKeyIdentifier" value="DirectReference"/>
<property name="securementSignatureCrypto">
<ref bean="keystore"/>
</property>
<property name="securementEncryptionUser" value="wsclient"/>
<property name="securementEncryptionCrypto">
<ref bean="keystore"/>
</property>
</bean>
<!-- keystore -->
<bean id="keystore" class="org.springframework.ws.soap.security.wss4j.support.CryptoFactoryBean">
<property name="keyStorePassword" value="password"/>
<property name="keyStoreLocation" value="WEB-INF/MyTruststore.jks"/>
</bean>
<!-- interceptors -->
<sws:interceptors>
<ref bean="wss4jSecurityInterceptor"/>
<bean id="validatingInterceptor"
class="org.springframework.ws.soap.server.endpoint.interceptor.PayloadValidatingInterceptor">
<property name="schema" value="/WEB-INF/person.xsd"/>
<property name="validateRequest" value="true"/>
<property name="validateResponse" value="true"/>
</bean>
<bean id ="loggingInterceptor" class="org.springframework.ws.server.endpoint.interceptor.PayloadLoggingInterceptor">
</bean>
</sws:interceptors>
Client basicly uses the same config, except that he uses server public key for encryption, and his private key for decryption.
Keystores are ok, i guess, because signing works ok...Everything juust falls apart when i add Encrypt action, part of server log says:
DEBUG [org.springframework.ws.server.MessageTracing.recei ved] - Received request [SaajSoapMessage {http://www.w3.org/2001/04/xmlenc#}EncryptedData]
DEBUG [org.springframework.ws.server.endpoint.mapping.Pay loadRootAnnotationMethodEndpointMapping] - Looking up endpoint for [{http://www.w3.org/2001/04/xmlenc#}EncryptedData]
DEBUG [org.springframework.ws.soap.server.SoapMessageDisp atcher] - Endpoint mapping [org.springframework.ws.server.endpoint.mapping.Pay loadRootAnnotationMethodEndpointMapping#30a14083] has no mapping for request
...
No endpoint mapping found for [SaajSoapMessage {http://www.w3.org/2001/04/xmlenc#}EncryptedData]
org.springframework.ws.client.WebServiceTransportE xception: Not Found [404]
...
I think I must somehow instruct ws to decrypt SOAP body before it starts to look for an endpoint for message,but I don't know how. Suggestions?
Since your comments were helpful but kind of incomplete, I took a shoot of answering with a bit more of a detail.
In the spring tutorial, the endpoint method is annotated with #PayloadRoot: #PayloadRoot(localPart = "orderInput", namespace = "http://samples")
This works fine when the soap message is not encrypted. PayloadRootAnnotationMethodEndpointMapping is able to map to soap message to the corresponding method.
When the soap message is encrypted, the PayloadRootAnnotationMethodEndpointMapping is unable to map the soap message because The security interceptor did not have yet the time to decipher it. The solution is to replace #PayloadRoot with #SoapAction.
When a soap message is received, spring-ws calls first the PayloadRootAnnotationMethodEndpointMapping then SoapActionAnnotationMethodEndpointMapping. You can use both in order to be full compatible with non-spring client (axis for example or .net):
#PayloadRoot(localPart = "orderInput", namespace = "http://samples")
#SoapAction("http://samples/order")
Last but not least: If you are using a spring client with secured soap message, spring does not send soap action automatically. Your server will not be able to map the soap message with the appropriate action. In order to solve this problem, you should use a WebServiceMessageCallback:
ClientMessageCallBack callBack = new ClientMessageCallBack(
"http://samples/order");
Object output = wsTemplate.marshalSendAndReceive(inputObject, callBack);
where ClientMessageCallBack class is
public final class ClientMessageCallBack
implements WebServiceMessageCallback {
/**the soapAction to be appended to the soap message.*/
private String soapAction;
/**constructor.
* #param action the soapAction to be set.*/
public ClientMessageCallBack(final String action) {
this.soapAction = action;
}
#Override
public void doWithMessage(final WebServiceMessage message)
throws IOException, TransformerException {
if (message instanceof SoapMessage) {
SoapMessage soapMessage = (SoapMessage) message;
soapMessage.setSoapAction(soapAction);
}
}
}
this happens because you did not defined securementEncryptionParts property. It causes to encrypt whole body and made to this Error
Is there anyway to decrypt request before it triggers #Endpoint? issue is that client can not add soapaction.

Categories

Resources