diff --git a/admin/openid-connect-generic-settings.php b/admin/openid-connect-generic-settings.php index 61d1611..080fd77 100644 --- a/admin/openid-connect-generic-settings.php +++ b/admin/openid-connect-generic-settings.php @@ -109,10 +109,22 @@ class OpenID_Connect_Generic_Settings { 'section' => 'authorization_settings', ), 'enforce_privacy' => array( - 'title' => __('Enforce Privacy'), - 'description' => __('Require users be logged in to see the site.'), - 'type' => 'checkbox', - 'section' => 'authorization_settings', + 'title' => __('Enforce Privacy'), + 'description' => __('Require users be logged in to see the site.'), + 'type' => 'checkbox', + 'section' => 'authorization_settings', + ), + 'enable_logging' => array( + 'title' => __('Enable Logging'), + 'description' => __('Very simple log messages for debugging purposes.'), + 'type' => 'checkbox', + 'section' => 'log_settings', + ), + 'log_limit' => array( + 'title' => __('Log Limit'), + 'description' => __('Number of items to keep in the log. These logs are stored as an option in the database, so space is limited.'), + 'type' => 'number', + 'section' => 'log_settings', ), ); @@ -153,10 +165,16 @@ class OpenID_Connect_Generic_Settings { $this->options_page_name ); - add_settings_section( 'authorization_settings', - __('Authorization Settings'), - array( $this, 'authorization_settings_description' ), - $this->options_page_name + add_settings_section( 'authorization_settings', + __('Authorization Settings'), + array( $this, 'authorization_settings_description' ), + $this->options_page_name + ); + + add_settings_section( 'log_settings', + __('Log Settings'), + array( $this, 'log_settings_description' ), + $this->options_page_name ); // preprocess fields and add them to the page @@ -228,10 +246,39 @@ class OpenID_Connect_Generic_Settings { submit_button(); ?> +

+ + +

+ + + + + + + + + + + + + + + + + +
TypeDateUserData
user_login : 'anonymous'; ?>' . print_r( $log['data'], 1 ) . ''; ?>
+ - 0, 'enforce_privacy' => 0, 'identity_key' => 'sub', + 'enable_logging' => 0, + 'log_limit' => 1000, ); // storage for plugin settings @@ -60,6 +62,8 @@ class OpenID_Connect_Generic { private $redirect_uri; + private $logs = null; + /** * Initialize the plugin */ @@ -97,6 +101,58 @@ class OpenID_Connect_Generic { $this->settings = wp_parse_args( get_option( OPENID_CONNECT_GENERIC_SETTINGS_NAME, array() ), $this->default_settings ); return $this->settings; } + + /** + * Retrieve all log messages + */ + public function get_logs(){ + if ( is_null( $this->logs ) ) { + $this->logs = get_option( 'openid_connect_generic_logs', array() ); + } + + return $this->logs; + } + + /** + * + */ + public function log( $data, $type = 'error' ){ + if ( (bool) $this->settings['enable_logging'] ) { + $this->add_log_message( $data, $type ); + } + } + + /** + * Add a new message to the log + * + * @param $data array - extra data about the message + * @param $type string - simple message type string, defaults to error + */ + public function add_log_message( $data = array(), $type = 'error' ){ + // construct our message + $message = array( + 'type' => $type, + 'time' => time(), + 'user_ID' => get_current_user_id(), + 'data' => is_array( $data ) ? $data : array( $data ), + ); + + // add our message to the logs + $logs = $this->get_logs(); + $logs[] = $message; + + // keep our log count under the limit + $items_to_remove = count( $logs ) - (int) $this->settings['log_limit']; + + while ( $items_to_remove > 0 ) { + array_shift( $logs ); + $items_to_remove--; + } + + // save our logs + $this->logs = $logs; + update_option( 'openid_connect_generic_logs', $logs, false ); + } /** * Implements hook init @@ -182,12 +238,12 @@ class OpenID_Connect_Generic { // look for an existing error of some kind if ( isset( $_GET['error'] ) ) { - $this->error_redirect( 99 ); + $this->error( 99 ); } // make sure we have a legitimate authentication code and valid state if ( !isset( $_GET['code'] ) || !isset( $_GET['state'] ) || !$this->check_state( $_GET['state'] ) ) { - $this->error_redirect( 1 ); + $this->error( 1 ); } // we have an authorization code, make sure it is good by @@ -196,7 +252,7 @@ class OpenID_Connect_Generic { // ensure the token is not an error generated by wp if ( is_wp_error( $token_result ) ){ - $this->error_redirect( 2 ); + $this->error( 2, $token_result ); } // extract token response from token @@ -207,7 +263,7 @@ class OpenID_Connect_Generic { if ( ! isset( $token_response['id_token'] ) || ! isset( $token_response['access_token'] ) || ! isset( $token_response['token_type'] ) || $token_response['token_type'] !== 'Bearer' ) { - $this->error_redirect( 4 ); + $this->error( 4 ); } // - end authentication @@ -225,7 +281,7 @@ class OpenID_Connect_Generic { // make sure we can find our identification data and that it has a value if ( ! isset( $id_token_claim[ $settings['identity_key'] ] ) || empty( $id_token_claim[ $settings['identity_key'] ] ) ) { - $this->error_redirect( 5 ); + $this->error( 5 ); } // if desired, admins can use regex to determine if the identity value is valid @@ -233,7 +289,7 @@ class OpenID_Connect_Generic { if ( isset( $settings['allowed_regex'] ) && !empty( $settings['allowed_regex'] ) && preg_match( $settings['allowed_regex'], $id_token_claim[ $settings['identity_key'] ] ) !== 1) { - $this->error_redirect( 5 ); + $this->error( 5 ); } // send a userinfo request to get user claim @@ -241,14 +297,14 @@ class OpenID_Connect_Generic { // make sure we didn't get an error, and that the response body exists if ( is_wp_error( $user_claim_result ) || ! isset( $user_claim_result['body'] ) ) { - $this->error_redirect( 3 ); + $this->error( 3, $user_claim_result ); } $user_claim = json_decode( $user_claim_result['body'], true ); // make sure the id_token sub === user_claim sub, according to spec if ( $id_token_claim[ $settings['identity_key'] ] !== $user_claim['sub'] ) { - $this->error_redirect( 4 ); + $this->error( 4 ); } // retrieve the identity from the id_token @@ -262,7 +318,7 @@ class OpenID_Connect_Generic { $login_user = apply_filters( 'openid-connect-generic-user-login-test', true, $user_claim ); if ( ! $login_user ){ - $this->error_redirect( 8 ); + $this->error( 8 ); } // look for user by their openid-connect-generic-user-identity value @@ -298,7 +354,7 @@ class OpenID_Connect_Generic { // make sure we didn't get an error if ( is_wp_error( $user_claim_result ) ) { - $this->error_redirect( 3 ); + $this->error( 3, $user_claim_result ); } $user_claim = json_decode( $user_claim_result['body'], true ); @@ -314,7 +370,7 @@ class OpenID_Connect_Generic { $create_user = apply_filters( 'openid-connect-generic-user-creation-test', true, $user_claim ); if ( ! $create_user ) { - $this->error_redirect( 9 ); + $this->error( 9 ); } // create the new user @@ -322,8 +378,12 @@ class OpenID_Connect_Generic { // make sure we didn't fail in creating the user if ( is_wp_error( $uid ) ) { - $this->error_redirect( 6 ); + $this->error( 6, $uid ); } + + $this->log(array( + 'message' => 'New user created: '. $uid + ), 'success' ); $user = get_user_by( 'id', $uid ); @@ -337,7 +397,7 @@ class OpenID_Connect_Generic { // ensure our found user is a real WP_User if ( ! is_a( $user, 'WP_User' ) || ! $user->exists() ) { - $this->error_redirect( 7 ); + $this->error( 7, $user ); } // hey, we made it! @@ -352,6 +412,11 @@ class OpenID_Connect_Generic { // get a cookie and go home! wp_set_auth_cookie( $user->ID, false ); + + $this->log(array( + 'message' => "Successful login for: {$user->user_login} ({$user->ID})" + ), 'success' ); + wp_redirect( home_url() ); // - end user handling } @@ -500,7 +565,7 @@ class OpenID_Connect_Generic { // errors and auto login can't happen at the same time if ( isset( $_GET['login-error'] ) ) { - $message = $this->error_message( $_GET['login-error'] ); + $message = $this->get_error_message( $_GET['login-error'] ); } else if ( $settings['login_type'] == 'auto' ) { wp_redirect( $this->make_authentication_url() ); @@ -519,11 +584,27 @@ class OpenID_Connect_Generic { * Handle errors by redirecting the user to the login form * along with an error code * - * @param $error_number + * @param $error_number - required */ - function error_redirect( $error_number ){ + function error( $error_number ) { + $args = func_get_args(); + $error_number = array_shift($args); $url = wp_login_url() . '?login-error=' . $error_number; - + + $error = array( + 'error id' => $error_number, + 'error message' => $this->errors[ $error_number ], + ); + + // allow for additional error details + if ( !empty( $args ) ){ + $error['details'] = $args; + } + + // attempt to log the error + $this->log( $error ); + + // redirect user back to login page wp_redirect( $url ); exit; } @@ -534,7 +615,7 @@ class OpenID_Connect_Generic { * @param $error_number * @return string */ - function error_message( $error_number ){ + function get_error_message( $error_number ){ // fallback to unknown error if ( ! isset( $this->errors[ $error_number ] ) ) { $error_number = 99;