Saturday 4 October 2014

Azure: Building an online company - Part 2


The shopping list to get me up and running with an inexpensive public site was as follows:-
  1. A public server to host the website
  2. A database server
  3. Source control
  4. A copy of Visual Studio

After signing up and creating a pay-as-you-go account on Azure I configured the following:-

1. A public server to host the website

Using the FREE web hosting plan mode I have a single-server, 32-bit host (on shared metal) for my web site. I also get the option to specify a domain suffix giving mysite.azurewebsites.net. Neat.

Start-up performance is not great, especially if the site hasn't been touched for a while. This suggests that the site image is stopped after a period of inactivity requiring the CLR to be reloaded and re-compilation of the MSIL. Once it is warmed up it is fine however. Amazing given the £0 price tag. Pricing and scaling options can be found here

Running total £0

2. A database server

On the basis that I am sticking with my areas of expertise and with my requirement for a relational database (SQL Server or similar), I signed up for the "Web" sku/tier of SQL Server. This tier has since been superseded by the BASIC service tier and offers pay as you go storage and 5 DTU's, So what is a DTU?

Extracted from the online reference

"DTUs are based on a blended measure of CPU, memory, reads, and writes. As DTUs increase, the power offered by the performance level increases. For example, a performance level with 5 DTUs has five times more power than a performance level with 1 DTU. A maximum DTU quota applies to each server. For more information on DTU quotas, see Azure SQL Database General Guidelines and Limitations.

Running total £0 (expected £3.18)

3. Source control

I like TFS, especially the recent upgrades to the SCRUM templates in TFS 2013 with the simple backlog management. So I signed up for the free edition of TFS online or "Visual Studio Online Basic" as it is known.

Signing up for this includes a free Web Edition of Visual Studio which means that I now have everything I need to get started.

The BONUS is that by linking the Azure account with the Visual Studio account, I also get Continuous Integration for free, put simply whenever I check in my web project, an MSBuild job (no doubt wrapped in powershell) launches in the background and deploys may latest code to the site. If anything goes wrong the Azure portal keeps a log of the deployment  history.
The number of CI hours per-month is limited on the free plan, but this hasn't caused me a problem yet, given that I am developing in my free time once or twice a week.

Running total £0

Having received my first bill after a month, the cost is £3.18, the charge is for SQL Server - not bad considering the cost of a standard license.

Month 1: £3.18



Saturday 6 September 2014

Azure: Building an online company - Part 1

In 2009 at the beginning of cloud computing boom, I attempted to see how far I could get building an online company for free - on the understanding that my leisure time working on the project was considered "free" and that numerous organisations were offering database access, storage and hosting for for free, certainly for developer or low-volume skus.

The project was a success and I had some interest from some small local companies at the time, so job done, but I wasn't satisfied with the experience or the product, however, this exercise in turn prompted me to use Azure for a successful mobile gateway project in my full time job as an Architect.

So, 5 years later I am looking to do this again and I plan to record what I have been up to.
A lot has changed and I believe that now, more then ever, the options available should mean that start-up costs are close to zero and that enterprise products and tooling are also available with no initial start-up costs.

In the main I will use Azure hosting and Microsoft development tools. This is what I know and if this is going to be successful this isn't the time to stall the process with new technology.

My measures of success are:-

  1. That the product is used by someone that I don't know.
  2. That my monthly outlay is less than £50 during the "bootstrap" phase
  3. That the product is used by someone that I don't know
  4. That the low-cost approach does not result in a compromise in features or quality

Wish me luck.

Monday 31 October 2011

Azure, ACS & MVC3 Caution

I was about to write a Rob Conery style rant about how this quirk of MVC3, Azure and ACS has been annoying for the last week, but I'll keep it brief and to the point.
I have, what I believe, is a relatively common situation.

I'm building a site using MVC3 and Razor to be hosted on Azure.
I'm using Azure ACS to give me Google, Live, Yahoo and other Identity Provider options to access my site.

The problem I have is that when I bundle my MVC3/ACS solution to the cloud using the out of the box tooling, I hit a problem, in short when I attempt to access a restricted path on the site, the WIF/ACS logon redirect isn't fired and the user is sent directly to the target page, unauthenticated!

The steps I took were as follows:-

1. Create my MVC3 solution/project using the Internet Application template
2. Add an Azure project to my solution and then add a web role reference to the MVC3 project within the same solution.
3. Configure ACS to accept request from, and issue tokens to the instance running on my localhost
4. Use the Windows Identity Foundation Federation Utility to automatically update my web.config with entries required to use Azure ACS as my Identity Provider.
5. Add the following entry to web.config to force authentication when an attempt is made to access the account/signin page

So far so good.I fired it up locally and it worked a treat.

I then added the configuration on the Azure ACS for my Azure hosted version of the solution, using the public facing URL.
Before deploying to Azure, you need to consider what is installed in the GAC on the target machine - in short, not a lot. To overcome this you need to bundle the MVC3 DLL dependencies into your bin folder - known as "Bin Deploying". This is a little clumsy, so there is a handy feature in MVC3 which packages the dependent binaries required on the Azure host.

To use this feature, right click on your MVC3 project and choose: "Add Deployable Dependencies". In the dialog select "ASP.NET MVC". This puts all of these tenuous dependencies in place. *Do NOT select "ASP.NET Web Pages with Razor syntax" - this is NOT what it seems.

This will create/update a folder named _bin_DeployableAssemblies containing all of the non-GAC'd DLL's that you need. At compile time these assemblies are automatically copied across to you bin folder.

With the bin folder ready and the project deployed to the cloud, the ACS authentication simply doesn't kick in, so why?

I retraced my steps and through trial and error and some educated guesses found that the problem was with the _bin_DeployableAssemblies entries, specifically the WebMatrix.WebData dll: a security plugin that clashes with the Microsoft.Identity namespace

Once I knew what the problem was, it was then easy to find someone else who had blogged about this
http://brockallen.wordpress.com/2011/06/01/beware-bin-deployment-of-mvc-and-razor-with-formsauthentication/

Copied from this post...

What’s happening is that when you ~/bin deploy MVC and Razor, the Razor DLLs are auto-registering some pre-App_Start code to run (which I thought was a neat idea, until now). For the curious it’s WebMatrix.WebData.PreApplicationStartCode.SetupFormsAuthentication from WebMatrix.WebData.dll. If this assembly is not ~/bin deployed then this pre-App_Start code doesn’t run. This pre-App_Start code will force Forms authentication to be enabled (with the login URL at the aforementioned path) unless it finds config data telling it otherwise. Here’s the kicker: the absence of any config data is sufficient to enable this feature. You have to explicitly disable it (as described above). This is quite annoying.

I concur, annoying! Phil Haack has a good post on bin deploying assemblies.

http://haacked.com/archive/2011/05/25/bin-deploying-asp-net-mvc-3.aspx

*this is the key problem, to quote Phil Haack "When building an ASP.NET MVC application, you only need to check the first option. Ignore the fact that the second one says "Razor". ASP.NET Web Pages with Razor syntax was the official full name of the product we simply call ASP.NET Web Pages now. Yeah, it’s confusing.

Sunday 16 January 2011

Building secure, authenticated WCF services for Windows Phone 7 using the ASPNET membership framework

 

I have done a bit of digging around in order to work out how to "go public" with many of the internal facing services that are offered to our enterprise and applications.

With the exception of 1 or 2 web services that we expose to our partners on a private circuit, we do not have any public web services so our security considerations to-date have been very different.

We use ASPNET membership as the basis for our authorisation and authentication so it makes sense to re-use this for our phone applications. In later posts I will look at how federation can be used to achieve a more seamless login approach.

This particular approach uses the "stateless" model where credentials are passed for every service call. There are other options which I will cover in later posts.

Pre-requisites

1. Admin/sa access to SQL Server 2005 or 2008

2. A VeriSign SSL certificate or a certificate where the root CA is VeriSign (such as a GoDaddy issued cert for use with SSL)

3. Visual Studio 2010 with the Windows Phone 7 emulator and tools

Anyway, I have broken this into stages on the basis that you may already have some of the below in place or ready - that was my situation, if so jump to Step 3.

 

Step 1: Creating the ASPNET membership database

Goal: Create the database, roles and associated stored procedures to support the ASPNET membership framework

I'm using a local instance of SQL Server 2008 R2 but this will work equally well on 2005 or SQLExpress. Launch SQL Server management studio and create a new database, let's call it ASPNET

Run the following command from the Framework libraries. This needn't be in the V4 library as I have been using this since .NET V2.0
C:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_regsql.exe
Running this without any command line parameters will launch the wizard which keeps things simple

Image(1)

Image(2)

Confirm your settings in the wizard and all of the default tables for the ASPNET membership, roles, personalisation, applications etc. with associated stored procedures have been created for you.

Image(3)

 

Step 2: Tools to manage the ASPNET membership data

Goal: Demonstrate how to configure users and roles within the ASPNET tables

In my case at least, we have developed a custom tool for managing our authentication and authorisation data, but Microsoft (as part of the ASP.NET experience in Visual Studio) have created a nice tool to get you going.

In Visual Studio 2010 (this is also available in 2008) create a new ASP.NET web application. The standard template will create all of the membership tables and stored procedures for you in a local .mdf as well as a simple project with a login control that makes use of the membership framework. We will make use of this standard template later for testing our configuration.

To see the admin UI, simply select "Project--> ASP.NET Configuration" from within VS and this will launch the following admin site - for free!

Image(4)

This points to a local SQLExpress .mdf so  we need to change the configuration slightly to point at our SQL 2008 database.

In the web.config for the site, change the following entries in line with the database that contains your membership schema, for this example it is my local machine "." with a database of ASPNET

Before
  <connectionStrings>
    < add name ="ApplicationServices "
        connectionString=" data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\aspnetdb.mdf;User Instance=true"
        providerName=" System.Data.SqlClient" />
  </connectionStrings>
 
After
 
  <connectionStrings>
    < add name ="ApplicationServices "
        connectionString=" data source=.;Integrated Security=SSPI;Initial Catalog=ASPNET"
        providerName=" System.Data.SqlClient" />
  </connectionStrings>

It is worth reviewing the other entries in the web.config to familiarise yourself with the membership and role provider entries.

If you re-launch the admin tool you can now set up your users and roles. 

 

Step 3 - Create the Users and Roles used in this example

Goal: Create some standard users and roles for this sample

For the purpose of this example, I am going to create the following users

     jon who is an administrator role

     sarah who has a user role

In the Web Site Administration Tool click on the Security tab

Enable Roles and then create the following roles

     admin, user

Go back to the security home and create two users

jon (with an admin and user role)

sarah (with a user role)

the password used will be Complex!

To test this set up, add the following code to the page load event of the web project. I have kept this simple as we are not really too interested in authentication and authorisation for standard asp.net web sites, but it is a good place to start.

        protected void Page_Load(object sender, EventArgs e)
        {
           if (User.Identity.IsAuthenticated)
            {
               if (User.IsInRole("admin" ))
                    Response.Write( "You have admin rights\n");

               if (User.IsInRole("user" ))
                    Response.Write( "You have standard user rights\n" );

            }
           else
                Response.Write( "You need to log in");
        }

By logging in and out of the site using the different usernames you can now see how content can be controlled using authentication (identifying the user) and authorisation (identifying the roles associated with the user).

Image(5)

 

Step 4: Creating a Silverlight Enabled WCF Service

Goal: Demonstrate how Silverlight and WCF work together


Silverlight and moreover  WinPhone7 has a restricted set of WCF capabilities. In order to authenticate the user for a WCF call we have to send the username/password in clear text in the SOAP header. DON'T PANIC. By using https and some simple config all of the heavy lifting is done for us.

1. Add a WCF Service Application project named SimpleService

2. Delete the default Service.svc and IService.cs

3. Add a new item from the Silverlight item templates: Silverlight-enabled WCF Service. Call this Simple.cs

4. Change the Simple.svc code to reflect the following code

namespace SimpleService
{
    [ServiceContract(Namespace = "")]
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode .Allowed)]
   public class Simple
    {
        [ OperationContract]
       public bool DoWork()
        {
           return true ;
        }
    }
}

It is worth reviewing and digesting the generated WCF config before it is modified...

        < binding name ="SimpleService.Simple.customBinding0">
          < binaryMessageEncoding />
          < httpTransport />
        </ binding>

A custom binding has been created in order to make Silverlight apps faster, essentially this is standard http with binaryMessageEncoding. The binary encoding will typically make the XML on the wire 30-40%  smaller.

At this stage I like to create a unit test. The unit test will simple add a reference to this service to ensure that all is well.

 

Step 5: Re-configure the service to use https

Goal: Set up https on IIS and WCF


This is not complicated but requires a bit of care.

1. Create a new application on your local IIS instance call SimpleService 

Image(6)

2. Open up the Server Certificates and use this to install/import your Verisign issued cert. Note: this must be the cert that contains the PRIVATE key 

Image(7)

3. Click on the website instance where this app is created (Default Web Site in my case) and then click on the bindings link. Associated https: on port 443 with the certificate. You may need to add https if it doesn't already exist.

Image(8) Image(9)

4. Now that we have https enabled, update our Simple service to make use of it. Fortunately this is very easy.

     Modify the web.config binding entry on the service to read httpsTransport

Before

          < httpTransport />

After

          < httpsTransport />

If you have a unit test then update the app.config entry as above and update the address to point at the IIS server (instead of the local project instance). 

You will need to publish the service to the IIS server. 

Once published, now is a good time to try and browse to the service to make sure that it is still working.

The SSL certificate will  be for a public URL, so when browsing to https://localhost/SimpleService/Simple.svc (for example) you will see

Image(10)

To overcome this, add an entry into your hosts file, found in C:\Windows\System32\drivers\etc

127.0.0.1     mywebsite.com

Where mywebsite.com is the URL that the certificate is registered to.

Browsing to https://mywebsite.com/SimpleService/Simple.svc should now take you to your service without complaining

As a checkpoint, use your unit test to call the updated service before continuing.

 

Step 6: Adding the membership provider to the service

Goal: Use configuration to integrate WCF with the ASPNET membership provider

Rather than walk you through this, the inline comments are probably clearer. Key points to note are the membership provider entry and the corresponding reference to it in service credentials section of the binding.

Update your web.config as follows (essentially replace all of the corresponding sections as below).

 

  <connectionStrings>
    <!-- Connection used to point to the ASPNET membership provider database -->
    < add name ="ApplicationServices "
        connectionString=" data source=.;User Id=membershipuser; Password=membershippwd;Initial Catalog=ASPNET"
        providerName=" System.Data.SqlClient" />
  </connectionStrings>

  <system.web>
    < compilation debug ="true " targetFramework ="4.0 "  />
     <!-- Configure the Sql Membership Provider-->
    < membership defaultProvider ="AspNetSqlMembershipProvider " userIsOnlineTimeWindow=" 15">
      < providers>
        < clear />
        < add name ="AspNetSqlMembershipProvider " type=" System.Web.Security.SqlMembershipProvider " connectionStringName=" ApplicationServices"
            enablePasswordRetrieval=" false" enablePasswordReset=" true" requiresQuestionAndAnswer=" false" requiresUniqueEmail=" false"
            maxInvalidPasswordAttempts=" 5" minRequiredPasswordLength=" 6" minRequiredNonalphanumericCharacters ="0 " passwordAttemptWindow ="10 "
            applicationName=" /" />
      </ providers>
    </ membership>
  </system.web>
  <system.serviceModel>
    < bindings>
      < customBinding>
        < binding name ="SimpleService.Simple.customBinding0 ">
          < security authenticationMode ="UserNameOverTransport ">
            <!-- Placeholder. Add attribute for such things as including Timestamp and Authentication modes-->
            < secureConversationBootstrap />
          </ security>
          <!-- Optimal way to transmit compressed XML SOAP messages -->
          < binaryMessageEncoding />
          <!-- Configure https-->
          < httpsTransport />
        </ binding>
      </ customBinding>
    </ bindings>
    < services>
      < service name ="SimpleService.Simple ">
        < endpoint address ="" binding=" customBinding" bindingConfiguration=" SimpleService.Simple.customBinding0"
         contract=" SimpleService.Simple" />
        < endpoint address ="mex " binding ="mexHttpBinding " contract=" IMetadataExchange" />
      </ service>
    </ services>
    < behaviors>
      < serviceBehaviors>
        < behavior>
          < serviceMetadata httpGetEnabled ="true "/>
          < serviceDebug includeExceptionDetailInFaults ="true "/>
          <!-- specify how the credentials are verified -->
          < serviceCredentials>
            <!-- Use the aspnet membership provider-->
            < userNameAuthentication userNamePasswordValidationMode ="MembershipProvider "  membershipProviderName=" AspNetSqlMembershipProvider"/>
          </ serviceCredentials>
        </ behavior>
      </ serviceBehaviors>
    </ behaviors>
    < serviceHostingEnvironment aspNetCompatibilityEnabled ="true "
     multipleSiteBindingsEnabled=" true" />
  </system.serviceModel>

 

Step 7 - Calling the service.

Update your web reference from the unit test and call the service as follows. Note how credentials are passed in through the proxy. To get the required client config it is probably easier to delete and recreate the web reference. Note how credentials are passed in through the proxy in the calling code.

       [ TestMethod]
       public void TestMethod1()
        {
            ServiceReference1. SimpleClient proxy = new ServiceReference1.SimpleClient ();
            proxy.ClientCredentials.UserName.UserName = "jon";
            proxy.ClientCredentials.UserName.Password = "Complex!";
           bool result = proxy.DoWork();
        }

You can now add the same to your Windows Phone app, using the asynchronous WCF approach of course. I created a simple ThisMobile.Phone application and called the https/aspnet service as follows.

namespace ThisMobile.Phone
{
   public partial class MainPage : PhoneApplicationPage
    {
       public MainPage()
        {
            InitializeComponent();
            Loaded += new RoutedEventHandler (MainPage_Loaded);
        }

       void MainPage_Loaded(object sender, RoutedEventArgs e)
        {

            SimpleProxy. SimpleClient proxy = new SimpleProxy.SimpleClient();
            proxy.ClientCredentials.UserName.UserName = "jon";
            proxy.ClientCredentials.UserName.Password = "Complex!";
            proxy.DoWorkCompleted += new EventHandler<SimpleProxy.DoWorkCompletedEventArgs >(client_DoWorkCompleted);
            proxy.DoWorkAsync();
        }

       void client_DoWorkCompleted(object sender, SimpleProxy.DoWorkCompletedEventArgs e)
        {
            LoggedInStatus.Text = "Logged id, hurray";
        }

    }
}

Hope this was useful....

Cheers - Jon.

 

References:

patterns & practices: WCF Security Guidance

http://wcfsecurity.codeplex.com/

Configuring Secure Sockets Layer in IIS 7

http://technet.microsoft.com/en-us/library/cc771438(WS.10).aspx

WCF Services and ASP.NET (Hosting side by side)

http://msdn.microsoft.com/en-us/library/aa702682.aspx

WCF, ASP.NET Membership Provider and Authentication Service

http://stackoverflow.com/questions/56112/wcf-asp-net-membership-provider-and-authentication-service

Configuring an ASP.NET application to use Membership

http://msdn.microsoft.com/en-us/library/6e9y4s5t.aspx

How to: Use the ASP.NET membership provider

http://msdn.microsoft.com/en-us/library/ms731049.aspx

Manging shared cookies in WCF

http://megakemp.wordpress.com/2009/02/06/managing-shared-cookies-in-wcf/

Cannot import wsdl:portType

http://forums.silverlight.net/forums/p/117406/335336.aspx

WCF Binary Bindings in Silverlight 3

http://johnpapa.net/silverlight/wcf-binary-bindings-in-silverlight-3/

Whats new with web services in Silverlight 3 Beta

http://blogs.msdn.com/b/silverlightws/archive/2009/03/20/what-s-new-with-web-services-in-silverlight-3-beta.aspx

Consuming web services in Silverlight 3

http://videos.visitmix.com/MIX09/T42F

(Security piece from 30 mins in)

Fiddler and the Windows Phone 7 Emulator

http://blogs.msdn.com/b/fiddler/archive/2010/10/15/fiddler-and-the-windows-phone-emulator.aspx

Access control and Identity on WP7

http://blogs.msdn.com/b/card/archive/2010/11/06/access-control-for-windows-phone-7-apps.aspx