Thursday 21 June 2007

OpenID in ASP.NET

I found a helpful ASP.NET OpenID control that lets you implement an OpenID login on your website. The instructions are a little weak so I thought I'd post a quick how-to here.

First you need to download the binaries and copy them into the bin folder of your web application.

  • Boo.Lang.dll (because JanRain is written in Boo)
  • JanRain.dll (an OpenID library for .NET)
  • Mono.Security.dll
  • NerdBank.Tools.dll (contains the ASP.NET control)

Then you simply register the assembly at the top of your aspx page:

<%@ Register Assembly="NerdBank.Tools" Namespace="NerdBank.Tools.WebControls" TagPrefix="nb" %> 

And then insert the control:

<nb:OpenIdLogin ID="openIdLogin" runat="server" 
        RequestEmail="Request" RequestTimeZone="Request" RequestNickname="Request" 
        PolicyUrl="http://mysite.com/PrivacyPolicy.aspx" />

Here I have requested the email, timezone and nickname. I could also say Require for these if I absolutely must have them. You should also provide a privacy policy URL, or else the user will be warned that it is missing.

The control itself provides a Register link that is customizable, allowing users to sign up with an Open ID provider such as www.myopenid.com.

When you login, if you have entered a valid OpenID URL, you will go to your OpenID provider who will ask for your password if necessary, confirm whether you want to allow that site to log you in once, always or never, and ask you what persona you want to use.

On a successful login, you can retrieve the OpenID URL as well as anything from the persona that has been made available. Here's some sample code-behind.

protected void Page_Load(object sender, EventArgs e)
{
    Uri openIdUri = Session["OpenIdUri"] as Uri;
    if (openIdUri == null)
    {
        openIdLogin.LoggedIn += new EventHandler<NerdBank.Tools.WebControls.OpenIdTextBox.OpenIdEventArgs>(openIdLogin_LoggedIn);
        openIdLogin.Visible = true;
    }
    else
    {
        openIdLogin.Visible = false;
        Response.Write("Welcome " + openIdUri.ToString() + "<br />");
        Response.Write("Email: " + Session["openIdEmail"] + "<br/>");
        Response.Write("Nickname: " + Session["openIdNickname"] + "<br/>");
        Response.Write("TimeZone: " + Session["openIdTimeZone"] + "<br/>");            
    }
}

void openIdLogin_LoggedIn(object sender, NerdBank.Tools.WebControls.OpenIdTextBox.OpenIdEventArgs e)
{
    Session["OpenIdUri"] = e.OpenIdUri;
    Session["OpenIdEmail"] = e.ProfileFields.Email;
    Session["OpenIdNickname"] = e.ProfileFields.Nickname;
    Session["OpenIdTimeZone"] = e.ProfileFields.TimeZone;
}

As you can see, it is pretty simple. I still need to work out how I am then going to integrate the OpenID login with my own site login database. The control itself also has a few limitations. In particular, entering an invalid URL causes an unhandled exception. It also doesn't give you an event for login failure (although there is a "logging in" event which I am not sure what it is for).

7 comments:

Andrew Arnott said...

Thanks for your explanatory post. I'm sorry my instructions weren't that good, but I see you've made up for that.

The LoggingIn event gives your site a chance to reject a particular URL before the user is redirected to his OpenID provider. You might do this if you only allowed, say, a given set of administrators with known OpenIDs to log into your site.

The unhandled exception isn't good. There should be a validation control to handle that, but I'll have to check.

In the meantime, you and your readers should know that the NerdBank.Tools version of my ASP.NET OpenID control is now deprecated. The controls were merged into the dotnetopenid project and have been worked on there. You should give that library a try and see if you find it better. I welcome comments. Just post to the dotnetopenid Google Group.

aaballboy said...

hi~ Mark!
I can't download dll from the url.
Do u know where I can find these dll?
Thank you!

Unknown said...

hi aaballboy,
have you tried from the google project link? ...
http://code.google.com/p/dotnetopenid/

aaballboy said...

Thanks for ur reply!
I have found dll.
But now I have another problem.
where can I download source code?
Because I can't change the OpenID control.
For example,I want to change the OpenID provider from myopenid to yahoo.

Andrew Arnott said...

aaballboy,
The source code is also available from the googlecode site that Mark pointed out. But FWIW, you don't need the source to change the OpenId Provider that is suggested in the OpenIdLogin control. You can change that through a property on the control itself. Much easier.

judekblog said...

Thanks your code works great. But now I am trying to break it down indivigual users and allow only certain users in. For example, what would I set my xxx to in allow users="xxx" in the web.config file?

Andrew Arnott said...

judekblog,

Rather than using your web.config file to list the individual users allowed to log in, if the purpose is to whitelist who is allowed to log in at all then inside your openIdLogin_LoggedIn handler you should check e.ClaimedIdentifier and if it isn't on your whitelist, set e.Cancel = true, and display a message to the user saying that they're not allowed to log in.