Skip to content

Commit

Permalink
Merge pull request #70 from auth0/dev
Browse files Browse the repository at this point in the history
New jwt auth integration + auto user creation with JWT
  • Loading branch information
glena committed May 27, 2015
2 parents a7bd9ad + acb2ccd commit c9e2970
Show file tree
Hide file tree
Showing 14 changed files with 227 additions and 104 deletions.
113 changes: 29 additions & 84 deletions WP_Auth0.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
/**
* Plugin Name: Wordpress Auth0 Integration
* Description: Implements the Auth0 Single Sign On solution into Wordpress
* Version: 1.2.5
* Version: 1.2.6
* Author: Auth0
* Author URI: https://auth0.com
*/
Expand All @@ -12,10 +12,10 @@
define('WPA0_PLUGIN_URL', trailingslashit(plugin_dir_url(__FILE__) ));
define('WPA0_LANG', 'wp-auth0');
define('AUTH0_DB_VERSION', 2);
define('WPA0_VERSION', '1.2.5');
define('WPA0_VERSION', '1.2.6');

class WP_Auth0 {
public static function init(){
public static function init(){
spl_autoload_register(array(__CLASS__, 'autoloader'));

// WP_Auth0_Referer_Check::init();
Expand Down Expand Up @@ -63,6 +63,7 @@ public static function init(){
add_action( 'wp_footer', array( __CLASS__, 'a0_render_message' ) );
}

WP_Auth0_UsersRepo::init();
WP_Auth0_Settings_Section::init();
WP_Auth0_Admin::init();
WP_Auth0_ErrorLog::init();
Expand Down Expand Up @@ -99,7 +100,7 @@ public static function isJWTConfigured() {
JWT_AUTH_Options::get('aud') == WP_Auth0_Options::get('client_id') &&
JWT_AUTH_Options::get('secret') == WP_Auth0_Options::get('client_secret') &&
JWT_AUTH_Options::get('secret_base64_encoded') &&
JWT_AUTH_Options::get('override_user_repo') == 'WP_Auth0_UsersRepo' &&
WP_Auth0_Options::get('jwt_auth_integration') &&
JWT_AUTH_Options::get('jwt_attribute') == 'sub'
);

Expand Down Expand Up @@ -387,7 +388,7 @@ public static function init_auth0(){
}

$userinfo = json_decode( $response['body'] );
if (self::login_user($userinfo, $data)) {
if (self::login_user($userinfo, $data->id_token)) {
if ($stateFromGet !== null && isset($stateFromGet->interim) && $stateFromGet->interim) {
include WPA0_PLUGIN_DIR . 'templates/login-interim.php';
exit();
Expand Down Expand Up @@ -455,23 +456,6 @@ private static function findAuth0User($id) {
return $user;
}

private static function insertAuth0User($userinfo, $user_id) {
global $wpdb;
$wpdb->insert(
$wpdb->auth0_user,
array(
'auth0_id' => $userinfo->user_id,
'wp_id' => $user_id,
'auth0_obj' => serialize($userinfo)
),
array(
'%s',
'%d',
'%s'
)
);
}

public static function insertAuth0Error($section, $wp_error) {

if ($wp_error instanceof WP_Error) {
Expand Down Expand Up @@ -519,11 +503,11 @@ public static function delete_user ($user_id) {
$wpdb->delete( $wpdb->auth0_user, array( 'wp_id' => $user_id), array( '%d' ) );
}

private static function dieWithVerifyEmail($userinfo, $data) {
private static function dieWithVerifyEmail($userinfo, $id_token) {

ob_start();
$domain = WP_Auth0_Options::get( 'domain' );
$token = $data->id_token;
$token = $id_token;
$email = $userinfo->email;
$connection = $userinfo->identities[0]->connection;
$userId = $userinfo->user_id;
Expand All @@ -534,7 +518,7 @@ private static function dieWithVerifyEmail($userinfo, $data) {
wp_die($html);

}
private static function login_user( $userinfo, $data ){
public static function login_user( $userinfo, $id_token ){
// If the userinfo has no email or an unverified email, and in the options we require a verified email
// notify the user he cant login until he does so.
$requires_verified_email = WP_Auth0_Options::get( 'requires_verified_email' );
Expand All @@ -548,10 +532,8 @@ private static function login_user( $userinfo, $data ){
wp_die($msg);
}



if (!$userinfo->email_verified) {
self::dieWithVerifyEmail($userinfo, $data);
self::dieWithVerifyEmail($userinfo, $id_token);
}

}
Expand All @@ -564,69 +546,31 @@ private static function login_user( $userinfo, $data ){
wp_set_auth_cookie( $user->ID );
return true;
} else {
// If the user doesn't exist we need to either create a new one, or asign him to an existing one
$isDatabaseUser = false;
foreach ($userinfo->identities as $identity) {
if ($identity->provider == "auth0") {
$isDatabaseUser = true;
}
}
$joinUser = null;
// If the user has a verified email or is a database user try to see if there is
// a user to join with. The isDatabase is because we don't want to allow database
// user creation if there is an existing one with no verified email

if (isset($userinfo->email) && ((isset($userinfo->email_verified) && $userinfo->email_verified) || $isDatabaseUser)) {
$joinUser = get_user_by( 'email', $userinfo->email );
}

// $auto_provisioning = WP_Auth0_Options::get('auto_provisioning');
// $allow_signup = WP_Auth0_Options::is_wp_registration_enabled() || $auto_provisioning;
$allow_signup = WP_Auth0_Options::is_wp_registration_enabled();
try {
$creator = new WP_Auth0_UserCreator();
$user_id = $creator->create($userinfo, $id_token);

if (!is_null($joinUser) && $joinUser instanceof WP_User) {
// If we are here, we have a potential join user
// Don't allow creation or assignation of user if the email is not verified, that would
// be hijacking
if (!$userinfo->email_verified) {
self::dieWithVerifyEmail($userinfo, $data);
}
$user_id = $joinUser->ID;
} elseif ($allow_signup) {
// If we are here, we need to create the user
$user_id = WP_Auth0_Users::create_user($userinfo);

// Check if user was created

if( is_wp_error($user_id) ) {
$msg = __('Error: Could not create user.', WPA0_LANG);
$msg = ' ' . $user_id->get_error_message();
$msg .= '<br/><br/>';
$msg .= '<a href="' . site_url() . '">' . __('← Go back', WPA0_LANG) . '</a>';
wp_die($msg);

}elseif($user_id == -2){
$msg = __('Error: Could not create user. The registration process were rejected. Please verify that your account is whitelisted for this system.', WPA0_LANG);
$msg .= '<br/><br/>';
$msg .= '<a href="' . site_url() . '">' . __('← Go back', WPA0_LANG) . '</a>';

wp_die($msg);
}elseif ($user_id <0){
$msg = __('Error: Could not create user.', WPA0_LANG);
$msg .= '<br/><br/>';
$msg .= '<a href="' . site_url() . '">' . __('← Go back', WPA0_LANG) . '</a>';
wp_die($msg);
}
} else {
wp_set_auth_cookie( $user_id );
}
catch (WP_Auth0_CouldNotCreateUserException $e) {
$msg = __('Error: Could not create user.', WPA0_LANG);
$msg = ' ' . $e->getMessage();
$msg .= '<br/><br/>';
$msg .= '<a href="' . site_url() . '">' . __('← Go back', WPA0_LANG) . '</a>';
wp_die($msg);
}
catch (WP_Auth0_RegistrationNotEnabledException $e) {
$msg = __('Error: Could not create user. The registration process is not available.', WPA0_LANG);
$msg .= '<br/><br/>';
$msg .= '<a href="' . site_url() . '">' . __('← Go back', WPA0_LANG) . '</a>';
wp_die($msg);
}
// If we are here we should have a valid $user_id with a new user or an existing one
// log him in, and update the auth0_user table
self::insertAuth0User($userinfo, $user_id);
wp_set_auth_cookie( $user_id );
catch (WP_Auth0_EmailNotVerifiedException $e) {
self::dieWithVerifyEmail($e->userinfo, $e->id_token);
}


return true;
}
}
Expand Down Expand Up @@ -787,6 +731,7 @@ private static function autoloader($class){

$paths[] = $path;
$paths[] = $path.'lib/';
$paths[] = $path.'lib/exceptions/';

foreach($paths as $p)
foreach($exts as $ext){
Expand Down
19 changes: 17 additions & 2 deletions lib/WP_Auth0_Admin.php
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ public static function init_admin(){

/* ------------------------- ADVANCED ------------------------- */

self::init_option_section('Advanced', array(
$advancedOptions = array(

array('id' => 'wpa0_dict', 'name' => 'Translation', 'function' => 'render_dict'),
array('id' => 'wpa0_username_style', 'name' => 'Username style', 'function' => 'render_username_style'),
Expand All @@ -89,7 +89,16 @@ public static function init_admin(){
array('id' => 'wpa0_extra_conf', 'name' => 'Extra settings', 'function' => 'render_extra_conf'),
array('id' => 'wpa0_cdn_url', 'name' => 'Widget URL', 'function' => 'render_cdn_url'),

));
);



if (WP_Auth0::isJWTAuthEnabled()) {
$advancedOptions[] = array('id' => 'wpa0_jwt_auth_integration', 'name' => 'Enable JWT Auth integration', 'function' => 'render_jwt_auth_integration');
}

self::init_option_section('Advanced', $advancedOptions);


register_setting(WP_Auth0_Options::OPTIONS_NAME, WP_Auth0_Options::OPTIONS_NAME, array(__CLASS__, 'input_validator'));
}
Expand All @@ -107,6 +116,11 @@ public static function render_remember_last_login () {
echo '<input type="checkbox" name="' . WP_Auth0_Options::OPTIONS_NAME . '[remember_last_login]" id="wpa0_remember_last_login" value="1" ' . checked( $v, 1, false ) . '/>';
echo '<br/><span class="description">' . __('Request for SSO data and enable Last time you signed in with[...] message.', WPA0_LANG) . '<a target="_blank" href="https://github.com/auth0/lock/wiki/Auth0Lock-customization#rememberlastlogin-boolean">' . __('More info', WPA0_LANG) . '</a></span>';
}
public static function render_jwt_auth_integration () {
$v = absint(WP_Auth0_Options::get( 'jwt_auth_integration' ));
echo '<input type="checkbox" name="' . WP_Auth0_Options::OPTIONS_NAME . '[jwt_auth_integration]" id="wpa0_jwt_auth_integration" value="1" ' . checked( $v, 1, false ) . '/>';
echo '<br/><span class="description">' . __('This will enable the JWT Auth\'s Users Repository override.', WPA0_LANG) . '</span>';
}

public static function create_account_message(){
echo '<div id="message" class="updated"><p><strong>'
Expand Down Expand Up @@ -301,6 +315,7 @@ public static function input_validator( $input ){

$input['requires_verified_email'] = (isset($input['requires_verified_email']) ? 1 : 0);
$input['wordpress_login_enabled'] = (isset($input['wordpress_login_enabled']) ? 1 : 0);
$input['jwt_auth_integration'] = (isset($input['jwt_auth_integration']) ? 1 : 0);
$input['allow_signup'] = (isset($input['allow_signup']) ? 1 : 0);
$input['auth0_implicit_workflow'] = (isset($input['auth0_implicit_workflow']) ? 1 : 0);

Expand Down
13 changes: 13 additions & 0 deletions lib/WP_Auth0_Api_Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,17 @@ public static function get_user_info($domain, $access_token) {

}

public static function get_user($domain, $jwt, $user_id) {
$endpoint = "https://$domain/api/v2/users/" . urlencode($user_id);

$headers = self::get_info_headers();

$headers['Authorization'] = "Bearer $jwt";

return wp_remote_get( $endpoint , array(
'headers' => $headers
));

}

}
3 changes: 1 addition & 2 deletions lib/WP_Auth0_Configure_JWTAUTH.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,11 @@ public static function render_settings_page(){

protected static function setupjwt() {
if(WP_Auth0::isJWTAuthEnabled()) {
global $wpdb;

JWT_AUTH_Options::set('aud', WP_Auth0_Options::get('client_id'));
JWT_AUTH_Options::set('secret', WP_Auth0_Options::get('client_secret'));
JWT_AUTH_Options::set('secret_base64_encoded', true);
JWT_AUTH_Options::set('override_user_repo', 'WP_Auth0_UsersRepo');
WP_Auth0_Options::set('jwt_auth_integration', true);
}
}

Expand Down
1 change: 1 addition & 0 deletions lib/WP_Auth0_Options.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ private static function defaults(){
'custom_css' => '',
'auth0_implicit_workflow' => false,
'gravatar' => true,
'jwt_auth_integration' => false,
// 'auto_provisioning' => true,
'default_login_redirection' => home_url(),
);
Expand Down
86 changes: 86 additions & 0 deletions lib/WP_Auth0_UserCreator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
<?php

class WP_Auth0_UserCreator {

public function tokenHasRequiredScopes($jwt) {

return (
(isset($jwt->email) || isset($jwt->nickname))
&& isset($jwt->identities)
);

}

public function create($userinfo, $token) {

// If the user doesn't exist we need to either create a new one, or asign him to an existing one
$isDatabaseUser = false;
foreach ($userinfo->identities as $identity) {
if ($identity->provider == "auth0") {
$isDatabaseUser = true;
}
}
$joinUser = null;
// If the user has a verified email or is a database user try to see if there is
// a user to join with. The isDatabase is because we don't want to allow database
// user creation if there is an existing one with no verified email

if (isset($userinfo->email) && ((isset($userinfo->email_verified) && $userinfo->email_verified) || $isDatabaseUser)) {
$joinUser = get_user_by( 'email', $userinfo->email );
}

// $auto_provisioning = WP_Auth0_Options::get('auto_provisioning');
// $allow_signup = WP_Auth0_Options::is_wp_registration_enabled() || $auto_provisioning;
$allow_signup = WP_Auth0_Options::is_wp_registration_enabled();

if (!is_null($joinUser) && $joinUser instanceof WP_User) {
// If we are here, we have a potential join user
// Don't allow creation or assignation of user if the email is not verified, that would
// be hijacking
if (!$userinfo->email_verified) {
throw new WP_Auth0_EmailNotVerifiedException($userinfo, $token);
}
$user_id = $joinUser->ID;
} elseif ($allow_signup) {
// If we are here, we need to create the user
$user_id = WP_Auth0_Users::create_user($userinfo);

// Check if user was created

if( is_wp_error($user_id) ) {
throw new WP_Auth0_CouldNotCreateUserException($user_id->get_error_message());
}elseif($user_id == -2){
throw new WP_Auth0_CouldNotCreateUserException('Could not create user. The registration process were rejected. Please verify that your account is whitelisted for this system.');
}elseif ($user_id <0){
throw new WP_Auth0_CouldNotCreateUserException();
}
} else {
throw new WP_Auth0_RegistrationNotEnabledException();
}

// If we are here we should have a valid $user_id with a new user or an existing one
// log him in, and update the auth0_user table
self::insertAuth0User($userinfo, $user_id);

return $user_id;

}

public function insertAuth0User($userinfo, $user_id) {
global $wpdb;
$wpdb->insert(
$wpdb->auth0_user,
array(
'auth0_id' => $userinfo->user_id,
'wp_id' => $user_id,
'auth0_obj' => serialize($userinfo)
),
array(
'%s',
'%d',
'%s'
)
);
}

}
Loading

0 comments on commit c9e2970

Please sign in to comment.