Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to integrate OpenId with ASP.Net Membership in MVC

I am using the following code from MVC Storefront to test OpenId in MVC. How do I integrate it with my ASP.Net Membership so I can use roles and save a user name for the user in my tables? I believe that SO is also using something similar.

    public ActionResult OpenIdLogin()
    {
        string returnUrl = VirtualPathUtility.ToAbsolute("~/");
        var openid = new OpenIdRelyingParty();
        var response = openid.GetResponse();
        if (response == null)
        {
            // Stage 2: user submitting Identifier
            Identifier id;
            if (Identifier.TryParse(Request["openid_identifier"], out id))
            {
                try
                {
                    IAuthenticationRequest req = openid.CreateRequest(Request["openid_identifier"]);

                    var fetch = new FetchRequest();
                    //ask for more info - the email address
                    var item = new AttributeRequest(WellKnownAttributes.Contact.Email);
                    item.IsRequired = true;
                    fetch.Attributes.Add(item);
                    req.AddExtension(fetch);

                    return req.RedirectingResponse.AsActionResult();
                }
                catch (ProtocolException ex)
                {
                    ViewData["Message"] = ex.Message;
                    return View("Logon");
                }
            }
            else
            {
                ViewData["Message"] = "Invalid identifier";
                return View("Logon");
            }
        }
        else
        {
            // Stage 3: OpenID Provider sending assertion response
            switch (response.Status)
            {
                case AuthenticationStatus.Authenticated:

                    var fetch = response.GetExtension<FetchResponse>();
                    string name = response.FriendlyIdentifierForDisplay;
                    if (fetch != null)
                    {
                        IList<string> emailAddresses = fetch.Attributes[WellKnownAttributes.Contact.Email].Values;
                        string email = emailAddresses.Count > 0 ? emailAddresses[0] : null;
                        //don't show the email - it's creepy. Just use the name of the email
                        name = email.Substring(0, email.IndexOf('@'));
                    }
                    else
                    {

                        name = name.Substring(0, name.IndexOf('.'));
                    }

                    //FormsAuthentication.SetAuthCookie(name, false);
                    SetCookies(name, name);
                    AuthAndRedirect(name, name);

                    if (!string.IsNullOrEmpty(returnUrl))
                    {
                        return Redirect(returnUrl);
                    }
                    else
                    {
                        return RedirectToAction("Index", "Home");
                    }
                case AuthenticationStatus.Canceled:
                    ViewData["Message"] = "Canceled at provider";
                    return View("Logon");
                case AuthenticationStatus.Failed:
                    ViewData["Message"] = response.Exception.Message;
                    return View("Logon");
            }
        }
        return new EmptyResult();

    }

    ActionResult AuthAndRedirect(string userName, string friendlyName)
    {
        string returnUrl = Request["ReturnUrl"];
        SetCookies(userName, friendlyName);

        if (!String.IsNullOrEmpty(returnUrl))
        {
            return Redirect(returnUrl);
        }
        else
        {
            return RedirectToAction("Index", "Home");
        }
    }
like image 255
Picflight Avatar asked Jul 27 '09 05:07

Picflight


2 Answers

There are several questions like yours already on StackOverflow. This one seems particularly similar.

If you're already using the Membership provider for your site and are just adding OpenID to it, then I guess you're stuck with Membership for now and can use one of the answers to the question I linked to to get a semi-decent membership provider that MAY work for you.

But if you're writing a new site and just want "use roles and save a user name for the user in my tables" as you said, then DON'T use ASP.NET Membership at all. It's SO not worth it! It doesn't fit OpenID's password-less paradigm and just causes more grief than anything else. If you're not afraid of a little bit of database access yourself, do it that way. And you can get Roles behavior very easily by just issuing your own FormsAuthentication.RedirectFromLoginPage or FormsAuthentication.SetAuthCookie call and passing in the roles the user fills.

like image 77
Andrew Arnott Avatar answered Oct 21 '22 21:10

Andrew Arnott


The open id provider will return data about the user. If you don't request/require specific tokens of information, then all you'll be given is the user's display name and identity URL.

Depending on what open id library you're using, you can request tokens like FirstName LastName, DOB (if you really cared) and if the user provided that information on their chosen identity, then you'd get it returned to you.

You can then use this to create a new user in the membership system. You'll probably have to give them a dummy password to get around the requirements of the Membership API.

To validate a login, provide 1 form that takes username & password and the other that takes an identity URL. After you've validated the user via open id, try to find the user by username (identity url) in the Membership API. If it doesn't exist, create it.

like image 27
Ben Scheirman Avatar answered Oct 21 '22 21:10

Ben Scheirman