Re: WSE 3.O Web Service with ASP.Net Client using VB.Net



Steven

Unfortunately I am still having problems so I will try to explain my
progress so far.

I have a solution with three projects running on Win 2003 server with IIS6.

The first project is the web service (WS Auth) which returns a "Hello World
response. This works without any of the authentication added. This I have
then configured authentication to work with the Username/password option.

Code for the service is:

<WebService(Namespace:="http://ws.networkclub.co.uk/";)> _
<WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
<Policy("WebServicePolicy")> _
Public Class Service
Inherits System.Web.Services.WebService

Enum Result
Success
Failure
NotAuthorised
End Enum

<WebMethod()> _
Public Function HelloWorld(ByRef Value As String) As Result

Try

Value = "Hello World"
Return Result.Success

Catch ex As Exception

Return Result.Failure

End Try

End Function

End Class

The web.config is as follows:

<?xml version="1.0" encoding="utf-8"?>

<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0";>
<configSections>
<section name="microsoft.web.services3"
type="Microsoft.Web.Services3.Configuration.WebServicesConfiguration,

Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35" />
</configSections>
<appSettings />
<connectionStrings />
<system.web>

<customErrors mode="Off" />
<compilation debug="false" strict="false" explicit="true">
<assemblies>
<add assembly="Microsoft.Web.Services3, Version=3.0.0.0,
Culture=neutral, PublicKeyToken=31BF3856AD364E35"

/>
<add assembly="System.Security, Version=2.0.0.0, Culture=neutral,
PublicKeyToken=B03F5F7F11D50A3A" />
<add assembly="System.Design, Version=2.0.0.0, Culture=neutral,
PublicKeyToken=B03F5F7F11D50A3A" />
<add assembly="System.Configuration.Install, Version=2.0.0.0,
Culture=neutral,

PublicKeyToken=B03F5F7F11D50A3A" />
</assemblies>
</compilation>
<pages>
<namespaces>
<clear />
<add namespace="System" />
<add namespace="System.Collections" />
<add namespace="System.Collections.Specialized" />
<add namespace="System.Configuration" />
<add namespace="System.Text" />
<add namespace="System.Text.RegularExpressions" />
<add namespace="System.Web" />
<add namespace="System.Web.Caching" />
<add namespace="System.Web.SessionState" />
<add namespace="System.Web.Security" />
<add namespace="System.Web.Profile" />
<add namespace="System.Web.UI" />
<add namespace="System.Web.UI.WebControls" />
<add namespace="System.Web.UI.WebControls.WebParts" />
<add namespace="System.Web.UI.HtmlControls" />
</namespaces>
</pages>

<authentication mode="Windows" />

<webServices>
<soapExtensionImporterTypes>
<add type="Microsoft.Web.Services3.Description.WseExtensionImporter,
Microsoft.Web.Services3,

Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</soapExtensionImporterTypes>
<soapServerProtocolFactory
type="Microsoft.Web.Services3.WseProtocolFactory, Microsoft.Web.Services3,

Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</webServices>
</system.web>
<microsoft.web.services3>
<policy fileName="wse3policyCache.config" />
<security>
<securityTokenManager>
<add
type="WSAuthUsernameAssertionLibrary.CustomUsernameTokenManager,
CustomUsernameTokenManager"

namespace="Microsoft.Practices.WSSP.WSE3.QuickStart.UsernameTokenWithDatabase.Service"

localName="CustomUsernameTokenManager" />
</securityTokenManager>
</security>
</microsoft.web.services3>
</configuration>

The policy Cache is as follows:

<policies xmlns="http://schemas.microsoft.com/wse/2005/06/policy";>
<extensions>
<extension name="usernameForCertificateSecurity"

type="Microsoft.Web.Services3.Design.UsernameForCertificateAssertion,
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" />
<extension name="requireActionHeader"
type="Microsoft.Web.Services3.Design.RequireActionHeaderAssertion,

Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35" />
<extension name="authorization"
type="Microsoft.Web.Services3.Design.AuthorizationAssertion,

Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35" />
</extensions>
<policy name="WebServicePolicy">
<usernameForCertificateSecurity establishSecurityContext="false"
renewExpiredSecurityContext="true"

requireSignatureConfirmation="false"
messageProtectionOrder="SignBeforeEncrypt" requireDerivedKeys="true"

ttlInSeconds="300">
<serviceToken>
<x509 storeLocation="LocalMachine" storeName="My"
findValue="CN=WSE2QuickStartServer"

findType="FindBySubjectDistinguishedName" />
</serviceToken>
<protection>
<request signatureOptions="IncludeAddressing, IncludeTimestamp,
IncludeSoapBody" encryptBody="true" />
<response signatureOptions="IncludeAddressing, IncludeTimestamp,
IncludeSoapBody" encryptBody="true" />
<fault signatureOptions="IncludeAddressing, IncludeTimestamp,
IncludeSoapBody" encryptBody="false" />
</protection>
</usernameForCertificateSecurity>
<requireActionHeader />
</policy>
</policies>

The second project is a Class Library (WSAuthUsernameAssertionLibrary) with
a single class file in VB converted from C# from the online example (I hope!).

Code as follows:

Imports System
Imports System.Xml
Imports System.Security.Permissions
Imports System.Web.Security
Imports System.Security.Principal

Imports Microsoft.Web.Services3.Security
Imports Microsoft.Web.Services3.Security.Tokens

Namespace
Microsoft.Practices.WSSP.WSE3.QuickStart.UsernameTokenWithDatabase.Service

''' <summary>
''' By implementing UsernameTokenManager we can verify the signature
''' on messages received.
''' </summary>
<SecurityPermissionAttribute(SecurityAction.Demand,
Flags:=SecurityPermissionFlag.UnmanagedCode)> _
Public Class CustomUsernameTokenManager
Inherits UsernameTokenManager
''' <summary>
''' Constructs an instance of this security token manager.
''' </summary>
Public Sub New()
End Sub

''' <summary>
''' Constructs an instance of this security token manager.
''' </summary>
''' <param name="nodes">An XmlNodeList containing XML elements from
a configuration file.</param>
Public Sub New(ByVal nodes As XmlNodeList)
MyBase.New(nodes)
End Sub

''' <summary>
''' Returns the password or password equivalent for the username
provided.
''' Adds a principal to the token with user's roles.
''' </summary>
''' <param name="token">The username token</param>
''' <returns>The password (or password equivalent) for the
username</returns>
Protected Overrides Function AuthenticateToken(ByVal token As
UsernameToken) As String

If token.Username = "Username" And token.Password = "Password"
Then

Dim identity As GenericIdentity = New
GenericIdentity(token.Username)
Dim principal As GenericPrincipal = New
GenericPrincipal(identity,

Roles.GetRolesForUser(token.Username))
token.Principal = principal

End If

'Dim validCredentials As Boolean =
Membership.ValidateUser(token.Username, token.Password)
'If (Not validCredentials) Then
'Throw New ApplicationException("Authentication Failed")
'End If

'Dim identity As GenericIdentity = New
GenericIdentity(token.Username)
'Dim principal As GenericPrincipal = New
GenericPrincipal(identity,

Roles.GetRolesForUser(token.Username))
'token.Principal = principal

Return token.Password

End Function

End Class

End Namespace

Note I have commented out theAuthenticateToken logic and entered some
hardcoded values ie "Username" amd "Password".

Once this example works I intend to cross check on a seperate database.

The client project is a web application (WsClient) with some variation from
the examples. There is a logon page which takes a Username and Password,
creates a Token and adds it to Session.

Code as follows:

Session("Token") = New UsernameToken(Username.Text, Password.Text,
PasswordOption.SendPlainText)
Response.Redirect("Default.aspx")

The Default page basically checks the Session on page load and if it doesnt
exist passes the user to the logon page, if Session does exist it gets the
Token and queries the web service.

Code as follows:

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)
Handles Me.Load

If Session("Token") Is Nothing Then
Response.Redirect("Logon.aspx")
End If

End Sub

Protected Sub Button1_Click(ByVal sender As Object, ByVal e As
System.EventArgs) Handles Button1.Click

Dim ws As New WSAuth.ServiceWse

ws.SetClientCredential(Of UsernameToken)(Session("Token"))
ws.SetPolicy("WebClientPolicy")

Dim result As New Result
Dim Value As String = ""

result = ws.HelloWorld(Value)

If result = WSAuth.Result.Success Then
Literal1.Text = Value.ToString
ElseIf result = WSAuth.Result.NotAuthorised Then
Literal1.Text = "Not Authorised"
Else
Literal1.Text = "Web Servivce Failed"
End If

End Sub

The client is configured for Username/pasword through WSE 3.0.

Web Config as follows:

<?xml version="1.0" encoding="utf-8"?>

<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0";>
<configSections>
<section name="microsoft.web.services3"
type="Microsoft.Web.Services3.Configuration.WebServicesConfiguration,

Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35" />
</configSections>
<appSettings>
<add key="WSAuth.Service"
value="http://192.168.103.21/WSAuth/Service.asmx"; />
</appSettings>
<connectionStrings />
<system.web>

<customErrors mode="Off" />
<compilation debug="false" strict="false" explicit="true">
<assemblies>
<add assembly="Microsoft.Web.Services3, Version=3.0.0.0,
Culture=neutral, PublicKeyToken=31BF3856AD364E35"

/>
</assemblies>
</compilation>
<pages>
<namespaces>
<clear />
<add namespace="System" />
<add namespace="System.Collections" />
<add namespace="System.Collections.Specialized" />
<add namespace="System.Configuration" />
<add namespace="System.Text" />
<add namespace="System.Text.RegularExpressions" />
<add namespace="System.Web" />
<add namespace="System.Web.Caching" />
<add namespace="System.Web.SessionState" />
<add namespace="System.Web.Security" />
<add namespace="System.Web.Profile" />
<add namespace="System.Web.UI" />
<add namespace="System.Web.UI.WebControls" />
<add namespace="System.Web.UI.WebControls.WebParts" />
<add namespace="System.Web.UI.HtmlControls" />
</namespaces>
</pages>

<authentication mode="Windows" />

<webServices>
<soapExtensionImporterTypes>
<add type="Microsoft.Web.Services3.Description.WseExtensionImporter,
Microsoft.Web.Services3,

Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</soapExtensionImporterTypes>
<soapServerProtocolFactory
type="Microsoft.Web.Services3.WseProtocolFactory, Microsoft.Web.Services3,

Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</webServices>
</system.web>
<microsoft.web.services3>
<policy fileName="wse3policyCache.config" />
</microsoft.web.services3>
</configuration>

and the Policy Cache as follows:

<policies xmlns="http://schemas.microsoft.com/wse/2005/06/policy";>
<extensions>
<extension name="usernameForCertificateSecurity"

type="Microsoft.Web.Services3.Design.UsernameForCertificateAssertion,
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" />
<extension name="requireActionHeader"
type="Microsoft.Web.Services3.Design.RequireActionHeaderAssertion,

Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35" />
</extensions>
<policy name="WebClientPolicy">
<usernameForCertificateSecurity establishSecurityContext="false"
renewExpiredSecurityContext="true"

requireSignatureConfirmation="false"
messageProtectionOrder="SignBeforeEncrypt" requireDerivedKeys="true"

ttlInSeconds="300">
<serviceToken>
<x509 storeLocation="LocalMachine" storeName="AddressBook"
findValue="CN=WSE2QuickStartClient"

findType="FindBySubjectDistinguishedName" />
</serviceToken>
<protection>
<request signatureOptions="IncludeAddressing, IncludeTimestamp,
IncludeSoapBody" encryptBody="true" />
<response signatureOptions="IncludeAddressing, IncludeTimestamp,
IncludeSoapBody" encryptBody="true" />
<fault signatureOptions="IncludeAddressing, IncludeTimestamp,
IncludeSoapBody" encryptBody="false" />
</protection>
</usernameForCertificateSecurity>
<requireActionHeader />
</policy>
</policies>

Both the client and server certificates are installed on the server as both
applications run on the server and Network Service has full security rights
to the certificates. Or at least I believe this to be correct.

Currently I recievee the error:

"Security requirements are not satisfied because the security header is not
present in the incoming message."

which I understand from research means that the user is not authenticated ie
username/password details are wrong.

I therefore assume that the client is sending some type of token across
which indicates that the certificates are installed correctly. I assume if
the certificates were wrong then the client wouldnt be able to create the
token in the first instance. Above and beyond this im not sure where to go
next.

Sorry this is a long post but at least I have included pretty much
everyuthing (I think).

Thanks for any comments.
--
Regards

Martyn Fewtrell


"Steven Cheng[MSFT]" wrote:

Hello Martyn,

Have you got the VB.NET version of a workable custom username token.
Actually the WSE 3.0 sdk's sample just contains a "usernameToken" security
example which demonstate on using a custom username token manager, it
provides both VB.NET and CSharp version. You can find it in the WSE 3.0
install directory if you've installed the WSE 3.0's sdk:

#Web Services Enhancements (WSE) 3.0 for Microsoft .NET
http://www.microsoft.com/downloads/details.aspx?familyid=018a09fd-3a74-43c5-
8ec1-8d789091255d&displaylang=en

The full example path is as below(in case you also installed it in C: drive)

C:\Program Files\Microsoft
WSE\v3.0\Samples\VB\QuickStart\Security\WSSecurityUsername

Hope this also helps.

Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead

==================================================



This posting is provided "AS IS" with no warranties, and confers no rights
.