Windows Integrated Authentication in ScrewTurn Wiki

ScrewTurn Wiki is a simple, open source wiki engine that reproduces much of the functionality found in Mediawiki. ScrewTurn Wiki is powered by ASP.NET 2 and Microsoft SQL Server, which makes it ideal for Windows-centric corporate environments. Unfortunately, ScrewTurn Wiki has no out-of-the box support for Windows Integrated Authentication (and, according to the developer, never will).

Windows Integrated Authentication allows users’ credentials to be automatically passed to IIS. This allows the application (if it supports it) to use Windows login details – i.e., the same user name across an entire domain. The user is automatically and seamlessly logged in to the application – a huge benefit over having to remember multiple user names and passwords.

I have created a simple Windows Integrated Authentication implementation for ScrewTurn Wiki, similar to that used by Community Server (another ASP.NET/SQL Server-based collaboration tool). Note that ScrewTurn Wiki’s Plugin Framework does not cater for extra functionality at this level (yet). When a new session is spawned on the web server, the application searches for an account matching the user’s login name. If none is found, a new account is created automatically. Events are logged via the standard ScrewTurn Wiki event log.

Replace Session_Start in ScrewTurn Wiki’s Global.asax with the following:

void Session_Start(object sender, EventArgs e)
{
    // Code that runs when a new session is started
    ScrewTurn.Wiki.Users.OnlineUsers++;
    ScrewTurn.Wiki.SessionFacade.Breadcrumbs = new ScrewTurn.Wiki.BreadcrumbsManager();

    // Get identity name from web server.
    string identityName = System.Web.HttpContext.Current.User.Identity.Name;
    if (identityName == null || identityName.Length < 1)
        throw new System.ApplicationException("Could not get current Windows user name." +
            "Ensure Integrated Windows Authentication is enabled.");

    string username;

    // Strip domain prefix (e.g. "\\COMPANY.NET\DoeJ").
    int domainDelimOffset = identityName.IndexOf("\\");
    if (domainDelimOffset > 0)
        username = identityName.Substring(domainDelimOffset + 1);
    else
        username = identityName;

    if (username.Length < 1)
        throw new System.ApplicationException("Username " + identityName +
            " is empty after domain stripped.");

    // Locate user.
    ScrewTurn.Wiki.PluginFramework.UserInfo user =
            ScrewTurn.Wiki.Users.Instance.Find(username);

    if (user == null)
    {
        // User not found, add a new one.
        if (!ScrewTurn.Wiki.Users.Instance.AddUser(username, string.Empty,
                string.Empty, true, false, null))
            throw new System.ApplicationException("Could not add user \""
                + username + "\".");

            // Get freshly-added user.
            user = ScrewTurn.Wiki.Users.Instance.Find(username);
            if (user == null)
                throw new System.ApplicationException("Could not find user \""
                    + username + "\".");
    }

    // Set up session.
    ScrewTurn.Wiki.SessionFacade.LoginKey =
        ScrewTurn.Wiki.Tools.ComputeSecuredUsernameHash(user.Username);
    ScrewTurn.Wiki.SessionFacade.Username = user.Username;
    ScrewTurn.Wiki.SessionFacade.Admin = user.Admin;

    // Log event.
    ScrewTurn.Wiki.Log.LogEntry("User " +
        ScrewTurn.Wiki.SessionFacade.Username +
        " logged in through Windows Integrated Authentication",
        ScrewTurn.Wiki.EntryType.General, "SYSTEM");
}

For more information about Windows Integrated Authentication and ScrewTurn Wiki (including comments on this implementation), see this thread at the ScrewTurn Wiki forum.

4 thoughts on “Windows Integrated Authentication in ScrewTurn Wiki

  1. I think line 9 contanis a bug:

    an exception is thrown when the length of the identity name is greater than 1.

    you have to replace “>” with “<“.

  2. Hi – ScrewTurn has undergone some API changes since this was posted but it fundamentally still seems to work, and I don’t know a better way. Here is my revised one, against ScrewTurn v3.04.560:

    protected void Session_Start(Object sender, EventArgs e)
    {
    // Code that runs when a new session is started
    ScrewTurn.Wiki.Cache.OnlineUsers++;
    //ScrewTurn.Wiki.SessionFacade.Breadcrumbs = new ScrewTurn.Wiki.BreadcrumbsManager();

    // Get identity name from web server.
    string identityName = System.Web.HttpContext.Current.User.Identity.Name;
    if (identityName == null || identityName.Length 0)
    username = identityName.Substring(domainDelimOffset + 1);
    else
    username = identityName;

    if (username.Length < 1)
    throw new System.ApplicationException("Username " + identityName +
    " is empty after domain stripped.");

    // Locate user.
    var user =
    ScrewTurn.Wiki.Users.FindUser(username);

    if (user == null)
    {
    // User not found, add a new one.
    if (!ScrewTurn.Wiki.Users.AddUser(username, string.Empty,
    "password", "bob@example.com", true, null))
    throw new System.ApplicationException("Could not add user \""
    + username + "\".");

    // Get freshly-added user.
    user = ScrewTurn.Wiki.Users.FindUser(username);
    if (user == null)
    throw new System.ApplicationException("Could not find user \""
    + username + "\".");

    ScrewTurn.Wiki.Users.SetUserMembership(user, new string[] {"Users"});
    }

    // Set up session.
    ScrewTurn.Wiki.SessionFacade.LoginKey =
    ScrewTurn.Wiki.Users.ComputeLoginKey(user.Username, user.Email, user.DateTime);
    ScrewTurn.Wiki.SessionFacade.CurrentUsername = user.Username;
    // ScrewTurn.Wiki.SessionFacade.Admin = user.Admin;

    // Log event.
    ScrewTurn.Wiki.Log.LogEntry("User " +
    ScrewTurn.Wiki.SessionFacade.CurrentUsername +
    " logged in through Windows Integrated Authentication",
    ScrewTurn.Wiki.PluginFramework.EntryType.General, "SYSTEM");
    }

Comments are closed.