I have a WCF client connecting to a Java based Axis2 web service (outside my control). It is about to have WS-Security applied to it, and I need to fix the .NET client. However, I am struggling to provide the correct authentication. I am aware that WSE 3.0 might make it easier, but I would prefer not to revert to an obsolete technology.

Similar issues (unsolved), include thisthis and this.

The SOAP message should look like this:

<wsse:UsernameToken>
<wsse:Username><!-- Removed--></wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest"><!-- Removed--></wsse:Password>
<wsse:Nonce><!-- Removed--></wsse:Nonce>
<wssu:Created>2010-05-28T12:50:33.675+01:00</wssu:Created>
</wsse:UsernameToken>

However, mine looks like this:

<s:Header>
<h:Security xmlns:h="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"></h:Security>
<o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<u:Timestamp u:Id="_0">
<u:Created>2010-06-23T10:31:23.441Z</u:Created>
<u:Expires>2010-06-23T10:36:23.441Z</u:Expires>
</u:Timestamp>
<o:UsernameToken u:Id="uuid-d329b3b2-6a1f-4882-aea6-ec6b8a492de7-1">
<o:Username>
<!-- Removed-->
</o:Username>
<o:Password>
<!-- Removed-->
</o:Password>
</o:UsernameToken>
</o:Security>
</s:Header>

My client looks like this: P.S. Note the required SecurityHeaderType param. What is that?

public MyAck SendRequest(MyRequest request)
{
RemoteServicePortTypeClient client = new RemoteServicePortTypeClient(); client.ClientCredentials.UserName.UserName = "JAY";
client.ClientCredentials.UserName.Password = "AND"; // what is the difference between the two different Credential types??
//client.ClientCredentials.HttpDigest.ClientCredential.UserName = "SILENT";
//client.ClientCredentials.HttpDigest.ClientCredential.Password = "BOB"; SecurityHeaderType sht = new SecurityHeaderType();
//sht.Any = ???; // How do I use this???
//sht.AnyAttr = ???; // How do I use this ??? // SecurityHeaderType is a required parameter
return client.RemoteServiceOperation_Provider(sht, request);
}

Current binding is as follows:

<basicHttpBinding>
<binding name="CustomBinding">
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="None"></transport>
<message clientCredentialType="UserName" />
</security>
</binding>
</basicHttpBinding>

I've also tried a custom binding and got a similar error:

<customBinding>
<binding name="myCustomBindingConfig">
<security authenticationMode="UserNameOverTransport"
messageSecurityVersion="WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11"
securityHeaderLayout="Strict"
includeTimestamp="false"></security>
<textMessageEncoding messageVersion="Soap11"></textMessageEncoding>
<httpsTransport />
</binding>
</customBinding>

And endpoint (Address obviously changed...):

<endpoint address="https://www.somecompany.com/uat/axis/services/RemoteServiceOperation_Provider"
binding="basicHttpBinding" bindingConfiguration="CustomBinding"
contract="RemoteService.RemoteServicePortType"
name="RemoteService_UAT" />

The custom fault that is being returned is as follows:

<ErrorID>0</ErrorID>
<ErrorType>UNEXPECTED</ErrorType>
<ErrorDescription><![CDATA[Array index out of range: 0]]></ErrorDescription>
<TimeStamp>2010-06-23T13:28:54Z</TimeStamp>

I've read lots about custom headers, tokens, bindings and my brain is completely confused. Can anyone suggest a step by step process for sending the message in the right format?

This appears to be the way forward for WCF, using custom tokens, but how should one apply the digest and nonce as required?

Any help welcomed.

UPDATE

I've had some limited success. I've used the Microsoft.Web.Services3 library to create a UsernameToken with the correct digest. I've then created my own custom behavior and in the BeforeSendRequest method I've done the following to inject the header:

object IClientMessageInspector.BeforeSendRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel)
{
UsernameToken ut = new UsernameToken("USERNAME", "PASSWORD", PasswordOption.SendHashed); XmlElement securityElement = ut.GetXml(new XmlDocument()); MessageHeader myHeader = MessageHeader.CreateHeader("Security", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", securityElement, false);
request.Headers.Add(myHeader); return Convert.DBNull;
}

I add the behavior like so:

CustomBehavior behavior = new CustomBehavior("USERNAME", "PASSWORD");
client.Endpoint.Behaviors.Add(behavior);

I can now see the headers going across:

<s:Header>
<Security xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:UsernameToken wsu:Id="SecurityToken-c6aeb72d-4d36-4650-abd3-33cc66caac6d" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsse:Username>
<!-- Removed-->
</wsse:Username>
<wsse:Password>
<!-- Removed-->
</wsse:Password>
<wsse:Nonce>
<!-- Removed-->
</wsse:Nonce>
<wsu:Created>2010-06-24T16:23:58Z</wsu:Created>
</wsse:UsernameToken>
</Security>
</s:Header>

But I'm getting the error:

<soapenv:Fault>
<faultcode xmlns="">soapenv:Server</faultcode>
<faultstring xmlns="">WSDoAllReceiver: security processing failed; nested exception is:
org.apache.ws.security.WSSecurityException: General security error (WSSecurityEngine: Callback supplied no password for: USERNAME)</faultstring>
<faultactor xmlns="">urn:Remote_Provider</faultactor>
<detail xmlns="">
<CUSTOMError xmlns="urn:customerror:v01">
<ErrorID>0</ErrorID>
<ErrorType>UNEXPECTED</ErrorType>
<ErrorDescription><![CDATA[WSDoAllReceiver: security processing failed; nested exception is:
org.apache.ws.security.WSSecurityException: General security error (WSSecurityEngine: Callback supplied no password for: USERNAME)]]></ErrorDescription>
<TimeStamp>2010-06-24T17:23:59Z</TimeStamp>
</CUSTOMError>
</detail>
</soapenv:Fault>

There appears to be a missing Type attribute on the password node:

Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest"

However, I'm not sure if the security tracing and logging settings are blanket removing the attributes and content of those nodes. I've attempted to use the logKnownPii setting in the diagnostics logging, but the security information remains obscured. Any ideas on that one?

asked Jun 23 '10 at 14:47
Junto

7,57975393
 

3 Answers

I can confirm that the UPDATE from my question actually works:

object IClientMessageInspector.BeforeSendRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel)
{
UsernameToken ut = new UsernameToken("USERNAME", "PASSWORD", PasswordOption.SendHashed); XmlElement securityElement = ut.GetXml(new XmlDocument()); MessageHeader myHeader = MessageHeader.CreateHeader("Security", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", securityElement, false);
request.Headers.Add(myHeader); return Convert.DBNull;
}

And the client:

CustomBehavior behavior = new CustomBehavior("USERNAME", "PASSWORD");
client.Endpoint.Behaviors.Add(behavior);

The error message was unrelated. The security header works with a very simple basicHttpBinding:

<basicHttpBinding>
<binding name="BasicSOAPBinding">
<security mode="Transport" />
</binding>
</basicHttpBinding>

Code sample of this in action can be found on my blog: http://benpowell.org/supporting-the-ws-i-basic-profile-password-digest-in-a-wcf-client-proxy/

answered Jul 15 '10 at 16:35
Junto

7,57975393
 

This question is well written -- many thanks. In reference to @Junto's "How do I use this" comment, it turns out that the SecurityHeader param on the service method can be used to add the header. I've included an example below. I believe that what's happening is that the SvcUtil.exe tool is barfing when trying to read the WS* DTDs. This is not obvious when you use the "Add Service Reference" wizard. But it is very obvious when you run svcutil.exe from the command line. Because svcutil.exe fails to read the WS* DTD's, the SecurityHeader object is not well developed. But Microsoft gives you an out with the .Any property. You can serialize the UsernameToken class right into the .Any property and your header will be added to the message. Again, thanks for this excellent question.

How to use the SecurityHeader parameter to add a UsernameToken security header:

Required tools:

Fiddler2 (or similar) -- you really can't figure any of this out without inspecting the http headers.

Required Reference:

Microsoft.Web.Services3.dll -- you can reference this 2.0 framework assembly from your 4.0 assembly

WCF service call:

// Initialization of the service...
_service = new MyService("MyEndpoint", RemoteUri); // etc. // Calling the service -- note call to GetSecurityHeader()
_service.ServiceAction(GetSecurityHeader(), "myParam1"); // etc. /// <summary>
/// Construct the WSE 3.0 Security Header
/// </summary>
private SecurityHeader GetSecurityHeader()
{
SecurityHeader h = new SecurityHeader();
UsernameToken t = new UsernameToken(RemoteLogin, RemotePassword, PasswordOption.SendPlainText);
h.Any = new XmlElement[1];
h.Any[0] = t.GetXml(new XmlDocument());
return h;
}

App.config:

  <system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="MyBinding" closeTimeout="00:01:00" openTimeout="00:01:00"
receiveTimeout="00:10:00" sendTimeout="00:10:00" allowCookies="false"
bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="1048576" maxBufferPoolSize="524288" maxReceivedMessageSize="1048576"
messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="Transport">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://myservice.com/service.asmx"
binding="basicHttpBinding" bindingConfiguration="MyBinding" contract="MyContract"
name="MyEndpoint" />
</client>
</system.serviceModel>
answered Sep 12 '11 at 12:41
Brett

4,84921530
 
    
GetSecurityHeader() did it for me, thanks! – Robotron Apr 24 '14 at 13:44

I had a similar problem recently and gave up searching for a non-WSE solution. After a couple days of pulling my hair out I ended downloading the WSE 3.0 SDK, generating a proxy class using WseWsdl3.exe, and creating a new policy for the UsernameToken. I was up and running in 15min. The following is currently working for me.

RemoteService service = new RemoteService();  //generated class

UsernameToken token = new UsernameToken(username, password, PasswordOption.SendPlainText);
Policy policy = new Policy();
policy.Assertions.Add(new UsernameOverTransportAssertion()); service.SetClientCredential(token);
service.SetPolicy(policy); var result = service.MethodCall();
answered Jun 26 '10 at 21:26

Error in WCF client consuming Axis 2 web service with WS-Security UsernameToken PasswordDigest authentication scheme的更多相关文章

  1. 应用Apache Axis进行Web Service开发

    转自(http://tscjsj.blog.51cto.com/412451/84813) 一.概述 SOAP原意为Simple Object Access Protocol(简单对象访问协议),是一 ...

  2. Axis开发Web Service

    可以自动生成代码的 一.Axis环境的安装 1.安装环境 J2SE SDK 1.4,Tomcat 5.0,eclipse 3.2. 2.到 http://xml.apache.org 网站下载Axis ...

  3. iOS 中client和server的 Web Service 网络通信 (1)

    当你打开你手机上新浪微博应用或者知乎应用是.你是否会去想这些显示在手机上的图片和数据时从哪里来的?又是通过如何的方法实现的?好.那么接下来就介绍是如何实现的.过程又是怎么样的.      当我们浏览着 ...

  4. 使用axis开发web service服务端

    一.axis环境搭建 1.安装环境 JDK.Tomcat或Resin.eclipse等. 2.到 http://www.apache.org/dyn/closer.cgi/ws/axis/1_4下载A ...

  5. WCF、Net remoting、Web service概念及区别

    Windows通信基础(Windows Communication Foundation,WCF)是基于Windows平台下开发和部署服务的软件开发包(Software Development Kit ...

  6. Consuming a RESTful Web Service

    本篇文章将介绍使用Spring来建立RESTful的Web Service. 我们通过一个例子来说明这篇文章:这个例子将会使用Spring的RestTemplate来从Facebook的提供的API中 ...

  7. WCF、.Net Remoting、Web Service概念及区别

    此文章主要参考http://www.cnblogs.com/weiweibtm/archive/2013/06/21/3148583.html 参考书籍<WCF全面解析上册>.<WC ...

  8. iOS 中client和server的 Web Service 网络通信 (2)

    在实际的应用开发过程中,同步请求的用户体验并非非常好:我们都知道.Apple是非常重视用户体验的.这一点也成为了行业的标杆,没实用户哪里来的好产品.所以用户体验是极其重要的.貌似废话有点多.接下来进入 ...

  9. Part 17 Consuming ASP NET Web Service in AngularJS using $http

    Here is what we want to do1. Create an ASP.NET Web service. This web service retrieves the data from ...

随机推荐

  1. zw版【转发·台湾nvp系列Delphi例程】HALCON HSerializedItem

    zw版[转发·台湾nvp系列Delphi例程]HALCON HSerializedItem procedure TForm1.FormShow(Sender: TObject);var img, im ...

  2. Mybatis 之动态代理

    使用Mybatis 开发Web 工程时,通过Mapper 动态代理机制,可以只编写接口以及方法的定义. 如下: 定义db.properties driver=oracle.jdbc.OracleDri ...

  3. WPF usercontrol 自定义依赖属性

    1.依赖属性不同意一般属性,一般属性主要定义在对象中,而依赖属性是存在一个特殊的依赖属性表中.2.当我们触发改变值时,需要通过SetValue这种方式进行触发. UserControl1.xaml: ...

  4. INNODB存储引擎表空间

    这片文章主要是对innodb表空间的一些说明: innodb中表空间可以分为以下几种: 系统表空间 独立表空间 undo表空间 临时表空间(temporary tablespace) 通用表空间(ge ...

  5. Python3.x的BeautifulSoup解析html常用函数

    Python3.x的BeautifulSoup解析html常用函数 1,初始化: soup = BeautifulSoup(html) # html为html源代码字符串,type(html) == ...

  6. # 20145122 《Java程序设计》第3周学习总结

    教材学习内容总结 1一类一文件. 2一个原始码中只能有一个公开类,一个类定义产生一个.class文档. 3如果参考名称与数据成员同名时,将参数的值指定给对象的数据成员时要在数据成员前加this. 4当 ...

  7. Python3基础 try-except 几个异常采取同样的处理方法

             Python : 3.7.0          OS : Ubuntu 18.04.1 LTS         IDE : PyCharm 2018.2.4       Conda ...

  8. [BZOJ1176]Mokia

    Description 维护一个W*W的矩阵,初始值均为S.每次操作可以增加某格子的权值,或询问某子矩阵的总权值.修改操作数M<=160000,询问数Q<=10000,W<=2000 ...

  9. LA 3268 号码簿分组(最大流+二分)

    https://vjudge.net/problem/UVALive-3268 题意: 有n个人和m个组.一个人可能属于很多组.现在请你从某些组中去掉几个人,使得每个人只属于一个组,并使得人数最多的组 ...

  10. Codeforces Round #394 (Div. 2) A,B,C,D,E

    A. Dasha and Stairs time limit per test 2 seconds memory limit per test 256 megabytes input standard ...