Skip to content

Commit 07a3a0b

Browse files
committed
Adds some more debugging and error handling
1 parent cc48018 commit 07a3a0b

File tree

1 file changed

+77
-48
lines changed

1 file changed

+77
-48
lines changed

aad-sso-wordpress.php

Lines changed: 77 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
Plugin URI: http://github.com/psignoret/aad-sso-wordpress
66
Description: Allows you to use your organization's Azure Active Directory user accounts to log in to WordPress. If your organization is using Office 365, your user accounts are already in Azure Active Directory. This plugin uses OAuth 2.0 to authenticate users, and the Azure Active Directory Graph to get group membership and other details.
77
Author: Philippe Signoret
8-
Version: 0.6.1
8+
Version: 0.6.2
99
Author URI: https://www.psignoret.com/
1010
Text Domain: aad-sso-wordpress
1111
Domain Path: /languages/
@@ -17,6 +17,9 @@
1717
define( 'AADSSO_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
1818
define( 'AADSSO_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
1919

20+
defined( 'AADSSO_DEBUG' ) or define( 'AADSSO_DEBUG', FALSE );
21+
defined( 'AADSSO_DEBUG_LEVEL' ) or define( 'AADSSO_DEBUG_LEVEL', 0 );
22+
2023
// Proxy to be used for calls, should be useful for tracing with Fiddler
2124
// BUGBUG: Doesn't actually work, at least not with WP running on WAMP stack
2225
//define( 'WP_PROXY_HOST', '127.0.0.1' );
@@ -278,7 +281,8 @@ function authenticate( $user, $username, $password ) {
278281
$antiforgery_id
279282
);
280283

281-
AADSSO::debug_log( json_encode( $jwt ) );
284+
AADSSO::debug_log( 'id_token: iss: \'' . $jwt->iss . '\', oid: \'' . $jwt->oid, 10 );
285+
AADSSO::debug_log( json_encode( $jwt ), 50 );
282286

283287
} catch ( Exception $e ) {
284288
return new WP_Error(
@@ -338,22 +342,18 @@ function get_wp_user_from_aad_user( $jwt ) {
338342
$unique_name = isset( $jwt->upn ) ? $jwt->upn : ( isset( $jwt->unique_name ) ? $jwt->unique_name : null );
339343
if ( null === $unique_name ) {
340344
return new WP_Error(
341-
'unique_name_not_found',
342-
__( 'ERROR: Neither \'upn\' nor \'unique_name\' claims not found in ID Token.',
343-
'aad-sso-wordpress' )
344-
);
345+
'unique_name_not_found',
346+
__( 'ERROR: Neither \'upn\' nor \'unique_name\' claims not found in ID Token.',
347+
'aad-sso-wordpress' )
348+
);
345349
}
346350

347351
$user = get_user_by( $this->settings->field_to_match_to_upn, $unique_name );
348352

349-
if( true === $this->settings->match_on_upn_alias ) {
350-
if ( ! is_a( $user, 'WP_User' ) ) {
351-
$username = explode( sprintf( '@%s', $this->settings->org_domain_hint ), $unique_name );
352-
$user = get_user_by( $this->settings->field_to_match_to_upn, $username[0] );
353-
}
354-
}
355-
356-
if ( ! is_a( $user, 'WP_User' ) ) {
353+
if ( is_a( $user, 'WP_User' ) ) {
354+
AADSSO::debug_log( sprintf(
355+
'Matched Azure AD user [%s] to existing WordPress user [%s].', $unique_name, $user->ID ), 10 );
356+
} else {
357357

358358
// Since the user was authenticated with AAD, but not found in WordPress,
359359
// need to decide whether to create a new user in WP on-the-fly, or to stop here.
@@ -372,20 +372,19 @@ function get_wp_user_from_aad_user( $jwt ) {
372372

373373
$new_user_id = wp_insert_user( $userdata );
374374

375-
if (is_wp_error( $new_user_id ) ) {
375+
if ( is_wp_error( $new_user_id ) ) {
376376
// The user was authenticated, but not found in WP and auto-provisioning is disabled
377377
return new WP_Error(
378378
'user_not_registered',
379379
sprintf(
380-
__( 'ERROR: Cannot create user %s.', 'aad-sso-wordpress' ),
380+
__( 'ERROR: Error creating user \'%s\'.', 'aad-sso-wordpress' ),
381381
$unique_name
382382
)
383383
);
384384
}
385385
else
386386
{
387387
AADSSO::debug_log( 'Created new user: \'' . $unique_name . '\', user id ' . $new_user_id . '.' );
388-
389388
$user = new WP_User( $new_user_id );
390389
}
391390
} else {
@@ -394,8 +393,9 @@ function get_wp_user_from_aad_user( $jwt ) {
394393
return new WP_Error(
395394
'user_not_registered',
396395
sprintf(
397-
__( 'ERROR: The authenticated user %s is not a registered user in this blog.', 'aad-sso-wordpress' ),
398-
$jwt->upn
396+
__( 'ERROR: The authenticated user \'%s\' is not a registered user in this site.',
397+
'aad-sso-wordpress' ),
398+
$unique_name
399399
)
400400
);
401401
}
@@ -411,47 +411,70 @@ function get_wp_user_from_aad_user( $jwt ) {
411411
* @param string $aad_user_id The AAD object id of the user
412412
* @param string $aad_tenant_id The AAD directory tenant ID
413413
*
414-
* @return WP_User|WP_Error Return the WP_User with updated rols, or WP_Error if failed.
414+
* @return WP_User|WP_Error Return the WP_User with updated roles, or WP_Error if failed.
415415
*/
416416
function update_wp_user_roles( $user, $aad_user_id, $aad_tenant_id ) {
417417

418-
// Pass the settings to GraphHelper
418+
// TODO: Cleaner (but still lazy) initialization of GraphHelper
419419
AADSSO_GraphHelper::$settings = $this->settings;
420420
AADSSO_GraphHelper::$tenant_id = $aad_tenant_id;
421421

422422
// Of the AAD groups defined in the settings, get only those where the user is a member
423423
$group_ids = array_keys( $this->settings->aad_group_to_wp_role_map );
424424
$group_memberships = AADSSO_GraphHelper::user_check_member_groups( $aad_user_id, $group_ids );
425+
426+
// Check for errors in the group membership check response
427+
if ( isset( $group_memberships->value ) ) {
428+
AADSSO::debug_log( sprintf(
429+
'Out of [%s], user \'%s\' is a member of [%s]',
430+
implode( ',', $group_ids ), $aad_user_id, implode( ',', $group_memberships->value ) ), 20
431+
);
432+
} elseif ( isset ( $group_memberships->{'odata.error'} ) ) {
433+
AADSSO::debug_log( 'Error when checking group membership: ' . json_encode( $group_memberships ) );
434+
return new WP_Error(
435+
'error_checking_group_membership',
436+
sprintf(
437+
__( 'ERROR: Unable to check group membership in Azure AD: <b>%s</b>.',
438+
'aad-sso-wordpress' ), $group_memberships->{'odata.error'}->code )
439+
);
440+
} else {
441+
AADSSO::debug_log( 'Unexpected response to checkMemberGroups: ' . json_encode( $group_memberships ) );
442+
return new WP_Error(
443+
'unexpected_response_to_checkMemberGroups',
444+
__( 'ERROR: Unexpected response when checking group membership in Azure AD.',
445+
'aad-sso-wordpress' )
446+
);
447+
}
425448

426449
// Determine which WordPress role the AAD group corresponds to.
427-
// TODO: Check for error in the group membership response
428-
$role_to_set = array();
450+
$roles_to_set = array();
429451

430452
if ( ! empty( $group_memberships->value ) ) {
431453
foreach ( $this->settings->aad_group_to_wp_role_map as $aad_group => $wp_role ) {
432454
if ( in_array( $aad_group, $group_memberships->value ) ) {
433-
array_push( $role_to_set, $wp_role );
455+
array_push( $roles_to_set, $wp_role );
434456
}
435457
}
436458
}
437459

438-
if ( ! empty( $role_to_set ) ) {
439-
$user->set_role("");
440-
foreach ( $role_to_set as $role ){
460+
if ( ! empty( $roles_to_set ) ) {
461+
$user->set_role( '' );
462+
foreach ( $roles_to_set as $role ) {
441463
$user->add_role( $role );
442464
}
443-
}
444-
else if ( null != $this->settings->default_wp_role || "" != $this->settings->default_wp_role ){
465+
AADSSO::debug_log( sprintf(
466+
'Set roles [%s] for user [%s].', implode( ', ', $roles_to_set ), $user->ID ), 10 );
467+
} else if ( ! empty( $this->settings->default_wp_role ) ) {
445468
$user->set_role( $this->settings->default_wp_role );
446-
}
447-
else{
448-
return new WP_Error(
449-
'user_not_member_of_required_group',
450-
sprintf(
451-
__( 'ERROR: AAD user %s is not a member of any group granting a role.', 'aad-sso-wordpress' ),
452-
$aad_user_id
453-
)
469+
AADSSO::debug_log( sprintf(
470+
'Set default role [%s] for user [%s].', $this->settings->default_wp_role, $user->ID ), 10 );
471+
} else {
472+
$error_message = sprintf(
473+
__( 'ERROR: Azure AD user %s is not a member of any group granting a role.', 'aad-sso-wordpress' ),
474+
$aad_user_id
454475
);
476+
AADSSO::debug_log( $error_message, 10 );
477+
return new WP_Error( 'user_not_member_of_required_group', $error_message );
455478
}
456479

457480
return $user;
@@ -574,14 +597,21 @@ function print_login_link() {
574597
);
575598
}
576599

577-
public static function debug_log( $message ) {
578-
if ( defined('AADSSO_DEBUG') && true === AADSSO_DEBUG ) {
579-
if ( strpos( $message, "\n" ) === false ) {
600+
/**
601+
* Emits debug details to the logs. The higher the level, the more verbose.
602+
*
603+
* If there are multiple lines in the message, they will each be emitted as a log line.
604+
*/
605+
public static function debug_log( $message, $level = 0 ) {
606+
607+
// AADSSO_DEBUG and AADSSO_DEBUG_LEVEL are already defined.
608+
if ( AADSSO_DEBUG && AADSSO_DEBUG_LEVEL >= $level ) {
609+
if ( FALSE === strpos( $message, "\n" ) ) {
580610
error_log( 'AADSSO: ' . $message );
581611
} else {
582612
$lines = explode( "\n", str_replace( "\r\n", "\n", $message ) );
583613
foreach ( $lines as $line ) {
584-
AADSSO::debug_log( $line );
614+
AADSSO::debug_log( $line, $level );
585615
}
586616
}
587617
}
@@ -590,20 +620,15 @@ public static function debug_log( $message ) {
590620
/**
591621
* Prints the debug backtrace using this class' debug_log function.
592622
*/
593-
public static function debug_print_backtrace() {
623+
public static function debug_print_backtrace( $level = 10 ) {
594624
ob_start();
595625
debug_print_backtrace();
596626
$trace = ob_get_contents();
597627
ob_end_clean();
598-
self::debug_log( $trace );
628+
self::debug_log( $trace, $level );
599629
}
600630
}
601631

602-
// Load settings JSON contents from DB and initialize the plugin
603-
$aadsso_settings_instance = AADSSO_Settings::init();
604-
$aadsso = AADSSO::get_instance( $aadsso_settings_instance );
605-
606-
607632
/*** Utility functions ***/
608633

609634
if ( ! function_exists( 'com_create_guid' ) ) {
@@ -626,3 +651,7 @@ function com_create_guid() {
626651
return $uuid;
627652
}
628653
}
654+
655+
// Load settings JSON contents from DB and initialize the plugin
656+
$aadsso_settings_instance = AADSSO_Settings::init();
657+
$aadsso = AADSSO::get_instance( $aadsso_settings_instance, com_create_guid() );

0 commit comments

Comments
 (0)