WCF Service using UserNamePasswordValidation and Sessions - wcf

I have a WCF Service that currently uses basicHttpBinding, userNamePasswordValidationMode and TransportWithMessageCredential, Here is my Configuration:
<behavior name="Secure">
<serviceMetadata httpsGetEnabled="true" httpGetEnabled="false" />
<serviceDebug includeExceptionDetailInFaults="true"/>
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType="Kestrel.MIS3.Server.Services.Security.LoginAuthentication, Kestrel.MIS3.Server.Services" />
</serviceCredentials>
<serviceAuthorization principalPermissionMode="Custom">
<authorizationPolicies>
<add policyType="Kestrel.MIS3.Server.Services.Security.AuthorizationPolicy, Kestrel.MIS3.Server.Services"/>
</authorizationPolicies>
</serviceAuthorization>
<behaviour>
<services>
<service name="Kestrel.MIS3.Server.Services.UserService" behaviorConfiguration="Secure">
<endpoint address=""
binding="wsHttpBinding"
bindingConfiguration="wsSecure"
contract="Kestrel.MIS3.Server.Services.IUserService" />
<endpoint address="mex"
binding="mexHttpsBinding"
contract="IMetadataExchange" />
</service>
</services>
<wsHttpBinding>
<binding name="wsSecure">
<reliableSession enabled="true"/>
<security mode="TransportWithMessageCredential">
<message clientCredentialType="UserName" />
</security>
</binding>
</wsHttpBinding>
I want to be able to use a Session so that when an Instance of the Service is created I dont need to look up the user details evertime. Is this possible?
I have marked the Services with the following but with no luck:
[ServiceContract(SessionMode = SessionMode.Required)]
public interface IUserService
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
public class UserService : ServiceBase, IUserService

Related

WCF Ws-Seciurity service configuration

I'm having truble with configuration around my WCF service and WS-Seciurity.
I don't have access to the client side, so far I'm trying to use SoapUI as a client with WS-A adressing, userName, Password and WSS Password Type 'PasswordDigest' options.
I use IIS and https with a simple certificate, .NET 4.7.
I've tried many versions, but without success. I just want to find simplest, working solution to read 'Seciurity' header from SoapUI/client request with WS-Seciurity PasswordDigest options enabled.
The current error with the current config file 'InvalidSecurity' 'An error occurred when verifying security for the message'
<system.serviceModel>
<protocolMapping>
<add scheme="https" binding="wsHttpBinding"/>
</protocolMapping>
<services>
<service name="SoapService" behaviorConfiguration="SoapServiceConf">
<!--<endpoint address="SoapService" binding="wsHttpBinding" contract="MPA.SoapService.References.ServiceReference.SentSOAP" /> -->
<endpoint address="" binding="wsHttpBinding" contract="Interfaces.ISoap" bindingConfiguration="wsHttpBind"/>
<endpoint contract="IMetadataExchange" binding="mexHttpsBinding" address="mex" />
</service>
</services>
<bindings>
<wsHttpBinding>
<binding maxReceivedMessageSize="10485760" name="wsHttpBind">
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="Basic"/>
<message clientCredentialType="UserName" algorithmSuite="Default" establishSecurityContext="false" />
</security>
<reliableSession enabled="false" />
<readerQuotas maxArrayLength="10485760" maxDepth="1024" maxStringContentLength="10485760" />
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="SoapServiceConf">
<serviceCredentials>
<serviceCertificate findValue="soapservice"
storeName="My"
x509FindType="FindByIssuerName" />
</serviceCredentials>
<serviceMetadata httpGetEnabled="false" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="False" />
</behavior>
<behavior name="MyServiceTypeBehaviors" >
<!-- Add the following element to your service behavior configuration. -->
<serviceMetadata httpGetEnabled="false" httpsGetEnabled="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
Thanks.

Not able to access the methods from secure wcf rest service

I have a running wcf rest service hosted on IIS. I have successfully added the .x509 certificates to the client and the server and it works fine.As it is a secure service it is accessed using https The problem I am facing is that I am not able to access any of the methods from the service it keeps throwing 404 error however when I browse the service from IIS using https link it open the WSDL fine but throws 404 error while accessing any of the methods.
Here is my Interface implementation of a method from the service.
[ServiceContract]
public interface IRestDemo
{
[OperationContract]
[WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Xml, BodyStyle = WebMessageBodyStyle.Bare, UriTemplate = "/DoWork/{name}")]
string DoWork(string name);
}
Here is my configuration file:
<system.serviceModel>
<services>
<service name="RestDemo.RestDemo" behaviorConfiguration="serviceBehavior">
<host>
<baseAddresses>
<add baseAddress="https://localhost/RestDemo/RestDemo.svc" />
</baseAddresses>
</host>
<endpoint address="" binding="webHttpBinding" contract="RestDemo.IRestDemo" behaviorConfiguration="web">
<!--<identity>
<dns value="localhost"/>
</identity>-->
</endpoint>
<endpoint address="mex" binding="mexHttpsBinding" contract="RestDemo.IRestDemo" />
</service>
</services>
<bindings>
<webHttpBinding>
<binding name="web" crossDomainScriptAccessEnabled="true">
<security mode="Transport">
<transport clientCredentialType="Certificate" />
</security>
</binding>
</webHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="serviceBehavior">
<!--<serviceCredentials>
<clientCertificate>
<authentication certificateValidationMode="PeerTrust"
trustedStoreLocation="LocalMachine" />
</clientCertificate>
<serviceCertificate findValue="ServerCertificate"
storeLocation="LocalMachine"
storeName="My"
x509FindType="FindBySubjectName" />
</serviceCredentials>-->
<!-- To avoid disclosing metadata information, set the values below to false before deployment -->
<serviceMetadata httpGetEnabled="false" httpsGetEnabled="true" httpsGetUrl="/RestDemo.svc" />
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="web">
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
<standardEndpoints>
<webScriptEndpoint>
<standardEndpoint
crossDomainScriptAccessEnabled="true">
</standardEndpoint>
</webScriptEndpoint>
</standardEndpoints>
</system.serviceModel>
Any suggestions would be really appreciated.

WCF custom username and password validation is not executed

I have a WCF service hosted on IIS 7.5 with the settings of basicHttpBinding binding and TransportWithMessageCredential security. I would like to send a FaultException to the client in case of failed authentication but unfortunately the Validate method of custom validator class is not executed.
I have read here, that custom validator works only for self-hosting scenario:
Is it true, or I made a mistake somewhere?
public class ServiceUserNamePasswordValidator : UserNamePasswordValidator
{
public override void Validate(string userName, string password)
{
if (null == userName || null == password)
{
throw new ArgumentNullException();
}
if (!(userName == MobilApp.Helper.SiteGlobal.UserName && password == MobilApp.Helper.SiteGlobal.Password))
{
throw new FaultException("Unknown Username or Incorrect Password");
}
}
}
web.config:
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="True" />
<bindings>
<basicHttpBinding>
<binding name="ServiceBinding" useDefaultWebProxy="false">
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="Certificate" />
<message clientCredentialType="UserName" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<services>
<service name="Service.TestService" behaviorConfiguration="CustomValidator">
<endpoint address="" binding="basicHttpBinding" bindingConfiguration="ServiceBinding"
bindingNamespace="https://service/TestService/"
contract="Service.ITestService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="https://service/TestService/" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="CustomValidator">
<useRequestHeadersForMetadataAddress/>
<serviceMetadata httpGetEnabled="false" httpsGetEnabled="True" httpsGetUrl="wsdl" />
<serviceDebug includeExceptionDetailInFaults="false" httpHelpPageEnabled="false" httpsHelpPageEnabled="true" />
<serviceCredentials>
<clientCertificate>
<authentication
certificateValidationMode="ChainTrust"
revocationMode="NoCheck" />
</clientCertificate>
<serviceCertificate
findValue="test.com"
x509FindType="FindBySubjectName"
storeLocation="LocalMachine"
storeName="My" />
<userNameAuthentication
userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType="ServiceUserNamePasswordValidator, Service" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
Thank you.

DotNetOpenAuth and ResourceServer service https configuration

I am trying to configure the DataApi.svc service of the DotNetOpenAuth to call my resources via https using AJAX.
I can call the service and hit the code behind but the OperationContext.Current.ServiceSecurityContext will be not authenticated
In IIS, I have "Anonymous authentication" set to "true".
In Fiddler I can see that the header is sent:
Authorization: Bearer gAAAAMcRmG5vw3LykShq7cNOEGUACBiNtlVGxGYdSVfkkXjR-[truncated]
The interface is decorated like that:
[ServiceContract]
public interface IDataApi {
[OperationContract, WebGet(UriTemplate = "/email", ResponseFormat = WebMessageFormat.Json)]
string GetEmail();
And here is my config:
<bindings>
<wsHttpBinding>
<binding>
<security mode="Transport">
<transport clientCredentialType="None"/>
</security>
</binding>
</wsHttpBinding>
<webHttpBinding>
<binding>
<security mode="Transport">
<transport clientCredentialType="None"/>
</security>
</binding>
</webHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="DataApiBehavior">
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceMetadata httpsGetEnabled="true" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="DataApiWebBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="DataApiBehavior" name="OAuthResourceServer.DataApi">
<endpoint address="" binding="wsHttpBinding" contract="OAuthResourceServer.Code.IDataApi" />
<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange" />
<endpoint address="web" binding="webHttpBinding" contract="OAuthResourceServer.Code.IDataApi" behaviorConfiguration="DataApiWebBehavior">
</endpoint>
</service>
</services>
Any idea of what can be wrong?
Thanks!
I was missing the
<serviceAuthorizationserviceAuthorizationManagerType="OAuthResourceServer.Code.OAuthAuthorizationManager, OAuthResourceServer" principalPermissionMode="Custom" />
in the service behavior! Solved :)

Contract requires Session, but Binding ‘WSHttpBinding’ doesn’t support it or isn’t configured properly to support it

I have specified the service contract to require the session.
[ServiceContract(SessionMode = SessionMode.Required)]
public interface ITicketSales
{
}
The service decorated like this:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession, ConcurrencyMode = ConcurrencyMode.Single)]
public class TicketSalesService : ITicketSales
{
}
Here is my App.config file:
<system.serviceModel>
<services>
<service name="InternetRailwayTicketSales.TicketSalesImplementations.TicketSalesService" behaviorConfiguration="defaultBehavior">
<host>
<baseAddresses>
<add baseAddress = "https://localhost/TicketSales/"></add>
</baseAddresses>
</host>
<endpoint address="MainService" binding="wsHttpBinding" bindingConfiguration="wsSecureConfiguration"
contract="InternetRailwayTicketSales.TicketSalesInterface.ITicketSales" />
<endpoint address="mex" binding="mexHttpsBinding"
contract="IMetadataExchange"/>
</service>
</services>
<bindings>
<wsHttpBinding>
<binding name="wsSecureConfiguration">
<security mode="Transport">
<transport clientCredentialType="None"></transport>
</security>
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="defaultBehavior">
<serviceThrottling maxConcurrentInstances="5000" maxConcurrentSessions="5000"/>
<serviceMetadata httpGetEnabled="false" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="True" />
</behavior>
</serviceBehaviors>
</behaviors>
When I press F5 I receive the error message "Contract requires Session, but Binding ‘WSHttpBinding’ doesn’t support it or isn’t configured properly to support it."
I really need the channel which supports SSL and requires session.
You can support sessions by enabling message security:
<binding name="wsHttpSecureSession">
<security>
<message establishSecurityContext="true"/>
</security>
</binding>
If you need to go with transport security you may need to specify a client credential type