Wwsapi Windows Web Services Api Http Kerberos Client
- 31 Mar 2009
Further adventures with the WWSAPI Beta. If you find this useful please take the time to Jot me a quick comment or note!
I decided to investigate these API’s and make a simple call to the same WebService in my previous blog post using Kerberos. I first copied the WebService inside my network so I could use Kerberos and configured the IIS 6 WebSite to use Windows Integrated authentication only.
There are several examples of using Negotiate with SSL but I did not want to use SSL. I figured all I needed to do was remove the SSL bindings from the samples… WRONG!
Here are the other steps I took and the challenges I faced:
</font><font color=#008000 size=2><font color=#008000 size=2>// use the default client credential if the thread opening the channel/proxy is impersonating,
</font></font><font color=#008000 size=2><font color=#008000 size=2>// the thread token will be used; otherwise, the process token will be used
</font></font>WS_DEFAULT_WINDOWS_INTEGRATED_AUTH_CREDENTIAL defaultCred = {}; <font color=#008000 size=2><font color=#008000 size=2>// zero out the struct
</font></font>
</p>
defaultCred.credential.credentialType = WS_DEFAULT_WINDOWS_INTEGRATED_AUTH_CREDENTIAL_TYPE;
</font><font color=#008000 size=2><font color=#008000 size=2>// declare and initialize properties to set the authentication scheme to Negotiate
</p>
WS_SECURITY_BINDING_PROPERTY headerAuthBindingProperties [1] =
</font><font color=#008000 size=2><font color=#008000 size=2>// declare and initialize an header authentication security binding
</font></font>
</p>
headerAuthBinding.binding.bindingType = WS_HTTP_HEADER_AUTH_SECURITY_BINDING_TYPE;
</p>
</font><font color=#008000 size=2><font color=#008000 size=2>// declare and initialize the array of all security bindings
</p>
</font><font color=#008000 size=2><font color=#008000 size=2>// declare and initialize the security description
<font color=#008000 size=2><font color=#008000 size=2>
</p>
// Create the proxy
<font color=#008000 size=2><font color=#008000 size=2>// set the protection level to none – you have to do this to avoid the error: E_INVALIDARG when you call a SOAP method
securityDescription.properties = securityProperties; <s:Envelope xmlns:a=”<font color=#0000ff size=3 face=Calibri>http://www.w3.org/2005/08/addressing</font>” xmlns:s=”<font color=#0000ff size=3 face=Calibri>http://www.w3.org/2003/05/soap-envelope</font>“><s:Header
><a:Action s:mustUnderstand=”1″><font color=#0000ff size=3 face=Calibri>http://tempuri.org/HelloWorld</a:Action> <?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /> Error: System.Web.Services.Protocols.SoapHeaderException: SOAP header
Action was not understood… at System.Web.Services.Protocols.SoapHeaderHandling.SetHeaderMembers(SoapHeaderCollection headers, Object target, SoapHeaderMapping[] mappings, SoapHeaderDirection direction, Boolean client).. at System.Web.Services.Protocols.SoapServerProtocol.CreateServerInstance().. at System.Web.Services.Protocols.WebServiceHandler.Invoke().. at System.Web.Services.Protocols.WebServiceHandler.CoreProcessRequest() WS_CHANNEL_PROPERTY channelProperties[1];
</p>
// Then you pass the channelProperties and channelPropertyCount to WsCreateServiceProxy (or WsCreateChannel if you are working at channel layer).
hr = WsCreateServiceProxy(
</font></font><font color=#008000 size=2><font color=#008000 size=2>// Since the default scheme for WWSAPI header authentication is Negotiate, this property
</font></font><font color=#008000 size=2><font color=#008000 size=2>// may be omitted but included for clarity.
</font></font>ULONG scheme = WS_HTTP_HEADER_AUTH_SCHEME_NEGOTIATE;
{
{ WS_SECURITY_BINDING_PROPERTY_HTTP_HEADER_AUTH_SCHEME, &scheme, </font><font color=#0000ff size=2><font color=#0000ff size=2>sizeof</font></font>(scheme) }
};
</p>
</font></font>WS_HTTP_HEADER_AUTH_SECURITY_BINDING headerAuthBinding = {}; <font color=#008000 size=2><font color=#008000 size=2>// zero out the struct
headerAuthBinding.binding.properties = headerAuthBindingProperties;
headerAuthBinding.binding.propertyCount = WsCountOf(headerAuthBindingProperties);
headerAuthBinding.clientCredential = &defaultCred.credential;
</font></font>WS_SECURITY_BINDING* securityBindings[1] = { &headerAuthBinding.binding };
</font></font>WS_SECURITY_DESCRIPTION securityDescription = {}; <font color=#008000 size=2><font color=#008000 size=2>// zero out the struct
</font></font>securityDescription.securityBindings = securityBindings;
securityDescription.securityBindingCount = WsCountOf(securityBindings);
securityDescription.properties = securityProperties;
securityDescription.propertyCount = WsCountOf(securityProperties);
</font></font>hr = WsCreateServiceProxy(
WS_CHANNEL_TYPE_REQUEST,
WS_HTTP_CHANNEL_BINDING,
&securityDescription, <font color=#008000 size=2><font color=#008000 size=2>// added for Negotiate
</font></font>NULL,
0,
NULL,
,
&serviceProxy,
error);
</font></font>WS_PROTECTION_LEVEL protectionLevel = WS_PROTECTION_LEVEL_NONE;
WS_SECURITY_PROPERTY securityProperties[1] = {
{WS_SECURITY_PROPERTY_TRANSPORT_PROTECTION_LEVEL, &protectionLevel, <font color=#0000ff size=2><font color=#0000ff size=2>sizeof</font></font>(protectionLevel)}
};
</p>
</div>
and then set these on the securityDescription like this:
securityDescription.propertyCount = WsCountOf(securityProperties);
ULONG channelPropertyCount = 0;
WS_ADDRESSING_VERSION addressingVersion = WS_ADDRESSING_VERSION_TRANSPORT;
channelProperties[channelPropertyCount].id = WS_CHANNEL_PROPERTY_ADDRESSING_VERSION;
channelProperties[channelPropertyCount].value = &addressingVersion ;
channelProperties[channelPropertyCount].valueSize = <font color=#0000ff size=2><font color=#0000ff size=2>sizeof</font></font>(addressingVersion );
channelPropertyCount++; // in this case only one property
WS_CHANNEL_TYPE_REQUEST,
WS_HTTP_CHANNEL_BINDING,
&securityDescription, </font><font color=#008000 size=2><font color=#008000 size=2>// added for Negotiate
</font></font>NULL,
0,
channelProperties, <font color=#008000 size=2><font color=#008000 size=2>// channel properties
</font></font>channelPropertyCount, <font color=#008000 size=2><font color=#008000 size=2>// channel property count
</font></font>&serviceProxy,
error);