Logo

Maarten Balliauw {blog}

ASP.NET, ASP.NET MVC, Azure, PHP, OpenXML, VSTS, ...

About the author

Maarten Balliauw is currently employed as .NET Technical Consultant at RealDolmen. His interests are mainly web applications developed in ASP.NET (C#) or PHP and the Windows Azure cloud platform.
More about me More about me
Send mail E-mail me


ASP.NET MVC Quickly Subscribe to my RSS feed Follow me on Twitter! View Maarten Balliauw's profile on LinkedIn
View Maarten Balliauw's MVP profile

Search

Latest Twitter

    Follow me on Twitter...

    My projects

    Disclaimer

    The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

    © Copyright Maarten Balliauw 2010

    Authenticating users with RPXNow (in ASP.NET MVC)

    ASP.NET MVC RPX RPXNow Don’t you get sick of having to register at website X, at website Y, at website Z, …? It is really not fun to maintain all these accounts, change passwords, … Luckily, there are some large websites offering delegated sign-in (for example Google Accounts, Live ID, Twitter OAuth, …). You can use these delegated sign-in methods on your own site, removing the need of registering yet another account. Unfortunately, not everyone has an account at provider X…

    A while ago, I found out about the free service JanRain is offering: RPXNow. This (free!) service combines the strengths of several major account providers (Google Accounts, Live ID, Twitter, Facebook, OpenID, …) into one simple API. This means that people are able to log in to your website if they have an account at one of these providers! Here’s how to use it in ASP.NET MVC…

    Download sample code: Rpx4Mvc.zip (246.97 kb)

    kick it on DotNetKicks.com

    Creating some HTML helpers

    After registering at RPXNow, you will receive an application name and API key. This application name should be used when embedding the login control that is provided. To simplify embedding a login link, I’ve created two HtmlHelper extension methods: one for embedding the login control, another one for providing a login link:

    public static class HtmlHelperExtensions
    {
        public static string RpxLoginEmbedded(this HtmlHelper helper, string applicationName, string tokenUrl)
        {
            return "<iframe src=\"https://" + applicationName + ".rpxnow.com/openid/embed?token_url=" + tokenUrl + "\" scrolling=\"no\" frameBorder=\"no\" style=\"width:400px;height:240px;\" class=\"rpx-embedded\"></iframe>";
        }

        public static string RpxLoginPopup(this HtmlHelper helper, string applicationName, string tokenUrl, string linkText)
        {
            return "<script src=\"https://rpxnow.com/openid/v2/widget\" type=\"text/javascript\"></script><script type=\"text/javascript\">RPXNOW.overlay = true; RPXNOW.language_preference = 'en';</script>" +
                "<a class=\"rpxnow\" onclick=\"return false;\" href=\"https://" + applicationName + ".rpxnow.com/openid/v2/signin?token_url=" + tokenUrl + "\">" + linkText + "</a>";     
        }
    }

    I can now add a login link in my views more easily:

    <%=Html.RpxLoginPopup("localtestapp", "http://localhost:1234/Account/Login", "Login") %>

    Creating the RPX implementation

    The RPX implementation is quite easy. When a user logs in, a token is posted to your web application. Using this token and the API key, you can query the RPX service for a profile Here’s a simple class which can take care of all this:

    public class RpxLogin
    {
        protected string apiKey = "";

        public RpxLogin(string apiKey)
        {
            this.apiKey = apiKey;
        }

        public RpxProfile GetProfile(string token)
        {
            // Fetch authentication info from RPX
            Uri url = new Uri(@"https://rpxnow.com/api/v2/auth_info");
            string data = "apiKey=" + apiKey + "&token=" + token;

            // Auth_info request
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            request.Method = "POST";
            request.ContentType = "application/x-www-form-urlencoded";
            request.ContentLength = data.Length;

            StreamWriter requestWriter = new StreamWriter(request.GetRequestStream(), Encoding.ASCII);
            requestWriter.Write(data);
            requestWriter.Close();

            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            TextReader responseReader = new StreamReader(response.GetResponseStream());
            string responseString = responseReader.ReadToEnd();
            responseReader.Close();

            // De-serialize JSON
            JavaScriptSerializer serializer = new JavaScriptSerializer();
            RpxAuthInfo authInfo = serializer.Deserialize<RpxAuthInfo>(responseString);

            // Ok?
            if (authInfo.Stat != "ok")
            {
                throw new RpxException("RPX login failed");
            }

            return authInfo.Profile;
        }
    }

    Note that the RPX service returns JSON data, which I can deserialize using the JavaScriptSerializer. That’s really all it takes to get the logged-in user name.

    Plumbing it all together

    All of the above can be plumbed together in a new AccountController. This will have to be extended for your application (i.e. for storing the logged in username in a membership database, … Simply add these two action methods in a blank AccountController and you are ready to RPX!

    [HandleError]
    public class AccountController : Controller
    {
        public ActionResult Login(string token)
        {
            if (string.IsNullOrEmpty(token)) {
                return View();
            } else {
                IRpxLogin rpxLogin = new RpxLogin("b2e418e8e2dbd8cce612b829a9234ed4a763b2c0");
                try
                {
                    RpxProfile profile = rpxLogin.GetProfile(token);

                    FormsAuthentication.SetAuthCookie(profile.DisplayName, false);
                }
                catch (RpxException)
                {
                    return RedirectToAction("Login");
                }

                return RedirectToAction("Index", "Home");
            }
        }

        [Authorize]
        public ActionResult Logout()
        {
            FormsAuthentication.SignOut();
            return RedirectToAction("Index", "Home");
        }
    }

    Download a sample application: Rpx4Mvc.zip (246.97 kb)

    kick it on DotNetKicks.com


    Categories: ASP.NET | C# | General | MVC

    Comments

    DotNetKicks.com | Reply

    Monday, July 27, 2009 11:15 AM

    trackback

    Authenticating users with RPXNow (in ASP.NET MVC)

    You've been kicked (a good thing) - Trackback from DotNetKicks.com

    Steve Burman Australia | Reply

    Monday, July 27, 2009 12:59 PM

    Steve Burman

    You could also leverage RpxLib to do some of the heavy lifting.
    Check out the MVC example on the wiki at -
    code.google.com/.../GettingStartedWithMVC

    maartenba Belgium | Reply

    Monday, July 27, 2009 1:29 PM

    maartenba

    Thanks! Did not know that one.

    ITmeze | Reply

    Monday, July 27, 2009 2:34 PM

    ITmeze

    I don't really like that one. I am still looking for better one.

    Yves Goeleven Belgium | Reply

    Monday, July 27, 2009 5:43 PM

    Yves Goeleven

    Maarten,

    Have you tried to use one of these services as a trusted issuer for the Azure access control service, it would be really interesting to do that...

    Kind regards,
    Yves

    maartenba Belgium | Reply

    Monday, July 27, 2009 6:20 PM

    maartenba

    Nope, but good idea! Will see if I find some time for that.

    DotNetBurner - ASP.net MVC | Reply

    Monday, July 27, 2009 11:59 PM

    trackback

    Authenticating users with RPXNow (in ASP.NET MVC)

    DotNetBurner - burning hot .net content

    progg.ru | Reply

    Tuesday, July 28, 2009 5:42 AM

    trackback

    Аутентификация пользователей с помощью RPXNow (и ASP.NET MVC)

    Thank you for submitting this cool story - Trackback from progg.ru

    DotNetShoutout | Reply

    Tuesday, July 28, 2009 4:06 PM

    trackback

    Authenticating users with RPXNow (in ASP.NET MVC) - Maarten Balliauw

    Thank you for submitting this cool story - Trackback from DotNetShoutout

    Ercüment ESER Turkey | Reply

    Wednesday, July 29, 2009 4:22 PM

    Ercüment ESER

    Why use another service to log in open-id providers? Every service will require paying in the future, it may be free for just now. Just roll up your own open-id handler, or use one of those examples on the web.

    Maarten Belgium | Reply

    Thursday, July 30, 2009 7:20 AM

    Maarten

    I just want authentication, not to implement 10 providers in an application. RPXNow seems to work great in combining multiple providers into one easy-to-use.

    Rex Harrison United States | Reply

    Thursday, September 10, 2009 7:55 PM

    Rex Harrison

    Thanks for posting this project.  This really helps me get going on the integration of RPX and MVC.

    Jeff Garoutte United States | Reply

    Thursday, August 13, 2009 8:33 PM

    Jeff Garoutte

    If you are storing the user name in your local database how are you handling a reapeat of a user name across several providers?

    For example two siblings Edan and Ethan Smith may each have a username of ESmith, one at provider x and the other at provider y.  What happens when the both register at a site using this service and the username is stored as the key for an account?  Im just wondering as I havent really looked into the subject much.

    maartenba Belgium | Reply

    Friday, August 14, 2009 7:22 AM

    maartenba

    Best thing would be to also store the provider. ANother option is creating a local account "esmith", where you can add trusted providers. FOr example, local esmith can state he will login via Twitter and sometimes via OpenID.

    mh415 United States | Reply

    Thursday, November 05, 2009 3:39 AM

    mh415

    Correct me if I'm wrong, but you could just store RpxProfile.Identifier in your local datastore.  That property appears to be the same each time I log in with the same credentials.  I believe this takes care of the ESmith/ESmith name collision problem.  Is this right, Maarten?

    maartenba Belgium | Reply

    Thursday, November 05, 2009 7:52 AM

    maartenba

    That is indeed a good one to store. Thanks for the tip!

    Shawn United States | Reply

    Tuesday, September 01, 2009 12:58 PM

    Shawn

    This code works great.  I tried the sample MVC app that comes with RpxLib and it kept logging me out right after I would log in.

    Your app logs me in perfectly and has some nice clean code.

    Thanks for the examples.

    Shawn

    Shan McArthur Canada | Reply

    Friday, September 18, 2009 5:01 PM

    Shan McArthur

    Your ASP.NET example uses a SQL membership provider.  Since all authentication in ASP.NET is handled with a membership provider, don't you think that modifying your implementation to model a membership provider would be useful for the asp.net community?  JanRain isn't aware of any customers that use their product with ASP.NET which makes me worry about the feasibility of using their product in ASP.NET and getting ANY customer support from them.

    Maarten Balliauw Belgium | Reply

    Friday, September 18, 2009 5:10 PM

    Maarten Balliauw

    Membership is something that is relative to your own site,while RPXNow is solely used as an authentication mechanism. Of couse, it provides extra properties, but you can basically think of RPXNow as an alternative to Forms / Windows auth.

    fernando Brazil | Reply

    Thursday, August 12, 2010 8:36 PM

    fernando

    Thanks for you code!
      
    How to get the previous url using the Janrain RPX login?

    Thanks

    Add comment




      Country flag

    biuquote
    • Comment
    • Preview
    Loading