Welcome to blogs.conchango.com Sign in | Join | Help

Welcome to blogs.conchango.com

Anthony Steele's Blog

Adding OpenId to Oxite, part 1

I am following up on my last post on Oxite by showing how to add OpenId login support to it. I won't finish this today. This first one will cover the repository changes needed.

First, download the Oxite source and set up the database. From a database perspective, the table where user logins are stored is called oxite_user. In code this is referenced via the IUser interface.

In general, I would like to use the OpenId "claimed identifier" as the user name. User names have to be unique, so this the user name “http://AnthonySteele.myopenid.com/” is used up by my OpenID login, but I think we can live with that. We can tell OpenId logins from regular ones by eye (OpenId logins look like Urls), but I'd like a flag to do it unambiguously.

In the code this flag is an enumeration:

namespace Oxite.Data

{

    /// <summary>

    /// How does the user log in

    /// </summary>

    public enum UserLoginMethod: byte

    {

        /// <summary>

        /// Default/unknown value

        /// </summary>

        Unknown = 0,

 

        /// <summary>

        /// The user has a local user name and password

        /// </summary>

        LocalLogin = 1,

 

        /// <summary>

        /// The user logs in using an openId from a different site

        /// </summary>

        OpenId = 2

    }

}

 

There could be Cardspace or some other kind of login later. the flag needs to be stored on the user data in the database, with all existing logins marked as “local login”. In SQL, execute:

alter table oxite_user

add UserLoginMethod tinyint not null default 1;


Add the login method to the IUser interface:

    public interface IUser

    {

... as before...

 

        UserLoginMethod LoginMethod { get; set; }

Then fix the fake implementation of IUser with an auto property:

    public class FakeUser : IUser

    {

        #region IUser Members

... as before...

 

        public UserLoginMethod LoginMethod { get; set; }

 

Then do some drag and drop to regenerate the LINQ data classes, which will give the database-backed User class a property UserLoginMethod, of type short. Now we want the strongly-typed wrapper:

 

    partial class oxite_User : IUser

    {

        #region IUser Members

 

        ... as before ...

 

 

        public UserLoginMethod LoginMethod

        {

            get

            {

                return (UserLoginMethod)UserLoginMethod;

            }

            set

            {

                UserLoginMethod = (byte)value;

            }

        }

 

The Oxite membership repository does not yet have a way to add users, so we need to add one:

 

    public interface IMembershipRepository

    {

        ... as before ...

 

        /// <summary>

        /// Add a new user with an OpenId login

        /// </summary>

        /// <param name="userName">The claimed identifier</param>

        /// <param name="displayName">the name to use onscreen</param>

        /// <param name="email"></param>

        /// <param name="defaultLanguageId"></param>

        /// <returns></returns>

        IUser AddOpenIdUser(string userName, string displayName, string email, Guid defaultLanguageId);

 

This is implemented in the fake repository as follows:

        public IUser AddOpenIdUser(string userName, string displayName, string email, Guid defaultLanguageId)

        {

            FakeUser newUser = new FakeUser();

            newUser.ID = Guid.NewGuid();

 

            newUser.Username = userName;

            newUser.DisplayName = displayName;

            newUser.Email = email;

 

            newUser.LoginMethod = UserLoginMethod.OpenId;

 

            Users.Add(newUser);

 

            return newUser;

        }

And in the Linq to SQL repository as follows. This isn't perfect (particularly the choice of salt should be unique to the user, and it's not clear how the email should be hashed), but it will do until more complete user-adding code is in place in Oxite.

        public IUser AddOpenIdUser(string userName, string displayName, string email, Guid defaultLanguageId)

        {

            oxite_User newUser = new oxite_User();

            newUser.ID = Guid.NewGuid();

            newUser.Username = userName;

            newUser.DisplayName = displayName;

 

            newUser.Email = email;

            newUser.PasswordSalt = "NaCl";

 

            newUser.Password = saltAndHash(userName, newUser.PasswordSalt);

            newUser.HashedEmail = saltAndHash(email, newUser.PasswordSalt);

 

            newUser.LoginMethod = UserLoginMethod.OpenId;

            newUser.DefaultLanguageID = defaultLanguageId;

            newUser.Status = 1;

 

            dataContext.oxite_Users.InsertOnSubmit(newUser);

            dataContext.SubmitChanges();

 

            return newUser;

        }

 

So that’s the repositories and domain objects.  Next: the controller and view code to make OpenId logins possible.

Published 22 December 2008 15:05 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