few reads for my reference
Securing services
Authentication, Authorization, and Identities in WCF
Federated Security
Showing posts with label WCF. Show all posts
Showing posts with label WCF. Show all posts
Thursday, 30 May 2013
Message Security with Certificates for Client/Server validation
few reads
http://msdn.microsoft.com/en-us/library/ms733098.aspx
http://msdn.microsoft.com/en-us/library/ms751516.aspx
http://stackoverflow.com/questions/1570939/wcf-message-security-without-certificate-and-windows-auth
and create two certificates - for client/server.
Server
ICalculator.cs
http://msdn.microsoft.com/en-us/library/ms733098.aspx
http://msdn.microsoft.com/en-us/library/ms751516.aspx
http://stackoverflow.com/questions/1570939/wcf-message-security-without-certificate-and-windows-auth
and create two certificates - for client/server.
Server
ICalculator.cs
using System.ServiceModel; namespace MySimpleCalculator { [ServiceContract] public interface ICalculator { [OperationContract] int Add(int num1, int num2); [OperationContract] string GetCallerIdentity(); } }
Calculator.svc
<%@ ServiceHost Language="C#" Debug="true" Service="MySimpleCalculator.Calculator" CodeBehind="Calculator.svc.cs" %>
Calculator.svc.cs
using System.ServiceModel; namespace MySimpleCalculator { public class Calculator : ICalculator { public int Add(int num1, int num2) { return num1 + num2; } public string GetCallerIdentity() { // The client certificate is not mapped to a Windows identity by default. // ServiceSecurityContext.PrimaryIdentity is populated based on the information // in the certificate that the client used to authenticate itself to the service. return ServiceSecurityContext.Current.PrimaryIdentity.Name; } } }
web.config
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceCredentialsBehavior">
<serviceCredentials>
<serviceCertificate findValue="CN=Server"
x509FindType="FindBySubjectDistinguishedName"/>
<clientCertificate>
<authentication certificateValidationMode="PeerOrChainTrust"
revocationMode="NoCheck" />
</clientCertificate>
</serviceCredentials>
<!-- 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>
<services>
<service name="MySimpleCalculator.Calculator" behaviorConfiguration="ServiceCredentialsBehavior">
<endpoint contract="MySimpleCalculator.ICalculator" address="/SimpleCalculator"
binding="wsHttpBinding"
bindingConfiguration="MessageUsingCertificate" />
</service>
</services>
<bindings>
<wsHttpBinding>
<binding name="MessageUsingCertificate">
<security mode="Message">
<message clientCredentialType="Certificate"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
------------------------------------------------------------------------
client
class Program { static void Main(string[] args) { ServiceReference1.CalculatorClient client = new ServiceReference1.CalculatorClient(); Console.WriteLine(client.Add(1, 2)); Console.WriteLine(client.GetCallerIdentity()); Console.ReadLine(); } }
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_ICalculator">
<security>
<message clientCredentialType="Certificate" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="endpointCredentialsBehavior">
<clientCredentials>
<clientCertificate findValue="CN=client"
storeLocation="LocalMachine"
x509FindType="FindBySubjectDistinguishedName" />
<serviceCertificate>
<authentication revocationMode="NoCheck"/>
</serviceCertificate>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
<client>
<endpoint address="http://localhost:18499/Calculator.svc/SimpleCalculator"
binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_ICalculator"
contract="ServiceReference1.ICalculator" name="WSHttpBinding_ICalculator"
behaviorConfiguration="endpointCredentialsBehavior">
<identity>
<certificate encodedValue="server certificate value" />
</identity>
</endpoint>
</client>
</system.serviceModel>
</configuration>
Issues
1. {"The request for security token could not be satisfied because authentication failed."} - It means
Server tries to authenticate Client certificate and its revocation status. So add 'No Revocation'
@ server side for client certificate.
2. SOAP security negotiation with "uri" fails.
The X.509 certificate CN=subject chain building failed. The certificate that was used has
a trust chain that cannot be verified. Replace the certificate or change the
certificateValidationMode. The revocation function was unable to check revocation for
the certificate. - This happens if server certificate is not trusted by client, add no revocation.
Labels:
Certificates,
Message Security,
WCF
Location:
Bangalore, Karnataka, India
Tuesday, 26 February 2013
WCF serviceAuthorizationManager
ServiceAuthorizationManager can be used as custom authentication mechanism for WCF operations. So we can configure this in behavior tag
<behavior name="Behavior">
<serviceAuthorization serviceAuthorizationManagerType="ClassThatImplementsServiceAuthorizationManager, Assembly" />
</behavior>
This is can code thru code like below
host = new WebServiceHost(typeof(Rest), address.Uri);
host.Authorization.ServiceAuthorizationManager=ClassThatImplementsServiceAuthorizationManager;
<behavior name="Behavior">
<serviceAuthorization serviceAuthorizationManagerType="ClassThatImplementsServiceAuthorizationManager, Assembly" />
</behavior>
This is can code thru code like below
host = new WebServiceHost(typeof(Rest), address.Uri);
host.Authorization.ServiceAuthorizationManager=ClassThatImplementsServiceAuthorizationManager;
Location:
Bangalore, Karnataka, India
WCF Restful service with BASIC Authentication
Just wanted to show code for configuring BASIC authentication on REST service.
Hosting part
---------------
WebHttpBinding binding = new WebHttpBinding();
binding.Security.Mode = WebHttpSecurityMode.TransportCredentialOnly;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
binding.Security.Transport.Realm = "domain"; //Enter domain name
host = new WebServiceHost(typeof(Service), address.Uri);
host.AddServiceEndpoint(typeof(IService), binding, address.Uri);
host.Open();
Client
--------
WebHttpBinding binding = new WebHttpBinding();
binding.Security.Mode = WebHttpSecurityMode.TransportCredentialOnly;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
using (WebChannelFactory factory = new WebChannelFactory(binding, address.Uri))
{
factory.Credentials.UserName.UserName = "user";
factory.Credentials.UserName.Password = "password";
var channel = factory.CreateChannel();
channel.CallSomething();
}
Hosting part
---------------
WebHttpBinding binding = new WebHttpBinding();
binding.Security.Mode = WebHttpSecurityMode.TransportCredentialOnly;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
binding.Security.Transport.Realm = "domain"; //Enter domain name
host = new WebServiceHost(typeof(Service), address.Uri);
host.AddServiceEndpoint(typeof(IService), binding, address.Uri);
host.Open();
Client
--------
WebHttpBinding binding = new WebHttpBinding();
binding.Security.Mode = WebHttpSecurityMode.TransportCredentialOnly;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
using (WebChannelFactory
{
factory.Credentials.UserName.UserName = "user";
factory.Credentials.UserName.Password = "password";
var channel = factory.CreateChannel();
channel.CallSomething();
}
Labels:
BASIC,
c#,
Custom Basic Authentication,
REST,
WCF
Location:
Bangalore, Karnataka, India
Thursday, 21 June 2012
IRequestChannel - Demo 1
Let's assume below ServiceContract
so how can we invoke above using IRequestChannel
[ServiceContract] public interface IDemo1 { [OperationContract] string HelloWorld(string name); }
so how can we invoke above using IRequestChannel
var httpsBasicBinding = new BasicHttpBinding(BasicHttpSecurityMode.Transport); var endpoint = "https://host/service.svc"; var channelFactory = new ChannelFactory<IRequestChannel>(httpsBasicBinding, endpoint); var channel = null;
try
{
channelFactory.Open();
channel = channelFactory.CreateChannel();
channel.Open();
string body = "<HelloWorld xmlns="http://tempuri.org/"><name>Suresh</name></HelloWorld>";
var messageBody = XmlReader.Create(new MemoryStream(Encoding.UTF8.GetBytes(body)
Message message = Message.CreateMessage(MessageVersion.Soap11,
"http://tempuri.org/IDemo1/HelloWorld"); Message response = channel.Request(message);
var result = response.GetReaderAtBodyContents().ReadOuterXml(); //parse based on the requirments Console.WriteLine(result);
channel.Close();
}
finally
{
channel.close(); //abort if faulted
channelFactory.Close(); //abort if faulted }
reference : http://www.codeproject.com/Articles/34632/How-to-pass-arbitrary-data-in-a-Message-object-usi
Labels:
c#,
IRequestChannel,
WCF
Location:
Bangalore, Karnataka, India
Monday, 23 April 2012
HTTP 500.0 - Internal Server Error in Windows 2008 R2 Server
After deploying a 32-Bit WCF service in IIS 7.5(Windows 2008 R2 server), browsing the service failed with
HTTP 500.0 - Internal Server Error, and from the error message i figured out something wrong with PageHandlerFactory. For 32-Bit web apps, it is mandatory to set 'Enable 32-Bit Applications' to 'True'. We can either set it @ 'Application Pool Defaults' or the specific Application Pool in question.
HTTP 500.0 - Internal Server Error, and from the error message i figured out something wrong with PageHandlerFactory. For 32-Bit web apps, it is mandatory to set 'Enable 32-Bit Applications' to 'True'. We can either set it @ 'Application Pool Defaults' or the specific Application Pool in question.
Labels:
WCF,
Windows Server 2008 R2,
x64
Location:
Bangalore, Karnataka, India
Wednesday, 4 January 2012
Console client for a WCF Restful service protected with BASIC authentication(windows credential)
Please refer my earlier post for REST service details, below is an sample code to pass on windows credentials while calling WCF REST service(in IIS - Anonymous access is disabled and BASIC is enabled)
static void Main(string[] args)
{
Uri baseAddress = new Uri("http://localhost:8080/SimpleService");
try
{
WebHttpBinding binding = new WebHttpBinding();
binding.Security.Mode = WebHttpSecurityMode.TransportCredentialOnly;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
WebChannelFactory cf = new WebChannelFactory(binding, baseAddress);
//If Default domain is not added in IIS, provide it below - else not needed
cf.Credentials.UserName.UserName = "user";
cf.Credentials.UserName.Password = "password";
SimpleInterface channel = cf.CreateChannel();
Console.WriteLine("Reply Hi : {0}", channel.ReplyHi("Hello, world"));
Console.WriteLine("Reply Hii : {0}",channel.ReplyHii("Hello, world"));
}
catch (CommunicationException ex)
{
Console.WriteLine("An exception occurred: " + ex.Message);
}
}
static void Main(string[] args)
{
Uri baseAddress = new Uri("http://localhost:8080/SimpleService");
try
{
WebHttpBinding binding = new WebHttpBinding();
binding.Security.Mode = WebHttpSecurityMode.TransportCredentialOnly;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
WebChannelFactory
//If Default domain is not added in IIS, provide it below - else not needed
cf.Credentials.UserName.UserName = "user";
cf.Credentials.UserName.Password = "password";
SimpleInterface channel = cf.CreateChannel();
Console.WriteLine("Reply Hi : {0}", channel.ReplyHi("Hello, world"));
Console.WriteLine("Reply Hii : {0}",channel.ReplyHii("Hello, world"));
}
catch (CommunicationException ex)
{
Console.WriteLine("An exception occurred: " + ex.Message);
}
}
Location:
Bengaluru, Karnataka, India
WCF Absolute Vs Relative address
After long break, i started working on WCF services and i struck with a problem when i hosted my service in IIS. I figured out that i have given an absolute end point address, which is wrong. So i figured out below in MSDN
'When hosting with IIS, you do not manage the ServiceHost instance yourself. The base address is always the address specified in the .svc file for the service when hosting in IIS. So you must use relative endpoint addresses for IIS-hosted service endpoints. Supplying a fully-qualified endpoint address can lead to errors in the deployment of the service. For more information, see Deploying an Internet Information Services-Hosted WCF Service."
So with following config
<services>
<service name="RestService.SimpleService">
<endpoint address="/Sample" binding="webHttpBinding"
contract="RestService.SimpleInterface" behaviorConfiguration="webby"
bindingConfiguration="secure"/>
</service>
</services>
i hosted my WCF(REST) as 'SimpleRestService' application, so i need to use http://localhost/SimpleRestService/yoursvcfilename.svc/Sample/youroperationname
'When hosting with IIS, you do not manage the ServiceHost instance yourself. The base address is always the address specified in the .svc file for the service when hosting in IIS. So you must use relative endpoint addresses for IIS-hosted service endpoints. Supplying a fully-qualified endpoint address can lead to errors in the deployment of the service. For more information, see Deploying an Internet Information Services-Hosted WCF Service."
So with following config
<services>
<service name="RestService.SimpleService">
<endpoint address="/Sample" binding="webHttpBinding"
contract="RestService.SimpleInterface" behaviorConfiguration="webby"
bindingConfiguration="secure"/>
</service>
</services>
i hosted my WCF(REST) as 'SimpleRestService' application, so i need to use http://localhost/SimpleRestService/yoursvcfilename.svc/Sample/youroperationname
Issues while hosting Restful WCF services in IIS
When i hosted my Hello World WCF Restful services, i faced below issue
The requested content appears to be script and will not be served by the static file handler.
My application is using 'DefaultAppPool', For reasons
unknown to me, running the below did work.
c:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_regiis.exe -i
But soon after this i ran into below issue
"Could not load type 'System.ServiceModel.Activation.HttpModule'"
For reasons unknown to me, running the below did work :(.
c:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_regiis.exe /iru
http://forums.asp.net/t/1432329.aspx/1
http://www.fredmastro.com/post/HTTP-Error-40417-Not-Found-e28093-Using-WCF-SVC-Service.aspx
http://support.microsoft.com/kb/2015129
Location:
Bengaluru, Karnataka, India
Tuesday, 3 January 2012
Restful WCF services hosted in Console Application
Sorry - No descriptions, i am bored to death, hence only the code.
namespace SimpleConsoleWCFHost
{
[ServiceContract]
public interface SimpleInterface
{
///
/// POST, bare body message - http://localhost:8080/SimpleService/SayHi/Suresh
/// Content-Type: text/html
///
///
[OperationContract]
[WebInvoke(Method="POST", BodyStyle = WebMessageBodyStyle.Bare,
UriTemplate="SayHi/{name}")]
void SayHi(string name);
///
/// GET, http://localhost:8080/SimpleService/ReplyHi/Suresh
/// Content-Type: text/html
///
///
///
[OperationContract]
[WebInvoke(Method = "GET", BodyStyle = WebMessageBodyStyle.Bare,
UriTemplate = "ReplyHi/{name}")]
string ReplyHi(string name);
///
/// GET, http://localhost:8080/SimpleService/ReplyHii?name=Suresh
/// Content-Type: text/html
///
///
///
[OperationContract]
[WebGet]
string ReplyHii(string name);
///
/// GET, http://localhost:8080/SimpleService/ReplyByJson?name=Suresh
/// Content-Type: text/json
///
///
///
[OperationContract]
[WebGet(ResponseFormat=WebMessageFormat.Json)]
SimpleData ReplyByJson(string name);
///
/// GET, http://localhost:8080/SimpleService/ReplyByXml?name=Suresh
/// Content-Type: application/xml
///
///
///
[OperationContract]
[WebGet(ResponseFormat = WebMessageFormat.Xml)]
SimpleData ReplyByXml(string name);
///
/// POST, http://localhost:8080/SimpleService/ConverseUsingJson
/// Content-Type: text/json
/// {"Body":"Comment received at 03-01-2012 10:13:55","Header":"Welcome to JSON - Suresh"}
///
///
///
[OperationContract]
[WebInvoke(UriTemplate = "ConverseUsingJson", Method = "POST",
RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
SimpleData ConverseUsingJson(SimpleData data);
///
/// POST, http://localhost:8080/SimpleService/ConverseUsingXml
/// Content-Type: application/xml
///colin
/// http://www.britishdeveloper.co.uk/2011/01/how-to-post-rest-fiddler.html
///
///
///
[OperationContract]
[WebInvoke(UriTemplate = "ConverseUsingXml", Method = "POST",
RequestFormat = WebMessageFormat.Xml, ResponseFormat = WebMessageFormat.Xml)]
SimpleData ConverseUsingXml(SimpleData data);
}
[DataContract(Namespace = "")]
public class SimpleData
{
[DataMember]
public string Header { get; set; }
[DataMember]
public string Body { get; set; }
}
public class SimpleService : SimpleInterface
{
public void SayHi(string name)
{
Console.WriteLine("Hi " + name);
}
public string ReplyHi(string name)
{
return "Hi " + name;
}
public string ReplyHii(string name)
{
return "Hii " + name;
}
public SimpleData ReplyByJson(string name)
{
return new SimpleData
{
Header = "Welcome to JSON - " + name,
Body = "Comment received at " + DateTime.UtcNow.ToString()
};
}
public SimpleData ReplyByXml(string name)
{
return new SimpleData
{
Header = "Welcome to XML - " + name,
Body = "Comment received at " + DateTime.UtcNow.ToString()
};
}
public SimpleData ConverseUsingJson(SimpleData value)
{
value.Header = "JSON Conversation";
return value;
}
public SimpleData ConverseUsingXml(SimpleData value)
{
value.Header = "XML Conversation";
return value;
}
}
class Program
{
static void Main(string[] args)
{
Uri baseAddress = new Uri("http://localhost:8080/");
string serviceName = "SimpleService";
using (WebServiceHost webHost = new WebServiceHost(typeof(SimpleService), baseAddress))
{
ServiceEndpoint sp = webHost.AddServiceEndpoint(typeof(SimpleInterface), new WebHttpBinding(), serviceName);
//ServiceDebugBehavior sdb = webHost.Description.Behaviors.Find();
//sdb.HttpHelpPageEnabled = false;
webHost.Open();
Console.WriteLine("Host Opened");
Console.ReadLine();
webHost.Close();
Console.WriteLine("Host Closed");
}
}
}
}
Some fiddler shots below



namespace SimpleConsoleWCFHost
{
[ServiceContract]
public interface SimpleInterface
{
///
/// POST, bare body message - http://localhost:8080/SimpleService/SayHi/Suresh
/// Content-Type: text/html
///
///
[OperationContract]
[WebInvoke(Method="POST", BodyStyle = WebMessageBodyStyle.Bare,
UriTemplate="SayHi/{name}")]
void SayHi(string name);
///
/// GET, http://localhost:8080/SimpleService/ReplyHi/Suresh
/// Content-Type: text/html
///
///
///
[OperationContract]
[WebInvoke(Method = "GET", BodyStyle = WebMessageBodyStyle.Bare,
UriTemplate = "ReplyHi/{name}")]
string ReplyHi(string name);
///
/// GET, http://localhost:8080/SimpleService/ReplyHii?name=Suresh
/// Content-Type: text/html
///
///
///
[OperationContract]
[WebGet]
string ReplyHii(string name);
///
/// GET, http://localhost:8080/SimpleService/ReplyByJson?name=Suresh
/// Content-Type: text/json
///
///
///
[OperationContract]
[WebGet(ResponseFormat=WebMessageFormat.Json)]
SimpleData ReplyByJson(string name);
///
/// GET, http://localhost:8080/SimpleService/ReplyByXml?name=Suresh
/// Content-Type: application/xml
///
///
///
[OperationContract]
[WebGet(ResponseFormat = WebMessageFormat.Xml)]
SimpleData ReplyByXml(string name);
///
/// POST, http://localhost:8080/SimpleService/ConverseUsingJson
/// Content-Type: text/json
/// {"Body":"Comment received at 03-01-2012 10:13:55","Header":"Welcome to JSON - Suresh"}
///
///
///
[OperationContract]
[WebInvoke(UriTemplate = "ConverseUsingJson", Method = "POST",
RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
SimpleData ConverseUsingJson(SimpleData data);
///
/// POST, http://localhost:8080/SimpleService/ConverseUsingXml
/// Content-Type: application/xml
///
/// http://www.britishdeveloper.co.uk/2011/01/how-to-post-rest-fiddler.html
///
///
///
[OperationContract]
[WebInvoke(UriTemplate = "ConverseUsingXml", Method = "POST",
RequestFormat = WebMessageFormat.Xml, ResponseFormat = WebMessageFormat.Xml)]
SimpleData ConverseUsingXml(SimpleData data);
}
[DataContract(Namespace = "")]
public class SimpleData
{
[DataMember]
public string Header { get; set; }
[DataMember]
public string Body { get; set; }
}
public class SimpleService : SimpleInterface
{
public void SayHi(string name)
{
Console.WriteLine("Hi " + name);
}
public string ReplyHi(string name)
{
return "Hi " + name;
}
public string ReplyHii(string name)
{
return "Hii " + name;
}
public SimpleData ReplyByJson(string name)
{
return new SimpleData
{
Header = "Welcome to JSON - " + name,
Body = "Comment received at " + DateTime.UtcNow.ToString()
};
}
public SimpleData ReplyByXml(string name)
{
return new SimpleData
{
Header = "Welcome to XML - " + name,
Body = "Comment received at " + DateTime.UtcNow.ToString()
};
}
public SimpleData ConverseUsingJson(SimpleData value)
{
value.Header = "JSON Conversation";
return value;
}
public SimpleData ConverseUsingXml(SimpleData value)
{
value.Header = "XML Conversation";
return value;
}
}
class Program
{
static void Main(string[] args)
{
Uri baseAddress = new Uri("http://localhost:8080/");
string serviceName = "SimpleService";
using (WebServiceHost webHost = new WebServiceHost(typeof(SimpleService), baseAddress))
{
ServiceEndpoint sp = webHost.AddServiceEndpoint(typeof(SimpleInterface), new WebHttpBinding(), serviceName);
//ServiceDebugBehavior sdb = webHost.Description.Behaviors.Find
//sdb.HttpHelpPageEnabled = false;
webHost.Open();
Console.WriteLine("Host Opened");
Console.ReadLine();
webHost.Close();
Console.WriteLine("Host Closed");
}
}
}
}
Some fiddler shots below
Location:
Bengaluru, Karnataka, India
Subscribe to:
Posts (Atom)