adventures in the new and the old

Category Archives: IIS

Ah, the heady days of Visual Studio 2005 and the sparkly .Net 2.0 Framework with its newly minted Generics support. Who could forget them? For many, it seems, they are not so much recent history but an ongoing job to feed and maintain. A lot, in part, is due to the updates to .Net 3.0 and 3.5 leveraging the same CLR and BCL as the original .Net 2.0 release.

In this post I am going to do a walk through of how we can take an existing ASP.Net 2.0 WebForms application that’s using Forms Based Authentication (FBA) with Membership and Role Provider support and update it to utilise a more modern Claims Based Authentication approach based on Thinktecture IdentityServer v2.

There are two main reasons why you should be interested in making this transition: (1) to remove authentication logic entirely from your application’s codebase; (2) to allow you to share identity information with other applications to support Single Sign On (SSO).

Setting up Thinktecture IdendityServer v2

The first thing I’d recommend is that you setup a copy of the server we’ll use for Claims Based Authentication – download the most recent version. This is primarily because we can leverage the SSL certificate that is generated as part of the setup to secure our Forms Based Application as well. The good news is that the IdentityServer application is just an ASP.Net web application itself so we can use IIS to host it for us. I set it up on https://localhost/idsrv/ and you’ll see that URL used throughout this post.

The 2.0 FBA-secured Application

For the purposes of this blog I am going to use an extremely basic WebForms project that has a sub-folder (~/Secured/) that is access controlled. Note that I didn’t go back and install Visual Studio 2005 – I created a new WebForm project using Visual Studio 2013 and targetted the .Net 2.0 Framework. You can download this project as a zip from Github.

The membership, role and profile database was setup simply by creating a new database on SQL Server by running this command (at the location denoted):

aspnet_regsql.exe -S {YOUR_SERVER} -E -A mrp -d {YOUR_DATABASE}

Make sure to run in the right Framework folder (C:\Windows\Microsoft.NET\Framework\v2.0.50727\).

This gives us a set of tables in SQL Server (shown below) are used for storage of user authentication, authorisation and profile information.

The ASP.Net SQL backend is designed to support multiple applications (multi-tenant) so the important thing to make sure we do is specify the applicationName attribute (“AuthDemoApp”) when defining our member and role providers in our web.config which looks like this:

For the purpose of this demo you can load the ‘AddUser.aspx’ page and then use the two buttons to create a new user account and then create and assign a new role to the user as well. The result of this couple of commands is as follows in the SQL Server tables.

aspnet_Application

ApplicationName: AuthDemoApp

LoweredApplicationName: authdemoapp

ApplicationId: D0EBB6DF-45F6-40AD-A1EA-AEC9919CDFF4

Description: NULL

aspnet_Users (partial)

ApplicationId: D0EBB6DF-45F6-40AD-A1EA-AEC9919CDFF4

UserId: D747A14C-579C-4F6C-80BE-99414A823EDD

UserName: bob@smith.com

LoweredUserName: bob@smith.com

aspnet_Membership (partial)

ApplicationId: D0EBB6DF-45F6-40AD-A1EA-AEC9919CDFF4

UserId: D747A14C-579C-4F6C-80BE-99414A823EDD

Password: vdmWH7boQ0lY0zBmUYHWSN7j/q4=

Email: bob@smith.com

The important take away from the above tables is that our new Application can be uniquely identified by the GUID D0EBB6DF-45F6-40AD-A1EA-AEC9919CDFF4 which ties everything else together. Additionally we can infer that our user (bob@smith.com) can be granted access to other applications because the User D747A14C-579C-4F6C-80BE-99414A823EDD can be associated with any Application that is registered in future by way of the aspnet_Membership table.

You can log in by loading the web app and then clicking on the “Login” link which takes you to a login form. Once logged in I am redirected to a secure page that displays which role the current user is in. We are using the standard LoginName and LoginStatus ASP.Net controls in the master page.

Upgrading to Claims Based Authentication

1. Update to the 4.5.1 Framework

Firstly we’re going to open our existing .Net 2.0 Web Application and change the target Framework to the most recent (4.5.1) – do this by right-clicking on the web project and selecting Properties. Then change the Framework as per below. I’m happy to admit that such a big jump will probably break a bunch of your custom code but in this demo we’re just focusing on updating the authentication aspects of your application.

2. Include the Claims Assemblies

As we’ve upgraded from .Net 2.0 Forms-based we’ll need to add some new assemblies to leverage claims properly in our application.

Note that prior to .Net 4.5 you had to leverage Windows Identity Foundation (WIF) to integrate claims authentication with your application – with 4.5 it’s now baked into the core framework though you still need to add references and install the nuget package above.

3. Update web.config

Rather than detail the changes to make to the web.config one-by-one I’m going to link to a Gist that shows you the updated config file (based on the 2.0 one above). You’ll notice that the majority of the changes are adding IdentityModel configuration to ensure we trust with our Secure Token Service (STS). The one other scary item you’ll note is that we set the authentication mode to “None”!!!

At this stage if you fire up the web application (you’ll need to do it over HTTPS) you’ll find if you try and browse the ~/Secured folder that you’ll be directed to the ThinkTecture IdentityServer login page.

Important note: If you don’t set httpRuntime to support .Net 4.5 (line 17 of the Gist above) you’ll get a YSOD on login with a request validation failure due to the way WS-Fed passes the necessary authentication information to your application.

4. Setup ThinkTecture IdentityServer Databases

Whew! If you’re still with me you’re going strong! Now that we have web application ready for claims lets get our STS in working order as well (don’t worry if you’ve previously set it up – we can get it working as we need pretty easily).

As a first step make a backup of your existing ASP.Net SQL database for safety :).

The Thinktecture IdentityServer will utilise an existing Membership database if it can find one and will automatically create its configuration database schema if one isn’t found on the target SQL Server. Let’s create an empty database called ‘IdentityServerConfiguration’ into which the IdentityServer can create it’s own schema.

Open up the location on disk that you installed the IdentityServer in and then open the ~/Configuration/connectionStrings.config file and:

Point both databases at your SQL Server instance.

Set the ‘ProviderDB’ connection string to utilise the same ASP.Net memberhsip and role database as your existing web application.

Set the ‘IdentityServerConfiguration’ connection string to point at the empty database we just created.

You file should look like this:

Now when you visit the IdentityServer at https://localhost/idsrv/ you’ll be presented with the initial configuration screen. Go ahead and change the values as you wish – the important one in our case is the value for “Issuer URI” which is used by the relying parties we set to use this STS (hint: our web application already has this value in the web.config – http://identityserver.v2.thinktecture.com/trust/claimsdemo).

Also make sure you setup a default admin account for your STS! Your page will look like this:

5. Make Your Users Claims Users

Now that we’ve done all of the above the next bit is the trick to all of this :).

If you look at the aspnet_Applications table in your database you will find a new one listed that has an ApplicationName of “/” – this is your STS and is the key to this step.

You have two choices at this point – simply run some SQL to update all existing user and membership entries to map them to the STS ApplicationId or create duplicate entries within the necessary tables to ensure that old user records remain unchanged.

The final piece of the user puzzle is to add all your existing users to the “IdentityServerUsers” role. This can be achieved by writing SQL to simply add entries to the aspnet_UsersInRole table that maps the appropriate RoleId to all the UserId’s you imported.

6. Define your Web Application as a Relying Party

Open up the https://localhost/idsrv/Admin/RP page on the IdentityServer as the admin user and define a new relying party (your web app) – details are shown below.

Are we there yet?

Well, yes, we are. *Almost*.

If you’re leveraging the in-built role provider in your web application you will find that it is not working. The easiest way to fix it is to shift the roles to your STS and then everything will start working as expected. As your role database is already available to the STS simply go through the same exercise of updating each Role in aspnet_Roles to be assigned to the IdentityServer ApplicationId.

… and, finally, there’s a little sign-in / sign-out magic you’ll need – if you take a peak at the Main.Master page you’ll see the changes to make the button work (you could easily wrap in your own control to avoid needing to put code into the master page :)).

So, there we are, I hope you find this useful and that you start your journey to moving your web applications to be claims aware.

Install and Configure Web Deploy

When you install Web Deploy you need to make sure all components are available. Either select ‘Complete’ or ‘Custom’ when prompted for what to install. You should find that the components to install looks like the following.

Once you have finished the installation you can verify the state of your configuration by reviewing your server and you should find:

1. A new local user called WdeployAdmin.

2. Two new services – Web Deployment Agent Service and the Web Management Service.

Add Windows Login

We’re going to be using a non-Admin user for our deployments so lets go ahead and add a new Standard Windows login (i.e. one that is not an Administrator).

Note: Username and password should be chosen with care – in some deployment scenarios your password (particularly) may cause issues if it has characters that cannot be included in XML without being escaped. A simple rule of thumb is to avoid &, < and >.

Tip: If you have authentication issues test using a simple password that has no special characters.

Configure Management Service

We need configure the management service to allow remote connections and (in this instance) to only allow Windows credentials (the default).

Open up the IIS Manager on your server and ensure you have Features View on in the right pane.

Look for the Management Group (usually at the bottom) and then within that group select Management Service (see below).

When this view opens you will most likely find the form is disabled – this is because the service is running – you can’t change the configuration. If you look at the right pane you will see an option to Stop the service.

Make sure to check the ‘Enable remote connections’ option and to leave the ‘Windows credentials only’ selected (as below). Now restart the service.

Grant Windows Login IIS Manager Permissions

You can now grant the non-Admin user you created earlier the rights to manage sites on your IIS machine.

In the left pane of the IIS Manager select the site you wish to add your Windows login as a manager for (you will need to repeat for each site).

In the right pane you should see a Management group with two options (Configuration Editor and IIS Manager Permissions). Open the IIS Manager Permissions view.

In the new view that opens on the right hand pane near the top you should see ‘Allow User…’ – click on it and a popup will appear.

From the popup you can select the Windows user you wish to add – click on the Select button and then search for the user you create previously. Finally click OK on the two dialogs so you return to the initial screen where you will see a new entry for your user (sample below).

The Missing Link

I can almost guarantee you at this point that if you run the deployment it will fail. This is something I spent a fair amount of time trying to troubleshoot and so I have this advice for you:

The non-Admin Windows login you granted IIS Manager Permissions to must be able to read / write to the root folder location that the IIS site is deployed to.

Using this approach I’ve been able to get non-Admin users publishing successfully so the approach should work for you too.

May 2012 – Updated!

One important addition to add to all of the above.

When you setup Web Deploy it will create a two local users on the host that have priveleges to setup IIS sites and modify configuration files. The logins are WDeployAdmin and WDeployConfigWriter.

If you find that after a period of time Web Deploy starts giving errors and not deploying it is most likely due to the passwords for these users expiring and Windows setting the “user must change password on next logon” flag (assuming you left the default password policy in place on your Windows server). Either set the password not to expire or update it and clear the next logon flag.

As a .Net developer you will most likely have come across the need to create and send an SMTP (email) message as part of a solution you’ve built. When under development you will have either stubbed out the mail delivery code or will have substituted a test email address for those of the final recipients in a live environment (did your mailbox get full?!).

This approach is simple and works pretty well under development, but you know one day someone will come to you with a production problem relating to mail delivery to multiple recipients with each receiving their own copy of the message. How do you test this without needing multiple test mailboxes and without spamming the real recipients?

A few years back I learnt of a way to test mail delivery with real email addresses that can be performed locally of a development machine with minimal risk (note I didn’t say “no risk”) that email will actually be delivered to the intended recipients. The great thing is you don’t need to understand a lot about networking or being a sysadmin god to get this working.

IIS To The Rescue

Yes, IIS.

In this case you don’t even need any third party software – just the web application server that most ASP.Net developers know (“and love” is probably pushing the relationship a little though I think).

First off, you will need to install the SMTP feature support for IIS on your local machine. You can get instructions for IIS 7 from TechNet as well as for IIS 6. If you’re on IIS Express, you’re out of luck – it only supports HTTP and HTTPS.

Once you have the SMTP Feature installed you will need to make one important change – set the SMTP server to use a drop folder. The IIS SMTP process will simply drop files into a location you’ve selected and there they will sit – each file containing an emaill message.

To make this change open the IIS Manager and select the main server node. You should see (screenshot below) an option for SMTP E-mail.

IIS Manager with SMTP Email Option Highlighted.

Double-click the SMTP E-mail option to open the settings dialog. Notice at the bottom the option labelled Store e-mail in pickup directory – you should select this and then select an appropriate location on disk.

SMTP Email Settings Page with Drop Folder Highlighted.

Right, that’s the hard bit done.

Run Teh Codez

Now you have a safe place for your test mail to sit you need to ensure that your code is configured to attempt delivery via the SMTP instance you just configured. You can most likely achieve this by changing your application’s settings (they’re in an XML config file, right?) so that you use either of “localhost” or “127.0.0.1” as the SMTP host name – you won’t need to change the port from the standard port 25.

Now when you run your code you should find that the mail delivery folder you set will be populated with a range of files consisting of a GUID with a .EML extension – each of these is an individual email awaiting your eager eyes.

Lovely EML Files Ready To View.

The files are plain text so can be opened using Notepad or your favourite equivalent – you can view all the SMTP headers as well as the message body. For extra goodness you can also open these files in Outlook Express (does anyone even use that any more?!) or Outlook as shown below.

Outlook Goodness – See HTML Email Body Content Easily.

I used this approach just recently to help debug some problems for a customer and I could do it using their real email addresses safe in the knowledge that I would not end up spamming them with junk test emails.

Hope you find this approach useful.

Update

I had a reader pass on a service link to Mailtrap which might be more useful if you’re looking to test with a large diverse team.