<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>MaisonBisson.com &#187; authentication</title>
	<atom:link href="http://maisonbisson.com/blog/post/tag/authentication/feed/" rel="self" type="application/rss+xml" />
	<link>http://maisonbisson.com</link>
	<description>A bunch of stuff I would have emailed you about.</description>
	<lastBuildDate>Sat, 14 Nov 2009 20:14:03 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.5.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Hacking WordPress Login and Password Reset Processes For My University Environment</title>
		<link>http://maisonbisson.com/blog/post/14110/wordpress-user-authentication-hacks/</link>
		<comments>http://maisonbisson.com/blog/post/14110/wordpress-user-authentication-hacks/#comments</comments>
		<pubDate>Tue, 29 Sep 2009 16:16:16 +0000</pubDate>
		<dc:creator>Casey</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[authentication]]></category>
		<category><![CDATA[CAS]]></category>
		<category><![CDATA[hacks]]></category>
		<category><![CDATA[identity]]></category>
		<category><![CDATA[identity management]]></category>
		<category><![CDATA[idm]]></category>
		<category><![CDATA[login]]></category>
		<category><![CDATA[single sign on]]></category>
		<category><![CDATA[university portal]]></category>
		<category><![CDATA[wordpress]]></category>
		<category><![CDATA[WordPress MU]]></category>

		<guid isPermaLink="false">http://maisonbisson.com/?p=14110</guid>
		<description><![CDATA[
ny university worth the title is likely to have a very mixed identity environment. At Plymouth State University we&#8217;ve been pursuing a strategy of unifying identity and offering single sign-on to web services, but an inventory last year still revealed a great number of systems not integrated with either our single sign-on (AuthN) or authorization [...]]]></description>
			<content:encoded><![CDATA[<abbr class="unapi-id" title="maisonbisson-14110"><!-- &nbsp; --></abbr>
<div class="contents innerindex"><h3>Contents</h3><ol><li><a href="http://maisonbisson.com/blog/post/14110/wordpress-user-authentication-hacks/#14110_platform-choices_1">Platform Choices</a></li><li><a href="http://maisonbisson.com/blog/post/14110/wordpress-user-authentication-hacks/#14110_our-needs-vs-wordpre_1">Our Needs vs. WordPress</a></li><li><a href="http://maisonbisson.com/blog/post/14110/wordpress-user-authentication-hacks/#14110_what-we-did_1">What We Did</a></li><li><a href="http://maisonbisson.com/blog/post/14110/wordpress-user-authentication-hacks/#14110_what-it-looks-like_1">What It Looks Like</a></li></ol></div>Any university worth the title is likely to have a very mixed identity environment. At <a href="http://www.plymouth.edu/">Plymouth State University</a> we&#8217;ve been pursuing a strategy of unifying identity and offering single sign-on to web services, but an inventory last year still revealed a great number of systems not integrated with either our single sign-on (<a title="Authentication - Wikipedia, the free encyclopedia" href="http://en.wikipedia.org/wiki/Authentication">AuthN</a>) or authorization systems (<a title="Authorization - Wikipedia, the free encyclopedia" href="http://en.wikipedia.org/wiki/Authorization">AuthZ</a>, see <a href="http://en.wikipedia.org/wiki/Authentication#Authentication_vs._authorization">difference</a>). And in addition to the many application/system specific stores of identity information (even for those systems integrated into our single sign-on environment), we also use both LDAP and AD (which we try to synchronize at the application level). Worst of all, the entire environment is provisioned solely from our <a href="http://en.wikipedia.org/wiki/Management_information_system">MIS database</a>, which is good if you want to make sure that students and faculty get user accounts, but bad if you want to provision an account for somebody who doesn&#8217;t fit into one of those roles.</p>
<p>The one way relationship between our user accounts and the MIS database also makes it difficult to engage with new users online. If you can&#8217;t get an account until you become a student, how do you allow potential students to apply online if all your systems are integrated with single sign-on? And if you can&#8217;t authenticate the online identity of your users, how do you set initial passwords into your system? Or allow them to reset a forgotten password online?</p>
<p>Internet companies never struggled with this issue, as their customers could only approach them online, but most universities built systems around paper applications and have fond (and relatively recent) memories of offering their students their first internet experience. It&#8217;s still not unusual for universities to offer their students their campus computing account with a default password based on supposedly secret data shared between the user and the school. But your SSN, birth date, and mother&#8217;s name are no longer secret. A proposed change in FERPA policy (see the <a href="http://edocket.access.gpo.gov/2008/pdf/E8-5790.pdf">the top of page 15586 in the NPRM</a>) would have barred the use of “a common form user name (e.g., last name and first name initial) with date of birth or SSN, or a portion of the SSN, as an initial password to be changed upon first use of the system” in systems that store academic data. The final rule excluded that provision, much to the relief of those schools with more lobbying clout than brains.</p>
<p><span id="more-14110"></span></p>
<h3 id="14110_platform-choices_1">Platform Choices</h3>
<p>Rather than wait to see how the ruling played out last year, we went to work trying to improve security while easing access to our systems (no, that is not self-contradictory). Our challenges were thus:</p>
<ul>
<li>Fix initial password assignment</li>
<li>Fix password resets</li>
<li>Allow users with a loose or undefined relationship to the institution to create limited accounts for the purpose of interacting with the institution or its members</li>
</ul>
<p>We considered a number of paths to a solution, including hacking of our university portal (which hosts the CAS single sign-on in our environment), expansion of a limited home-built solution, and a review of commercial and open source products and frameworks. We simplified the problem by confirming that the FERPA rule did not require us to authenticate the “real life” identity of a person; rather, we had only to validate the online identity of a person (saving us from needing to do things like send confirmation PINs by postal mail to a person&#8217;s home address).</p>
<p>In the end, we chose WordPress MU. Significant factors were our experience with the software (all the MIS developers use it personally), the extensibility of it as an application platform, the development focus on user experience (especially in recent versions), and our interest in using it as a framework for other user-facing services (especially BuddyPress).</p>
<h3 id="14110_our-needs-vs-wordpre_1">Our Needs vs. WordPress</h3>
<ul>
<li>The system must serve as the front end to our single sign-on environment, using our AD and LDAP password stores to authenticate users who have accounts in those systems.</li>
<li>External email addresses, once verified with some challenge/response, can be used to reset a password.</li>
<li>Users who are presently affiliated with the school have a school-provided email address, but no external address with which to reset their lost passwords.</li>
<li>Users who are not presently affiliated with the school have no school-provided email address, and must verify their external email address before their account is activated. They can then set their own password once they verify their email address.</li>
<li>The ability to send password reset codes via SMS would be nice (especially considering the number of long-time employees of the university who do not have personal email accounts), though that also requires the verification of the user&#8217;s cell phone number.</li>
</ul>
<p>After reviewing what we wanted to do, we surveyed WordPress&#8217; code to develop an implementation plan. And, because a number of aspects of our application process were changing, we decided to focus on allowing current users to self-reset their password and postpone development of account self-creation features for new users. Still, a few issues quickly emerged:</p>
<ul>
<li>WordPress requires a username be assigned to each user, rather than relying on email address (this is <a href="http://core.trac.wordpress.org/ticket/9568">likely to change in WP 2.9</a>) Creating a new username for our users is unacceptable, but adding a large number of new users to our existing username space will quickly deplete the “good” usernames. And changing a user&#8217;s username as their affiliation with the institution is unacceptable.</li>
<li>The <a href="http://core.trac.wordpress.org/browser/tags/2.8.4/wp-includes/pluggable.php#L456">core user authentication function</a> can be replaced with our own function. (And in 2.8 it became filterable)</li>
<li><a href="http://trac.mu.wordpress.org/browser/tags/2.8.4a/wp-admin/includes/mu.php#L250">WordPress MU will validate email addresses</a>, but the system isn&#8217;t built to be extensible.</li>
<li>WordPress only stores <a href="http://codex.wordpress.org/Database_Description#Table:_wp_users">one email address per user</a>, but the <a href="http://codex.wordpress.org/Function_Reference/update_usermeta">user meta system</a> can be used to store a second one. Unfortunately (and in a manner inconsistent with post meta), <a href="http://core.trac.wordpress.org/ticket/7540">only one value per meta key per user is allowed</a>, making it difficult to allow users to have an arbitrary number of email addresses associated with their account.</li>
<li>The function that <a href="http://core.trac.wordpress.org/browser/tags/2.8.4/wp-includes/pluggable.php#L211">identifies a user by a given email address</a> can be replaced with a function that also checks the secondary address.</li>
<li><a href="http://codex.wordpress.org/Users_Your_Profile_SubPanel">WordPress user profiles</a> have no phone field, but the user meta system can be used to store one. A function to identify a user by a given phone number must also be created.</li>
<li>Unlike <a href="http://core.trac.wordpress.org/browser/tags/2.8.4/wp-admin/options-privacy.php">some settings pages</a>, the fields on the user profile editor cannot be changed simply by modifying the <code>$wp_settings_fields</code> array.</li>
<li>Upon doing a password reset, the user is <a href="http://core.trac.wordpress.org/browser/tags/2.8.4/wp-login.php#L203">sent a temporary password</a>, rather than being allowed to set a new password. This contradicts University policy about how passwords are used and communicated and could train users that sending passwords by mail is acceptable.</li>
<li>The various functions in <code><a href="http://core.trac.wordpress.org/browser/tags/2.7/wp-login.php">wp-login.php</a></code> <em>cannot</em> be replaced, and in WP 2.7 the code had no way to add or replace various login actions (<a href="http://core.trac.wordpress.org/browser/tags/2.8.4/wp-login.php#L307">WP 2.8 changed that</a>).</li>
<li><a href="http://trac.mu.wordpress.org/browser/tags/2.8.4a/wp-includes/wpmu-functions.php">WPMU-specific functions</a> don&#8217;t always follow WP coding standards or models.</li>
</ul>
<p>(Note that we began our work and deployed the system under WPMU 2.7. WPMU 2.8 included a few changes that made the process easier. I&#8217;m proud to say that some of those changes were a result of code we offered back to WP during our development.)</p>
<h3 id="14110_what-we-did_1">What We Did</h3>
<ul>
<li>We decided that email addresses (both PSU addresses and external addresses), as well as PSU usernames would be acceptable identifiers for an account, and that a person should be able to log in to our web services using any of those identifiers. So&#8230;</li>
<li>We replaced <code>wp_autenticate()</code> with our own function that accepts either email address or university username, checks to see if the user exists locally, checks to see if they exist in AD or LDAP, confirms their password, provisions their WordPress account (for university users who&#8217;ve not logged in via this method yet), establishes a session with our university portal and redirects them there (unless $redirect is set to something more specific that the dashboard).</li>
<li>We decided to replace WordPress&#8217; usernames with a random string matching a pattern we established. This became the WPID. Doing this required us to hide references to username (easy if you set a preferred display name)</li>
<li>To store phone numbers and secondary email addresses, and allow users to edit those within their profile, I created the <a href="http://wordpress.org/extend/plugins/alternate-contact-info/">Alternate Contact Info plugin</a> (<a href="http://plugins.trac.wordpress.org/browser/alternate-contact-info/trunk/altcontact.php">browse source</a>). This requires more use of <a href="http://php.net/ob_start">output buffering</a> than I&#8217;d like, but it gets the job done.</li>
<li>To confirm email addresses and phone numbers via a challenge/response message (and support other interactions), I created the <a title="WordPress › WordPress Ticket Framework « WordPress Plugins" href="http://wordpress.org/extend/plugins/wp-ticket-framework/">WordPress Ticket Framework plugin</a> (<a href="http://maisonbisson.com/blog/post/13862/wordpress-action-ticketing-api/">my introduction</a>, <a title="/wp-ticket-framework/trunk/ticket-framework.php – WordPress Plugin Repository" href="http://plugins.trac.wordpress.org/browser/wp-ticket-framework/trunk/ticket-framework.php">browse source</a>).</li>
<li>To send messages via SMS, we used my <a title="» wpSMS MaisonBisson.com" href="http://maisonbisson.com/projects/wpsms/">wpSMS plugin</a> (<a title="WordPress › wpSMS « WordPress Plugins" href="http://wordpress.org/extend/plugins/wpsms/">in the plugin directory</a>, <a title="/wpsms/trunk/wpsms.php – WordPress Plugin Repository" href="http://plugins.trac.wordpress.org/browser/wpsms/trunk/wpsms.php">browse source</a>).</li>
<li><a href="http://borkweb.com/">Matther Batchelder</a> <a href="https://connect.plymouth.edu/wp-login.php">re-skinned the login screen</a> via a plugin that inserts our custom CSS.</li>
<li>After determining that our university portal could not be made to authenticate via CAS, I gave up work on my <a href="http://plugins.trac.wordpress.org/browser/wpcas-server/trunk/wpcas-server.php">wpCAS Server plugin</a> and developed another method to initiate the portal session (which then establishes a CAS session using the portal&#8217;s CAS server).</li>
<li>We replaced most of the functionality of the <code>wp-login.php</code> page (by hacking core at first, then taking advantage of the action hook in 2.8). In doing so we were able to change the password reset behavior to allow users to immediately change their password after entering their reset code (which was sent to their email address or phone via SMS).</li>
</ul>
<p>Over time we extended the system to <a href="http://maisonbisson.com/blog/post/14028/wordpress-hacks-managing-multiple-sub-domains/">host multiple domains</a> and <a href="http://maisonbisson.com/blog/post/14052/wordpress-hacks-nested-paths-for-wpmu-blogs/">replace our CMS</a>. Soon we&#8217;ll consolidate our  <a href="http://blogs.plymouth.edu/">public blogging instance</a> into it, and we&#8217;re building an invite system that we can use to invite people to join our community.</p>
<h3 id="14110_what-it-looks-like_1">What It Looks Like</h3>
<p><div id="attachment_14121" class="wp-caption aligncenter" style="width: 310px"><a href="http://maisonbisson.com/files/2009/09/login.png"><img class="size-medium wp-image-14121" src="http://maisonbisson.com/files/2009/09/login-300x159.png" alt="The re-skinned WordPress login" width="300" height="159" /></a><p class="wp-caption-text">The re-skinned WordPress login</p></div>
<div id="attachment_14122" class="wp-caption aligncenter" style="width: 310px"><a href="http://maisonbisson.com/files/2009/09/password-recovery.png"><img class="size-medium wp-image-14122" src="http://maisonbisson.com/files/2009/09/password-recovery-300x179.png" alt="Entering an email address or username to get a password reset code" width="300" height="179" /></a><p class="wp-caption-text">Entering an email address or username to get a password reset code</p></div>
<div id="attachment_14129" class="wp-caption aligncenter" style="width: 310px"><a href="http://maisonbisson.com/files/2009/09/sms-text.PNG"><img class="size-medium wp-image-14129" src="http://maisonbisson.com/files/2009/09/sms-text-300x126.PNG" alt="SMS text with password reset code" width="300" height="126" /></a><p class="wp-caption-text">SMS text with password reset code</p></div>
<div id="attachment_14123" class="wp-caption aligncenter" style="width: 310px"><a href="http://maisonbisson.com/files/2009/09/password-reset.png"><img class="size-medium wp-image-14123" src="http://maisonbisson.com/files/2009/09/password-reset-300x268.png" alt="Enter the password reset code from the SMS text message here, or follow the link from the email" width="300" height="268" /></a><p class="wp-caption-text">Enter the password reset code from the SMS text message here, or follow the link from the email</p></div>
<div id="attachment_14124" class="wp-caption aligncenter" style="width: 310px"><a href="http://maisonbisson.com/files/2009/09/personal-profile.png"><img class="size-medium wp-image-14124" src="http://maisonbisson.com/files/2009/09/personal-profile-300x201.png" alt="Your extended contact information in the WordPress profile" width="300" height="201" /></a><p class="wp-caption-text">Extended contact information in the WordPress profile</p></div>
<p>And that&#8217;s how we replaced our authentication system with WordPress, gained self-service password resets, and built the foundation to invite new users into our system.</p>
]]></content:encoded>
			<wfw:commentRss>http://maisonbisson.com/blog/post/14110/wordpress-user-authentication-hacks/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>WordPress Hacks: Serving Multiple Domains</title>
		<link>http://maisonbisson.com/blog/post/14028/wordpress-hacks-managing-multiple-sub-domains/</link>
		<comments>http://maisonbisson.com/blog/post/14028/wordpress-hacks-managing-multiple-sub-domains/#comments</comments>
		<pubDate>Thu, 03 Sep 2009 17:41:57 +0000</pubDate>
		<dc:creator>Casey Bisson</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[authentication]]></category>
		<category><![CDATA[cms]]></category>
		<category><![CDATA[cookies]]></category>
		<category><![CDATA[hacks]]></category>
		<category><![CDATA[sub-domains]]></category>
		<category><![CDATA[wordpress]]></category>
		<category><![CDATA[WordPress MU]]></category>

		<guid isPermaLink="false">http://maisonbisson.com/?p=14028</guid>
		<description><![CDATA[
strong>Situation: using WordPress MU (possibly including BuddyPress) on multiple domains or sub-domains of a large organization with lots of users.
WordPress MU is a solid CMS to support a large organization. Each individual blog has its own place in the organization&#8217;s URL scheme (www.site.org/blogname), and each blog can have its own administrators and other users. Groups [...]]]></description>
			<content:encoded><![CDATA[<abbr class="unapi-id" title="maisonbisson-14028"><!-- &nbsp; --></abbr>
<div class="contents innerindex"><h3>Contents</h3><ol><li><a href="http://maisonbisson.com/blog/post/14028/wordpress-hacks-managing-multiple-sub-domains/#14028_challenge-setting-up_1">Challenge: setting up service on multiple (sub-) domains</a><ol><li><a href="http://maisonbisson.com/blog/post/14028/wordpress-hacks-managing-multiple-sub-domains/#14028_set-up-your-web-serv_1">Set up your web server</a></li><li><a href="http://maisonbisson.com/blog/post/14028/wordpress-hacks-managing-multiple-sub-domains/#14028_set-up-your-dns_1">Set up your DNS</a></li><li><a href="http://maisonbisson.com/blog/post/14028/wordpress-hacks-managing-multiple-sub-domains/#14028_create-a-new-blog-in_1">Create a new blog in WPMU</a></li><li><a href="http://maisonbisson.com/blog/post/14028/wordpress-hacks-managing-multiple-sub-domains/#14028_reconfigure-wp-confi_1">Reconfigure wp-config.php</a></li><li><a href="http://maisonbisson.com/blog/post/14028/wordpress-hacks-managing-multiple-sub-domains/#14028_set-up-your-new-site_1">Set up your new Site</a></li><li><a href="http://maisonbisson.com/blog/post/14028/wordpress-hacks-managing-multiple-sub-domains/#14028_set-up-the-admins-of_1">Set up the admins of the new site</a></li><li><a href="http://maisonbisson.com/blog/post/14028/wordpress-hacks-managing-multiple-sub-domains/#14028_sub-domains-or-just-_1">Sub-domains or just different domains?</a></li></ol></li><li><a href="http://maisonbisson.com/blog/post/14028/wordpress-hacks-managing-multiple-sub-domains/#14028_challenge-unified-lo_1">Challenge: unified log in cookies</a><ol><li><a href="http://maisonbisson.com/blog/post/14028/wordpress-hacks-managing-multiple-sub-domains/#14028_set-your-cookie-path_1">Set your cookie path</a></li><li><a href="http://maisonbisson.com/blog/post/14028/wordpress-hacks-managing-multiple-sub-domains/#14028_avoid-conflicts-with_1">Avoid conflicts with other WordPress installations at your domain</a></li></ol></li><li><a href="http://maisonbisson.com/blog/post/14028/wordpress-hacks-managing-multiple-sub-domains/#14028_challenge-unified-lo_2">Challenge: unified log in location/URL</a><ol><li><a href="http://maisonbisson.com/blog/post/14028/wordpress-hacks-managing-multiple-sub-domains/#14028_filter-login_url-and_1">Filter login_url and logout_url</a></li><li><a href="http://maisonbisson.com/blog/post/14028/wordpress-hacks-managing-multiple-sub-domains/#14028_filter-allowed_redir_1">Filter allowed_redirect_hosts</a></li></ol></li></ol></div><strong>Situation:</strong> using WordPress MU (possibly including BuddyPress) on multiple domains or sub-domains of a large organization with lots of users.</p>
<p>WordPress MU is a solid CMS to support a large organization. Each individual blog has its own place in the organization&#8217;s URL scheme (<code>www.site.org/blogname</code>), and each blog can have its own administrators and other users. Groups of blogs in WPMU make up a &#8220;Site&#8221; and one or more Sites can be hosted with a single implementation. (I&#8217;m capitalizing Site for the same reason WordPress docs capitalize <a href="http://codex.wordpress.org/Pages">Page</a>) Each Site has a defined set of administrators and options controlling various features. You might, for instance, lock down the plugins on your <code>blogs.site.org</code>, while keeping it open on your <code>www.site.org</code>. Or maybe you&#8217;d like to let your helpdesk staff create new blogs at <code>blogs.site.org</code>, but not at <code>www.site.org</code>. That&#8217;s what WPMU&#8217;s notion of Site can help you control.<br />
<span id="more-14028"></span></p>
<h3 id="14028_challenge-setting-up_1">Challenge: setting up service on multiple (sub-) domains</h3>
<p>WordPress MU makes it easy to host both blogs.site.org and www.site.org within a single implementation, but there&#8217;s little documentation for how to do it.</p>
<p>Once you get WPMU up and running on one of your domains you can add another. The following assumes that you&#8217;re using the <code>vhost=no</code> setting (correct: I really mean vhost=no), that you have access to and know how to manipulate your MySQL, that you have control over your DNS and know how to use it, and that you know how to configure Apache or similar. You&#8217;d also be smart to turn off any object caching you may have running, at least until we&#8217;re done doing direct database manipulation.</p>
<p>Some might ask why I&#8217;m not simply using <a href="http://wordpress.org/extend/plugins/wordpress-mu-domain-mapping/">Donncha&#8217;s plugin</a>, and the answer is simple: it only works for <code>vhost=yes</code> sites. For my own use, I find that sub-directories are easier for users to make sense of (go ahead, try to tell your mom to go to &#8220;<code>myblog.sub.domain.org</code>&#8220;).</p>
<h4 id="14028_set-up-your-web-serv_1">Set up your web server</h4>
<p>If you&#8217;re using Apache, you&#8217;ll either need to create an <a href="http://httpd.apache.org/docs/2.2/vhosts/ip-based.html">IP-based virtual host</a> or <a href="http://maisonbisson.com/blog/post/12781/apache-virtual-hosting-black-magic/">manually configure</a> your name-based virtual host for every (sub-)domain you plan to serve. Why: WordPress will handle the domain mapping for you, so it&#8217;s better to keep Apache out of the way and let WPMU own the entire IP.</p>
<h4 id="14028_set-up-your-dns_1">Set up your DNS</h4>
<p>Point each subdomain you plan to host in WordPress to your webserver. You can use a wildcard domain, but you don&#8217;t have to.</p>
<h4 id="14028_create-a-new-blog-in_1">Create a new blog in WPMU</h4>
<p>It doesn&#8217;t matter what you call it or what the path is, just create one. Now go edit it in the Site Admin:</p>
<p><div id="attachment_14029" class="wp-caption aligncenter" style="width: 310px"><a href="http://maisonbisson.com/files/2009/09/Screen-shot-2009-09-02-at-8.41.56-PM.png"><img class="size-medium wp-image-14029" src="http://maisonbisson.com/files/2009/09/Screen-shot-2009-09-02-at-8.41.56-PM-300x69.png" alt="edit blog 1" width="300" height="69" /></a><p class="wp-caption-text">Change the domain and path to match your new domain.</p></div>
<p style="text-align: left">One quirk of WPMU is that it strips &#8220;www&#8221; from any domain name you enter (or is requested), so don&#8217;t bother trying to enter it (unless you&#8217;re willing to do some hacking to make it work). WPMU stores domain and path information in three locations: the wp_#_options table for the blog, the wp_blogs table, and the wp_sites table. When you edit a blog in the Site Admin, you&#8217;ll get a chance to edit the domain and path for both the wp_#_options and the wp_blogs tables. Clicking the helpful checkbox above will do most of that for you, but you&#8217;ll need to manually update the Upload Path.</p>
<div id="attachment_14030" class="wp-caption aligncenter" style="width: 310px"><a href="http://maisonbisson.com/files/2009/09/Screen-shot-2009-09-02-at-8.42.34-PM.png"><img class="size-medium wp-image-14030" src="http://maisonbisson.com/files/2009/09/Screen-shot-2009-09-02-at-8.42.34-PM-300x48.png" alt="Now make sure the new domain is shown in the blog's options as well." width="300" height="48" /></a><p class="wp-caption-text">Now make sure the new domain is shown in the blog&#39;s options as well.</p></div>
<p>You might be able to load the blog at the new URL as soon as you update those settings, but recent versions of WPMU set some constants in <code>wp-config.php</code> that can get in your way.</p>
<h4 id="14028_reconfigure-wp-confi_1">Reconfigure wp-config.php</h4>
<p>Your <code>wp-config.php</code> might have something like this:</p>
<pre class="brush: php;">$base = '/';
define('DOMAIN_CURRENT_SITE', 'sub.site.org' );
define('PATH_CURRENT_SITE', '/' );
define('SITE_ID_CURRENT_SITE', 1);
define('BLOGID_CURRENT_SITE', '1' );</pre>
<p>Those constants override the database checking that goes on in <code>wpmu-settings.php</code> to map the requested domain to a site. You have three choices: leave it as it is (and use only one &#8220;Site&#8221;), remove it and have WPMU do the mapping against the database, or expand the hard-coded mapping to include other sites.</p>
<p>I&#8217;ve used code like the following to do just that:</p>
<pre class="brush: php;">if( preg_match( '/(.+?\.)?([^\.]+?)\.site.org/i', 'www'. $_SERVER['SERVER_NAME'] , $matchedsubdomains ))
{
	switch( array_pop( $matchedsubdomains )){
		case 'connect':
			define('DOMAIN_CURRENT_SITE', 'blogs.site.org' );
			define('PATH_CURRENT_SITE', '/' );
			define('BLOGID_CURRENT_SITE', '1' );
			break;
		case 'www':
		default:
			define('DOMAIN_CURRENT_SITE', 'site.org' );
			define('PATH_CURRENT_SITE', '/' );
			define('BLOGID_CURRENT_SITE', '2' );
			break;
}
}
else
{
	define('DOMAIN_CURRENT_SITE', 'site.org' );
	define('PATH_CURRENT_SITE', '/' );
	define('BLOGID_CURRENT_SITE', '2' );
}</pre>
<h4 id="14028_set-up-your-new-site_1">Set up your new Site</h4>
<p>Once you have your new sub-domain working with one blog, you can create your new Site. Even if you don&#8217;t plan to create separate management policies for the different sites, it&#8217;s easier to create new blogs at each sub-domain if they each have their own Site.</p>
<p>Go in to your MySQL tool of choice and browse the <code>wp_site</code> table. There you&#8217;ll see just one row, but if you&#8217;ve made it this far you can also probably figure out how to create a new row representing the site at the new sub-domain. And once you do that, you can change the entry in the <code>wp_blogs</code> table to associate it with your new Site.</p>
<h4 id="14028_set-up-the-admins-of_1">Set up the admins of the new site</h4>
<p>Creating the new entry in <code>wp_site</code> doesn&#8217;t set the options for the new Site, and that means there are no Site administrators yet. Once again in your MySQL tool of choice, open up the <code>wp_sitemeta</code> table and look for an entry with <code>meta_key = 'site_admins'</code>. The <code>meta_value</code> for that entry is a serialized array containing WordPress usernames of the people who have site-wide administration privileges on the first Site. I&#8217;m assuming that if you have MySQL access you&#8217;re also a Site admin, so the easy thing to do is copy that row and change the <code>site_id</code> to match the auto-increment value from the new <code>wp_site</code> entry you made in the last step.</p>
<p>With the database manipulation done, you should now be able to go to the WP dashboard at your new Site, visit the WPMU admin options screen, and set the other options as necessary. You could decide to make one of your Sites open registration (remember, however, that users are shared across all Sites), while making other Sites more closed. And, obviously, you can delegate different Site admins for each Site. </p>
<h4 id="14028_sub-domains-or-just-_1">Sub-domains or just different domains?</h4>
<p>It&#8217;s worth noting that the instructions so far apply to both sub-domains and domains. You can use a single implementation of WPMU to manage content at both <code>lolzors.org</code> and <code>tehsite.org</code>. The detail about sub-domains really only applies to the next part. It&#8217;s also worth noting that you can support an arbitrary number of blogs, sites, and domains; I&#8217;m just using two sub-domains as an example.</p>
<h3 id="14028_challenge-unified-lo_1">Challenge: unified log in cookies</h3>
<p>What&#8217;s the point of hosting multiple sub-domains with one WPMU implementation if you&#8217;ll need to log in separately at each one?</p>
<h4 id="14028_set-your-cookie-path_1">Set your cookie path</h4>
<p>Setting a cookie path that that&#8217;s broad enough to cover the entire domain will solve this:</p>
<pre class="brush: php;">define('COOKIE_DOMAIN', 'site.org');
define('ADMIN_COOKIE_PATH', '/');
define('COOKIEPATH', '/');
define('SITECOOKIEPATH', '/');</pre>
<h4 id="14028_avoid-conflicts-with_1">Avoid conflicts with other WordPress installations at your domain</h4>
<p>But having such a broad cookie domain can interfere with other WordPress implementations. You&#8217;ll have to solve that by setting a unique cookiehash:</p>
<pre class="brush: php;">define( 'COOKIEHASH', 'asdf_arbitrary_string' );</pre>
<p>You&#8217;d do better to keep it shorter than that, though.</p>
<h3 id="14028_challenge-unified-lo_2">Challenge: unified log in location/URL</h3>
<p>WordPress MU is happy to handle authentication requests wherever it hosts a blog, but some organizations prefer to funnel all authentication requests through a single location. The idea is to provide some protection against fishing (assuming users can ever be taught to look at URLs) and make it easer to integrate external applications.</p>
<h4 id="14028_filter-login_url-and_1">Filter login_url and logout_url</h4>
<p>Set the log in and log out path to whatever you want, just make sure the destination knows how to create (or destroy) the WordPress cookies.</p>
<pre class="brush: php;">
$hack_base_domain = 'site.org';

function hack_login_url( $path ){
	global $hack_base_domain;

	return preg_replace( '/^.+?\/wp-login.php/' , 'https://login.'. $hack_base_domain .'/wp-login.php', $path );
}
add_filter( 'login_url' , 'hack_login_url' , 10 );
add_filter( 'logout_url' , 'hack_login_url' , 10 );
</pre>
<h4 id="14028_filter-allowed_redir_1">Filter allowed_redirect_hosts</h4>
<p>WP will normally block redirects outside the web root of the active blog, so you&#8217;ll need to tell it about your other sub-domains.</p>
<pre class="brush: php;">
function hack_allowed_redirect_hosts( $allowed_domains ){
	global $hack_base_domain;

	$allowed_domains[] = $hack_base_domain;
	$allowed_domains[] = 'www.'. $hack_base_domain;
	$allowed_domains[] = 'blogs.'. $hack_base_domain;

	return $allowed_domains;
}
add_filter( 'allowed_redirect_hosts' , 'hack_allowed_redirect_hosts' , 10 );
</pre>
]]></content:encoded>
			<wfw:commentRss>http://maisonbisson.com/blog/post/14028/wordpress-hacks-managing-multiple-sub-domains/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>CAS Is A Standard Protocol, Not A Standard Application</title>
		<link>http://maisonbisson.com/blog/post/13693/cas-is-a-standard-protocol-not-a-standard-application/</link>
		<comments>http://maisonbisson.com/blog/post/13693/cas-is-a-standard-protocol-not-a-standard-application/#comments</comments>
		<pubDate>Tue, 14 Apr 2009 16:52:09 +0000</pubDate>
		<dc:creator>Casey Bisson</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[authentication]]></category>
		<category><![CDATA[authn]]></category>
		<category><![CDATA[CAS]]></category>
		<category><![CDATA[identity management]]></category>
		<category><![CDATA[idm]]></category>
		<category><![CDATA[single sign on]]></category>
		<category><![CDATA[standards]]></category>

		<guid isPermaLink="false">http://maisonbisson.com/?p=13693</guid>
		<description><![CDATA[
I&#8217;m not really part of the Jasig CAS Community (learn more), but I do maintain the wpCAS WordPress CAS client and I&#8217;ve started development of a CAS server component for WordPress. That project is on hold because one of the products that I&#8217;d expected to integrate with it doesn&#8217;t use standard CAS and the vendor [...]]]></description>
			<content:encoded><![CDATA[<abbr class="unapi-id" title="maisonbisson-13693"><!-- &nbsp; --></abbr>
<p><a href="http://www.jasig.org/cas/"><img class="alignright" src="http://www.jasig.org/sites/jasig.webchuckhosting.com/files/casLogo.jpg" alt="CAS logo" width="124" height="66" /></a>I&#8217;m not really part of the <a href="http://www.jasig.org/cas/">Jasig CAS Community</a> (<a href="http://en.wikipedia.org/wiki/Central_Authentication_Service">learn more</a>), but I do maintain the <a href="http://wordpress.org/extend/plugins/wpcas/">wpCAS</a> <a href="http://maisonbisson.com/projects/wpcas/">WordPress CAS client</a> and I&#8217;ve <a href="http://svn.wp-plugins.org/wpcas-server/trunk/wpcas-server.php">started development</a> of a <a href="http://wordpress.org/extend/plugins/wpcas-server/">CAS server component for WordPress</a>. That project is on hold because one of the products that I&#8217;d expected to integrate with it doesn&#8217;t use standard CAS and the vendor of that app has chosen to modify the JASIG CAS server to support their apps.</p>
<p><a href="http://www.jasig.org/cas/protocol">The standard is the protocol</a>, not <a href="http://www.jasig.org/cas/download/cas-server-331-final">the server application</a>, though we probably won&#8217;t really understand that until we see more CAS server implementations. Nonetheless, it&#8217;s important to keep that point in mind if we we hope to grow the usefulness of CAS.</p>
]]></content:encoded>
			<wfw:commentRss>http://maisonbisson.com/blog/post/13693/cas-is-a-standard-protocol-not-a-standard-application/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Acronym Overload: IIS + ISAPI + CAS</title>
		<link>http://maisonbisson.com/blog/post/12705/acronym-overload-iis-isapi-cas/</link>
		<comments>http://maisonbisson.com/blog/post/12705/acronym-overload-iis-isapi-cas/#comments</comments>
		<pubDate>Tue, 07 Oct 2008 18:57:54 +0000</pubDate>
		<dc:creator>Casey</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[authentication]]></category>
		<category><![CDATA[authn]]></category>
		<category><![CDATA[CAS]]></category>
		<category><![CDATA[central authentication service]]></category>
		<category><![CDATA[identity management]]></category>
		<category><![CDATA[idm]]></category>
		<category><![CDATA[IIS]]></category>
		<category><![CDATA[ISAPI]]></category>

		<guid isPermaLink="false">http://maisonbisson.com/?p=12705</guid>
		<description><![CDATA[
I&#8217;m working to integrate an application on a remote-hosted IIS server into our CAS environment. CASisapi (svn trunk or svn tags/production) may do the trick, though Phil Sladen struggled with it (in 2005). There&#8217;s reason to doubt it. Not only is the sparse information all old, I first learned about it from a page full [...]]]></description>
			<content:encoded><![CDATA[<abbr class="unapi-id" title="maisonbisson-12705"><!-- &nbsp; --></abbr>
<p>I&#8217;m working to integrate an application on a remote-hosted IIS server into our CAS environment. CASisapi (<a href="http://svn.portal.aau.dk/cas/trunk/client/isapi/" title="/cas/trunk/client/isapi">svn trunk</a> or <a href="http://svn.portal.aau.dk/cas/tags/production/client/isapi/" title="/cas/tags/production/client/isapi">svn tags/production</a>) may do the trick, though <a href="http://tp.its.yale.edu/pipermail/cas/2005-March/001066.html" title="Has anyone been able to get the CASIsapi filter to work?">Phil Sladen struggled with it</a> (in 2005). There&#8217;s reason to doubt it. Not only is the sparse information all old, I first learned about it <a href="http://www.ja-sig.org/wiki/display/CASC/ISAPI+Filter" title="ISAPI Filter - CAS Clients - JA-SIG Wiki">from a page full of broken links</a> and the apparent author <a href="http://tp.its.yale.edu/pipermail/cas/2006-January/002040.html">recommends against it</a>. There&#8217;s a little more information <a href="http://wiki.portal.aau.dk/AauPortal/CASIis" title="PortalWiki - CAS-iis - Aalborg Universitet Cowiki">here</a> for those who can read Danish. </p>
<p><a href="https://confluence.ucdavis.edu/confluence/display/IETP/CAS+ISAPI+Client" title="CAS ISAPI Client - Confluence">UC Davis&#8217; CAS ISAPI client</a> may be a better solution (it certainly looks <a href="https://confluence.ucdavis.edu/confluence/display/IETP/CAS+ISAPI+Installation">easy to install</a>). <a href="http://www.builderau.com.au/program/windows/soa/Secure-your-NET-smart-client-apps-with-CAS/0,339024644,320272878,00.htm?feed=pt_identity" title="Secure your .NET smart client apps with CAS - Program - Windows - Builder AU">Builder AU talks about .NET + CAS</a>, and <a href="http://wiki.case.edu/Central_Authentication_Service" title="Central Authentication Service - CaseWiki">Case Western has a lot of documentation</a>. Only partially related: it <a href="http://groups.apu.edu/awg/node/156" title="World of Warcraft uses CAS | AWG">looks like</a> <a href="http://blogs.yale.edu/roller/page/jdb53/20050510#cas_in_the_wild" title="lumina">World of Warcraft uses CAS</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://maisonbisson.com/blog/post/12705/acronym-overload-iis-isapi-cas/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Dick Hardt &#8217;s Identity 2.0 Presentation</title>
		<link>http://maisonbisson.com/blog/post/10927/dick-hardt-s-identity-20-presentation/</link>
		<comments>http://maisonbisson.com/blog/post/10927/dick-hardt-s-identity-20-presentation/#comments</comments>
		<pubDate>Wed, 26 Oct 2005 16:19:55 +0000</pubDate>
		<dc:creator>Casey Bisson</dc:creator>
				<category><![CDATA[Libraries & Networked Information]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[authentication]]></category>
		<category><![CDATA[authorization]]></category>
		<category><![CDATA[dick hardt]]></category>
		<category><![CDATA[identity]]></category>
		<category><![CDATA[identity 2.0]]></category>
		<category><![CDATA[identity management]]></category>
		<category><![CDATA[identity2.0]]></category>
		<category><![CDATA[idm]]></category>
		<category><![CDATA[sxip]]></category>

		<guid isPermaLink="false">http://maisonbisson.com/blog/?p=10927</guid>
		<description><![CDATA[

I said “identity management is the next big thing” back in September. That was before I&#8217;d seen Sxip founder Dick Hardt&#8217;s presentation on Identity 2.0. Zach peeped me the link and told me I wouldn&#8217;t regret watching the presentation. He was right. Everybody, especially the people who don&#8217;t yet care about identity management, should take [...]]]></description>
			<content:encoded><![CDATA[<abbr class="unapi-id" title="maisonbisson-10927"><!-- &nbsp; --></abbr>
<div id="identity2.0_movie"><object CLASSID="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B" WIDTH="480" HEIGHT="360" CODEBASE="http://www.apple.com/qtactivex/qtplugin.cab"><param name="SRC" VALUE="http://oz.plymouth.edu/~cbisson/gfx/Dumbkins/identity20.mov"></param><param name="VOLUME" VALUE="1"></param><param name="AUTOPLAY" VALUE="true"></param><param name="LOOP" VALUE="true"><embed src="http://oz.plymouth.edu/~cbisson/gfx/Dumbkins/identity20.mov" width="480" height="360" volume="1" name="Get QuickTime" loop="true" cache="true" controller="false" pluginspage="http://www.apple.com/quicktime/download/" autoplay="true"></embed></param></object></div>
<p>I said “<a href="http://maisonbisson.com/blog/post/10754/">identity management is the next big thing</a>” back in September. That was before I&#8217;d seen <a href="http://www.identity20.com/media/WEB2_2005/">Sxip founder Dick Hardt&#8217;s presentation on Identity 2.0</a>. <a href="http://nosheep.net/story/identity-20/">Zach</a> peeped me the link and told me I wouldn&#8217;t regret watching the presentation. He was right. Everybody, especially the people who don&#8217;t yet care about identity management, should take a look.<br />
<tags>authentication, authorization, dick hardt, identity, identity 2.0, identity 20, identity management, identity2.0, identity20, idm, sxip</tags></p>
]]></content:encoded>
			<wfw:commentRss>http://maisonbisson.com/blog/post/10927/dick-hardt-s-identity-20-presentation/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
<enclosure url="http://homepage.mac.com/misterbisson/Dumbkins/identity20.mov" length="545589" type="video/quicktime" />
<enclosure url="http://oz.plymouth.edu/~cbisson/gfx/Dumbkins/identity20.mov" length="545589" type="video/quicktime" />
		</item>
	</channel>
</rss>