Welcome to EMC Consulting Blogs Sign in | Join | Help

Anthony Steele's Blog

Adding OpenId to Oxite, Part 2

(Part 1 is here)

The main part of the Openid support is in the controllers and in the view. Fortunately the heavy lifting has been done already, with a library called DotNetOpenId and sample code that started life in Rob Connery's storefront sample, and was worked on by my colleagues Howard Van Rooijen and Pete Worthington before I got hold of it.

First, install the DotNetOpenId library and reference it from the Oxite.MVC project

Add an action called OpenIdSignIn to AccountController:

        public ActionResult OpenIdSignIn()

        {

            var openid = new OpenIdRelyingParty();

 

            if (openid.Response == null)

            {

                string claimedUrl = Request["openid.claimed_id"];

 

                // Stage 2: user submitting Identifier

                Identifier id;

                if (Identifier.TryParse(claimedUrl, out id))

                {

                    IAuthenticationRequest request = openid.CreateRequest(claimedUrl);

 

                    // email and display name would be nice, but we can do without it

                    ClaimsRequest claimsRequest = new ClaimsRequest

                        {

                            Email = DemandLevel.Request,

                            Nickname = DemandLevel.Request

                        };

                    request.AddExtension(claimsRequest);

 

                    request.RedirectToProvider();

                }

                else

                {

                    ModelState.AddModelError("_FORM", "Invalid identifier");

                    return View("SignIn");

                }

            }

            else

            {

                // Stage 3: OpenID Provider sending assertion response

                switch (openid.Response.Status)

                {

                    case AuthenticationStatus.Authenticated:

                        {

                            ClaimsResponse claimsResponse = openid.Response.GetExtension<ClaimsResponse>();

 

                            string nickname;

                            string email;

                            // did we get a claims response?

                            if (claimsResponse == null)

                            {

                                nickname = openid.Response.ClaimedIdentifier.ToString();

                                email = string.Empty;

                            }

                            else

                            {

                                nickname = claimsResponse.Nickname;

                                email = claimsResponse.Email;

                            }

 

                            LogOpenIdLogin(openid.Response.ClaimedIdentifier, nickname, email);

                            return RedirectToRoute("Home");

                        }

                    case AuthenticationStatus.Canceled:

                        ModelState.AddModelError("_FORM", "Canceled at provider");

                        return View("SignIn");

 

                    case AuthenticationStatus.Failed:

                        ModelState.AddModelError("_FORM", openid.Response.Exception.Message);

                        return View("SignIn");

                }

            }

            return new EmptyResult();

        }

 

        private void LogOpenIdLogin(Identifier claimedIdentifier, string nickname, string email)

        {

            // if the user record does not exist, create it

            string userName = claimedIdentifier.ToString();

            IUser user = MembershipRepository.GetUser(userName);

 

            if (user == null)

            {

                Guid defaultLanguageID = LanguageRepository.GetLanguage(Config.Site.LanguageDefault).ID;

 

                MembershipRepository.AddOpenIdUser(userName, nickname, email, defaultLanguageID);

            }

 

            FormsAuth.SetAuthCookie(userName, false);

        }

 

And in the SignIn.aspx view add a form for the OpenId to be entered:

             <div id="openid">

                <h2>Use Your Open ID</h2>

                <div id="spacer"></div>

                <form method="post" action="<% =Url.Action("OpenIdSignIn") %>" class="login">

              

                <!-- BEGIN ID SELECTOR -->

                <input type="text" class="openidinput" size="40" id="openid.claimed_id" name="openid.claimed_id" />

                <script type="text/javascript" >

                    idselector_input_id = "openid.claimed_id";

                </script>

                <script type="text/javascript" id="__openidselector" src="https://www.idselector.com/selector/9ef50c2962fc7066564dc829214efbe0ef945335" charset="utf-8"></script>

                <!-- END ID SELECTOR -->

                <input type="submit" value="<%= Localize("Login") %>" class="submit button" />

                <br />

                </form>

                <div class="hint">

                    Open ID is an identity system that allows you to sign in to websites with a single account.

                    Your username and password are secure with Open ID - and you don't have to remember yet another password.

                </div>

            </div>

 

And that's all.

We are using a nice bit of Javascript Ui from IdSelector.com which, as you can see, has a serial number in it. Unfortunately they've stopped issuing these. I hope a good replacement comes along.

There’s lots more that can be done with OpenId here. For instance, the OpenId login form would be useful on the comments page - OpenId users are more likely to be just casual commenters, whereas the people writing the blog could take the time to make a local login. The users created via OpenId do not have any permissions, so they can add comments but not post; which is a sensible default.

I have more than one OpenId, so it would be nice to group them together into my account. Oxite is not yet an OpenId provider, which would be interesting.

A mature system would be able to block open ids based on patterns in the url, allowing or disallowing providers based on security considerations. But Oxite first should gain ability to list users, and change their permissions – e.g. admin, editor, contributor or locked out, and track the user's time and IP of the last login, etc

I’m sure that I made mistakes in this implementation – there’s lots that I don’t know about MVC and about OpenId.

Published Tuesday, December 23, 2008 12:48 PM by Anthony.Steele

Comments

No Comments
Anonymous comments are disabled

About Anthony.Steele

Programmer in c# for Conchango

This Blog

Syndication

Powered by Community Server (Personal Edition), by Telligent Systems