ASP.NET MVC Simple authentication without a database

Sometimes you just need a really simple authentication method in your ASP.NET MVC applications. The default MVC application has the necessary providers setup so that you can have a more flexible Membership system, but if you just want a single username and password, then this will help you.

In your web.config change the Authentication section to the following:

Then in the AccountModel.cs file, find the method ValidateUser and change the code to the following:

The default setup should now work without using the provider.

Implementing RPX without ASP.NET Membership

I’ve almost completed my test of RPX with ASP.NET webforms. My first pass attempted to mix the ASP.NET Membership with RPX, and although I got it working, it felt like a fudge. I wrote a custom Membership Provider, and pushed the RPX identities through it, but somehow it just felt dirty.

In fact I’ve never liked the ASP.NET Membership model, and it has always bugged me. It forces you into a model of username over email address (where email addresses are always more memorable and unique) and never seems to deliver a profesional finish. Now OpenID is here to stay, making registration and login so simple, the Membership model feels slightly wonky. It still has its place, especially in intranet applications with Windows / LDAP, but as an internet model it just sucks. Look at any of the big popular websites out there, and then imagine the CreateUserWizard. I know it can be customized, but hell, they could have made it just a little bit more snazzy.

Membership rant aside and to cut a long story short, I dropped the custom Membership Provider. I cut everything down to the bare minimum, and aimed to produce a skeleton website, that uses RPX as an authentication mechanism, and would be my base framework for any new sites I build.

I used two tables, the first stores our base Account information, and it’s dead simple, containing only an AccountId and a Nickname. The second table is AccountIdentity and stores identities for each Account, and one Account can be associated to multiple identities.

Why multiple identities? Well, users often have more than one OpenID provider. They might have a Google Account and YahooID, they might also have a Myspace or a Facebook account. Any of these can be used as an OpenID, and the user might want to tie these all together into one Account with us, or not – the choice is theirs.

Our AccountIdentity table stores all of the common information provided by the RXPAuthenticationDetails, delivered after a callback to the RPX Service.

In more detail – when a user clicks on the sign-in button, provided by the easy to use login controls RPX Now gives you to get started, you give RPX a Url on your website, to which the user will be redirected to after they have authorised your website with their OpenID provider. In this authentication stage you’ll do a couple of things:

  1. Check if the user is already logged in. If so, we are going to check the existing AccountIdentity table to see if this RPX Identity already exists for this user, and if not, we’ll add it.
  2. If the user is not logged in, we check the RXPAuthenticationDetails to see if a “LocalKey” was provided. If so, we’ve already mapped this RPX Identity to an existing user account. We need to load the appropriate account, check the identity does indeed match, and then log the user in.
  3. Finally, if the user is not logged in, and no LocalKey was provided then this user is probably new. We should still check the existing AccountIdentity table to make sure the identity doesn’t exist, and then we’ll create a brand new account, and store the new associated identity.

Then we use the Account.AccountId as the Forms Authentication ticket, and sign the user in. That’s it, nothing more complicated.

So, what about Roles, and Profiles you ask? Well that’s to come…

RPX OpenID with ASP.NET Webforms and Membership Providers

This evening I started playing around with RPX, the OpenID consolidator from JanRain. I hit a few hurdles along the way, and I thought I would share a little of those experiences with others trying out RPX.

My first step was to download the RXPLib from Google Code, which is a full API wrapper for RPX. It gives you all the method calls you’ll need to work with the RPX API. It is built using the .NET 3.5 Framework, but it worked fine with my 2.0 web application.

The example code provided by RPXNow.com in C# isn’t particularly helpful. It is basically a Windows Console application, which allows you to basically interact with the API. N.B. It requires that you pass parameters to the application, so if you struggle to figure that out, view the project properties and edit the “Command Line Arguments” before you start to run the application in debug mode.

Step right past the console app, and login to RPXNow.com, with any OpenID enabled account and create a website profile. Then use the template created for you, and plug that code straight into your login page of your new website project. Create a call back page to which the authorisation token will be returned to. Add this URL to the script in the place holder (e.g. http://localhost:3456/ReceiveToken.aspx).

Running the web application you’ll get a simple “Sign In” link, which when clicked offers a number of OpenID providers to select. You need to select one, which will redirect you to that provider. Agreeing to the conditions of your provider, you login and are passed back to your token receiving page.

Here is where you implement your tie in to your Membership Provider. It makes a lot of sense to implement a custom Membership Provider, and hook the user into that.

The key areas you want to consider when a user logs into your application using OpenID is:

  1. The user won’t be using a password to login
  2. Does the email address provided by the OpenID provider already exist in your database?
  3. Does the preferred user name passed back also exist?

Because the OpenID user doesn’t need a password to login (although you can offer them one), the CreateUser method of your Membership provider will need to have a default password created for them. Ideally you create a random one and email it to them in their welcome email. This does two things. It allows them to continue logging in with their preferred OpenID, or if they want to, log in with their user name and password.

If the email address already exists in your database (and ideally email addresses would be unique in your provider), you are able to use the “Mapping” feature of RPX. Mappings lost me to start with, because they are not very well explained on the RPX Now website. Quite simply, it allows you to tie up your existing user, to an identity on RPX. After authentication in your Token page, you can call the RPX service to map your local UserId (CustomerId, AccountId, etc) to an identity in RPX. In this way, you can map one of your user accounts to multiple RPX identities.

If the preferred user name returned by RPX already exists in your database, you’ll obviously have to offer the user an alternative user name (unless you use email addresses as user names).

In summary, RPX looks great, and is very simple to implement in a basic format. I’m sure I’ve only just scratched the surface in the few hours I’ve played around with it.

Notably, the basic version of RPX is free, but offers a limited subset of features compared to the premium accounts. One of the issues with the basic version is that your users won’t log in to your website directly, but be transferred to https://youraccount.rpxnow.com. As a result, users may be put off as they are warned constantly about phishing these days, and this looks like a blatant phishing attempt.

Secondly, implementing RPX means that you are putting all of your eggs into one basket. That’s not to say that RPX is going to disappear, but it could.

However, saying all of that, I think RPX is a great idea. Having a single simple control that offers users a great selection of OpenID providers in a easy to understand format is what OpenID needs at the moment.

I look forward to getting something more concrete together soon.

ASP.NET – Disabling the submit button to prevent double submissions

If a user clicks on a form submit button and the page response is slow, the user may often re-click that button. Because the original request has already been submitted, you may find that the user has made a double submission. In e-commerce sites, the double submission of a credit card payment may be very unpopular with your customers.

This is a common problem faced by web developers, and there are a variety of ways to try to prevent it. However, I have not seen a really elegant way to solve the problem, so I set about trying to find a simple and effective solution.

There were some key issues I wanted to address:

  1. I wanted to disable the button when it was clicked, but only if the page was valid
  2. I did not want to manually add code to every button in my application
  3. I did not want to break the existing validation, especially when using validation groups
  4. I wanted to preserve the CausesValidation property

To achieve these goals, I set about creating a custom button that inherited the standard ASP Button. This custom button would replace the existing buttons in my application.

First add a new class to your App_Code directory called “EnhancedButton” and then override the OnPreRender event:

Now, we add the following to our web.config to take advantage of the tagMapping feature:

The result is that all instances of standard Buttons are replaced with our new Enhanced custom button. You have no need to add extra code in every Page_Load. The Tag Mapping takes care of replacing the standard button across the web application.

And Voilà, our job is done!