Friday 16 October 2009

Using RPX with ASP.NET

RPX is a technology provided by a company called Janrain, allowing users to log into your web application using their existing Facebook, Twitter, Hotmail, Open ID or Google account (plus many more). The benefit to the user is that they don't have to divulge their details to yet another website and the benefits to developers are:
  1. You can achieve all this with only a small amount of development effort.
  2. You don't have to write mundane user management and authentication code for your application, allowing you to focus on your application's features and get to market quicker.
  3. People will be more likely to use to your application or website because they can log in with their existing credentials and don't have to register.
This article is intended for experienced ASP.NET developers and explains how to use RPX from ASP.NET without the need for a custom MembershipProvider.

Before getting started you will have to register for an RPX developer account, which only takes a few minutes. Once you've registered you will be given a secret API key for your application, which must be used in all communications with the RPX server. You should also take a look at the QuickStart Guide they provide before you continue reading.

Now that you have registered for RPX and read the QuickStart guide, you are ready to start cutting the code, so create a new ASP.NET project in Visual Studio and follow these steps:

Create a Login.aspx page in your ASP.NET project and add the following Hyperlink control:

<asp:HyperLink ID="lnkSignIn" runat="server" CssClass="rpxnow" onclick="return false;" Text="Sign In" />

Add this mark-up to the very end of your page, after the </html> tag:

<script src="https://rpxnow.com/openid/v2/widget" type="text/javascript"></script>

<script type="text/javascript">
RPXNOW.overlay = true;
RPXNOW.language_preference = 'en';
</script>

In the page load event of your Login.aspx page, add the following code, which sets the Navigation URL of the Hyperlink control you've just added to point to the RPX authentication service:

this.lnkSignIn.NavigateUrl = "https://[Your RPX Realm].rpxnow.com/openid/v2/signin?token_url=http://" + Request.Url.Authority + "/RpxResponse.aspx";

NOTE: The RPX Realm value is assigned by RPX to your application and can be found in your application's setting page, above the secret API key.

When the user clicks the Login hyperlink they will be taken to the authentication provider's website where they can log in securely. This also proves to the user that your website isn't phishing for their details and should make them feel more confident that their password won't be divulged.

The link you set in the code above tells the RPX service to redirect the user back to a page called RpxResponse.aspx, which is in the root folder of your website, so add a new ASP page to your project called RpxResponse.aspx and then add the following method in the code behind:

using System.Xml;
using System.Web.Security;

private void loginUser(XmlElement authInfo)
{
// Get the user's unique identifier (this will ALWAYS be returned regardless of the login provider
string userProvidersUniqueID = authInfo.GetElementsByTagName("identifier")[0].InnerText;

// See if the user's display name is provided (not supplied by some providers
XmlNodeList displayNameNodeList = authInfo.GetElementsByTagName("displayName");
string displayName = null;
if (displayNameNodeList != null && displayNameNodeList.Count > 0)
{
// Got a display name
displayName = displayNameNodeList[0].InnerText;
}
else
{
// No display name
}
// See if the user's email address is provided (not supplied by some providers)
XmlNodeList emailAddressNodeList = authInfo.GetElementsByTagName("email");

string emailAddress = null;

if (emailAddressNodeList != null && emailAddressNodeList.Count > 0)
{
// Got an email address
emailAddress = emailAddressNodeList[0].InnerText;
}
else
{
// No email address
}
// Set the authentication cookie and go back to the home page
FormsAuthentication.SetAuthCookie(userProvidersUniqueID, false);
Response.Redirect("~/Default.aspx");
}

Each authentication provider returns a different set of data about the user, for example, Facebook and Twitter do not return the user's email address, but every provider will supply their unique user ID in the identifier element returned in the RPX auth_info xml document passed back from the RPX authentication service.

The RPX web services uses HTTP POSTs to perform actions and send the results back in XML as a HttpWebResponse (there is also a JSON interface but I won't be covering that here). In order to hide the complexity of these operations you can download a wrapper class from the RPX website, which you should also add to your ASP.NET project.

Now add the following code to the page_load event of your RpxResponse.aspx page:

const string apiKey = "[Your secret API key goes here]";
const string paramToken = "token";

// Get the login token passed back from the RPX authentication service
string loginToken = Request.Form[paramToken];

// Create an RPX wrapper to get the user's data
Rpx rpx = new Rpx(apiKey, "https://[Your RPX Realm].rpxnow.com/");

// Get the user's details
XmlElement authInfo = rpx.AuthInfo(loginToken);

// Log the user in
this.loginUser(authInfo);

And that's all there is to it. You now have access to the user's ID from the Page.User.Identity.Name property until they log out.

Copyright © 2009 Software Nation