WordPress Plugin: CAS/LDAP Authentication with Redirect

casldap_w_redirectMy workplace is implementing a single sign on architecture (SSO) and several of our user facing sites need to provide a means to authenticate those users before allowing them to use the resources, or participate in the discussions on those sites.  Partly because of its ease of use and flexibility in customization, we chose WordPress as our CMS of choice for many of these sites.  The next step was to integrate all of these sites with our SSO architecture.

The Requirements

The requirements for this plugin were fairly straightforward:

  1. If a user had been signed in to another of our sites but was not a “registered user” on the WordPress site, create their user with data from the LDAP and log them in to the main page with basic “User” privileges.
  2. If a user had been signed in to another of our sites and was a “registered user” on the WordPress site, sign them in to the main page with their username.
  3. If a user had been signed in to another of our sites and was an “Administrator” on the WordPress site, sign them in to the Administrator Dashboard upon signing in.
  4. Make it an “all-in-one” plugin so that no additional items needed to be downloaded and installed.  For this reason, the Jasig PHP CAS client is bundled right into the plugin.  (The current version bundled with this plugin is phpCAS 1.3.2)

Since we wanted to be able to redirect users based on their level of authorization, I knew that I would not only need to authenticate each user, but also retrieve the user roles and capabilities appropriately; if we can determine the role of the user, we can potentially expand the plugin to include additional redirects.  The added benefit of needing to redirect actually turned out to be a useful notification tool.  If we needed a landing page for users to express some vital information, we could change the redirect for registered users to push them to the notification page upon login.

How it works

The plugin takes control of the wp_login() and wp_logout() functions by hooking into them.  Both the sign in process and the sign out process are sent to the CAS server.  After successfully authenticating, the plugin checks the WordPress instance if the user already exists.  If the user exists, it authenticates the user and signs them into the site, redirecting them if necessary.  The plugin only determines if a user is an administrator; if not, the user is directed the standard page.  If the user does not exist, then the plugin takes advantage of the wp_create_user() function and uses the information it retrieves from the LDAP to create the new user.  The lowest level of user (subscriber) is used to create the new user.  Once the user has been created, any administrator can adjust the user’s settings to give them access to more of the dashboard.

Setting up an instance

Installation is fairly straightforward if you have the information for your CAS and LDAP servers.  To install, follow the instructions below:

  1. Upload the ZIP archive to your server via “Plugins > Add New > Upload”
  2. Activate the Plugin from the list of installed plugins
  3. Go to “Settings > CAS/LDAP Settings” and enter in the information for your servers.
  4. Important! Set up the redirect options.  If you do not set up the redirect options, WP will simply drop the user back onto the login page.  And, because the user has been created with a random password, that user will not be able to log in.  The simplest option is to use “index.php” as the user redirect as that brings users to the main page of the site, and to use “wp-admin/index.php” for the administrators, as it brings them to the site dashboard.
  5. Set up the data mapping from the LDAP.  This plugin does not have default settings for the username, first and last names, and email fields.  In fact, the primary LDAP system at work is somewhat non-standard, so the data mapping was included to allow us to hook this plugin into various LDAP schemas and map those fields to the proper LDAP fields.  Note: if you don’t set this up, new users will not be created, and the authentication process will fail.  The most common settings are “uid or username” for the username field, “mail” for email, “givenName” for first name, “sn” for surname, and “displayName” for display name.  You do not need to enter a nickname.
  6. Important!  Test out your settings in another browser.  If you made a mistake in the settings, you will be locked out of your own account, as the hooks for logging in and logging out will now be tied to the wp_login() and wp_logout() functions.  You’ll need database access to fix this if you made a mistake on the settings.  This has been fixed in V1.1; see update 12/9/13 below.

That’s all there is to the installation.  If you entered all your information correctly, all user authentication will now route through your CAS server and pull user data from your LDAP.

Troubleshooting

There are two potential pitfalls.  One is if your user does not have permission to create a directory for the plugin.  That will need to be taken care of on the server side; you will need to give permission to the plugin folder to the WordPress instance.  Another is if you used the same browser to check your settings and they were wrong.  If you did this, then you will need to deactivate the plugin either by logging in to the server and renaming the plugin folder (which will automatically deactivate the plugin), or by logging in to the database and searching for all “active_plugins” from the wp_options table.  Here is a good tutorial on that.

Update 12/9/2013

I’ve updated the plug in to allow users who don’t have a CAS account to login.  This also means that you can log in as site administrator now, even if there’s a problem with the CAS authentication.  You’ll simply need to point your browser to http://yoursiteurl.com/wp-login.php?auth=NOCAS.  This will revert the login process back to the WordPress authentication methods.  To use this for individual users who do not have a CAS account, you will need to modify your theme’s footer/sidebar to link to the login page using the extra variable.  e.g.:
<?php echo “<a href=\””.site_url().”/wp-login.php?auth=NOCAS\”>Log In (No School Account)</a>”; ?>

Download

Version 1.1

GitHub Repository

Version 1.1

14 thoughts on “CAS/LDAP WordPress Plugin

  1. The CAS/LDAP WordPress Plugin is awesome. It almost perfectly fits in my needs. I really wish to use it, but I cound not find license information about this plugin. So, please tell me about the license and if there is any restriction. Thank you.

  2. Have really enjoyed working with the plugin. Kudos! The code is extremely clean compared to some others I’ve worked with.

    We are having one problem – we get in a redirect loop when we authenticate. I’m starting to think that is has to do with the interaction with the plugin we are using to protect our pages until the user has authenticated – we’ve tried several, currently using the “Members” plugin. It keeps looping back to the wp-login.php page from index.php after we authenticate with CAS.

    Any ideas? Or can you share how you protect your pages until authentication/authorization occurs?

    Thanks!

    1. Richard, it appears that the most likely culprit is the redirector on your “Members” plugin. If it keeps trying to redirect to wp-login.php, then the CAS/LDAP plugin will grab that and redirect to the CAS server. So, if index.php is somehow in the array of “protected” pages, then I would remove that and see if that resolves the problem. Hard to say without looking at the code, though.

      As for how we do it on campus, we use the following snippet of code in our “functions.php” file to redirect people to a “welcome” page:

      //**this redirects non-logged-in users to the url listed
      add_action( 'init', 'redirect_visitors' );
      function is_login_page() {
      return in_array($GLOBALS['pagenow'], array('wp-login.php', 'wp-login-bd.php'));
      }
      function redirect_visitors() {
      $return_to = $_SERVER['REQUEST_URI'];
      if (!is_user_logged_in() && !is_login_page()) {
      wp_redirect("http://site.fuller.edu/welcome.php?return=".$return_to);
      exit;
      }
      }
      //end url redirect **/

      On the “Welcome” page, we have an explanation as to why people need to log in, with a button that takes them to the CAS server, and the original $return_to URL as the “service” on the CAS server.

      <a href="<?php echo "https://cas_server:8443/cas/login?service=http://site.fuller.edu/wp-login.php?send_to=".$return;? rel="nofollow">"><span class="button orange">Log In</span></a>

      Then, we have a slightly modified version of the CAS/LDAP plugin to track where the user originally wanted to go. On about line 220 of the plugin, we have this:

      if( isset($uname_result->caps['administrator']) && ($uname_result->caps['administrator'] == 1) )
      {
      if(isset($_GET['send_to']))
      {
      $return_me = site_url().$send_to;
      wp_redirect($return_me);
      } else {
      wp_redirect($admin_redirect);
      }
      }
      else
      {
      if(isset($_GET['send_to']))
      {
      $return_me = site_url().$send_to;
      wp_redirect($return_me);
      } else {
      wp_redirect($user_redirect);
      }
      }

      instead of this:

      if( isset($uname_result->caps['administrator']) && ($uname_result->caps['administrator'] == 1) )
      {
      wp_redirect($admin_redirect);
      }
      else
      {
      wp_redirect($user_redirect);
      }

      Normally, wp-login.php takes a $return_to parameter and redirects users to that page if it is set, but since the CAS/LDAP plugin hooks into (or hijacks) the normal login process, we had to do the redirect with the “send_to” inside of our plugin.

      Hope this helps.

  3. WooHoo! Thank you much that worked a dream.
    We actually don’t want the landing page in our situation so I just had the function in functions.php go straight to the CAS login.
    And of course it eliminated the Members plugin which was overkill for what we needed to do – and did not work well for us.

    Thank you again.

  4. Great plugin, almost have it working the way I would like. Is there anyway to use the users LDAP password and remove the field from their Profiles?

    My issue is we need the user to have a working account to post a message, so they need to fully login to have limited access to the Dashboard.

    Thanks for any help.

    1. Joel, I’m not sure I fully understand. The plugin hijacks the WP authentication, so the user is using their LDAP password – at least providing your CAS is tied to the same LDAP that you want WP to authenticate against. All of our sites at school use this plugin, and all users have full access to their dashboard, and to post/reply to messages; the lack of a password doesn’t limit a user’s ability to use their account. In fact, I routinely log in via this plugin and go directly to the admin dashboard (I’ve got full functionality). Can you rephrase your question a bit?

  5. I am looking for a word press multi site CAS plugin and from what is available, yours seems to be the best. I am new to pHp and wordpress and need your advise on:

    1. Can I use this on multi site installation(cas_ldap_wp_plugin-master) for multi site.
    2. All I need is authentication, not create users.
    3. I also need to retail the WP login and it looks like it is possible by direct access and it should work with the auth=NOCAS option.
    4.Our future WP sites are all pages.
    Best Regards,
    -Chandrika

    1. Chandrika,

      Yes, you can use this on a multi-site installation. We are using it for one of our internal multi-site WP setups. If you do not need the create users, simply comment out the section that checks authentication and if they exist in the WP instance (it’s the if/else block between lines ~227-283. Just remove the else block ~244-283. And you are correct about using the WP Admin; if you add auth=NOCAS, you can log in directly to the WP instance.

  6. We’re a group of volunteers and opening a brand new scheme in our community.
    Your web site offered us with useful information to
    work on. You have done an impressive job and our whole
    group can be grateful to you.

  7. For a multisite implementation, do I “network” activate the plugin? Or activate it only on the root / blog?

    Thanks very much.
    RC

    1. RC – The multi-site implementation requires some changes in the code. You are correct, all the functions need to be updated to the multi-site equivalent. So, update_option becomes update_site_option and get_option becomes get_site_option, etc.

Leave a Reply

Your email address will not be published. Required fields are marked *