Adding a Change Password ASPX page to MOSS for AD-authenticated extranet users

Goal: Add a Change Password capability to an extranet MOSS site so that users can change their password.

Assumptions: Environment uses Windows authentication not Forms Based Authentication. Active Directory is the Membership Provider.

Since this is an extranet, users will never have access to a workstation that is a member of the domain. Last time I had to do this, I was working with SharePoint Portal Server 2003 and had to write this as a custom web part that talked to Active Directory using the Directory Services API’s in .NET 1.1. Bringing that old web part into MOSS is not the best way to do this. It’s better to use the ChangePasword login control from the .NET 2.0 (and later) framework, and create a very simple _Layouts page to do the job. Then make that page available by putting a link to it on the Welcome menu.

But wait! Is creating a change password page necessary? Well, I think so: although there is a password.aspx page in _layouts, when I try to use it, it produces the following error: “Operation is not valid due to the current state of the object.” I suspect it would take more effort to try to figure out what it’s complaining about than to make our own change password page.

There are some differences between the most basic MOSS change password page and a generic ASP.NET change password page. They are:

MOSS Page

Pure ASP.NET Page

<%@ Assembly Name=”Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c”%>

<%@ Page Language=”C#” MasterPageFile=”~/_layouts/application.master”

Inherits=”Microsoft.SharePoint.WebControls.LayoutsPageBase” %>

<%@ Import Namespace=”Microsoft.SharePoint” %>

<asp:Content ID=”MainContent” ContentPlaceHolderID=”PlaceHolderMain” Runat=”Server”>

<asp:changepassword id=”ChangePassword1″ runat=”server”

PasswordHintText =

“Please enter a password at least 7 characters long,

containing a number and one special character.”

NewPasswordRegularExpression =

‘@\”(?=.{7,})(?=(.*\d){1,})(?=(.*\W){1,})’

NewPasswordRegularExpressionErrorMessage =

“Error: Your password must be at least 7 characters long,

and contain at least one number and one special character.” >

</asp:changepassword>

</asp:Content>

<%@ page language=“C#”%> <!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>

<html>

<head>

<title>Change Password with Validation</title>

</head>

<body>

<form id=“form1” runat=“server”>

<div>

<asp:changepassword id=“ChangePassword1” runat=“server” PasswordHintText = “Please enter a password at least 7 characters long, containing a number and one special character.” NewPasswordRegularExpression = ‘@\”(?=.{7,})(?=(.*\d){1,})(?=(.*\W){1,})’ NewPasswordRegularExpressionErrorMessage = “Error: Your password must be at least 7 characters long, and contain at least one number and one special character.” >

</asp:changepassword>

</div>

</form>

</body>

</html>

In other words, all the tags other than the <asp:changepassword> tags provide the chrome, and the <asp:changepassword> tag provides the functionality we care about. Note that neither page needs a code-behind at this point. Of course, if you need to do custom logic, you would want a code behind.

So now that the code is developed, how do we deploy it? Well, we want to put the file in the _Layouts directory, and have a link to it show up on the Welcome (Personal Actions) menu. So we need a SharePoint Feature that specifies a custom action. Wrapping that in a SharePoint Solution Package wouldn’t hurt either.

References:

Useful examples: http://glorix.blogspot.com/2007/08/custom-action-locations-and-groupid.html and http://office12.blogspot.com/2007/07/changepassword-page-for-fbaform-based.html

MSDN ChangePassword Control reference: http://msdn2.microsoft.com/en-us/library/system.web.ui.webcontrols.changepassword.aspx

Except that we are forgetting one very important thing: testing! So before I actually deployed this via a feature, I dropped the Change Password ASPX page into the Layouts directory and tried it out. I ran into two issues:

  1. The regular expression documented in the MSDN page listed above does not work as advertised. I think there is an unmatched doublequote.
  2. When I click the button to change the password, I get back an “Unknown Error” message.

So now I am confused – isn’t the concept of a membership provider supposed to abstract away the question of which authentication method is being used? But it seems like it isn’t. That is, I have to conclude that I can’t use the Change Password login control with Windows Authentication, only with Forms Based Authentication.

Michael