Showing posts with label WCF. Show all posts
Showing posts with label WCF. Show all posts

Monday, December 10, 2012

Visual Studio LIVE! Day 1 - WCF and Web API



So it's day 1 here at Visual Studio LIVE!, and I'm here attending Miguel Castro's WCF & Web API full day workshop. There is a great attendance with probably 300-400 people from my estimation. I'm here on the 2nd row so I can get the most and interact without yelling. I am definitely refining my air traffic controller multitasking skills today trying to listen, take notes, and learn simultaneously.

I actually had the pleasure of having dinner with Miguel and his family along with Rocky Lhotka, and Andrew Burst at last years conference over at Bubba Gump Shrimp. I sat across from Miguel and had some great conversations on WCF. I also had lunch today with him as well which was cool! The man has a Black 560 HP Mustang GT he customized. Yes please. Here's a guy that has a wealth of knowledge on WCF, services, and SOA which you wish was sitting in the cube or office next to you on a daily basis. He validates himself easily as a Microsoft MVP for Connected Systems, and I enjoy his knowledge transfer.

This class was interesting to me because I have been using WCF since CTP in Framework 3.0, and by no means do I consider myself an expert (on this or anything), but I wonder about tracks I have a deeper experience in already. Meaning, will it be a lot of information I've digested previously. Fear not, one can never know it all. Case and point this class by Miguel. The byproduct of the architecture used behind some of the simple WCF samples shown is the real gem.

When Miguel asked how many in the room are WCF developers, to my surprise it was not the overall majority in the room. I am confident this was not telling of the technology but rather there were a lot of developers that have not been involved with writing services. I feel for some of these people because WCF is so deep as a technology that's it's hard to digest in a single day. This is exactly the reason though that I found this class so informative. This was a 300 level track masquerading a a 101 during introduction, and he states this is a 5 day class compressed to a single day. When DI, SOA, SoC, and OOP are all being discussed within the 1st hour or so... this is great stuff.

Where I really align beliefs in architecture with Miguel is on SoC. I always can get a feel of how an architecture is laid out simply but looking at all of the projects in a VS.NET solution collapsed and seeing the logical layers. Miguel is a strong proponent of separating the individual pieces of WCF into their own layers. He does not care for the bloating of the auto generated proxy classes created by 'Add Service Reference' within VS.NET, in addition to the tightly coupled nature of the service contract, implemented classes, and the associated channel communications. I too agree for the majority of applications. I still think there is a place for consuming a service and having the proxies created, along with a WCF Service Library on the back-end. I think if you have a simple 1 page app using a simple service (keeping in mind YAGNI principal, while still observing scalibility of functionality), there is a place for a compressed architecture. WCF Service Library or WCF Service Application + Consuming client application using 'Add Service Reference' within VS.NET is simple, straight forward, and easy to understand and consume. I try never to be what they call an 'Architecture Astronaut' and over-architect when not required; not implying Miguel is this by any means, but just that I rarely will use the word 'always' (he didn't either, just making a point) when using the sentence "This application should be architected like this ____" I also don't believe in spaghetti crap applications either, so hopefully I make proper decisions on building and constructing applications.

However for true enterprise applications using SOA as a basis, or even any large scale isolated applications I couldn't hold the flag with any more pride on properly separating the logic when working with WCF. I'm a big fan of the ideology around architectures like Domain Driven Design, MVC, MVVM, and heck even simple 3-layer UI-BLL-DAL. They all have at least a basic commonality which is the idea of logically separating responsibilities and concerns. Since WCF inherently has a lot of different responsibilities end-to-end it to makes sense to separate the major players into their own pieces. This isn't really a new concept as most advanced literature in our field will at minimum separate out the host and WCF functionality, but most even take it a step further and break the pieces down further. Why all of this work? In the long run it allows us to be extremely flexible and make isolated changes without a large ripple effect, and to allow switching out pieces like the host easily.

First let's look at an overall SOA architecture. This gives a great visual on a decent layering of the application (slide courtesy of Visual Studio LIVE! and Miguel Castro).



Here is a breakdown of the WCF components that will need to be created, each responsibility being its own project (slide courtesy of Visual Studio LIVE! and Miguel Castro):



Next let's look at the breakdown of the actual project layers and their high-level purpose:



Business Engine: This is the typical layer which contains the business rules and logic. Also referred to as the Business Logic Layer, Business Domain or just Domain Layer.

Client: This represents any UI client that will be making calls to our WCF service. This might be a ASP.NET, WPF, WinForms, etc. application.

Contracts: These are the Service Contracts and any DTO DataContracts used for transporting data across the wire. There are no implementation classes in this layer. Miguel had a nice suggestion to post fix the word 'Data' on a DataContract DTO, like 'ZipCodeData'. This helps distinguish them from service or business logic methods. DTOs are typically nothing more than getters and setters to move serilizable data across the network.

Host: This is the hosting layer for WCF. This might be contain the files necessary for hosting via a  self-hosted Windows Service or IIS (.svc file). Remember that  a svc. is a 'browsing point' for a WCF service. It invokes the appropriate WCF handler. ASP.NET needs a browsing point to know what world it's in.This also contains the .config file, and the only one that matters which is the one from the host. Within this config there is the WCF configuration

WebHost: This is an optional layer that provides an additional avenue if the 'Host' layer is implemented using an alternate self-hosted mechanism like a console application or Windows Service.

Again as you decipher each layer you see it has a very specific responsibility  It really is not a lot of extra work to segregate the layers and the benefit is the ability to make isolated changes or even switch out components more easily (like hosting methods) without a lot of 'unhooking'. The main thing here is *not* to couple the host and the service code in case the host needs to be changed out later. This architecture and layout of the layers has it's obvious benefits.

He then led into a great discussion on WCF Proxy Instancing and Concurrency. I was more interested in the instancing portion as I think there are more use cases for making changes. The following are the (3) main types of instancing:

Per-call instancing
    -each call spins up a new instance of the service.
    -On the client it appears that it's a single object, but it's not. Stateless behavior.
     -Advantage is stateless, scalable, and nothing is held on server's memory.
      -Not the default, but Miguel sets his services up like this.
Per-session instancing
    -WCF default
    -1st call spins up instance and calls constructor
    -2nd call uses SAME instance
    -Can maintain state using class-wide members in service
Singleton Instancing
    -when host opens, host instantiates service
    -one instance serves all proxies for all clients
    -very specific usage scenarios
    -With IIS hosting and the potential for app pool recycles, the Singleton instance is destroyed and dispose is called. This is a disadvantage and something to keep in mind if trying to use a Singleton for the WCF proxy.

On the topic of proxies, they are unmanaged objects. They are not CLR managed. Always dispose of proxy classes, and use a 'using' statement when possible to wrap instantiation of the proxy classes. Until the proxy is closed, WCF will keep an open connection and add to the value for service throttling thinking the connection is still active. Throttling is ability for WCF to manage concurrent calls, prior to queuing up to prevent server from breaking. This is really important to be on notice. If that proxy class is not disposed performance can hinder significantly  Miguel had instance where a DI proxy in MVC was not disposed. Calls went from 1.5 secs to 100ms once the issue was tracked down and the proxy was disposed. A few in the audience complained of problems with the 'using' statement throwing exceptions, but I would like to see the IL differences from calling manually. Bottom line, dispose of explicitly if the 'using' statement gives any issues.

Next he went into doing WCF callbacks. Very useful stuff. Callbacks have a place for keeping a proxy channel open to allow the server have the ability to make calls back to the client. The use of this could be as simple as updating a progress meter bar, updating sports scores during a game, updating stock prices, updating dashboards, etc. This is in my opinion a much more appropriate 'tool' for what often is done via a timer and polling. Polling definitely has its place and I use it and have blogged on it, but when the responsibility is on the server to notify the clients of updated data, then using duplex services are a good idea. If you have a need to constantly keep a client updated and are using a WCF SOAP based service, then using callbacks and a duplex service should be considered, especially if you are implementing some sort of polling to fetch data.

The topic of WCF exceptions was also highlighted. As always the main exception rules still apply when handling exceptions. Here are the main reasons to catch exceptions:

  • wrap and re-throw
  • log and re-throw
  • consume and dissolve

However with WCF operations it is acceptable to have one big Try-Catch with Throw FaultException.
My particular favorite way is using something like the following:

throw new FaultException("Blah, blah");

Something interesting, if you do not explicitly throw a FaultException server side or throw an exception of a specific type (i.e. DivideByZeroException), the proxy on the client will *not* be preserved and will be closed. However, if a FaultException or FaultException (where 'T' can be an exception or any data contract) is thrown by the service, the proxy state will be preserved. I asked why we would want to preserve the proxy state on the client? After all we are busted server side, should the client proxy survive? Odds are no it should not. But maybe you want to give the client a chance to absorb and go through some re-try logic without closing the proxy. This would be a rare use case, but it's important to understand.

Miguel also highlighted Transactions is WCF. I have not used transactions in WCF in a production setting, but as typical the best example to show how to use transactions is with a bank account example. The example used was one of a method called 'TransferMoney()' and underneath (2) additional methods are called 'DebitAccount()' and 'CreditAccount()'. Obviously if 'DebitAccount()' worked and 'CreditAccount()' did not, we do not want the transaction to complete and have it roll back. This is not the same as those that have worked with SQL transactions in ADO.NET. The rollback is independent of any SQL calls. You might still have a database call involved but you might not as well.

A few things to note on transaction in WCF. They are at the operation level. By default transactions are not turned on (Value = 'NotAllowed'). However there are (2) other settings which are 'Allowed' and 'Mandatory'. As Miguel mentions, setting the operation to 'Allowed' is a low risk as it actually does nothing until transactions are implemented; it just opens the door to allowing them if desired. Also, all methods downstream must participate in transactions or the transaction functionality will not work properly. Any method in the chain that does not support and implement transactions will not allow the rollback to occur if there is a failure. Lastly, the client does not need to worry about wrapping the initial call into a transaction. As long as the WCF service implements them properly it will still have the transaction implemented correctly. Transactions are not needed for all use cases, but the actual implementation when planned out properly is not too difficult.

In come REST services, my favorite topic of the day. I know not the end-all answer to everything, but its power and simplicity are great. WCF SOAP services for line-of-business intranet .NET to .NET apps using NetTcp bindings are still lightning fast and the way to go for performance. However the minute a non-.NET client is introduces especially outside the firewall, using RESTful services are the required solution. Miguel stated that even know the wsHttpBinding is supposed to have interoperability, it doesn't do uplevel perfectly so need to go with REST in these situations. Deciding SOAP services vs. REST services will mostly come down to the consuming clients, internet vs. intranet, and interoperability factors. Also remember with REST services many of the topics discussed previously like transactions, concurrency, etc. are not applicable. There is still a place very much so for SOAP based services albeit a much heavier implementation that that of REST based services.

REST based services are much lighter weight than SOAP services returning either XML or JSON typically. There is no heavy SOAP message to deal with and the constraints of what the consuming client will look like. REST services based on the REST architecture are an extension of web standards and the GET, PUT, PLACE, and DELETE verbs (note: PUT and DELETE verbs are turned off in IIS by default, so make sure to turn them on if you need them). In fact you can make REST based calls directly in a browser (browser calls are by default HTTP GET). Although the purists, the so-called 'RESTafarains' will never acknowledge a pure REST implementation most of the time there is at least one place I totally agree with them on implementing these types of services. Make sure to use the HTTP verbs properly  For example, don't abuse the verbs and do an 'update' behind the scenes as part of a GET. While possible it's incorrect and there are really no checks in place to prevent this.

With a WCF implementation, the deciding factor on the return type, XML or JSON, is configurable at the service level. Ideally you would expose (2) endpoints, (1) for each return type. Then it's up to the client to call the appropriate URL containing the endpoint that will return the desired type. However, technically the server is still deciding on the actual service what the return type will be.

What I REALLY like about Web API services is the ability for the client to set the 'Content-Type' value in the request header to indicate the return type! Yep no configuration or heavy implementation. Set the header and you get back the type you requested. If testing from a browser, Google Chrome by default returns XML, and IE returns JSON. My recommendation if you are not familiar with JSON is to begin using it because it is more compact and lightweight than XML. With so many JSON deserializers in .NET it makes it super simple to convert it to a DataContract once received and then work with a strongly typed object. You *can* do the same with XML via LINQ to XML into a type like a DataContract but it's much more cumbersome to work with in my opinion.

WCF REST service and ASP.NET Web API are competing products at Microsoft and have a single intended purpose to deliver data in a RESTful manner. However, REST was introduced 1st in WCF 3.5 with introduction of WebGet and WebInvoke attributes and webHttpBinding. Web API was originally born out of the WCF Starter Kit and was RC in MVC 4. You can use the Web API with .NET Framework 4.0.

The main deciding factor when looking at architecting an application is the decision to use a WCF REST based service vs. a Web API service. There are subtle advantages to both and Miguel warns of not getting all caught up in the 'Web API is the greatest thing since sliced bread' deal. If you already have a full blown WCF service layer implementation and need to add REST atop of that, then a WCF REST service may be the easier way to go. However if starting from scratch it appeared to seem that the general census was to use a Web API REST implementation.

Interesting tidbit - technically the largest REST based deployment in the world... the world wide web.

The final part of the day was to cover WCF security in 45 minutes. WHAT?!?! Yeah pretty much impossible. The good news is (at least for me) I was have done so much over the years with WCF security, authorization, authentication, and securing services that the security information 'blitz' made sense to me. However anyone in the audience that has not done anything with security will need to do a lot more research on the topics. May I recommend perusing this blog as I have dedicated several posts to WCF security and securing WCF services.

The main points I wanted to highlight here are the following. TCP is a secure binding by default. It's binary. You can't break the pipe. HTTP on the other hand is an open binding and the 'message' needs to be secured. You can actually secure the 'Transport' which will also secure the message with either a SSL certificate (HTTPS) or via X509 certificates  I prefer using a SSL cert and like I mentioned have several posts on the topic. However the points on NetTcp are important to restate. If you *can* use a TCP binding, you will get some blazing performance and native Windows Security so it's an attractive option when working on an intranet application with a .NET to .NET scenario. Check out the WCF Security Guide on CodePlex if you really want a deep dive. In reality an 8 hour course could easily be given just on the topic of security.



To wrap things up on this busy day, I must say I onloaded a LOT of information for the services world. If you have a chance check out Miguel at any of the mainstream conferences around the country, on his blog, or on Twitter @miguelcastro67. I only have one piece of advice for Miguel since he has provided so much information to me today... dump the Mac.

I will also leave you with some of Miguel's best quotes of the day. I always enjoy his candid style!


"What is exception handling? A slash block and then 'ToDo'"
"Can we even call them Metro apps anymore, or not because some food store in eastern Europe sued Microsoft."
"Compilation is the 1st unit test, right... sometimes it's the only unit test"
"I get to start shit and not have to finish it" (contractors)
"My shit don't break"
"Who does SharePoint in the room.... Why?"
"no, no Google, we use Bing here right?"
"Dude, i'm not covering security 2 hours in! I do it at the end of the day when you brains are fried so I can bull shit my way through"
"You just broke my shit, I'm going to be pissed"
"Rhode Island sucks! It's not even a real state."
"What do you have to do to slow a Windows system down... Nothing"
"I feel like I just gave birth to a callback."
"Most New Jerseyans can't spell DB2"
"The RESTafarains are as whacked out and smoke as much ganja as the Rastafarians"
"Regular Expressions are cartoon characters cursing"
"I don't agree with anything a DBA says except in table naming"

Tuesday, July 3, 2012

Using Basic Authentication In REST Based Services Hosted in IIS

So a colleague of mine asked a good question earlier today in reference to my last post on using Basic Authentication techniques in reference to REST based WCF services hosted in IIS. It turns out that there is conflicting documentation on whether or not a Custom User Name and Password Validator that has been configured works properly. In my last post I created a self-hosted service with full implementation and it does indeed work.

However best I can determine is that the IIS call stack is executed and handled, using Basic Authentication for your service does not allow you to override the IIS behavior and intercept those credentials using a custom username/password validator. This is because IIS is handling the authentication prior to the WCF service being called. Thus resulting in a lot of buzz around, "...why doesn't my custom user name and password validator" code get hit for a my WCF REST service hosted in IIS." I also believe I have found some definitive information on the support of this in IIS from Phil Henning's MSDN blog:

"In the version of WCF that shipped with .Net Framework 3.0 we didn't support custom validators with transport level HTTP security. We received much feedback from the community that this was a highly desired feature, so I'm happy to say we added support for this scenario in the 3.5 release of the .Net Framework. Note that this is only supported under self hosted services."

So that to me reads clearly. Also I found this tidbit from Yavor Georgiev of Microsoft confirming this and stating: "As the blog post mentions, this scenario is not supported while hosting in IIS. The reason is that IIS does the authentication before WCF receives the request." So there we have it - dual confirmation that the custom username/password validator is not supported in IIS hosted services.

In addition to this we have even yet another problem. Using Basic Authentication with REST based services hosted in IIS period. Even this vanilla security authorization technique is not supported. I didn't find much in the way of official documentation, but between my own failed tests, this forum post, and this blog post, it points in the direction that there is no 'out of the box' support for this combination.

At this point the easiest option if you need to use REST based services with a custom username/password validator and use Basic authentication may be to use a self-hosted service. I often hear and read, "Use an IIS based service unless there is a need to self-host." This is a scenario where self-hosting stands out as the winner... initially. But you know I wouldn't post without an IIS solution, right!

We do have another workable and legitimate solution to have a REST based service hosted in IIS using Basic Authentication. As I mentioned before in a few posts and shown examples for, we can implement our own CustomAuthorizationManager that inherits from ServiceAuthorizationManager and configure this for our service. This method is perfect for service level Authorization to your RESTful service. The best part is we can still inspect the incoming message headers to siphon out the client's passed credentials. In this manner we can still provide service level authorization.

As far as the 'Basic' authentication handling, we are going to need to do that ourselves. We can easily send back a response header to challenge for Basic Authentication credentials, and just have IIS wired up to "Anonymous Authentication." We are going to just let IIS do the hosting and take care of all of the authentication ourselves. After all IIS is just a huge, sophisticated wrapper in itself handling security (and a million other things) for us, so we will just shift control of this specific piece back to our service.

To begin, go ahead and configure the service to use a custom authorization manager, and point it to our class named: 'CustomAuthorizationManager'. Keep in mind that the format is [Assembly Namespace].[Classname], [Assembly Namespace] for the serviceAuthorizationManagerType value. Here is the configuration I used:

<serviceBehaviors>
  <behavior name="SecureRESTSvcTestBehavior">
    <serviceMetadata httpGetEnabled="false" 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"/>
    <serviceAuthorization serviceAuthorizationManagerType="RESTfulSecurityIIS.CustomAuthorizationManager, RESTfulSecurityIIS" />
  </behavior>
</serviceBehaviors>

Next, let's build out our class that will override the 'CheckAccessCore' method. This allows us to intercept calls early in the call stack and decide after analyzing things like the user context or request headers if we want the call to succeed. This method simply returns a Boolean. Returning 'false' will prevent the call from continuing. The code I use below is not completely filled out for production. You probably want to test to see if the header contains "Basic" within 1st, and also make sure all the credentials are supplied. If not, returning a proper .NET exception would be in order. Here is the code I used:

protected override bool CheckAccessCore(OperationContext operationContext)
{
    //Extract the Authorization header, and parse out the credentials converting the Base64 string:
    var authHeader = WebOperationContext.Current.IncomingRequest.Headers["Authorization"];
    if ((authHeader != null) && (authHeader != string.Empty))
    {
        var svcCredentials = System.Text.ASCIIEncoding.ASCII
                .GetString(Convert.FromBase64String(authHeader.Substring(6)))
                .Split(':');
        var user = new { Name = svcCredentials[0], Password = svcCredentials[1] };
        if ((user.Name == "user1" && user.Password == "test"))
        {
            //User is authrized and originating call will proceed
            return true;
        }
        else
        {
            //not authorized
            return false;
        }
    }
    else
    {
        //No authorization header was provided, so challenge the client to provide before proceeding:
        WebOperationContext.Current.OutgoingResponse.Headers.Add("WWW-Authenticate: Basic realm=\"MyWCFService\"");
        //Throw an exception with the associated HTTP status code equivalent to HTTP status 401
        throw new WebFaultException("Please provide a username and password", HttpStatusCode.Unauthorized);
    }
}

Looking above, I siphon out the "Authorization" request header value to inspect. This is just a Base64 encoded string, so we can just convert it back. This is the very reason why we need to secure our service with a SSL certificate because the credentials are not secure. Once I parse out the username and password I can use the same tests I did before when using a custom username/password validator for self-hosted services. You can use the identical test calling code that I used in the last post to add the basic authentication credentials to the request header.

HttpWebRequest req = (HttpWebRequest)WebRequest.Create(@"https://DevMachine1234:8099/MyRESTServices/Customer/1");
//Add a header to the request that contains our credentials
//DO NOT HARDCODE IN PRODUCTION!! Pull credentials real-time from database or other store.
string svcCredentials = Convert.ToBase64String(ASCIIEncoding.ASCII.GetBytes("user1"+ ":" + "test"));
req.Headers.Add("Authorization", "Basic " + svcCredentials);
//Just some example code to parse the JSON response using the JavaScriptSerializer
using (WebResponse svcResponse = (HttpWebResponse)req.GetResponse())
{
  using (StreamReader sr = new StreamReader(svcResponse.GetResponseStream()))
  {
    JavaScriptSerializer js = new JavaScriptSerializer();
    string jsonTxt = sr.ReadToEnd();
  }
} 

At this point we have the Basic Authentication credentials coming into our service and we are providing authorization based on the outcome. However, like I mentioned prior we now are responsible for enforcing Basic Authentication to be used. The way we can do this is to send a response header prompting for credentials (which will happen in a browser) if they are not provided. In our code above, we are alerted of this condition when the Authorization header is not present. This in turn sends the client back a challenge for credentials. After submitting valid credentials, they will be authorized to our service. Just keep in mind again, since we are handling all authentication and enforcement of security mode in Basic Authentication, you will configure IIS to use "Anonymous Authentication."


So we still can use Basic Authentication with IIS hosted REST services using the webHttpBinding. Once this all sinks in and you test the code, you will see how all the parts come together. You have a choice at least with self-hosting or IIS with REST services and in both environments we have workable options. Since Basic Authentication is a HTTP standard widely known, and not some specific .NET practice or implementation, it is an obvious choice for securing your services. I would have to believe there be some improved support for WCF REST services in IIS going forward, but in the meantime we do have legitimate workable solutions for this hosting scenario.

Friday, June 1, 2012

RESTful Services: Authenticating Clients Using Basic Authentication

Security is important... period. There is no getting around it and we should all have it in mind when developing services of any type. So today I want to speak to the 1st of 2 different mainstream methods used for authenticating client calls to your WCF RESTful service. This post will expand on my last post here titled: Creating a WCF RESTful Service And Secure It Using HTTPS Over SSL. Keeping in the same genre of services types as before, I am speaking about WCF RESTful Services hosted on the internet and authentication methods prominent to this type of scenario. For intranet based RESTful services, you can employ the help of Windows based authentication to authenticate clients inside a Windows domain. However with the popularity of exposing data in a RESTful manner via the internet and the lack of built in security (as opposed to the cradle that Windows can be), I am keeping this focus to the services exposing data for internet scenarios.

In my last post I showed that once you secured the service using a SSL certificate, you could now view a security context when debugging. This is important because now we need to populate that context so we can determine if we want to allow the client to be authenticated to the service, and then check to see if they are authorized for whichever method or operation they have requested.

Once again we can fall back to our knowledge of the web in general for this configuration. Basic Authentication is nothing new to RESTful or even WCF services in general. It is a 401 HTTP challenge/response mechanism to prompt the client for credentials. As we also know, 'Basic' authentication can get a black-eye because it is just a base64 encoded non-encrypted string that is not natively secure, unless used in conjunction with a SSL certificate to secure the transport of this sensitive information.

From my last post we configured a simple REST service using a security mode of 'Transport' with a SSL certificate, and we now need to configure the clientCredentialType attribute. If we add a <transport> element within our existing <security> parent element, we can select Basic as our clientCredentialType. Notice there are several options for this attribute and you can read about all of them here: HttpClientCredentialType Enumeration. You might be wondering about 'Digest' as the security mode, but it is not actually that much more secure than 'Basic' and requires the hosting server to be joined to a domain. As for the others like Windows and NTLM they are good in intranet or extranet hosted scenarios. The 'None' option is the default option, but the whole point of this conversation is about securing our service, so we don't want to use that. The 'Certificate' option will be the focus of my next post on another mainstream way to secure our internet facing RESTful service. Our focus continues to be on using Basic authentication as displayed below:

<bindings>
  <webHttpBinding>
    <binding name="webHttpTransportSecurity">
      <security mode="Transport">
        <transport clientCredentialType="Basic"></transport>          
      </security>
    </binding>
  </webHttpBinding>
</bindings>

Our next step is to configure the service to point to a custom user name and password validator method that we will create shortly. Within our <serviceBehaviors> element we can configure the <servicecredentials> element and dictate that we want to use a Custom 'userNamePasswordValidationMode' value. We need to do this so we can intercept the credentials provided by the client via the request message header.

<serviceBehaviors>
  <behavior name="SecureRESTSvcTestBehavior">
    <!-- To avoid disclosing metadata information, set the value below to 
         false and remove the metadata endpoint above before deployment -->
    <serviceMetadata httpGetEnabled="false" 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="false"/>

    <serviceCredentials>
      <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="RESTfulSecuritySH.CustomUserNameValidator, RESTfulSecuritySH" />
    </serviceCredentials>

   </behavior>
</serviceBehaviors>

Notice above that I have already provided a name for the class which will intercept and validate these credentials: 'CustomUserNameValidator'. The overridden 'Validate' method in this class will allow us to check if the user accessing our service is going to be authenticated. In the call stack, this method we are going to create will be called prior to the method being requested, so if authentication fails it will happen prior to accessing anything else inside the service. This code snippet that will follow is a close derivative to one that came from the MSDN (here: http://msdn.microsoft.com/en-us/library/aa702565.aspx).

public class CustomUserNameValidator : UserNamePasswordValidator
{
  // This method validates users. It allows in two users, user1 and user2
  // This code is for illustration purposes only and 
  // must not be used in a production environment because it is not secure. 
  public override void Validate(string userName, string password)
  {

    if (null == userName || null == password)
    {
      throw new ArgumentNullException("You must provide both the username and password to access this service");
    }

    if (!(userName == "user1" && password == "test") && !(userName == "user2" && password == "test"))
    {
      // This throws an informative fault to the client.
      throw new FaultException("Unknown Username or Incorrect Password");
      // When you do not want to throw an informative fault to the client,
      // throw the following exception.
      // throw new SecurityTokenException("Unknown Username or Incorrect Password");
     }
  }
}

Looking at the code above we see that we are able to inspect the username and password values to authenticate a user to the service. At this point you are seeing that this is preforming service level authentication and is more coarse grained than some of the method level authorization we will see in a minute. The point of this code is to validate if the client making the call has access to your service.

It should go without saying that you would not use the simplistic implementation from the code above. More than likely, you would probably make a call to a database to validate if the user's credentials are valid as opposed to hardcoding the logic. If the credentials are validated, control will pass on to the originally requested method. The 'Validate' method is void so there is nothing to set or return once authorized. It's a 'no news is good news' type of functionality, where exceptions should be raised only when there is an authentication issue.

This custom method of authenticating users is different as opposed to those of you that have overridden the 'CheckAccessCore' when using a defined 'serviceAuthorizationManagerType' that returns a bool indicating if the user is authorized. Since we are validating the username and password, configuring a value for the 'customUserNamePasswordValidatorType' is exactly what we need.

At this point test out what we have done, by starting your service (e.g. WCF Test Client) and make a call to the 'Customer' method as we built in my last post. This time we will be prompted for credentials by the browser.


Upon entering the correct credentials (username = "user1", password = "test") we get the returned JSON results expected. All of this authentication happened securely because our RESTful service is secured with a SSL certificate. Also note these credentials can be assigned programmatically in whatever language you are using. The beauty of REST services is they are platform and language agnostic and rely on the standards of the web and HTTP. If you happen to be a .NET client calling the service, then you would add the credentials to the request header as shown below:

HttpWebRequest req = (HttpWebRequest)WebRequest.Create(@"https://DevMachine1234:8099/MyRESTServices/Customer/1");
//Add a header to the request that contains our credentials
//DO NOT HARDCODE IN PRODUCTION!! Pull credentials real-time from database or other store.
string svcCredentials = Convert.ToBase64String(ASCIIEncoding.ASCII.GetBytes("user1"+ ":" + "test"));
req.Headers.Add("Authorization", "Basic " + svcCredentials);
//Just some example code to parse the JSON response using the JavaScriptSerializer
using (WebResponse svcResponse = (HttpWebResponse)req.GetResponse())
{
  using (StreamReader sr = new StreamReader(svcResponse.GetResponseStream()))
  {
    JavaScriptSerializer js = new JavaScriptSerializer();
    string jsonTxt = sr.ReadToEnd();
  }
} 

Now try entering incorrect credentials (in code or in a browser) and make the same REST call. This time as expected and exception is thrown, the client receives a HTTP 403 Forbidden, and we are not permitted to view the results or access the service.


The next and final step here is to take the provided client context a step further with authorization at the method level. The reason for doing this is to offer fine grained security at the method level. For example if you are hosting a RESTful weather service with 10 methods, but only 7 of the methods are served up to everyone and the remaining 3 are for paid subscribers only. In this case we need to preform authorization at the method level.

Remember from my last post I mentioned the importance of the 'ServiceSecurityContext' object. Here is where it will come into play. This is populated with the client's context after being validated by our custom 'Validate' method. Within the ServiceSecurityContext instance the 'PrimaryIdentity' is populated with an instance of System.Principal.Identity.GenericIdentity that contains the properties we need to determine if this user is authorized to the requested method.


The code below will examine this instance and determine if the call can proceed:

//NOTE: This code is within the actual method call (e.g. GetCustomer CLR method)


//Get current SecurityContext to inspect below for authorizing
ServiceSecurityContext securityCtx;
securityCtx = OperationContext.Current.ServiceSecurityContext;

//This code is a bit primitive and ideally you would call off to another method here that would 
//perform the logic and probably just return a bool value as in commented out line below:
//if (CheckIfAuthorized(securityCtx) != true)
if ((securityCtx.PrimaryIdentity.IsAuthenticated != true) || (securityCtx.PrimaryIdentity.Name != "user1"))
{
   throw new UnauthorizedAccessException("You are  permitted to call this method. Access Denied.");
}

If you use the "user1" account you can see that we are indeed both authenticated to the service and authorized to call this method. However, now try and log back into the service with the "user2" account. This account is authenticated to make calls to the site, but not authorized to call this method. Once again you would not hardcode this logic, but rather be calling out to a security file or database to determine the authorization for this user and returning a bool more than likely. This provides that method level fine grained security that many services require.


So to wrap this up, you can implement a well know HTTP authentication method in 'Basic' authentication to secure your RESTful services. We can then take the context of the authenticated client call a step further and implement fine grained authorization at a method level to limit access to methods when needed. By using a well know security protocol that has been secured with SSL over HTTPS, you will broaden your services use and popularity using well know security practices.

Thursday, May 24, 2012

Creating a WCF RESTful Service And Secure It Using HTTPS Over SSL

Well I have had a few posts now on security, and focused some specifically on HTTPS and WCF. One of the most popular types of services we can create using WCF are RESTful services. The REST architecture and RESTful services have become so popular due to their inherent flexibility and being more consumer and platform agnostic as opposed to their WCF SOAP WS-* counterparts. However with this popularity and quickly expanding use we must not forget about securing our RESTful services especially when exposing them for wide use on the internet. Since REST services communicate over HTTP, we can leverage our existing knowledge and security principals we use for traditional websites that communicate over HTTP.

I wanted to highlight a few options for securing and authenticating to RESTful services using WCF in some upcoming posts. This 1st one will speak to securing the pipeline that REST services communicate over which is HTTP.

As we all know (or if not, now you do!) you can secure the communication over HTTP by using a SSL certificate. This is the 1st step in securing the data being communicated from the client and our RESTful service. Let's begin by looking at our simple ServiceContract. It contains a GET method defined with a CLR name of 'GetCustomerData' being exposed as the noun 'Customer' to adhere to REST architecture standards:

namespace RESTfulSecuritySH
{
   [ServiceContract]
   public interface ISecureRESTSvcTest
   {

     [OperationContract]
     [WebInvoke(Method = "GET",
                ResponseFormat = WebMessageFormat.Json,
                UriTemplate = "/Customer/{CustID}")]
     Customer GetCustomerData(string CustID);
   }
}

Behind the scenes the implemented code is returning the ID provided along a 'Customer' data contract with a some fake customer data. Obviously in a real implementation we would be connecting to a data repository to get this information, but for this example we will just hardcode values to be returned as security is the focus here and not the service implementation details.

namespace RESTfulSecuritySH
{
  public class SecureRESTSvcTest : ISecureRESTSvcTest
  {
     public Customer GetCustomerData(string CustID)
     {

        Customer customer = new Customer()
        {
          ID = CustID,
          FirstName = "John",
          LastName = "Smithers",
          PhoneNumber = "800-555-5555",
          DOB = "01/01/70",
          Email = "jsmithers@fancydomain.com",
          AccountNumber = "1234567890"
        };

        return customer;
     }
  }

  [DataContract]
  public class Customer
  {
     [DataMember]
     public string FirstName { get; set; }
     [DataMember]
     public string LastName { get; set; }
     [DataMember]
     public string PhoneNumber { get; set; }
     [DataMember]
     public string DOB { get; set; }
     [DataMember]
     public string Email { get; set; }
     [DataMember]
     public string ID { get; set; }
     [DataMember]
     public string AccountNumber { get; set; }
  }
}

The default configuration for this service uses the webHttpBinding as required for RESTful services created using WCF. This configuration is for a self-hosted service as it provides a *baseAddress* value. This identical configuration could be used for an IIS hosted service. Just keep in mind the *baseAddress* will be ignored and replaced by the virtual directory structure set up in IIS.

<system.serviceModel>
  <services>
    <service behaviorConfiguration="SecureRESTSvcTestBehavior" name="RESTfulSecuritySH.SecureRESTSvcTest">
        
      <host>
        <baseAddresses>
          <add baseAddress="http://DevMachine1234:8099/MyRESTServices/"/>
        </baseAddresses>
      </host>

      <!--webHttpBinding allows exposing service methods in a RESTful manner-->
      <endpoint address=""
        binding="webHttpBinding"
        behaviorConfiguration="webHttpBehavior"
        contract="RESTfulSecuritySH.ISecureRESTSvcTest" />

      <endpoint address="mex"
        binding="mexHttpBinding"
        contract="IMetadataExchange" />

    </service>
  </services>
  <behaviors>
    <serviceBehaviors>
      <behavior name="SecureRESTSvcTestBehavior">
        <serviceMetadata httpGetEnabled="true"/>
        <serviceDebug includeExceptionDetailInFaults="false"/>
      </behavior>
    </serviceBehaviors>

    <!--Required default endpoint behavior when using webHttpBinding-->
    <endpointBehaviors>
      <behavior name="webHttpBehavior">
        <webHttp/>
      </behavior>
    </endpointBehaviors>

  </behaviors>

</system.serviceModel>

At this point if we start our service using the WCF Test Client (if trying this locally), and then call the RESTful URI http://DevMachine1234:8099/MyRESTServices/Customer/8 to our service, you will get the JSON output (below) as expected (use Chrome, FF, or Safari to test. IE and Opera make you open a separate file). 'DevMachine1234' is the name of my dev box and eventually will be the name that needs to match up with the one provided to the SSL certificate which we will discuss in a moment.

{"AccountNumber":"1234567890","DOB":"01\/01\/70","Email":"jsmithers@fancydomain.com","FirstName":"John","ID":"8","LastName":"Smithers","PhoneNumber":"800-555-5555"}

OK, simple enough but notice there is data here that really is sensitive. The structure and design of our Customer data contract is not the focus of this post and is a flattened view of example customer data, but regardless some of it is sensitive. Let's now secure the transmission of this data over HTTPS using a SSL certificate.

For this example I am going to use a self-signed certificate I created locally and assign it on my machine to port 8099. I have (2) posts already that explain how to do this: Create A Self-Signed SSL Certificate Using IIS 7 and Applying and Using a SSL Certificate With A Self-Hosted WCF Service.

Let's focus on the configuration changes that had to be made. Now depending on how you decide to host your WCF service there may be subtle differences in the configuration. Also I should mention here that all of the configuration can be done in code if you chose to do so. I typically prefer configuration 1st, and only rely on using code to configure and run my service if there are elements that could be different at runtime and the configuration needs the flexibility of being dynamic. If this is not the case, I lean toward configuration because of its on-the-fly configurability and ease of reading. This is one case where either method works fine.

If using IIS to host your service, the certificate can be added through the IIS Management console and applied to the site instead of using the command line netsh.exe tool for self-hosted services. The 1st configuration change is to update the base address if you are using a self-hosted service to HTTPS:

<add baseAddress="https://DevMachine1234:8099/MyRESTServices/"/>

Next we must add a bindingConfiguration value to our endpoint as shown below:

<endpoint address=""
     binding="webHttpBinding"
     bindingConfiguration="webHttpTransportSecurity"
     behaviorConfiguration="webHttpBehavior"
     contract="RESTfulSecuritySH.ISecureRESTSvcTest" />

We must also add in this new binding configuration section. If you add a bindings section at the root of the system.serviceModel section, we can configure the security to be "Transport". When using Transport security with WCF, it automatically expects we want to use HTTPS for our endpoint. There are (3) different modes in the enumeration for the security element: None, Transport, and TransportCredentialOnly. 'None' indicates there is no required security on the endpoint, 'Transport' indicates we want to secure our endpoint with a SSL certificate using HTTPS, and 'TransportCredentialOnly' provides HTTP-based client authentication only and does not provide message integrity and confidentiality. The new endpointConfiguration is below:

<bindings>
  <webHttpBinding>
    <binding name="webHttpTransportSecurity">
      <security mode="Transport" />
    </binding>
  </webHttpBinding>
</bindings>

Next within the service behavior we must enable HTTPS and disable HTTP. This way our RESTful service can only be accessed via HTTPS. This is a very important step if you intend to have your service only accessed in a secure manner. Otherwise you leave the door open to still access it via HTTP. This may be an OK scenario if hosting non-secure data that you want to be able to be accessed via HTTP or HTTPS, but otherwise it should only be one or the other.

<serviceMetadata httpGetEnabled="false" httpsGetEnabled="true"/>

Lastly, we need to update the metadata publishing endpoint to use HTTPS as well:

<endpoint address="mex"
  binding="mexHttpsBinding"
  contract="IMetadataExchange" />

At this point restart your service. If you encounter any errors, it is probably because the SSL certificate does not match the name of your service, the SSL cert has not been applied correctly to the port (self-hosted services only), or the all the configuration updates were not made correctly. If you completed everything successfully, you can now access your site at the following URL: https://DevMachine1234:8099/MyRESTServices/Customer/8

Now try opening a new browser and access it via HTTP; it will not work and this is what we wanted. We have now secured our RESTful service's communication.

One last big ticket item here that will set me up for my next posts on securing RESTful services has to do with the security context before and after securing our service. This will ultimately allow us to authenticate our users and move forward with security. Either debugging the RESTful call to your existing 'GetCustomer' method or from a new call that simply returns a string, try looking at the following lines of code:

//Look at the ServiceSecurityContext both using secured and non-secured service configurations:
ServiceSecurityContext svcSecurityContext;
svcSecurityContext = OperationContext.Current.ServiceSecurityContext;


Notice how if you run your service without Transport security using HTTPS, the ServiceSecurityContext instance will be 'null'. However once we secure our service, this instance will have value. Specifically if you look at the .IsAnonymous property, you will notice it is now = "true" upon securing our service.


We will work on populating this value in my next post and moving forward to authenticating the client.

Wednesday, February 8, 2012

Applying and Using a SSL Certificate With A Self-Hosted WCF Service

(Please read my 1st post on this topic called Create A Self-Signed SSL Certificate Using IIS 7 if you need to know how to create a self signed SSL certificate)
If you create enough WCF services eventually you are probably going to need to self host your WCF Service as opposed to using IIS. The most common way of doing this is probably a Windows Service which is a great environment to host WCF services as they automatically begin and end with the server and OS being up or down and are always running in the background.

However when using a Windows Service you might find it is not as straight forward to use a SSL certificate with your exposed WCF service. This is true as there is no wizard style interface for applying SSL certificates to Windows Services like IIS provides, however after following the steps outlined here you will see that it is not so bad. Overall the process is easy to repeat for multiple services and ports once you are used to doing it.

The 1st step is to configure your WCF service to use a binding and configuration that supports HTTPS and SSL. For this example, we will use a simple WCF service that uses the 'basicHttpBinding' configuration. As with any WCF configuration, remember the references to the contract Interface and implementing class are case sensitive so if you run into any errors check your spelling. The main configuration changes to allow HTTPS on the service are to change the metadata publication binding to 'mexHttpsBinding' and by setting 'httpsGetEnabled' to 'true' on the service behavior. The SSL is handled by transport-level security using certificates. The entire service configuration is below:
 <system.serviceModel>

<!--WCF Services Defined-->
<services>
<service name="WcfServiceTest.MyWCFService"
behaviorConfiguration="MyWCFServiceBehavior">
<endpoint address=""
binding="basicHttpBinding"
bindingConfiguration="BasicHttpSSLBinding"
contract="WcfServiceTest.IMyWCFService" />
<endpoint address="mex"
binding="mexHttpsBinding"
contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="https://DevMachine1234:8050/WCFServices/MyWCFService" />
</baseAddresses>
</host>
</service>
</services>

<!--WCF Service Behavior Configurations-->
<behaviors>
<serviceBehaviors>
<behavior name="MyWCFServiceBehavior">
<serviceMetadata httpsGetEnabled="true" httpGetEnabled="false" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>

<!--WCF Service Binding Configurations-->
<bindings>
<basicHttpBinding>
<binding name="BasicHttpSSLBinding">
<security mode="Transport" />
</binding>
</basicHttpBinding>
</bindings>

</system.serviceModel>
Notice the 'baseAddress' value I used. The most important part here is that the host name of the service must match that of the SSL certificate I bind to the port selected. In my instance the machine name is 'DevMachine1234' and so is the name of my SSL certificate. You can actually create a SSL certificate named 'localhost' if you prefer and use that instead. If this is a true production service and you make the service address MyWcfService.com, then you will need to get a SSL cert with a matching name from a provider like Verisign or GoDaddy. Test this all and have a complete understanding before spending money on SSL certificates; no use wasting money on a misunderstood process.

Also notice I selected port '8050'. This is arbitrary, but remember there are certain port restrictions, and only 1 SSL certificate can be bound to any single port. We now need to apply the SSL certificate for our service (we are using a self-signed certificate for testing purposes) to the 8050 port before we can test our service.

The 1st thing we need is the Thumbprint value from the SSL certificate. We can use IIS to look at the installed SSL cert and grab the thumbprint value. Open up IIS, and select 'Server Certificates'. Double-click on the appropriate SSL certificate and go to the details tab. Scroll to the bottom and find the 'thumbprint' value of the certificate. Copy it out from the 1st character to the last into notepad and remove all spaces. Take caution to not copy the 1st space as it will translate into a '?' (question mark) when pasted into the command window to apply the SSL certificate in a later step. Save this for the next step.


Begin by clicking on the 'Start' button in windows and type in 'CMD' in the search box but do not press enter yet. Right-click the 'cmd' program and select 'Run as administrator' as shown below. This ensures we add the SSL certificate to the port with proper rights.


We need to use the 'netsh' tool (replacement in W2K8 and Windows 7 for the old httpcfg.exe tool) to apply the SSL certificate. We need the certificate thumbprint (gathered above) and an application ID value. The easiest way to get the 'appid' value is to use the GUID in the 'AssemblyInfo' file for the WCF project as pictured below. Copy it out as well and have ready for applying to the command window in the next step.


The command to add the SSL certificate to the port we configured in our WCF service is as follows:

netsh http add sslcert ipport=0.0.0.0:8050 certhash=3e49906c01a774c888231e5092077d3d855a6861 appid={2d6059b2-cccb-4a83-ae08-8ce209c2c5c1}

After applying the command and pressing enter you should see a message that the certificate was successfully added.


If you want, you can verify it has been added and view any SSL certificate that has been applied by entering the following command:

netsh http show sslcert

You will see the command window output in groups displaying any SSL certificates that have been applied as shown below. Notice you can see the SSL certificate 'hash' value which is the thumbprint value we used.


If you were doing this process in a production environment or on a remote server, make sure to apply the appropriate SSL certificate that has been imported and installed on the server 1st, to the port you need prior to starting the Windows Service (it actually will not work without it).

At this point we are ready to start our service on our local machine. In VS.NET I set my service (not the host in this instance) to be the startup project. I then begin debugging. You will notice the 'WCF Test Client' tool will pop-up and display all locally hosted services. This is probably were most folks will encounter some errors. Read the error description because they are typically meaningful and give direction on what to fix. Odds are it is caused by the SSL certificate not being applied to the same port configured, a mismatched name on the certificate to the service's domain name, or a mistake in configuration. Go over all steps again to make sure everything is correct. As you can see below our WCF service exposed via a HTTPS endpoint is up and running.


The last step to verify everything is working properly is to copy the address of the locally hosted service and consume it in another test application.

Add the copied address as a service reference to the project and make sure you do not receive any exceptions.

The successfully added service will be shown in Solution Explorer with the name you provided.


My recommendation is to get all of this working as I did in a local test environment 1st and understand all of the pieces. For those totally new to WCF it can be a lot to digest and fixing problems can take time and a deeper understanding of WCF so be patient.

For more information on the other commands available to the netsh.exe command line tool (like removing SSL certificates from a port), please see the following reference:

Wednesday, September 21, 2011

Exposing Multiple Binding Types For The Same Service Class In WCF

Have you ever wanted to expose multiple binding types in WCF for the same service class? Well I have but it is not directly apparent on how to accomplish this. My thought was, “I have a single service and I want it to be consumable by both net.tcp and http bindings. Not a big deal, right?” Well in the end the code needed to make this happen is not all that complex, but getting to the solution took some work as usual.

My thought process initially was to try and figure out how to make the WCF configuration allow this condition with a single service, but this method has some side effects. My 1st attempt was to create a single service with multiple endpoints and mex configurations, with each endpoint configuration having a different binding type (http and net.tcp). This actually works, but comes along with a side effect which I did not care for. The problem was when a client would consume my service (either via net.tcp or https) both endpoint configurations were added to the client. This isn't a huge deal, but I wanted the service configurations to deploy independently to prevent any confusion. Also if the client requests only the http binding endpoint, then that is all I want them to get; not the net.tcp configuration as well or vice versa.

Next I wanted to try using (2) different service configurations within the same single WCF service. However, a WCF service class can at most be exposed once in configuration by a single service configuration. If you try and configure (2) separate services differing only in endpoint binding configuration but attempt to consume the same service class for both services, you are going to get an error. "A child element named 'service' with same key already exists at the same configuration scope. Collection elements must be unique within the same configuration scope". Simply changing the 'name' property on the service configuration is not an option, because the 'name' property represents the class that implements the service contract. Arbitrarily changing the name will break the service.

The solution I came up with that solves all of these requirements is to have the single main service class that contains the implemented logic, Implement (2) additional new Interfaces that will allow distinction or uniqueness for the endpoint contract configuration. We will also add (2) new service contract classes that inherit the main service class and provide uniqueness for service class configuration. This masquerade allows making the services appear to be unique in consumption, but really point back to the same logic which was what was the original requirement.

As I mentioned before I do not want to expose multiple endpoints from a single service implementing a single contract due to the unwanted side effects, but rather have multiple services each with a single endpoint, implementing the same contract. To do this each service needs to be unique, but when attempting to make separate services each serve up the same service class implementing the contract, there is no uniqueness. The 'ServiceEndpointElement.Name Property' in configuration must point to a class within the service. Because we want (1) unique endpoint per service, we need a unique service class as well. The new classes Inherit from the primary Service class providing all the main service functionality, but yet provides a unique service class entry point for the ServiceEndpointElement.Name Property. Again, the reason we do not want a single service exposing multiple bindings, is because upon client consumption all (1...n) binding configurations for a single service are downloaded and configured even if the client only wanted say the 'net.tcp' binding. To reduce confusion, each service configured ultimately exposes the identical functionality but provides a separate service class value for the ServiceEndpointElement.Name Property.

Let's take a look at how to implement this solution. To begin, here are the (3) main service contracts:
<ServiceContract()>
Public Interface IMyWcfServiceTcp
Inherits IMyWcfService

End Interface

<ServiceContract()>
Public Interface IMyWcfServiceHttp
Inherits IMyWcfService

End Interface

<ServiceContract()>
Public Interface IMyWcfService

<OperationContract(Name:="MyMethod1")>
Sub MyMethod1()

<OperationContract(Name:="MyMethod2")>
Sub MyMethod2()

<OperationContract(Name:="MyMethod3")>
Sub MyMethod3()

End Interface
Next are the (3) classes which WCF configuration will use in the service configuration:
Public Class MyWcfServiceTcp
Inherits MyWcfService

End Class

Public Class MyWcfServiceHttp
Inherits MyWcfService

End Class

Public Class MyWcfService
Implements IMyWcfServiceTcp, IMyWcfServiceHttp

Public Sub MyMethod1() Implements IMyWcfService.MyMethod1
End Sub

Public Sub MyMethod2() Implements IMyWcfService.MyMethod2
End Sub

Public Sub MyMethod3() Implements IMyWcfService.MyMethod3
End Sub

End Class
And finally, here is the WCF service configuration:
<!--*****WCF Hosted Service Endpoints*****-->
<services>
<service behaviorConfiguration="MyWcfServiceTcpBehavior" name="MyWcfServiceTcp">
<endpoint address="" binding="netTcpBinding" bindingConfiguration="MyWcfServiceTcpEndpoint"
name="MyWcfServiceTcpEndpoint" bindingName="MyWcfServiceTcpEndpoint"
contract="IMyWcfServiceTcp" />
<endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="net.tcp://localhost:8000/MyServices/MyWcfService" />
</baseAddresses>
</host>
</service>
<service behaviorConfiguration="MyWcfServiceHttpBehavior" name="MyWcfServiceHttp">
<endpoint address="" binding="wsHttpBinding" bindingConfiguration="MyWcfServiceHttpEndpoint"
name="MyWcfServiceHttpEndpoint" bindingName="MyWcfServiceHttpEndpoint"
contract="IMyWcfServiceHttp" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8001/MyServices/MyWcfService" />
</baseAddresses>
</host>
</service>
</services>
Notice how each service configuration points to its own class, and each endpoint points to its own individual contract. However we know under the covers, both services expose the identical functionality. The difference: choice of binding type, and ability to only get the single binding's configuration added to the client (not both types) upon consumption.

Take note - if having your client getting multiple binding configurations for requesting a single endpoint does not bother you then procedure is not needed. Just define a single service with multiple endpoint configurations and multiple mex endpoints and you are done. However, if exposing your service with multiple binding types and having the client only receive the single endpoints configuration is important, then this should help fulfill the requirement.

Tuesday, June 28, 2011

Create A Self-Signed SSL Certificate Using IIS 7

If you are a .NET developer that creates IIS or self-hosted WCF services, then you will probably have the need at some point to secure the transport with a SSL certificate if using a http binding type. If you have a WCF service hosted by IIS, applying a SSL certificate is a bit more trivial because the endpoint configuration does not dictate the URL. The virtual directory in IIS will create the URL for your endpoint. However, if you are hosting your WCF service in a Windows Service, you dictate the endpoint and applying the SSL certificate is a little more involved. Because of this you may want to create a self-signed SSL certificate while still in development to ensure that your 'https' endpoint works correctly. With IIS websites, legacy .asmx services, or WCF hosted services, applying a SSL certificate happens after the fact via IIS and the initial testing with a SSL certificate may not even be desired. Regardless of your situation, the following tutorial shown you a simple procedure to create a self-signed certificate on your local machine.

So what is a self-signed SSL certificate you may ask. A 'CA' or Certificate Authority is a trusted provided to generate a SSL certificate. Your local machine is a CA, but unfortunately and as expected the CA on your machine is not trusted (as should be) by any outside party, so any SSL certificate generated locally is good and trusted just there: locally! To get a SSL certificate generated by a trusted CA, you need to go to a commercial provider like 'GoDaddy' or 'Verisign' and purchase a SSL certificate. These Certificate Authorities are trusted on the internet and are able to provide SSL certificates with a set expiration time (i.e. 2 years out). Once applied, you can view the SSL certificate information of a secure site by pressing the secure lock icon in most browsers next to the URL, and will see who issued the SSL certificate, its expiration, and other public details like the public key.

If you happen to be on an Active Directory domain doing 'intranet' or internal software development, you may have a CA on the domain that will issue certificates which will be trusted within the domain. This is the way to go so one does not have to buy a GoDaddy or Verisign SSL certificate for every internal WCF service or hosted ASP.NET site. Check with your server folks (unless that's you!) to see if there is a CA that issues SSL certificates trusted by all on the domain.

If you don't have IIS7, generating a SSL certificate is still possible. You just do the similar steps under the 'Directory Security' tab in IIS for a given site. Using IIS to create the certificate does not mean we have to host our service in IIS. It just has a convenient 'wizard' style interface to generate certificates and place them in the proper 'stores'. You can manually decide which stores your certificate is placed in and trusted by using the Certificate Manager MMC snap-in. That is really off topic for this post, but good to see how local and purchased certificates are managed. The snap-in is not under the administrator tools by default so look to the following link if interested in adding or accessing this MMC utility:

How to Add Certificate Manager to Microsoft Management Console

To begin a new certificate request, open IIS7 and click on the root element which is your machine or server node. Locate the 'Server Certificates' icon and double click it:

On the right-hand side of the screen select the 'Create Self-Signed Certificate' link which will display the following dialog:

This is the important part which is dictating the friendly-name of your certificate. For local WCF development you really have (2) choices: name the certificate 'localhost' or the name of your machine. I recommend the name of your machine as it is more explicit. So in the example below my machine name is 'DevMachine1234'. The name is important for hosting WCF services and applying a SSL certificate to the exposed endpoint. If the SSL name does not match the domain of the hosted service it will not work. In the case of local development, name the certificate the same name as your machine.

After completing the request you will see the SSL certificate has been generated by the local machines CA, the friendly name, and the certificate hash.

The hash value will be important in the next post about applying this self-signed certificate to a port number that is dictated in the WCF configuration for a service hosted by a Windows Service. If you are applying the SSL certificate to a IIS hosted service or site, all you have to do is select it from the dropdown when configuring the 'https' binding in IIS7.