Skip to content

Instantly share code, notes, and snippets.

@mattsahr
Forked from adamcapriola/page_discourse-sso.php
Last active August 29, 2015 14:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mattsahr/d562a137621780a64a9e to your computer and use it in GitHub Desktop.
Save mattsahr/d562a137621780a64a9e to your computer and use it in GitHub Desktop.
<?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