5
5
Plugin URI: http://github.com/psignoret/aad-sso-wordpress
6
6
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.
7
7
Author: Philippe Signoret
8
- Version: 0.6.1
8
+ Version: 0.6.2
9
9
Author URI: https://www.psignoret.com/
10
10
Text Domain: aad-sso-wordpress
11
11
Domain Path: /languages/
17
17
define ( 'AADSSO_PLUGIN_URL ' , plugin_dir_url ( __FILE__ ) );
18
18
define ( 'AADSSO_PLUGIN_DIR ' , plugin_dir_path ( __FILE__ ) );
19
19
20
+ defined ( 'AADSSO_DEBUG ' ) or define ( 'AADSSO_DEBUG ' , FALSE );
21
+ defined ( 'AADSSO_DEBUG_LEVEL ' ) or define ( 'AADSSO_DEBUG_LEVEL ' , 0 );
22
+
20
23
// Proxy to be used for calls, should be useful for tracing with Fiddler
21
24
// BUGBUG: Doesn't actually work, at least not with WP running on WAMP stack
22
25
//define( 'WP_PROXY_HOST', '127.0.0.1' );
@@ -278,7 +281,8 @@ function authenticate( $user, $username, $password ) {
278
281
$ antiforgery_id
279
282
);
280
283
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 );
282
286
283
287
} catch ( Exception $ e ) {
284
288
return new WP_Error (
@@ -338,22 +342,18 @@ function get_wp_user_from_aad_user( $jwt ) {
338
342
$ unique_name = isset ( $ jwt ->upn ) ? $ jwt ->upn : ( isset ( $ jwt ->unique_name ) ? $ jwt ->unique_name : null );
339
343
if ( null === $ unique_name ) {
340
344
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
+ );
345
349
}
346
350
347
351
$ user = get_user_by ( $ this ->settings ->field_to_match_to_upn , $ unique_name );
348
352
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 {
357
357
358
358
// Since the user was authenticated with AAD, but not found in WordPress,
359
359
// 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 ) {
372
372
373
373
$ new_user_id = wp_insert_user ( $ userdata );
374
374
375
- if (is_wp_error ( $ new_user_id ) ) {
375
+ if ( is_wp_error ( $ new_user_id ) ) {
376
376
// The user was authenticated, but not found in WP and auto-provisioning is disabled
377
377
return new WP_Error (
378
378
'user_not_registered ' ,
379
379
sprintf (
380
- __ ( 'ERROR: Cannot create user %s . ' , 'aad-sso-wordpress ' ),
380
+ __ ( 'ERROR: Error creating user \' %s \' . ' , 'aad-sso-wordpress ' ),
381
381
$ unique_name
382
382
)
383
383
);
384
384
}
385
385
else
386
386
{
387
387
AADSSO ::debug_log ( 'Created new user: \'' . $ unique_name . '\', user id ' . $ new_user_id . '. ' );
388
-
389
388
$ user = new WP_User ( $ new_user_id );
390
389
}
391
390
} else {
@@ -394,8 +393,9 @@ function get_wp_user_from_aad_user( $jwt ) {
394
393
return new WP_Error (
395
394
'user_not_registered ' ,
396
395
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
399
399
)
400
400
);
401
401
}
@@ -411,47 +411,70 @@ function get_wp_user_from_aad_user( $jwt ) {
411
411
* @param string $aad_user_id The AAD object id of the user
412
412
* @param string $aad_tenant_id The AAD directory tenant ID
413
413
*
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.
415
415
*/
416
416
function update_wp_user_roles ( $ user , $ aad_user_id , $ aad_tenant_id ) {
417
417
418
- // Pass the settings to GraphHelper
418
+ // TODO: Cleaner (but still lazy) initialization of GraphHelper
419
419
AADSSO_GraphHelper::$ settings = $ this ->settings ;
420
420
AADSSO_GraphHelper::$ tenant_id = $ aad_tenant_id ;
421
421
422
422
// Of the AAD groups defined in the settings, get only those where the user is a member
423
423
$ group_ids = array_keys ( $ this ->settings ->aad_group_to_wp_role_map );
424
424
$ 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
+ }
425
448
426
449
// 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 ();
429
451
430
452
if ( ! empty ( $ group_memberships ->value ) ) {
431
453
foreach ( $ this ->settings ->aad_group_to_wp_role_map as $ aad_group => $ wp_role ) {
432
454
if ( in_array ( $ aad_group , $ group_memberships ->value ) ) {
433
- array_push ( $ role_to_set , $ wp_role );
455
+ array_push ( $ roles_to_set , $ wp_role );
434
456
}
435
457
}
436
458
}
437
459
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 ) {
441
463
$ user ->add_role ( $ role );
442
464
}
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 ) ) {
445
468
$ 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
454
475
);
476
+ AADSSO ::debug_log ( $ error_message , 10 );
477
+ return new WP_Error ( 'user_not_member_of_required_group ' , $ error_message );
455
478
}
456
479
457
480
return $ user ;
@@ -574,14 +597,21 @@ function print_login_link() {
574
597
);
575
598
}
576
599
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" ) ) {
580
610
error_log ( 'AADSSO: ' . $ message );
581
611
} else {
582
612
$ lines = explode ( "\n" , str_replace ( "\r\n" , "\n" , $ message ) );
583
613
foreach ( $ lines as $ line ) {
584
- AADSSO ::debug_log ( $ line );
614
+ AADSSO ::debug_log ( $ line, $ level );
585
615
}
586
616
}
587
617
}
@@ -590,20 +620,15 @@ public static function debug_log( $message ) {
590
620
/**
591
621
* Prints the debug backtrace using this class' debug_log function.
592
622
*/
593
- public static function debug_print_backtrace () {
623
+ public static function debug_print_backtrace ( $ level = 10 ) {
594
624
ob_start ();
595
625
debug_print_backtrace ();
596
626
$ trace = ob_get_contents ();
597
627
ob_end_clean ();
598
- self ::debug_log ( $ trace );
628
+ self ::debug_log ( $ trace, $ level );
599
629
}
600
630
}
601
631
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
-
607
632
/*** Utility functions ***/
608
633
609
634
if ( ! function_exists ( 'com_create_guid ' ) ) {
@@ -626,3 +651,7 @@ function com_create_guid() {
626
651
return $ uuid ;
627
652
}
628
653
}
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