WCF service - Custom Authentication doesn't work - vb.net

I am trying to set up authentication on my webservice, however, after setting up a validation class that inherits from UserNamePasswordValidator, the service still allows the client to work without a username or password
Web Service
Imports System.IdentityModel.Selectors
Public Class Authentication
Inherits UserNamePasswordValidator
Public Overrides Sub Validate(ByVal userName As String, ByVal password As String)
If Nothing = userName OrElse Nothing = password Then
Throw New ArgumentNullException()
End If
If Not (userName = "1" AndAlso password = "2") Then
' This throws an informative fault to the client.
Throw New FaultException("Unknown Username or Incorrect Password")
' When you do not want to throw an infomative fault to the client,
' throw the following exception.
' Throw New SecurityTokenException("Unknown Username or Incorrect Password")
End If
End Sub
End Class
Web.config
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="Binding1">
<security mode="Message">
<message clientCredentialType="UserName" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<services>
<service name="Webservice.Service1" behaviorConfiguration="ServiceBehavior">
<endpoint binding="basicHttpBinding" contract="Webservice.IService1"
behaviorConfiguration="webHttp"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehavior">
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="Webservice.Authentication, Webservice" />
</serviceCredentials>
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
<behavior>
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="true"/>
<!-- 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="webHttp">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
Client side
Dim client As Webservice.Service1Client = New Webservice.Service1Client()
'I was expecting this call to error as no username or password was produced
return client.getData(Data)
Is there anything I am missing?
Thanks

You will need more configuration to make it work.
But to get your error you need to actually use your bindingConfiguration.
So change your endpoint configuration to this:
<services>
<service name="Webservice.Service1" behaviorConfiguration="ServiceBehavior">
<endpoint binding="basicHttpBinding" contract="Webservice.IService1"
bindingConfiguration="Binding1"/>
</service>
</services>
Then you will start receiving errors that hopefully will guide you to create a proper configuration.

Related

Configuring Web.config to publish WCF Service

I am making the jump from asmx webservice to WCF (mostly to support working with Json)
I have gotten to the point that the Service works (locally only) in http only but not https. (On my server neither works as the server forces https)
Here is my simple Codes:
MyNewService.VB
Public Class MyNewService
Implements IMyNewService
Public Sub New()
End Sub
Public Function GetResults() As List(Of Person) Implements IMyNewService.GetResults
Dim rslt As New List(Of Person)
rslt.Add(New Person("Mike", "Anderson", 40))
rslt.Add(New Person("Drew", "Carry", 38))
rslt.Add(New Person("John", "Tavares", 43))
Return rslt
End Function
End Class
IMyNewService.VB
<ServiceContract()>
Public Interface IMyNewService
<OperationContract()>
<WebInvoke(Method:="GET", RequestFormat:=WebMessageFormat.Json, ResponseFormat:=WebMessageFormat.Json, UriTemplate:="getPeople")>
Function GetResults() As List(Of Person)
End Interface
<DataContract()>
Public Class Person
<DataMember()>
Public Property FirstName() As String
<DataMember()>
Public Property LastName() As String
<DataMember()>
Public Property Age() As Integer
Public Sub New(firstname As String, lastname As String, age As Integer)
Me.FirstName = firstname
Me.LastName = lastname
Me.Age = age
End Sub
End Class
Web.Config
<?xml version="1.0"?>
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.web>
<compilation debug="true" strict="false" explicit="true" targetFramework="4.7.2" />
<httpRuntime targetFramework="4.7.2"/>
<pages>
<namespaces>
<add namespace="System.Runtime.Serialization" />
<add namespace="System.ServiceModel" />
<add namespace="System.ServiceModel.Web" />
</namespaces>
</pages>
</system.web>
<system.serviceModel>
<protocolMapping>
<add scheme="http" binding="webHttpBinding"/>
</protocolMapping>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="true"/>
<!-- 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>
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
<!--
To browse web app root directory during debugging, set the value below to true.
Set to false before deployment to avoid disclosing web app folder information.
-->
<directoryBrowse enabled="true"/>
</system.webServer>
</configuration>
So, currently I can run:
http://localhost:61028/MyNewService.svc/getPeople
and I correctly get :
[{"Age":40,"FirstName":"Yoni","LastName":"Sudwerts"},{"Age":38,"FirstName":"Joshua","LastName":"Kishinef"},{"Age":43,"FirstName":"Saul","LastName":"Kaye"}]
But if I run:
https://localhost:44386/MyNewService.svc/getPeople
I get a 404 Error.
Can anyone find my mistake and help a guy out?
Thanks in advance
Generally speaking, I add two service endpoint address to host the service over http and https.
WCF Service not hitting from postman over https
Or the following simplified configuration.
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior>
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
<bindings>
<webHttpBinding>
<binding name="https">
<security mode="Transport">
<transport clientCredentialType="None"></transport>
</security>
</binding>
</webHttpBinding>
</bindings>
<protocolMapping>
<add binding="webHttpBinding" scheme="http" />
<add binding="webHttpBinding" scheme="https" bindingConfiguration="https" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
Feel free to let me know if there is anything I can help with.

XAMARIN, WCF with Custom User Name/Password and Principal

I am developing a WCF service that will provide data to a Xamarin client. I am trying to utilize custom user name/password and custom principle so I can attach usable information for the service to the identity. After many tries I have not been able to get anything but different error messages on the client. I believe the problem is in the WCF configuration, but I can not figure out what the problem is. My web.config code is below. Any help or tips on where to go would be greatly appreciated!
<system.serviceModel>
<diagnostics wmiProviderEnabled="true">
<messageLogging
logEntireMessage="true"
logMalformedMessages="true"
logMessagesAtServiceLevel="true"
logMessagesAtTransportLevel="true"
maxSizeOfMessageToLog="65535000"
maxMessagesToLog="3000"
/>
</diagnostics>
<behaviors>
<serviceBehaviors>
<behavior name="Behavior">
<!-- To avoid disclosing metadata information, set the values below
to false before deployment -->
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<!-- 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="true"/>
<serviceCredentials>
<serviceCertificate findValue="Cert" storeLocation="LocalMachine"
storeName="My" x509FindType="FindBySubjectName"/>
<userNameAuthentication userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType="Service.ServiceAuthenticator,
Service"/>
</serviceCredentials>
<serviceAuthorization
serviceAuthorizationManagerType="Service.CustomAuthorizationManager,
Service" principalPermissionMode="Custom">
<authorizationPolicies>
<add policyType="Service.AuthorizationPolicy, Service"/>
</authorizationPolicies>
</serviceAuthorization>
<serviceSecurityAudit
auditLogLocation="Application"
serviceAuthorizationAuditLevel="Failure"
messageAuthenticationAuditLevel="Failure"
suppressAuditFailure="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="Service" behaviorConfiguration="Behavior">
<endpoint address="" binding="basicHttpBinding"
contract="Service.IService" bindingConfiguration="Secure"/>
<endpoint address="mex" binding="mexHttpBinding"
contract="IMetadataExchange"/>
</service>
</services>
<bindings>
<basicHttpBinding>
<binding name="Secure">
<security mode="Transport">
<transport clientCredentialType="Basic"
proxyCredentialType="None" realm=""/>
<message clientCredentialType="UserName"
algorithmSuite="Default"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"
multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
<!--
To browse web app root directory during debugging, set the value
below to true.
Set to false before deployment to avoid disclosing web app folder
information.
-->
<directoryBrowse enabled="true"/>
<httpErrors errorMode="Detailed" />
</system.webServer>
I'm using the WFC service as a connected service in the main project of the Xamarin solution. The service is being called with the code below:
Service.ServiceClient _client;
_client = new Service.ServiceClient();
_client.ClientCredentials.UserName.UserName =
"username";
_client.ClientCredentials.UserName.Password = "password";
//To allow service to connect even though certificate was not
validated.
ServicePointManager.ServerCertificateValidationCallback =
MyRemoteCertificateValidationCallback;
lci = await _client.WCFTestMethod();
To update the post on the comments below. wsHttpBinding is not supported by Xamarin, so I do have to use basicHttpBinding. I have gotten the checkAccessCore procedure to execute when I set the authentication to Anonymous on the IIS site, but it throws this error "No Identity Found" when the AuthorizationPolicy is executing GetClientIdentity. Is there a way to assign an identity in checkAccessCore?
I was able to get the service to work the way I wanted it to, by making sure the authentication method on IIS was set to Anonymous and in the Evaluate method of the AuthorizationPolicy I created a GenericIdentity and used it (example code below) instead of calling the GetClientIdentity method. The service seems to be working now and is authenticating the user in the checkAccessCore method.
Dim client As IIdentity = New GenericIdentity("User")
Dim cp As CustomPrincipal = New CustomPrincipal(client)
evaluationContext.Properties("Identities") = l
evaluationContext.Properties("Principal") = cp

WCF Serice Not working in REST

I am trying to create custom wcf servic on sharepoint.
Unfoortuntly the service is working fine with WCF Test Client, But when i tried to access it through web/browser it is giving me empty screen or empty result in responce
Please some one assist me, Thank you so much in advance
Interface
[OperationContract]
[WebInvoke(Method = "GET",
UriTemplate = "/GetAllB/{value1}",
ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Wrapped)]
string GetAllB(int val);
Method
public string GetAllB(int val)
{
return "Enterted Value is this" + val;
}
Web.config File
<behaviors>
<serviceBehaviors>
<behavior name="Kuservice.Service1ServiceBehavior">
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deploying the solution. -->
<serviceMetadata httpGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deploying the solution to avoid disclosing exception information. -->
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="web">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
You can consider changing your config file to something like below,
<configuration>
<system.serviceModel>
<services>
<service name="WcfJsonRestService.Service1">
<endpoint address="http://localhost:8732/service1"
binding="webHttpBinding"
contract="WcfJsonRestService.IService1"/>
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior>
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
</startup>
</configuration>

Invoking WCF service in browser similar to asmx

I have made a WCF service in NET 4.0 and it returns the XML, I have tested it using SoapUI and i can see the required response xml. But my WCF service would be called by 3rd party software and they want to use it through a URL like asmx. I have googled and found that i need to make using REST guidelines. However i have not found a proper link showing making web-service using REST and then accessing the method from the browwer similar to web services.
Below is the interface code which i have used to return the format in XML
public interface IService1
{
[WebGet(
UriTemplate = "/GetDocument/",
BodyStyle = WebMessageBodyStyle.Bare,
ResponseFormat = WebMessageFormat.Xml)]
[OperationContract, XmlSerializerFormat]
XmlElement GetDocument();
// TODO: Add your service operations here
}
Below is my config settings.
<system.serviceModel>
<services>
<service name="BritishLandXML.BritishLandXML1" behaviorConfiguration="metadataBehavior">
<endpoint address="" binding="basicHttpBinding" contract="BritishLandXML.IService1" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<bindings>
<webHttpBinding>
<binding>
<security mode="None"></security>
</binding>
</webHttpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="rest">
<webHttp helpEnabled="true" faultExceptionEnabled="true" automaticFormatSelectionEnabled="true" />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="metadataBehavior">
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="true"/>
<!-- 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="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
Please let me know how can i achieve this and what exact settings will be required.

wsHttpBinding not working in a WCF service selfhosted; SOAP-based bindings do work

I have a simple WCF Service shown below.
[ServiceContract]
public interface IService1
{
[OperationContract]
[WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.WrappedRequest)]
string GetData(int value);
}
public class Service1 : IService1
{
public string GetData(int value)
{
return string.Format("You entered: {0}", value);
}
}
The server Web.config file is
<?xml version="1.0"?>
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="webHttpEndpointBehavior">
<webHttp faultExceptionEnabled="true" />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="serviceBehaviourDebug">
<!-- To avoid disclosing metadata information, set the values below to false before deployment -->
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<!-- 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="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="Diws.Service1" behaviorConfiguration="serviceBehaviourDebug">
<endpoint
address="/basicHttp"
binding="basicHttpBinding"
contract="Diws.IService1"/>
<endpoint
address="/webHttp"
binding="webHttpBinding"
behaviorConfiguration="webHttpEndpointBehavior"
contract="Diws.IService1"/>
<endpoint
address="/wsHttp"
binding="wsHttpBinding"
contract="Diws.IService1"/>
<endpoint
address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
</service>
</services>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.web>
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5"/>
</system.web>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
<!--
To browse web app root directory during debugging, set the value below to true.
Set to false before deployment to avoid disclosing web app folder information.
-->
<directoryBrowse enabled="true"/>
</system.webServer>
</configuration>
The client is a console app whose App.config is this.
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="webHttpEndpointBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IService1" />
</basicHttpBinding>
<wsHttpBinding>
<binding name="WsHttpBinding_IService1" />
</wsHttpBinding>
<webHttpBinding>
<binding name="WebHttpBinding_IService1" />
</webHttpBinding>
</bindings>
<client>
<endpoint
address="http://localhost:50001/Service1.svc/basicHttp"
binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_IService1"
contract="ServiceReference1.IService1"
name="BasicHttpEndpoint_IService1" />
<endpoint
address="http://localhost:50001/Service1.svc/webHttp"
behaviorConfiguration="webHttpEndpointBehavior"
binding="webHttpBinding"
bindingConfiguration="WebHttpBinding_IService1"
contract="ServiceReference1.IService1"
name="WebHttpEndpoint_IService1" />
<endpoint
address="http://localhost:50001/Service1.svc/wsHttp"
binding="wsHttpBinding"
bindingConfiguration="WsHttpBinding_IService1"
contract="ServiceReference1.IService1"
name="WsHttpEndpoint_IService1"/>
</client>
</system.serviceModel>
<system.web>
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5"/>
</system.web>
</configuration>
And the client program is this.
class Program
{
static void Main(String[] args)
{
String response = "";
Service1Client basicHttpClient = new Service1Client("BasicHttpEndpoint_IService1");
response = basicHttpClient.GetData(10);
basicHttpClient.Close();
Console.WriteLine(response);
///* Some communication exception
Service1Client webHttpClient = new Service1Client("WebHttpEndpoint_IService1");
response = webHttpClient.GetData(20);
webHttpClient.Close();
Console.WriteLine(response);
//*/
Service1Client wsHttpClient = new Service1Client("WsHttpEndpoint_IService1");
response = wsHttpClient.GetData(30);
wsHttpClient.Close();
Console.WriteLine(response);
Console.WriteLine();
Console.WriteLine("Done");
Console.ReadLine();
}
}
The basicHttpClient and the wsHttpClient work perfectly. However, the webHttpClient throws the exception "System.ServiceModel.CommunicationException was unhandled, HResult=-2146233087, Message=Internal Server Error"
I cannot debug on the servers side as Visual Studio 2012 says
"Unable to automatically debug 'MyProject'. The remote procedure could not be debugged. This usually indicates that debugging has not been enabled on the server."
However, debugging is enabled. I wasn't able to get any insights from using the SvcTraceViewer with diagnostics turned on.
My main interest is figuring out why the REST call using WebHttpBinding is failing, but help getting server side debugging working would be appreciated as well. I'm debugging both the client and the server in VS2012 using multiple startup projects. Localhost is the only server involved.
I understand that the REST endpoint won't show up in WcfTestClient since it provides no metadata exchange, but I expected to be able to call the service through that endpoint and I see no difference between my code and examples of calling RESTful WCF services.
For accessing a REST endpoint try making a HTTP POST request using a browser or HttpClient to the URL : $http://localhost:50001/Service1.svc/webHttp/GetData$. When you use webHttpClient as you do in your code to make a call to the service you are sending a SOAP request which a REST endpoint cannot process. I believe that's the reason your other two endpoints work fine but not this one.