Showing posts with label REST. Show all posts
Showing posts with label REST. Show all posts

Thursday, May 9, 2013

Using Postman for Google Chrome to call REST and OData Services

A tool I heard mentioned at the recent online DotNetConf virtual conference and have begun using recently is the 'Postman' developer tool for Google Chrome. You can find it on the Chrome Store at the following URL: Postman for Google Chrome This tool is another client utility to make HTTP calls to REST based services. Open a new tab in Google and you will see it as an option to open:
Interestingly, the side chat for DotNetConf contained a brief conversation about Fiddler vs. Postman. Most folks were fond of Postman and preferred it over Fiddler for basic HTTP calls because of its refined and smooth interface (in fact I think these were the paraphrased sentiments of Scott Hanselman in the conversation). While Postman is not by any means a replacement for the rich feature functionality of Fiddler, it certainly has a bit more polished UI and easier to use for constructing basic GET and POST calls. If you are not doing any special debugging, I would probably use Postman 1st and Fiddler in other scenarios.

The main features I like about Postman are the following:
  • History of calls down the left-hand pane for easy access to recall recent GET, POST, etc.
  • Ability to add in Basic Authentication Headers in their raw form without having to Base64 encode them 1st (Postman will do this for you)
  • Simplicity to add custom headers
  • Ability to have the URL contain spaces instead of having to encode the query string with %20. This is key for creating OData calls using OData commands.
  • Smooth, refined, easy to use interface
Below are the security option tabs across the top of the product. Often you will use 'Normal' or 'Basic Auth'. Normal would be used if you are not adding any authentication information to the headers. 


Basic Auth is used when adding HTTP Basic Authentication information to the request headers. As you can see you can enter in the credentials directly without having to encode the information manually:


Once you press the 'Refresh headers' button, the encoded basic authentication information will be added for you! Saves a bit of time as opposed to having to do this through a site, test harness, or code. 

You can also easily add custom headers by simply typing in he 'Header' and 'Value' text boxes and again pressing the 'Refresh headers' button. It's nice and organized and makes sure the headers are added properly to the request and reduces chances you might add the header values incorrectly.


As far as using OData command parameter, notice in my query string how I do not have to encode the 'spaces' in the URL. The tool will construct and encode the URL for me, making writing OData queries much easier. You can add the commands directly to the URL or type them in the 'URL Parameter Key' and 'Value' text boxes:


One other nicety to mention is if constructing a traditional query string parameter, you can add those parameters easily too, and Postman will make sure the query string is constructed properly.


This was just a brief introduction to Postman, but I highly recommend it's usage for OData service calls or any other REST based calls. It makes constructing OData queries easier, and its user friendly interface is a great choice for traditional REST based calls.

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 = "[email protected]",
          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":"[email protected]","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.

Monday, April 30, 2012

Using WCF Data Services Tutorial - Part 1

With the recent release of WCF Data Services 5.0 a few weeks ago, I thought it would be a good idea to introduce the technology to those of you that have not seen it before. 

WCF Data Services for those of you used to creating traditional SOAP based or REST services using WCF has a different purpose and use. It builds upon the Open Data Protocol (OData) that Microsoft created to expose data as resources that are addressable by URIs. OData builds upon the AtomPub protocol to represent data in a standardized method and then makes it accessible via HTTP. Through REST based services you can access any type of data using the standard HTTP verbs (GET, POST, PUT, DELETE).

These services offer a powerful way to quickly expose your data as services without a lot of the manual work involved otherwise. In addition the services are customizable via service operations and interceptors. The OData protocol is something not confined to .NET either. The idea is an open protocol for exposing your data in a platform agnostic manner via HTTP. There are a slew of .NET OData client libraries that sit atop of data services for accessing the data, and there are even libraries in other languages like Java and its OData4J library.

So why is this good? Well 1st off we are exposing data using a known and standardized protocol in OData. Think of the alternative using a traditional WCF service with a webHttpBinding to create a RESTful service. You would be creating from scratch how your data is being exposed and only you and your clients understand this model; it is not a standard. If you being on new clients to consume your services, you have to explain (typically through documentation) on how your data looks when exposed. This is obviously not as easy as telling clients that your services expose data that is built upon the AtomPub format in OData which is a standard. The other main attraction of data services is how much custom and manual plumbing work that gets cut out and streamlines. As you will see below, in just minutes I can have my relational data exposed and accessible via HTTP in a RESTful manner via URIs mapped to my entities.

In my example I am going to expose some relational data via WCF Data Services from the 'AdventureWorks' database on my local SQL Server instance. I just want you to get up and running to see the possibilities, so we will go through all the steps to preform a simple GET on some of the entities we will expose.

First let's start off by creating an Entity Framework model for the  AdventureWorks database. If you want to follow along and do not have the Adventureworks database you can download it from CodePlex here: (http://msftdbprodsamples.codeplex.com/). Begin by going to 'Add -> New Item' and under the 'Data' category on the left select 'ADO.NET Entity Data Model'.


For this example I am using the AdventureWorks database, so I select 'Generate from database' and then navigate through the wizard to set up a connection, naming conventions (I use the default values for this example), and then I selected all the tables before completing the Entity Framework Model.


Now that our EF model is created, we can create our WCF Data Service. I have the new WCF Data Services 5.0 installed which is built upon the OData v3.0 specification, and you can download it from here as well: http://www.microsoft.com/en-us/download/details.aspx?id=29306 In Solution Explorer on your project, select 'Add -> New Item' and under the 'Web' category on the left select 'WCF Data Service (for OData v3)', or similar option if you have an older version of WCF Data Services installed.




This will create a new WCF Data Service with it's default class and 'InitializeService' method. On this class we must Implement the Entity Framework model we created earlier. The default line below instructs you to do so:
public class WcfDataService1 : DataService< /* TODO: put your data source class name here */ >
For this example let's Implement the 'AdventureWorksEntities' class we created earlier like below:
public class WcfDataService1 : DataService<AdventureWorksEntities>
The next step requires us to be explicit on which entities we want to expose and with what level of permissions too. Just to give you a feel of what the exposed data representation looks like in the browser, lets go ahead and expose all entities using the asterisk with 'AllRead' permission:
config.SetEntitySetAccessRule("*", EntitySetRights.AllRead);
Before viewing the data in the browser, I recommend selecting the browser for VS.NET to use to Google Chrome instead of IE. IE9 at least does not display AtomPub data properly (See UPDATE at the end of this post for using IE), and upon doing a GET on the entities you not be able to view the data. To do this, right-click the WCF Data Service item in Solution Explorer and select: 'Browse With...' as shown below. Select 'Google Chrome' and the browser will display all of the entities that have been exposed. You can also permanently switch the default browser used in this dialog as well by pressing 'Set as Default'







As you see above, all of the 'Collections' from our EF model are exposed. Let's go ahead and only expose the 'Employees' entity by modifying the code to look as follows:
//Only allow the Employees entity collection to be exposed:
config.SetEntitySetAccessRule("Employees", EntitySetRights.AllRead);

//
Now when run in the browser we see only the Employees collection is exposed. Let's explore and expose what information we can get back on this collection by modifying the URI. If I want to get back the Employee with ID '1', I can simply request this using the URI below:



Upon making the GET request, you can see that I get back all of the information just for the Employee with the ID of '1'. 


One other nice feature is the ability to query the entity with some predetermined query string options. For example, when we did a GET for the Employee with an ID=1, you could see there were some related entities 'Employee1' and 'Employee2'. If we use the 'expand' query string option, we can expand on this employee to see related entity information. Modifying the URI to be as follows to expand on the 'Employee1' many to many relationship:



Upon making the GET request with the expand query option you will see the additional related entity information. Try the same procedure for expanding on 'Employee2' to see additional related entity information.

So look at this - in just a few minutes we are up and running by exposing our relational data accessible via HTTP in a RESTful manner using a know open protocol. Pretty cool if you ask me, and even better - really useful. This has just barely scraped the surface of what can be done with WCF Data Services. In the future I will expand on this tutorial getting a little more in depth with some of the additional functionality offered.

UPDATE: To get IE to format the OData as XML, do the following:
  • Tools -> Internet Options
  • Select the Content Tab
  • Under 'Feeds and Web Slices', select 'Settings'
  • Under the 'Advance' section deselect 'Turn on Feed reading view'