I have written a web service which I am hosting in a Windows service using a
SoapReceiver. I have this working and can call the web service from a
client. The client is running as a domain user and the service is running
as a different user on the same domain. Both the client and service are
.NET 2.0 assemblies and are using WSE 3.0. Currently the client and the
service are both running on the same Window XP machine. The 2 are
communicating over TCP port 3844 (the port number was picked arbitrarily).
Now I am trying to add Kerberos encryption to the messages. I have added
policies to both the client and the service that signs and encrypts the
messages. I have also added the references to the policies from both the
client and the service (the wse3policycache.config files are at the end of
this post). Now when I attempt to call the web service I get an error. The
error in the web service's input trace file is: "Exception thrown: An
invalid security token was provided". The web service's output trace file
has the error: "WSE594: AcceptSecurityContext call failed with the following
error message: Logon failure: unknown user name or bad password."
This MSDN page
(http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wse/html/486588
ab-b08d-4374-9390-3985c1df08e5.asp)
seems to indicate that I need to use SetSpn.exe to create a service
principal name. I guess I also have to use a different format for
"targetPrincipal" than HOST/MachineName. What I don't understand is what
format I should be using.
I'm hoping that somebody can tell me that yes, you can add Kerberos
encryption to the messages when using a SoapReceiver. I am also hoping
somebody can give a clue as to how to do that. Hopefully I have provided
adequate information. I am more than happy to provide more info, but I
figured any more info at this point may muddy things up (and nobody will
want to read it).
Thanks.
Brian Lenway
----------------------------
On the client I have this for the policy file:
<policies xmlns="http://schemas.microsoft.com/wse/2005/06/policy">
<extensions>
<extension name="kerberosSecurity"
type="Microsoft.Web.Services3.Design.KerberosAssertion,
Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35" />
<extension name="kerberos"
type="Microsoft.Web.Services3.Design.KerberosTokenProvider,
Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35" />
<extension name="requireActionHeader"
type="Microsoft.Web.Services3.Design.RequireActionHeaderAssertion,
Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35" />
<extension name="mutualCertificate11Security"
type="Microsoft.Web.Services3.Design.MutualCertificate11Assertion,
Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35" />
<extension name="x509"
type="Microsoft.Web.Services3.Design.X509TokenProvider,
Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35" />
</extensions>
<policy name="EncryptedMessage">
<kerberosSecurity establishSecurityContext="false"
renewExpiredSecurityContext="true" requireSignatureConfirmation="false"
messageProtectionOrder="SignBeforeEncrypt" requireDerivedKeys="false"
ttlInSeconds="300">
<token>
<kerberos targetPrincipal="HOST/ServiceMachineName"
impersonationLevel="Impersonation" />
</token>
<protection>
<request signatureOptions="IncludeAddressing, IncludeTimestamp,
IncludeSoapBody" encryptBody="true" />
<response signatureOptions="IncludeAddressing, IncludeTimestamp,
IncludeSoapBody" encryptBody="true" />
<fault signatureOptions="IncludeAddressing, IncludeTimestamp,
IncludeSoapBody" encryptBody="false" />
</protection>
</kerberosSecurity>
<requireActionHeader />
</policy>
</policies>
----------------------------
For the service I have:
<policies xmlns="http://schemas.microsoft.com/wse/2005/06/policy">
<extensions>
<extension name="authorization"
type="Microsoft.Web.Services3.Design.AuthorizationAssertion,
Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35" />
<extension name="kerberosSecurity"
type="Microsoft.Web.Services3.Design.KerberosAssertion,
Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35" />
<extension name="requireActionHeader"
type="Microsoft.Web.Services3.Design.RequireActionHeaderAssertion,
Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35" />
<extension name="mutualCertificate11Security"
type="Microsoft.Web.Services3.Design.MutualCertificate11Assertion,
Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35" />
<extension name="x509"
type="Microsoft.Web.Services3.Design.X509TokenProvider,
Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35" />
</extensions>
<policy name="EncryptedMessage">
<authorization>
<allow role="DOMAIN\Users" />
<deny user="*" />
</authorization>
<kerberosSecurity establishSecurityContext="false"
renewExpiredSecurityContext="true" requireSignatureConfirmation="false"
messageProtectionOrder="SignBeforeEncrypt" requireDerivedKeys="true"
ttlInSeconds="300">
<protection>
<request signatureOptions="IncludeAddressing, IncludeTimestamp,
IncludeSoapBody" encryptBody="true" />
<response signatureOptions="IncludeAddressing, IncludeTimestamp,
IncludeSoapBody" encryptBody="true" />
<fault signatureOptions="IncludeAddressing, IncludeTimestamp,
IncludeSoapBody" encryptBody="false" />
</protection>
</kerberosSecurity>
<requireActionHeader />
</policy>
</policies>
Pablo Cibraro - 17 Apr 2006 19:27 GMT
Hi Brian,
The answer is yes, you can use Kerberos security.
This article on the MSDN describes very well how to configure Kerberos for a
web service (It also describes what a SPN is and how to configure it).
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnpag2/html/WSS
_Ch7_KerbTechSupp.asp
Let me know if you continue having problems after reading that article.
Regards,
Pablo Cibraro
http://weblogs.asp.net/cibrax
>I have written a web service which I am hosting in a Windows service using
>a SoapReceiver. I have this working and can call the web service from a
[quoted text clipped - 126 lines]
> </policy>
> </policies>
Brian Lenway - 18 Apr 2006 23:07 GMT
Thanks for responding Pablo.
I read thru the relevant sections of that doc, and I read thru Keith Brown's
article in the 9/5 edition of MSDN Magazine. I'm having problems applying
the info to my specific issue, so let's get more concrete.
I have a machine we'll call 'Service' which exposes a web service called
ServiceWS. The web service is hosted in a Windows service (called
ServiceSvc) and is using a SoapReceiver, which is listening on TCP port
3844. I have defined a WSE 3.0 policy that sets up Kerberos Security. I
have added the [Policy] attribute on the web service class telling it to use
the policy. The Windows service was started as user "Domain\ServiceUser".
I have a machine we'll call 'Client'. This machine has an application that
calls the web service on the machine 'Service'. I have defined a WSE 3.0
policy that sets up Kerberos Security. I have called SetPolicy passing my
policy name. The application is started as "Domain\ClientUser".
When I call the web service, 'Service', running as "ServiceUser" will access
some resources that only it has rights to and will return some information
to the client.
So, now I have to figure out what should go in the client's WSE3 policy
config file for targetPrincipal. I know that I cannot put "HOST/Service"
because the MS article I referenced earlier says that I cannot use this
format when the "target Web service is created using a SoapReceiver class".
This means that I need to add my own SPN and reference it in the client's
policy file.
I do understand that the SPN is used to use a server's password to encrypt
and decrypt the message.
I don't fully understand what the 2 parameters that are passed into setspn
really do. Is there significance to both strings?
For this hopefully fully defined scenario, what would the format of this be?
Thanks again for the help and for any additional help you can provide.
> Hi Brian,
>
[quoted text clipped - 140 lines]
>> </policy>
>> </policies>
Brian Lenway - 19 Apr 2006 17:10 GMT
I got this to work. Apparently the 1st parameter of setspn is an arbitrary
string. All that matters is that the client specify the same string as the
one supplied to setspn. I used the following: setspn -A
CompanyName/WebService Domain\ServiceUser
Then I set targetPrincipal to CompanyName/WebService in the client's policy
file and it worked.
Thanks again Pablo.
> Thanks for responding Pablo.
> I read thru the relevant sections of that doc, and I read thru Keith
[quoted text clipped - 182 lines]
>>> </policy>
>>> </policies>
Brian Lenway - 24 Apr 2006 20:47 GMT
Turns out that the SPN name is important. The only way I could get this to
work was to use an SPN of "http/ServiceName", where "ServiceName" could be
any string, as long as the client's "targetPrincipal" matched.
>I got this to work. Apparently the 1st parameter of setspn is an arbitrary
>string. All that matters is that the client specify the same string as the
[quoted text clipped - 191 lines]
>>>> </policy>
>>>> </policies>