I’ve built a WCF Publish Subscribe Topic Service and can successfully publish/subscribe with a console appplication (meaning I know it at least works in a console), and can successfully add both service references to both in my Silverlight Application.
The Problem:
Every time I try to subscribe or publish (in other words, anytime, I pass through my user name and password) while using Silverlight, the ServiceSecurityContext.Current.PrimaryIdentity is NULL, but it works fine in the console. Also, when accessing the service, it doesn’t hit my custom user name and password validator when accessing it from Silverlight, but it does from a console.
What are my requirements?
I need to consume my publish subscribe service via Silverlight. The WCF Service needs to user UserName authentication. The WCF Service needs to be as secure as possible while still allowing for use with Silverlight. I have to use .Net, I have to use WCF PubSubTopic, I have to use Silverlight.
I am open to creating multiple subscriber endpoints(for instance, maybe a custom one for SL to use, and another for my api users), but I need to user the same publisher as the rest of my api users (oh yeah, btw, the WCF service is built as an api for my users to access if they want… I’m only allowing them access to the subscriber, and blocking the publisher)
I’m looking for example, advice, and/or troubleshooting help with my current problem. Here’s some of my code
VB.NET code of Silverlight trying to publish something
Private Const PUBLISHER_ENDPOINT_ADDRESS As String = "http://myserver/portal/api/v1/Publisher.svc"
Friend Shared Sub PublishSomething()
Dim binding As PollingDuplexHttpBinding = New PollingDuplexHttpBinding()
Dim endpoint_address As EndpointAddress = New EndpointAddress(PUBLISHER_ENDPOINT_ADDRESS)
Dim client As New PublisherClient(binding, endpoint_address)
client.ClientCredentials.UserName.UserName = String.Format("{0}\{1}", Common.CompanyName, Common.UserName)
client.ClientCredentials.UserName.Password = "mypassword"
Dim uUpdate As New PortalPublisherService.UserUpdatedNotification
uUpdate.CompanyID = CompanyId
uUpdate.CompanyName = CompanyName
uUpdate.isAdvisor = True
uUpdate.isMaster = True
uUpdate.MetaNotes = "Testing from silverlight."
uUpdate.updateById = UserId
uUpdate.updateByName = UserName
uUpdate.userEmail = "bill@domain.com"
uUpdate.userId = UserId
client.UserUpdateAsync(uUpdate)
End Sub
Here’s the web.config from the service
<system.serviceModel>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true"/>
<protocolMapping>
<add scheme="http" binding="wsDualHttpBinding"/>
</protocolMapping>
<extensions>
<bindingExtensions>
<add name="pollingDuplexHttpBinding"
type="System.ServiceModel.Configuration.PollingDuplexHttpBindingCollectionElement,
System.ServiceModel.PollingDuplex, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</bindingExtensions>
</extensions>
<behaviors>
<serviceBehaviors>
<!--primary behavior-->
<behavior name="Portal.Api.Behavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
<serviceCredentials>
<serviceCertificate findValue="PortalApiCert" storeLocation="LocalMachine" storeName="TrustedPeople" x509FindType="FindBySubjectName"/>
<clientCertificate>
<authentication certificateValidationMode="PeerOrChainTrust" revocationMode="NoCheck"/>
</clientCertificate>
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="Portal.Web.UserPassAuth, Portal.Web"/>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<pollingDuplexHttpBinding>
<binding name="pollingBindingConfig"
closeTimeout="00:01:00"
openTimeout="00:01:00"
receiveTimeout="00:10:00"
sendTimeout="00:01:00"
transferMode="Buffered"
hostNameComparisonMode="StrongWildcard"
maxBufferPoolSize="5242880"
maxBufferSize="655360"
maxReceivedMessageSize="655360">
<readerQuotas maxDepth="32"
maxStringContentLength="81920"
maxArrayLength="163840"
maxBytesPerRead="16384"
maxNameTableCharCount="163840" />
<security mode="TransportCredentialOnly" />
</binding>
</pollingDuplexHttpBinding>
</bindings>
<services>
<!--publisher endpoint configuration settings-->
<service behaviorConfiguration="Portal.Api.Behavior" name="Portal.Web.Publisher">
<endpoint address="" binding="pollingDuplexHttpBinding" contract="Portal.Publisher.IPublisher" bindingConfiguration="pollingBindingConfig"/>
<endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="meta"/>
<host>
<baseAddresses>
<add baseAddress="http://server/portal/api/v1/IPublisher"/>
</baseAddresses>
</host>
</service>
</services>
</system.serviceModel>
I want to emphasize that I’ve tried, figuratively, a million different configurations, but can’t remember every combination I’ve tried. I know I’m doing some stuff in the config I shouldn’t be, but I was just trying to get it to work period. Also, here are the links I’ve looked at already
there’s more, but … well… it’s been a long day…
Thanks in advance for any help
Additional NOTE:
This is the binding I’m successfully using with NON-Silverlight implementations
<wsDualHttpBinding>
<binding name="Portal.Api.Binding" maxReceivedMessageSize="2147483647" sendTimeout="00:10:00">
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647"/>
<security mode="Message">
<message clientCredentialType="UserName" negotiateServiceCredential="false"/>
</security>
</binding>
</wsDualHttpBinding>
Since no one has answered this, I will answer this with my findings. What I’m looking for here is not possible with RIA services and Silverlight over HTTPS. WCF RIA services just don’t offer this functionality at this time. If you know this statement not to be true.. please answer my question above with a solution.