Tag Archives: Wordpress

wordpress-logo-notext-rgb

Securing WordPress Admin Via SSL Using a Separate Admin Subdomain

Different WordPress and Site URLS

Our wordpress site has an SSL secured admin setup to protect our login credentials.   Since we do not have an SSL certificate for our main blog domain, but rather for secure.seriouslyproductions.com , the setup for WordPress to function properly was not standard and required some extra work.

mod_rewrite and Admin Pages

To accommodate this setup and ensure that the login page and all admin content was secured via SSL, I set the wordpress Address (in General Settings) to https://secure.seriouslyproductions.com.  The next step was to add a mod_rewrite rule to my .htaccess file to divert all traffic to https://secure.seriouslyproductions.com when attempting to access any admin page or the wp-login.php page.

If you are using Apache then adding the following lines to your .htaccess file should do the job.  These should be placed after the RewriteEngine has been turned on, but before the other rewrite rules that are in place for WordPress.  Naturally you would change out the https://secure.seriouslyproductions.com URL with your own website URL:

RewriteCond %{HTTPS} !=on [NC]
RewriteRule ^/?(wp-admin/|wp-login\.php) https://secure.seriouslyproductions.com%{REQUEST_URI} [R=301,QSA,L]

These lines added to the Basic WP htaccess file would look like:

# BEGIN WordPress

RewriteEngine On
RewriteBase /
RewriteCond %{HTTPS} !=on [NC]
RewriteRule ^/?(wp-admin/|wp-login\.php) https://secure.seriouslyproductions.com%{REQUEST_URI} [R=301,QSA,L]

RewriteRule ^index\.php$ – [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]

# END WordPress

PROBLEM: Unable to Preview Changes

At this point most things were working.  The login and admin pages were secure.  The only caveat was that I could not preview changes to any WordPress post or theme settings.  In addition, a logged in user would never see the WordPress admin bar at the top of the screen if viewing the blog URL.   By default, WordPress sends any preview request back over to the site URL (which in my case is set to http://www.seriouslyproductions.com/).  However, to preview a change a user must be logged in and have permissions to view the change.  This told me that the authentication cookie wasn’t available across the two domains (secure.seriouslyproductions.com and www.seriouslyproductions.com).

I wanted the preview functionality so I have been on a crusade to determine a way to enable this functionality with my cross subdomain setup.  In this earlier blog post I outlined a quick “fix” in which I used mod_rewrite rules that diverted preview post content over to my secured subdomain, https://secure.seriouslyproductions.com.  This solution worked for previewing posts and page updates, but failed miserably for previewing my custom theme updates.  In addition, this solution gave me SSL warnings because WordPress was serving insecure content over the SSL channel (images and other content) when previewing changes.  Clearly this was only a temporary solution, but it worked well enough for the time being.

SOLUTION: Modifying the Cookie Domain

Over the past few weeks, and as time permits, I’ve been doing research and I believe I’ve found the solution to my problem.  To start, I removed the “hack” fix that I put in place which diverts preview traffic over to secure.seriouslyproductions.com from the .htaccess file.

Now for some explanation…  By default, WordPress authentication cookies are only recognized for the domain entered into the WordPress Address (in my case secure.seriouslyproductions.com).  Any visit to www.seriouslyproductions.com will not acknowledge that a user is logged in as it cannot find a “logged in” cookie for the www subdomain.  This results in any request to preview content to fail.

The best solution I’ve found is to alter the cookie domain of the WordPress logged in cookie (NOT the auth cookie which is a security risk) to the value of my root domain without a subdomain, i.e “seriouslyproductions.com”.  This makes the cookie available across all subdomains of seriouslyproductions.com and now all is well in the world.  The code where all authentication cookies are set can be found in the wp-includes/pluggable.php file and is easy to modify.

  1. function wp_set_auth_cookie(…):  The cookies are set toward the end of this function.  There are two lines related to the LOGGED_IN_COOKIE that you need to locate.  In those lines, replace COOKIE_DOMAIN with a string literal containing your base domain name (e.g. change COOKIE_DOMAIN to “yourdomain.com”).  DO NOT change the COOKIE_DOMAIN for the auth cookie.

    Change this:
    setcookie(LOGGED_IN_COOKIE, $logged_in_cookie, $expire, COOKIEPATH, COOKIE_DOMAIN, $secure_logged_in_cookie, true);
    if ( COOKIEPATH != SITECOOKIEPATH )
         setcookie(LOGGED_IN_COOKIE, $logged_in_cookie, $expire, SITECOOKIEPATH, COOKIE_DOMAIN, $secure_logged_in_cookie, true);

    To this:
    setcookie(LOGGED_IN_COOKIE, $logged_in_cookie, $expire, COOKIEPATH, "yourdomain.com", $secure_logged_in_cookie, true);
    if ( COOKIEPATH != SITECOOKIEPATH )
         setcookie(LOGGED_IN_COOKIE, $logged_in_cookie, $expire, SITECOOKIEPATH, "yourdomain.com", $secure_logged_in_cookie, true);

  2. function wp_clear_auth_cookie(…):  In the first block of setcookie calls you will see two lines for the LOGGED_IN_COOKIE again.  As in step 1, replace COOKIE_DOMAIN with your base domain name.

    Change this:
    setcookie( LOGGED_IN_COOKIE, ' ', time() - YEAR_IN_SECONDS, COOKIEPATH, COOKIE_DOMAIN);
    setcookie( LOGGED_IN_COOKIE, ' ', time() - YEAR_IN_SECONDS, SITECOOKIEPATH, COOKIE_DOMAIN);

    To this:
    setcookie( LOGGED_IN_COOKIE, ' ', time() - YEAR_IN_SECONDS, COOKIEPATH, "yourdomain.com");
    setcookie( LOGGED_IN_COOKIE, ' ', time() - YEAR_IN_SECONDS, SITECOOKIEPATH, "yourdomain.com");

Once I updated the wordpress logged in cookie’s domain, all my previews work properly and the WordPress install is working like a champ.  I can see all preview content, both posts and theme updates, and I don’t receive any SSL warnings when previewing content.  The only down-side to this type of setup is that you must reapply the change every time WordPress updates the wp-includes/pluggable.php file.  If you have a code repository such as Git, then this isn’t such a big deal, but it’s something that is easy to forget if kept track of manually.

If you’ve benefited from this post and it saved you time, consider sending me a tip via PayPal.



wordpress-logo-notext-rgb

WordPress: Including a Page or Post within another Page or Post

As CEO of a start-up, I have the privilege of wearing a whole lot of hats. One of them is for the Web Developer. Within our WordPress site I have a situation where I want to display show specification content on both The 5 Dragon Daughter’s show page and also on the Booking page. Now, I could copy and paste, but if I make updates to that information I don’t want to have to change it in two places. I may forget that I have it in both spots and have information that is out of date on our website.

To solve this I went looking for how to include the contents of one page in another page. There was nothing available that I could simply plop into WordPress, but I did find this blog entry on how to Create Your Own WordPress Plugin.  The include functionality I wanted to add to WordPress is something that is ideal for a plugin rather than the functions.php as I might want it available across multiple themes.

Using info from that plugin tutorial and the modifying code from another blog article by the same author, I constructed code (appended at the end of this post) that enables me to include a page or post within another post in WordPress.  After setting up the proper directly structure and php files, I went to the Dashboard, activated my plugin, and now I’m good to go. I can include contents of pages or posts within other pages/posts by using the following syntax:

So, the show specs sections on The 5 Dragon Daughter Page and the Book a Show page are both coming from a third page which contains only the show specs.

 
<?php /*
 * Plugin Name: Include Plugin for WordPress
 * Plugin URI: http://www.seriouslyproductions.com/
 * Description: Displays the content of a page/post within a different page/post.
 * Author: David Wolff
 * Author URL: http://www.seriouslyproductions.com/about-us/dave-wolff/
 * Version: 1.0
 * License: GPL2
 */
function seriously_include ($atts) { 
    //If the id value isn't numeric then return nothing
    //to prevent any strange and unwanted behavior.
    if (!is_numeric($atts[id])) {
    	return '';
    }

    $includeId = intval($atts[id]); 
    $output = ''; 
    // Look for pages with the ID. 
    query_posts("page_id=$includeId"); 
    if (have_posts()) { 
        while (have_posts()) { 
            the_post(); 
            $output .= get_the_content($post->ID); 
        } 
    } else { 
        //The ID wasn't for a page, try a post. 
        query_posts("p=$includeId"); 
        while (have_posts()) { the_post(); 
            $output .= get_the_content($post->ID); 
        } 
    } wp_reset_query(); 
    return $output; 
} 

add_shortcode("sp_include", "seriously_include"); ?> 

mod_rewrite

WordPress, Apache, and mod_rewrite

I took some time this morning to sort out a problem that I’ve been having with my WordPress install.  I have the WordPress URL and the Site Address URL on different subdomains, the admin panel being located at a secured subdomain.  Using mod_rewrite I was able to redirect all attempts to access wp-login.php or anything in the /wp-admin tree to the SSL secured subdomain and it worked like a champ. There was one caveat though, any attempt to preview a post was directed over the insecure, main site URL was met with this message, “You do not have permission to preview drafts.”

Given my limitations with a shared hosting plan, my options were limited; however, the solution was simple enough (simple if you understand regular expressions, mod_rewrite, and the HTTP request protocol).  I included a second rewrite rule that matched the requested URL if the query string contains “preview=true” and redirected it over to the SSL secured subdomain.  At this point I was able to preview posts.

For those of you, like myself, that need to understand mod_rewrite a little better, take a look at this tutorial.