-
-
Save mattsahr/d562a137621780a64a9e to your computer and use it in GitHub Desktop.
This file contains 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 | |
/** | |
* SOURCE https://github.com/ArmedGuy/discourse_sso_php/blob/master/discourse_sso.php | |
* This Discourse_SSO class gets used in the full module below | |
*/ | |
class Discourse_SSO { | |
private $sso_secret; | |
function __construct($secret) { | |
$this->sso_secret = $secret; | |
} | |
public function validate($payload, $sig) { | |
$payload = urldecode($payload); | |
if(hash_hmac("sha256", $payload, $this->sso_secret) === $sig) { | |
return true; | |
} else { | |
return false; | |
} | |
} | |
public function getNonce($payload) { | |
$payload = urldecode($payload); | |
$query = array(); | |
parse_str(base64_decode($payload), $query); | |
if(isset($query["nonce"])) { | |
return $query["nonce"]; | |
} else { | |
throw new Exception("Nonce not found in payload!"); | |
} | |
} | |
public function buildLoginString($params) { | |
if(!isset($params["external_id"])) { | |
throw new Exception("Missing required parameter 'external_id'"); | |
} | |
if(!isset($params["nonce"])) { | |
throw new Exception("Missing required parameter 'nonce'"); | |
} | |
if(!isset($params["email"])) { | |
throw new Exception("Missing required parameter 'email'"); | |
} | |
$payload = base64_encode(http_build_query($params)); | |
$sig = hash_hmac("sha256", $payload, $this->sso_secret); | |
return http_build_query(array("sso" => $payload, "sig" => $sig)); | |
} | |
} | |
/** | |
* Template Name: Discourse SSO | |
* Author: Adam Capriola | |
* Version: 1.1 | |
* Author URI: https://meta.discourse.org/users/AdamCapriola/activity | |
* Adapted From: https://github.com/ArmedGuy/discourse_sso_php | |
* Uses: https://meta.discourse.org/t/official-single-sign-on-for-discourse/13045 | |
* | |
*/ | |
// Customize these two variables | |
$sso_secret = 'meow'; | |
$discourse_url = 'http://discourse.example.com'; // Note: No trailing slash! | |
// | |
// Check if user is logged in to WordPress | |
// | |
// Not logged in to WordPress, redirect to WordPress login page with redirect back to here | |
if ( ! is_user_logged_in() ) { | |
// Preserve sso and sig parameters | |
$redirect = add_query_arg(); | |
// Change %0A to %0B so it's not stripped out in wp_sanitize_redirect | |
$redirect = str_replace( '%0A', '%0B', $redirect ); | |
// Build login URL | |
$login = wp_login_url( $redirect ); | |
// Redirect to login | |
wp_redirect( $login ); | |
exit; | |
} | |
// Logged in to WordPress, now try to log in to Discourse with WordPress user information | |
else { | |
// Payload and signature | |
$payload = $_GET['sso']; | |
$sig = $_GET['sig']; | |
// Change %0B back to %0A | |
$payload = urldecode( str_replace( '%0B', '%0A', urlencode( $payload ) ) ); | |
// Check for helper class | |
if ( ! class_exists( 'Discourse_SSO' ) ) { | |
// Error message | |
echo( 'Helper class is not properly included.' ); | |
// Terminate | |
exit; | |
} | |
// Validate signature | |
$sso = new Discourse_SSO( $sso_secret ); | |
if ( ! ( $sso->validate( $payload, $sig ) ) ) { | |
// Error message | |
echo( 'Invalid request.' ); | |
// Terminate | |
exit; | |
} | |
// Nonce | |
$nonce = $sso->getNonce( $payload ); | |
// Current user info | |
get_currentuserinfo(); | |
// Map information | |
$params = array( | |
'nonce' => $nonce, | |
'name' => $current_user->display_name, | |
'username' => $current_user->user_login, | |
'email' => $current_user->user_email, | |
'about_me' => $current_user->description, | |
'external_id' => $current_user->ID | |
); | |
// Build login string | |
$q = $sso->buildLoginString( $params ); | |
// Redirect back to Discourse | |
wp_redirect( $discourse_url . '/session/sso_login?' . $q ); | |
exit; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment