danielchatfield / wordpress-raven-auth

A raven authentication plugin for WordPress
Artistic License 2.0
3 stars 2 forks source link

WordPress Raven Auth

A raven authentication plugin for WordPress. This plugin owes a lot to WPRavenAuth but attempts to address some of the shortcomings of that plugin - namely:

Structure of project

I have loosely split the project into a fairly generic PHP library and then a WordPress specific implementation. This would make it trivial to port the plugin to another CMS (or use in a standalone PHP application).

WordPress API

The wordpress API (RavenAuthPlugin) subclasses RavenAuthClient (see High level API below) and hooks it into the WordPress users system.

High level generic PHP API

The low level API (specified below) offers full flexibility and closely follows the raven spec (keeps the names of parameters the same as those in the spec). This makes it quite cumbersome to use so there is a higher level API that is more user friendly and does a lot of the heavy lifting for you (at the expense of flexibility)

RavenAuthClient

$client = new RavenAuthClient($raven_environment);

$raven_environment is an optional string value that can take two values:

If $raven_environment is not passed then the environment will be determined by the constant RAVEN_ENVIRONMENT (see below).

RavenAuthClient->authenticate()

// all arguments are optional
$client->authenticate(
    $site_name,              /* The site name that Raven displays to the user */
    $login_message,          /* The login message that Raven displays to the user */
    $require_password_entry, /* If true (defaults to false) then raven will require
                                user to enter password even if they have an active
                                session. */
    $allow_alumni,           /* If true (defaults to false) then it will accept people 
                                that don't meet Cambridge's definition of "current" */
    $redirect_to             /* Where to redirect to afterwards - if not set then it 
                                defaults to the current URL */
);

Calling $client->authenticate() will result in one of the following:

When calling authenticate you should catch RavenAuthExceptions and use the getMessage() method to display a helpful error message to the user. e.g. in WordPress you can do the following:

try {
    $client->authenticate()
} catch (RavenAuthException $e) {
    wp_die($e->getMessage());
}

RavenAuthClient->getSession($full_session = false)

Returns null if there is no active session.

If $full_session is true it will return the following:

return array(
    'crsid' => $crsid,                      // the CRSID of the user
    'current' => $current,                  // true if the user is a current member of 
                                            // the university
    'password_entered' => $password_entered // true if the user actually entered their 
                                            // password into raven
 );

Otherwise if it false then it will just return the crsid as a string.

Low Level generic PHP API

The low level API consists of RavenAuthRequest and RavenAuthResponse (which both inherit from RavenAuthResource) - these are essentially implementations of the request to and response from raven - including the neccessary methods for parsing and verifying the response.

RavenAuthRequest

new RavenAuthRequest($parameters = array(), $raven_service = null);

$parameters is an optional array of raven parameters as specified here.

$raven_service is an optional instance of a class that implements the RavenAuthServiceInterface - this is useful for using the demo raven server.

$request = new RavenAuthRequest();

$request->setParameter('msg', 'This is a message');

echo $request->getRavenURL();
// https://demo.raven.cam.ac.uk/auth/authenticate.html?ver=3&date=20141003131322z&msg=This%20is%20a%20message&url=https%3A%2F%2Fexample.com

RavenAuthResponse

new RavenAuthResponse($response = null, $raven_service = null);

$response is the response from raven.

$raven_service is an optional instance of a class that implements the RavenAuthServiceInterface - this is useful for using the demo raven server.

To check that a response is valid you must call the following methods.

The above methods all throw exceptions on failure.

If you set 'iact' in the request then you need verifyAuth() as well (returns true or false).

To only allow current university members then you need verifyPtags() (returns true or false.

Library configuration constants

RAVEN_ENVIRONMENT

If set to 'demo' then the default RavenAuthServiceInterface that will be used will be the demo one.

Alternatively you can pass an instance of the RavenAuthDemoService when instantiating the RavenAuthRequest like so:

$parameters = array(
    "desc" => "Readme example site"
);
$raven_service = new RavenAuthDemoService();
$request = new RavenAuthRequest($parameters, $raven_service);

echo $request->getRavenURL();
// https://demo.raven.cam.ac.uk/auth/authenticate.html?ver=3&date=20141003131322z&desc=Readme%20example%20site&url=https%3A%2F%2Fexample.com

RAVEN_TRUST_ALL_HOSTS

First, some background: when a website redirects to raven it includes the URL for raven to redirect back to. Raven uses this URL as part of the token that it signs to prevent tokens that were issued for one site being used on another. However, on many hosting environments it is not possible to reliably determine the host for the website since the server itself doesn't know it and just uses the HOST http header. By spoofing this header an attacker with an access token for one website can replay it onto another. At its lowest level (RavenAuthResponse), the library will let you take care of this however you want (but it will make sure that you take care of it) - you can pass a string (or array of strings) that contains a "trusted host" that the request host is matched against or you can signify that you (the application that is consuming the library) take full responsibility for verifying this by passing in a flag to the verifyURL method or setting RAVEN_TRUST_ALL_HOSTS to TRUE. This would be appropriate on a server that only responds to requests from the correct host (although you should be careful as some servers will blindly parse other headers like X-Forwarded-Host).