Jarrett's Tech Blog

.net, c#, asp.net, linq, htpc, woodworking

Add OpenID to BlogEngine.NET 1.4 Part 1

clock July 5, 2008 18:26 by author Jarrett

Here is a guide on how to add OpenID support to BlogEngine.NET 1.4. This first blog post will detail how to use an OpenID account to login as an existing blog user via impersonation.  I've used Andrew's blog post How to add OpenID support to BlogEngine.NET as a starting place. 

Pros

  • Quick, minimum changes required
  • Retains support of blogging tools (such as Live Writer)
  • Easy to understand and backwards compatible

Cons

  • Not "true" OpenID integration
  • Accounts are maintained separately
  • Impersonation file is required

Step 1: Download latest release of dotnetopenid library

Step 2: Place DotNetOpenId.dll into Bin folder (if compiling BlogEngine.Web then add reference to project)

Step 3: Update Login.aspx page

  • Add
<%@ Register Assembly="DotNetOpenId" Namespace="DotNetOpenId.RelyingParty" TagPrefix="RP" %>
  • Replace
<asp:Login ID="Login1" runat="server" class="loginbox" />

with

<RP:OpenIdLogin ID="OpenIdLogin1" runat="server" onloggedin="OpenIdLogin1_LoggedIn" /> 

Step 4: Update Login.aspx.cs code behind file

  • Replace
protected void Page_Load(object sender, EventArgs e) 
{ 
  if (Page.User.Identity.IsAuthenticated) 
  { 
    changepassword1.Visible = true; 
    changepassword1.ContinueButtonClick += new EventHandler(changepassword1_ContinueButtonClick); 
    lsLogout.Visible = true; 
    Login1.Visible = false; 
    Page.Title += Resources.labels.changePassword; 
  }  
  else 
  { 
    Login1.LoggedIn += new EventHandler(Login1_LoggedIn); 
    Login1.FindControl("username").Focus(); 
  } 
}

with

protected void Page_Load(object sender, EventArgs e) 
{ 
  if (Page.User.Identity.IsAuthenticated) 
  { 
    changepassword1.Visible = true; 
    changepassword1.ContinueButtonClick += new EventHandler(changepassword1_ContinueButtonClick); 
    lsLogout.Visible = true; 
    OpenIdLogin1.Visible = false; 
    Page.Title += Resources.labels.changePassword; 
  } 
} 
  • Replace
void Login1_LoggedIn(object sender, EventArgs e) 
{ 
  if (!Roles.IsUserInRole(Login1.UserName, BlogEngine.Core.BlogSettings.Instance.AdministratorRole)) 
    Response.Redirect(BlogEngine.Core.Utils.RelativeWebRoot, true); 
}

with

protected void OpenIdLogin1_LoggedIn(object sender, DotNetOpenId.RelyingParty.OpenIdEventArgs e) 
{ 
  //don't allow login control to login, we will do that manually 
  e.Cancel = true; 
  //get impersonated user 
  string user = Impersonation.Impersonate(e.ClaimedIdentifier); 
  if (!Roles.IsUserInRole(user, BlogEngine.Core.BlogSettings.Instance.AdministratorRole)) 
    Response.Redirect(BlogEngine.Core.Utils.RelativeWebRoot, true); 
  else 
    FormsAuthentication.RedirectFromLoginPage(user, OpenIdLogin1.RememberMe); 
}

Step 5: Add Impersonation.xml file to App_Data folder

<impersonation> 
  <impersonate> 
    <id>http://jarrettv.myopenid.com/</id> 
    <user>Jarrett</user> 
  </impersonate> 
</impersonation>

Step 6: Add Impersonation.cs to BlogEngineCore project and compile

using System;
using System.Linq;
using System.Xml.Linq;
using System.Web;
using System.Web.Hosting;

namespace BlogEngine.Core
{
    public class Impersonation
    {
        public static string Impersonate(string id)
        {
            string user = id;
            string path = BlogSettings.Instance.StorageLocation + "impersonation.xml";
            
            if (!VirtualPathUtility.IsAppRelative(path))
                throw new ArgumentException("xmlFileName must be app-relative");

            string fullyQualifiedPath = VirtualPathUtility.Combine
                (VirtualPathUtility.AppendTrailingSlash
                (HttpRuntime.AppDomainAppVirtualPath), path);

            string actualPath = HostingEnvironment.MapPath(fullyQualifiedPath);

            XDocument xDoc = XDocument.Load(actualPath);
            user = xDoc.Element("impersonation").Elements("impersonate")
                .Where(x => x.Element("id").Value == id).Select(x => x.Element("user")).Single().Value;
            return user;
        }
    }
}

Step 7: Deploy following changed files

  • Login.aspx
  • Login.aspx.cs
  • \Bin\BlogEngine.Core.dll
  • \Bin\DotNetOpenId.dll
  • \App_Data\Impersonation.xml

image

In the next part, I will add OpenID support to the comment system.

Technorati Tags: ,,,

Currently rated 4.7 by 3 people

  • Currently 4.666667/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5


Comments

Comment by DotNetKicks.com on Sunday, July 06, 2008 4:22 AM

trackback

Trackback from DotNetKicks.com

Add OpenID to BlogEngine.NET 1.4 Part 1

Comment by Andrew on Sunday, July 06, 2008 3:24 PM

Andrew

Great post, and great build on the post you link to.

One suggestion though: near where you demand file permissions on the impersonation file, your comment says you're checking for read permissions but you actually demand write permissions. Why do you need write permissions? And if you only need read permissions, why do you do the Demand before calling XDocument.Load? Internally it will demand those permissions anyway.

Comment by Jarrett on Sunday, July 06, 2008 6:21 PM

Jarrett

Andrew, you are right. I originally took the "pathing" code from the XmlMembershipProvider and failed to remove the demand lines. Thanks for pointing that out. I've updated the code.

Add comment