Introduction

There are a lots of code examples of how to create REST services but there are few example of how to secure them. As security is one of the most important things when building any kind of system this should not be undermined. Most of those securing features when using WCF and REST are using SSL, some kind of custom implementations and/or using ASP.NET features. There were some attempts to create OAUTH channels for WCF REST services and there are many types of implementations out there nut the question is what to use, but this is not easy and it is very confusing. How can I (very simple) use for example OAUTH for my WCF REST services?

Handling security in RESTful applications can be done using transport security (SSL), message security (encrypting), authentication (signing messages, tokens) and authorization (which is controlled by service).

When using token based authentication (OAUTH) token is retrieved from service by sending user name and password to the service, in some cases one will also send secret key and/or application key.

If one will use WCF data services (formerly Astoria, ADO.NET data service) this could be done relatively easy but in this case we will try to create an secure WCF REST service using Azure AppFabric Access Control Service.

As we will use Azure AppFabric Access Control here are key features listed from codeplex, AppFabric Access Control:

  • Integrates with Windows Identity Foundation (WIF) and tooling
  • Out-of-the-box support for popular web identity providers including: Windows Live ID, Google, Yahoo, and Facebook
  • Out-of-the-box support for Active Directory Federation Server v2.0
  • Support for OAuth 2.0 (draft 10), WS-Trust, and WS-Federation protocols
  • Support for the SAML 1.1, SAML 2.0, and Simple Web Token (SWT) token formats
  • Integrated and customizable Home Realm Discovery that allows users to choose their identity provider
  • An OData-based Management Service that provides programmatic access to ACS configuration
  • A Web Portal that allows administrative access to ACS configuration

Implementation

Steps that we will perform will look like this:

  1. Configure Windows Azure Access Control via its portal.
  2. Create “secure” local WCF REST service using WCF REST service template and implement custom ServiceAuthorizationManager.
  3. Create test client that will authenticate and retrieve token from Access Control Service, which will be then used by WCF REST service to validate calls. This can be viewed in figure bellow.

image

    Figure 1: Secure WCF REST service with ACS.

Configure Windows Azure Access Control (Define rules, keys, claims)

Administrator will register claims and keys with ACS management service or through Management Portal. ACS will be the one who takes care of safety and will sign all tokens with key that is generated in the ACS.
WCF service has key which is used to validate token received from the client.

I will go through all step to configure ACS via management portal, this can also be viewed in the ACS labs on the codeplex, otherwise go to step 2.

  1. Log in to https://portal.appfabriclabs.com
    ACS1
  2. By pressing project name one will be able to Add Service NameSpace (new page).
    ACS2
  3. Then pressing Access Control link
    ACS3
  4. By pressing Manage button we will be redirected to the Access Control Service main menu. Here we can administrate TOKENS, certificates, groups, claims, and so on.
    ACS4
  5. Press  Relaying Party Applications and Add Relaying Party Application to configure Relaying party (WCF REST Service).
    Here we are going to configure service endpoint which will be “secure”.
    a) Write Name of the Service under Name.
    b) Write URL of the service that will be “secure” (in our case local service)
    c) Under token format I have changed SAML 2.0 to SWT (optional).
    d) Under Identity providers unselect Windows Live ID
    e) Under Token Signing Options press generate to generate new Token signing key, which will be used by our service, so you can copy now this token or take it later.
    ACS12
  6. Press Save and go back to main menu (Look at image under 4.). Press Rule Groups and there should be Default Rule Group for WCF Rest Azure Service(one we created in previous step).
    a) Press  Default Rule Group for WCF Rest Azure Service (or you relaying part name).
    ACS13
    a) Press Add Rule
    ACS14

    b) After pressing Add Rule you will be redirected to another page there you can choose Access Control Service under Claim Issuer. All other can have default values.
    ACS15
  7. Last step if to create an Identity for service that client(consumer) will be using. In main menu (under 4.) press Service Identities and then Add Service Identity. This service identity name will be then used as a login name in the client code. Press Save.
    ACS10
  8. Finally Press Add Credentials and write name and password then save.
    ACS11

Now we can work with our service code. This configuration can also be done programmatically. More information can be found at http://acs.codeplex.com.

Creating Secure WCF REST Service

Create new Windows Azure Cloud Service and add Wcf Web Role. I have used new WCF REST template for that.

In Web.config add values for:

  • Service Namespace (which we created under point 2), in my case armanwcfrest.
  • Hostname for acs.
  • Signing key which we have generated (under point 5-e)
<appSettings>
    <add key="AccessControlHostName" value="accesscontrol.appfabriclabs.com"/>
    <add key="AccessControlNamespace" value="armanwcfrest"/>
    <add key="IssuerSigningKey" value="yourkey"/>
  </appSettings>

Now we need to create custom Authorization manager to authenticate each call to our service. For that purpose we need to create custom class and inherit from SecurityAuthorizationManager.

ServiceAuthorizationManager is called once for each message that is coming to the service (message that service is going to process). ServiceAuthorizationManager will determine if a user can perform operation before the deserialization or method invocation occurs on service instance. For that it is more preferable than using PrincipalPermission which will invoke method and why do that if the user will be rejected. Another advantage of using ServiceAuthorizationManager is that can separate service business logic from authorization logic.

This custom class will do following things:

  • Override CheckAccessCore to check for Authorization HttpHeader
  • Check if that header begins with WRAP
  • Take access_token value and use TokenValidator class (help class provided in code) to validate token.
  • Return true if token validation succeded or false if not.
public class AccessControlServiceAuthorizationManager : ServiceAuthorizationManager
    {
        string serviceNamespace = ConfigurationManager.AppSettings.Get("AccessControlNamespace");
        string acsHostName = ConfigurationManager.AppSettings.Get("AccessControlHostName");
        string trustedTokenPolicyKey = ConfigurationManager.AppSettings.Get("IssuerSigningKey");
        string trustedAudience = "http://localhost:81/Service1/";

        protected override bool CheckAccessCore(OperationContext operationContext)
        {
            string headerValue = WebOperationContext.Current.IncomingRequest.Headers[HttpRequestHeader.Authorization];

            // check that a value is there
            if (string.IsNullOrEmpty(headerValue))
            {
                GenerateErrorResponse();
                return false;
            }
            // check that it starts with 'WRAP'
            if (!headerValue.StartsWith("WRAP "))
            {
                GenerateErrorResponse();
                return false;
            }
            string[] nameValuePair = headerValue.Substring("WRAP ".Length).Split(new char[] { '=' }, 2);

            if (nameValuePair.Length != 2 ||
                nameValuePair[0] != "access_token" ||
                !nameValuePair[1].StartsWith("\"") ||
                !nameValuePair[1].EndsWith("\""))
            {
                GenerateErrorResponse();
                return false;
            }

            // trim off the leading and trailing double-quotes
            string token = nameValuePair[1].Substring(1, nameValuePair[1].Length - 2);

            // create a token validator
            TokenValidator validator = new TokenValidator(
                this.acsHostName,
                this.serviceNamespace,
                this.trustedAudience,
                this.trustedTokenPolicyKey);

            // validate the token
            if (!validator.Validate(token))
            {
                GenerateErrorResponse();
                return false;
            }

            //VALID!
            return true;
        }
        public void GenerateErrorResponse()
        {
        //    WebOperationContext.Current.OutgoingResponse.StatusCode =
        //HttpStatusCode.Unauthorized;
        //    WebOperationContext.Current.OutgoingResponse.StatusDescription = "Unauthorized";
        }
    }

In Global.asax.cs I have created SecureWebServiceHostFactory that will be using AccessControlServiceAuthorizationManager class.

Global.asax.cs

 public class Global : HttpApplication
    {
        void Application_Start(object sender, EventArgs e)
        {
            RegisterRoutes();
        }

        private void RegisterRoutes()
        {
            // Edit the base address of Service1 by replacing the "Service1" string below
            var securewebServiceHostFactory = new SecureWebServiceHostFactory();
            RouteTable.Routes.Add(new ServiceRoute("Service1", securewebServiceHostFactory, typeof(Service1)));
        }
    }
    public class SecureWebServiceHostFactory : WebServiceHostFactory
    {
        protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
        {
            ServiceHost host = base.CreateServiceHost(serviceType, baseAddresses);
            host.Authorization.ServiceAuthorizationManager = new AccessControlServiceAuthorizationManager();
            return host;
        }

        public override ServiceHostBase CreateServiceHost(string constructorString, Uri[] baseAddresses)
        {
            ServiceHostBase host = base.CreateServiceHost(constructorString, baseAddresses);
            host.Authorization.ServiceAuthorizationManager = new AccessControlServiceAuthorizationManager();
            return host;
        }
    }

Client Code

  1. Client application will retrive token from Azure AppFabric Access Control Service for specific adress (URL).
  2. It will send message to our service with token inside Authorization header.
  3. Hopefully receive response.

Client.cs

        static string accessControlHostName = ConfigurationManager.AppSettings.Get("AccessControlHostName");
        static string accessControlNamespace = ConfigurationManager.AppSettings.Get("AccessControlNamespace");

        static void Main(string[] args)
        {
            Console.WriteLine("\nPress Enter");
            string valueToReverse = Console.ReadLine();

            string token = GetTokenFromACS("http://localhost:81/Service1/");
            string serviceResponse = SendMessageToService(token);

            Console.WriteLine("Service responded with: {0}\n", serviceResponse);
            Console.WriteLine("Press  to exit");
            Console.ReadLine();
        }
        private static string SendMessageToService(string token)
        {
            WebClient client = new WebClient();
            client.BaseAddress = ConfigurationManager.AppSettings.Get("ServiceAddress") + "123";
            string headerValue = string.Format("WRAP access_token=\"{0}\"", token);

            client.Headers.Add("Authorization", headerValue);

            var serviceResponseBytes = client.DownloadString(String.Empty);
            return serviceResponseBytes;
        }

        private static string GetTokenFromACS(string scope)
        {
            string wrapPassword = ConfigurationManager.AppSettings.Get("WrapPassword");
            string wrapUsername = ConfigurationManager.AppSettings.Get("WrapUsername");

            // request a token from ACS
            WebClient client = new WebClient();
            client.BaseAddress = string.Format("https://{0}.{1}", accessControlNamespace, accessControlHostName);

            NameValueCollection values = new NameValueCollection();
            values.Add("wrap_name", wrapUsername);
            values.Add("wrap_password", wrapPassword);
            values.Add("wrap_scope", scope);

            byte[] responseBytes = client.UploadValues("WRAPv0.9/", "POST", values);

            string response = Encoding.UTF8.GetString(responseBytes);

            Console.WriteLine("\nreceived token from ACS: {0}\n", response);

            return HttpUtility.UrlDecode(
                response
                .Split('&')
                .Single(value => value.StartsWith("wrap_access_token=", StringComparison.OrdinalIgnoreCase))
                .Split('=')[1]);

        }

Fiddler View client requesting token

Fiddler1

Client call with Authorization Token and response from the service.

Fiddler2

Resources:

More information about OAUTH, identity and access control in the cloud can be found in Vittorio Bertocci’s session at PDC 2010.

Documentation about OAUTH.

Rest libraries Hammonck, RestSharp, WCF Web API.

Source Code: RestService

Note: Many thanks to my friend Herbjörn for reviewing this post. Do not miss his presentation on Azure Summit 17-18 Nov (2010)
Posted by: dotnetninja | February 23, 2010

IOC (Inversion Control) With XAML

Today I have read an post about IOC and XAML or how to use IOC with XAML. Original post was on Rob Relyea’s blog with a couple of links to other approaches and resources. In that post there was nothing about MVVM (model view view model) and my first thought was to somehow use IOC to bind my viewmodels to the source in XAML.

After searching the web I did not found anything simple and straight forward to use. So that leads me to create something “simple” and possible useful.

Basic idea is to bind DataContext of the View to the ViewModel contract. Something like this, and magically resolve correct viewmodel implementation.

<UserControl x:Class="Module2.Views.LogListView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:viewmodels="clr-namespace:ModuleA.Log.ViewModels;assembly=ModuleA">
<UserControl.DataContext>
<viewmodels:ILogListViewModel/>
</UserControl.DataContext>
...
<Grid>
        <ListBox ItemsSource="{Binding ApplicationLogs}">
...

Simplest way to do this is to create an Converter (IValueConverter), bind source to the interface and resolve the implementation by using the converter.

public class ViewModelResolverConverter : IValueConverter
  {
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {

      if (value == null)
        throw new ArgumentNullException("value");

      IUnityContainer unityContainer = Module.MyContainer;

      var typeToResolve=Type.GetType(value.ToString());
      if(typeToResolve==null)
        return DependencyProperty.UnsetValue;

      var resolvedViewModel = unityContainer.Resolve(typeToResolve);
      if(resolvedViewModel == null)
        return DependencyProperty.UnsetValue;
      return ret;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
      throw new NotImplementedException();
    }
  }

In this case I am using Unity from Microsoft pattern and practices but you could use any type of the IOC.

ViewModel could look something like this

public partial class LogListAViewModel:BaseViewModel, ILogListViewModel
  {
    public LogListAViewModel()
    {
       ...
    }

    private bool _isSelected = false;
    public bool IsSelected
    {
      get { return _isSelected; }
      set
      {
        if (_isSelected != value)
        {
          _isSelected = value;
          OnPropertyChanged(()=>IsSelected);
        }
      }
    }
    public string Info
    {
      get { return "Log View"; }
    }
...
  }

And finally XAML

<UserControl x:Class="Module2.Views.LogListView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:converter="clr-namespace:ModuleA.Converters"
xmlns:viewmodelscontracts="clr-namespace:ModuleA.ViewModelContracts;assembly=ModuleA">
<UserControl.Resources>
<converter:ViewModelResolverConverter x:Key="viewModelConverter"/>
</UserControl.Resources>
<UserControl.DataContext>
<Binding Source="{x:Type viewmodelscontracts:ILogListViewModel}"
             Converter="{StaticResource viewModelConverter}" />

</UserControl.DataContext>
...
<Grid>
        <ListBox ItemsSource="{Binding ApplicationLogs}">
...

As the final word, I prefer use binding view to viewmodel mainly to not end with application that is unpredictable, too loosely coupled and fragile, but in some cases this could be useful.

Posted by: dotnetninja | January 7, 2010

Cloud Patterns in Windows Azure

Finally article about SOA design patterns with Windows Azure got published. Some of the coolest part with REST implementation (WCF REST starter kit preview 2, idempotent capability with etag,..) was left out but I will blogg try to about it and there is also REST implementation in the source code for the article which can be downloaded here.

Whole article can be found http://msdn.microsoft.com/en-us/magazine/ee335719.aspx.

Posted by: dotnetninja | March 22, 2009

Virtual Earth Map Control for Silverlight

Finally, it is here, VE map for Silverlight. It has bean rumors and talk about it for more about year, last thing I heard was that it will be released after the summer 2008 but nothing happened, so I thought it was just a rumor or MS team drop it. I have tested as it was releasd and its performance is much better than all others earlier SL maps I tested.
To download it or to see interactive SDK go to http://connect.microsoft.com.
Enjoy…

Posted by: dotnetninja | March 19, 2009

Pixel Shaders with Silverlight 3

Wow this was the thing I was waiting for but not so sone, as it was not a long ago it was added to WPF.

 

Also the news, YouTube using Silverlight to stream High Quality video check it out.

http://www.youtube.com/marchmadness

In some cases when opening documents (for example documents from SharePoint document library) and when client machine is running Windows XP (in my case) you will open document directly in web browser.
That is fine but what if you want to use full power of the client application like Word or Excel when working with that document?
There is simple solution for that.There are two ways. One is to change the registry key int the Windows registry, which is not recommended if you are helping someone to do it by him self and with little knowledge with Windows. Another one goes like this.

For each file type you want to open in client application you have to do small modification.

  1. Open Windows File Explorer.
  2. Select Tools, Folder Options.
  3. Folder Options

    Folder Options

  4. On the Folder Options window select File Type tab.
  5. File Type

    File Type

  6. Find file type you want to open in client application (for example DOC for Word or XLS for Excel).
  7. Unselect option Browse in same window.
  8. Browse in same window

    Browse in same window

  9. Press OK.
Posted by: dotnetninja | January 22, 2009

Windows Mobile is dead (yes I agree)

Mobile market is emerging and yet again Microsoft is failing to deliver. I came across post by Cringley stating that Windows Mobile will die and I totally agree but with correction: “Windows mobile is on the death-bed”.

Developers are fleeing Windows Mobile which is true as I have noticed that on mobile blogs that I follow.
Windows Mobile is ugly, it is slow, IE on the windows mobile!?! (I am using Opera mini),…

Before IPhone and Android, Windows Mobile (CE) was competing with Symbian (for how many years now?) and they could not win, so please can someone tell me how will the win now against IPhone with killer design and Googles Android. No chance.

Instead of laying off employees today Microsoft should invest and reallocate these people to work with new Mobile platform, because Mobile platform and mobile devices ARE the future. Do it now, or not now it is to late do it yesterday. Time is running out for Microsoft and I do not believe they are going to win here, especially not after building crappy mobile platform like they have now.

IPhone and Android are attracting people (read developers) and even I (hardcore MS dude) am looking how to, or which mobile platform to invest my time on. As I see now Android is the best choice.
It is open, it is also possible to run Mono on the Android (see the video), and I also saw earlier post of how to use Mono with ahead of time compilation to run application on the IPhone, and also I was quite surprised when I read that there was about 40 application, most games that was build with C# and available for IPhone using Mono, nice.

It is time to go to the basement and find my old C/C++, Java and Linux books blow the dust of and start developing Android. I can not afford more time waiting for Microsofts new mobile platform.

Check out GREAT comment by Sebastian (first one) on the Windows Embedded blog.

And here news about the new Windows Mobile User Interface

Posted by: dotnetninja | January 15, 2009

Microsoft Tag

Microsoft released new beta product which I think I saw on the Microsoft research home page for about one year or six months.

It is like bar code but version 2, with different colors and shapes where tag can be identified by for example mobile devices.

Physical media can be identified by and translated to live link for accessing information. Imagine printing color tag on your T-shirt with URL to you page, and when someone is using mobile device it can browse to tag defined URL and get necessary information. I have to buy some T-Shirt transfer paper now🙂.

More  information can be found on http://www.microsoft.com/tag.

To download software for mobile device browse with you mobile device to this address:  http://gettag.mobi/.

On my HTC mobile I was browsing to the mobile page using Opera Mobile Browser and when accessed page my mobile was recognized as an J2ME (Java 2 Micro Edition), nothing strange because Operas browser was an Java application.

No comment on that🙂.

microsoft tag

microsoft tag

I was trying to install latest version of the Enterprise library (4.1) and I was constantly receiving this error.

My previous version of the Enterprise Library was uninstalled (4.0) so I did not have any idea what it went wrong. On the Patterns and Practices codeplex page under discussion, I found resolution to this problem.

Remove the key “HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Enterprise Library v4“.

The issue with the MSIs for 3.1 and 4.0 is that there are some duplicate component IDs. When uninstalling, reference counting kicks in and some components, like this registry key, are not deleted and must be manually cleared.

Ever tried to modify table using Managment Studio? and received this error.

Here is an simple fix.

In Management Studio (2008 ) click on:
Tools -> Options -> Designers, and uncheck the option “Prevent saving changes that require table re-creation”.

Older Posts »

Categories

Follow

Get every new post delivered to your Inbox.