I want to create a WCF console self hosted - server side authentication with Certificate - rest service.
I encountered a problem with actually invoking the Service, since i always get in the response 401 Unauthorized.
Since this is a "One-way" authentication, where the service is identifying itself to the client, why would i always get a 401 unautorized response as a client application (as if the client needs to identify itself to the service to access its resources?)
Could anyone help me with pinpointig where i am going wrong, and how to get my client-service communication working finally?
The Simple Service contract:
[ServiceContract]
public interface IService1
{
[OperationContract]
[WebGet(UriTemplate = "Students", ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json)]
List<Student> GetStudentDetails();
// TODO: Add GetMethod with parameter
[OperationContract]
[WebGet(UriTemplate = "Student/{id}", ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json)]
Student GetStudentWithId(string id);
//TODO: add one post method here
[OperationContract]
[WebInvoke(Method="POST", UriTemplate = "Student/New", ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json)]
void NewStudent(Stream stream);
//TODO: add one post method here
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "Student/NewS", ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json)]
void NewStudentS(Student stream);
}
// Use a data contract as illustrated in the sample below to add composite types to service operations.
[DataContract]
public class Student
{
[DataMember]
public int ID
{
get;
set;
}
[DataMember]
public string Name
{
get;
set;
}
}
Service Implementation:
public class Service1 : IService1
{
public List<Student> GetStudentDetails()
{
return new List<Student>() { new Student() { ID = 1, Name = "Goran" } };
}
public Student GetStudentWithId(string id)
{
return new Student() { ID = Int32.Parse(id), Name = "Ticbra RanGo" };
}
public void NewStudent(Stream stream)
{
using(stream)
{
// convert Stream Data to StreamReader
StreamReader reader = new StreamReader(stream);
var dataString = reader.ReadToEnd();
Console.WriteLine(dataString);
}
}
public void NewStudentS(Student student)
{
Console.WriteLine(student.Name);
}
}
My console application running the service:
static void Main(string[] args)
{
Uri httpUrl = new Uri("https://localhost:8080/TestService");
using (WebServiceHost host = new WebServiceHost(typeof(Service1)))
{
// Create the binding.
WSHttpBinding binding = new WSHttpBinding();
binding.Name = "binding1";
binding.Security.Mode = SecurityMode.Transport;
host.AddServiceEndpoint(typeof(IService1), binding, httpUrl/*"rest"*/);
// Enable metadata publishing.
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
host.Description.Behaviors.Add(smb);
//Add host certificate to service wcf for identification
host.Credentials.ServiceCertificate.SetCertificate(
StoreLocation.LocalMachine,
StoreName.My,
X509FindType.FindBySubjectName,
"localhost");
host.Open();
foreach (ServiceEndpoint se in host.Description.Endpoints)
Console.WriteLine("Service is host with endpoint " + se.Address);
Console.WriteLine("Host is running... Press < Enter > key to stop");
Console.ReadLine();
host.Close();
}
//Console.WriteLine("ASP.Net : " + ServiceHostingEnvironment.AspNetCompatibilityEnabled);
Console.WriteLine("Host is running... Press < Enter > key to stop");
Console.ReadLine();
}
Note that i create the certificate root and children through KeyStore Explorer, and placed them approriately in personal and trusted root certificates on windows.
I mapped the server certificate to the port 8080 though CMD.
The clients i was using are SOAPUI, and my manual coded client. Client Code:
WebRequest request = HttpWebRequest.Create(urlTextBox.Text);
var webResponse = request.GetResponse();
using (Stream dataStream = webResponse.GetResponseStream())
{
// Open the stream using a StreamReader for easy access.
StreamReader reader = new StreamReader(dataStream);
// Read the content.
string responseFromServer = reader.ReadToEnd();
// Display the content.
Console.WriteLine(responseFromServer);
HttpResonseTextBox.Text = responseFromServer;
}
Best regards and thank you in advance so much