Created
June 13, 2013 17:35
-
-
Save littlefyr/5775652 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
class FrozenSso { | |
protected $plugin_slug = 'frzn-sso'; | |
protected $auth_secret = 'super secret string :)'; | |
protected static $instance = null; | |
protected $plugin_screen_hook_suffix = 'FrozenSso'; | |
private function __construct() { | |
if ( NULL <> $this->auth_secret && !defined( 'FRZN_SSO_SECRET' ) ) | |
define( 'FRZN_SSO_SECRET', $this->auth_secret ); | |
//setup custom URLs | |
add_action('parse_request', array($this, 'parse_request'), $accepted_args = 1 ); | |
add_action('init', array($this, 'do_rewrite')); | |
add_action('send_headers', array($this, 'add_cors_headers')); | |
} | |
public static function get_instance() { | |
// If the single instance hasn't been set, set it now. | |
if ( null == self::$instance ) { | |
self::$instance = new self; | |
} | |
return self::$instance; | |
} | |
public static function activate( $network_wide ) { | |
self::add_rewrite_rule(); | |
flush_rewrite_rules( true ); | |
} | |
public static function deactivate( $network_wide ) { | |
// TODO: Define deactivation functionality here | |
flush_rewrite_rules( true ); | |
} | |
public function do_rewrite() | |
{ | |
self::add_rewrite_rule(); | |
} | |
public static function add_rewrite_rule() | |
{ | |
global $wp_rewrite; | |
add_rewrite_tag( '%sso%', '!|([a-zA-Z0-9_-]+)' ); | |
} | |
public function parse_request($wp) | |
{ | |
// only process requests with sso query_var | |
if (array_key_exists('sso', $wp->query_vars)) { | |
$action = $wp->query_vars['sso']; | |
switch ($action) { | |
case '!': | |
$this->get_session_token(); | |
break; | |
default: | |
// do the login | |
$this->do_login($action); | |
break; | |
} | |
} | |
} | |
public function get_session_token() { | |
$username = $_POST['username']; | |
$password = $_POST['password']; | |
$redirect = $_POST['redirect_url']; | |
$data = new StdClass; | |
$this->add_cors_headers(); | |
header('Content-Type: application/json'); | |
$user = wp_authenticate_username_password( null, $username, $password ); | |
if (is_wp_error($user)) { | |
$data->success = false; | |
$data->errors = $user->get_error_codes(); | |
} else { | |
$usr = new StdClass; | |
$usr->username = $username; | |
$usr->expiry = strtotime('+ 1 day'); | |
$usr->redirect = $redirect; | |
$usr->sig = sha1( json_encode($usr) . FRZN_SSO_SECRET ); | |
$usr_string = json_encode( $usr ); | |
$usr_string = $this->base64url_encode( $usr_string ); | |
// $usr_string = $this->encrypt_string($usr_string); | |
$data->success = true; | |
$data->uri = home_url( '?sso=' . $usr_string); | |
} | |
echo(json_encode($data)); | |
die(); | |
} | |
public function do_login($token) | |
{ | |
$this->add_cors_headers(); | |
header('Content-Type: application/json'); | |
$token = $this->base64url_decode($token); | |
$data = json_decode($token); | |
$token_sig = $data->sig; | |
unset($data->sig); | |
$calc_sig = sha1( json_encode($data) . FRZN_SSO_SECRET ); | |
$out = new StdClass; | |
if ($token_sig == $calc_sig && $data->expiry >= time()) { | |
add_filter('authenticate', array($this, 'token_authentication'), 41, 3); | |
$user = wp_signon( array( 'user_login' => $data->username, 'user_password' => $token_sig, 'rememberme' => false)); | |
// global $auth_secure_cookie; | |
// var_dump($auth_secure_cookie); | |
if (is_wp_error( $user )) { | |
$out->success = false; | |
$out->errors = $user->get_error_codes(); | |
} else { | |
$redirect =$data->redirect; | |
if (!empty($redirect)) { | |
wp_safe_redirect( $redirect ); | |
die(); | |
} | |
$out->success = true; | |
$out->userID = $user->ID; | |
} | |
} else { | |
$out->success = false; | |
$out->errors = array('invalid_token'); | |
} | |
echo(json_encode($out)); | |
die(); | |
} | |
public function token_authentication($user, $username, $password) | |
{ | |
if ( is_a($user, 'WP_User') ) { return $user; } | |
// This function is added to the filters ONLY if the token has | |
// passed the test in do_login so no need to revalidate | |
$user = get_user_by('login', $username); | |
//This is taken from the core wp_authenticate_username_password code http://core.trac.wordpress.org/browser/tags/3.5.1/wp-includes/user.php#L72 | |
if ( !$user ) | |
return new WP_Error('invalid_username', sprintf(__('<strong>ERROR</strong>: Invalid username. <a href="%s" title="Password Lost and Found">Lost your password</a>?'), wp_lostpassword_url())); | |
if ( is_multisite() ) { | |
// Is user marked as spam? | |
if ( 1 == $user->spam) | |
return new WP_Error('invalid_username', __('<strong>ERROR</strong>: Your account has been marked as a spammer.')); | |
// Is a user's blog marked as spam? | |
if ( !is_super_admin( $user->ID ) && isset($user->primary_blog) ) { | |
$details = get_blog_details( $user->primary_blog ); | |
if ( is_object( $details ) && $details->spam == 1 ) | |
return new WP_Error('blog_suspended', __('Site Suspended.')); | |
} | |
} | |
return $user; | |
} | |
public function add_cors_headers() { | |
//TODO: change the allowed origins to be taken from a setting set in the | |
header("Access-Control-Allow-Origin: *"); | |
} | |
private function create_hash() { | |
return substr( sha1( FRONT_END_COOKIE_SSO_SECRET ), 0, 32 ); | |
} | |
private function encrypt_string( $text ) { | |
$salt = $this->create_hash(); | |
return trim( $this->base64url_encode( mcrypt_encrypt( MCRYPT_RIJNDAEL_256, $salt, $text, MCRYPT_MODE_ECB, mcrypt_create_iv( mcrypt_get_iv_size( MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB ), MCRYPT_RAND ) ) ) ); | |
} | |
private function decrypt_string( $text ) { | |
$salt = $this->create_hash(); | |
return trim( mcrypt_decrypt( MCRYPT_RIJNDAEL_256, $salt, $this->base64url_decode( $text ), MCRYPT_MODE_ECB, mcrypt_create_iv( mcrypt_get_iv_size( MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB ), MCRYPT_RAND ) ) ); | |
} | |
//base64 encoding does not produce values that work well in URLs so we | |
// replace the + with - and / with _ and add the = padding on decode | |
// taken from http://us.php.net/manual/en/function.base64-encode.php#103849 | |
private function base64url_encode($data) | |
{ | |
return rtrim(strtr(base64_encode($data), '+/', '-_'), '='); | |
} | |
private function base64url_decode($data) { | |
return base64_decode(str_pad(strtr($data, '-_', '+/'), strlen($data) % 4, '=', STR_PAD_RIGHT)); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// If this file is called directly, abort. | |
if ( ! defined( 'WPINC' ) ) { | |
die; | |
} | |
// TODO: replace `class-frzn-sso.php` with the name of the actual plugin's class file | |
require_once( plugin_dir_path( __FILE__ ) . 'class-frzn-sso.php' ); | |
// Register hooks that are fired when the plugin is activated, deactivated, and uninstalled, respectively. | |
register_activation_hook( __FILE__, array( 'FrozenSso', 'activate' ) ); | |
register_deactivation_hook( __FILE__, array( 'FrozenSso', 'deactivate' ) ); | |
FrozenSso::get_instance(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment