diff --git a/icons/hex/custom.png b/icons/hex/custom.png new file mode 100644 index 0000000..232eec3 Binary files /dev/null and b/icons/hex/custom.png differ diff --git a/login-custom.php b/login-custom.php new file mode 100644 index 0000000..a52846f --- /dev/null +++ b/login-custom.php @@ -0,0 +1,264 @@ +wpoa_end_login("This third-party authentication provider has not been enabled. Please notify the admin or try again later."); +} +elseif (!CLIENT_ID || !CLIENT_SECRET) { + // do not proceed if id or secret is null: + $this->wpoa_end_login("This third-party authentication provider has not been configured with an API key/secret. Please notify the admin or try again later."); +} +elseif (isset($_GET['error_description'])) { + // do not proceed if an error was detected: + $this->wpoa_end_login($_GET['error_description']); +} +elseif (isset($_GET['error_message'])) { + // do not proceed if an error was detected: + $this->wpoa_end_login($_GET['error_message']); +} +elseif (isset($_GET['code'])) { + // post-auth phase, verify the state: + if ($_SESSION['WPOA']['STATE'] == $_GET['state']) { + // get an access token from the third party provider: + get_oauth_token($this); + // get the user's third-party identity and attempt to login/register a matching wordpress user account: + $oauth_identity = get_oauth_identity($this); + $this->wpoa_login_user($oauth_identity); + } + else { + // possible CSRF attack, end the login with a generic message to the user and a detailed message to the admin/logs in case of abuse: + // TODO: report detailed message to admin/logs here... + $this->wpoa_end_login("Sorry, we couldn't log you in. Please notify the admin or try again later."); + } +} +else { + // pre-auth, start the auth process: + if ((empty($_SESSION['WPOA']['EXPIRES_AT'])) || (time() > $_SESSION['WPOA']['EXPIRES_AT'])) { + // expired token; clear the state: + $this->wpoa_clear_login_state(); + } + get_oauth_code($this); +} +// we shouldn't be here, but just in case... +$this->wpoa_end_login("Sorry, we couldn't log you in. The authentication flow terminated in an unexpected way. Please notify the admin or try again later."); +# END OF AUTHENTICATION FLOW # + +# AUTHENTICATION FLOW HELPER FUNCTIONS # +function get_oauth_code($wpoa) { + $params = array( + 'response_type' => 'code', + 'client_id' => CLIENT_ID, + 'scope' => SCOPE, + 'state' => uniqid('', true), + 'redirect_uri' => REDIRECT_URI, + ); + $_SESSION['WPOA']['STATE'] = $params['state']; + $url = URL_AUTH . http_build_query($params); + header("Location: $url"); + exit; +} + +function get_oauth_token($wpoa) { + $params = array( + 'grant_type' => 'authorization_code', + 'client_id' => CLIENT_ID, + 'client_secret' => CLIENT_SECRET, + 'code' => $_GET['code'], + 'redirect_uri' => REDIRECT_URI, + ); + $url_params = http_build_query($params); + switch (strtolower(HTTP_UTIL)) { + case 'curl': + $url = URL_TOKEN; + + $response = wp_remote_post( + $url, array( + 'body' => $params, + 'sslverify' => get_option('wpoa_http_util_verify_ssl') + ) + ); + + if ( is_wp_error( $response ) ) { + $error_message = $response->get_error_message(); + error_log("token failed retrival - " . $result); + + $wpoa->wpoa_end_login( $error_message ); + return false; + } + + $result = $response['body']; + + break; + case 'stream-context': + $url = rtrim(URL_TOKEN, "?"); + $opts = array('http' => + array( + 'method' => 'POST', + 'header' => 'Content-type: application/x-www-form-urlencoded', + 'content' => $url_params, + ) + ); + $context = $context = stream_context_create($opts); + $result = @file_get_contents($url, false, $context); + if ($result === false) { + $wpoa->wpoa_end_login("Sorry, we couldn't log you in. Could not retrieve access token via stream context. Please notify the admin or try again later."); + } + break; + } + // parse the result: + $result_obj = json_decode($result, false, 512); // PROVIDER SPECIFIC: Google encodes the access token result as json by default + $access_token = $result_obj->access_token; // PROVIDER SPECIFIC: this is how Google returns the access token KEEP THIS PROTECTED! + + $expires_in = $result_obj->expires_in; // PROVIDER SPECIFIC: this is how Google returns the access token's expiration + $expires_at = time() + $expires_in; + // handle the result: + if (!$access_token || !$expires_in) { + // malformed access token result detected: + $wpoa->wpoa_end_login("Sorry, we couldn't log you in. Malformed access token result detected. Please notify the admin or try again later."); + } + else { + $_SESSION['WPOA']['ACCESS_TOKEN'] = $access_token; + $_SESSION['WPOA']['EXPIRES_IN'] = $expires_in; + $_SESSION['WPOA']['EXPIRES_AT'] = $expires_at; + return true; + } +} + +function get_oauth_identity($wpoa) { + // here we exchange the access token for the user info... + // set the access token param: + $params = array( + 'access_token' => $_SESSION['WPOA']['ACCESS_TOKEN'], // PROVIDER SPECIFIC: the access_token is passed to Google via POST param + ); + $url_params = http_build_query($params); + $result = ""; + // perform the http request: + switch (strtolower(HTTP_UTIL)) { + case 'curl': + $url = URL_USER; + + $response = wp_remote_get( + $url, + array( + 'headers' => array( + 'Authorization' => 'Bearer ' . $_SESSION['WPOA']['ACCESS_TOKEN'] + ) + ) + ); + + if ( is_wp_error( $response ) ) { + $error_message = $response->get_error_message(); + error_log("userinfo failed retrival - " . $result); + + $wpoa->wpoa_end_login( $error_message ); + return false; + } + + $result = $response['body']; + + $result_obj = json_decode($result, true); + break; + case 'stream-context': + $url = rtrim(URL_USER, "?"); + $opts = array('http' => + array( + 'method' => 'GET', + // PROVIDER NORMALIZATION: Reddit/Github User-Agent + 'header' => "Authorization: Bearer " . $_SESSION['WPOA']['ACCESS_TOKEN'] . "\r\n" . "x-li-format: json\r\n", // PROVIDER SPECIFIC: i think only LinkedIn uses x-li-format... + ) + ); + $context = $context = stream_context_create($opts); + $result = @file_get_contents($url, false, $context); + if ($result === false) { + $wpoa->wpoa_end_login("Sorry, we couldn't log you in. Could not retrieve user identity via stream context. Please notify the admin or try again later."); + } + $result_obj = json_decode($result, true); + break; + } + // parse and return the user's oauth identity: + $oauth_identity = array(); + $oauth_identity['provider'] = $_SESSION['WPOA']['PROVIDER']; + /* + Response example from Keycloack + { + "name": "Admin User", + "sub": "88dd0538-5f32-4222-af07-efe5cd809038", + "preferred_username": "admin@example.com", + "given_name": "Admin", + "family_name": "User", + "email": "admin@example.com" + } + { + "error_description":"Token invalid: Token audience doesn't match domain. Token ....", + "error":"invalid_grant" + } + */ + // Check if we got an error message + if( isset($result_obj["error"]) || strlen($result_obj["error"]) > 0 ) { + $message = strlen($result_obj["error_description"]) > 0 ? $result_obj["error_description"] : $result_obj["error"]; + $wpoa->wpoa_end_login("Sorry, we could not log you in. " . $message); + return $oauth_identity; + } + + $objtype = get_option('wpoa_custom_api_identity_id'); + if ($objtype == null || $objtype == false || $objtype == '') { + $objtype = 'id'; + } + $oauth_identity['id'] = $result_obj[$objtype]; + $objtype = get_option('wpoa_custom_api_identity_preferred_username'); + if ($objtype == null || $objtype == false || $objtype == '') { + $objtype = 'preferred_username'; + } + $oauth_identity['preferred_username'] = $result_obj[$objtype]; + + if (!$oauth_identity['id']) { + // $wpoa->wpoa_end_login("Sorry, we couldn't log you in. User identity was not found: " . $_SESSION['WPOA']['ACCESS_TOKEN']); + $wpoa->wpoa_end_login("Sorry, we could not log you in. User identity '" . $objtype . "' was not found. Please notify the admin or try again later."); + } + return $oauth_identity; +} +# END OF AUTHENTICATION FLOW HELPER FUNCTIONS # +?> diff --git a/register.php b/register.php index d3a93a8..aa983c7 100644 --- a/register.php +++ b/register.php @@ -1 +1 @@ -get_error_message(); header("Location: " . $_SESSION["WPOA"]["LAST_URL"]); exit; } // now try to update the username to something more permanent and recognizable: $username = "user" . $user_id; $update_username_result = $wpdb->update($wpdb->users, array('user_login' => $username, 'user_nicename' => $username, 'display_name' => $username), array('ID' => $user_id)); $update_nickname_result = update_user_meta($user_id, 'nickname', $username); // apply the custom default user role: $role = get_option('wpoa_new_user_role'); $update_role_result = wp_update_user(array('ID' => $user_id, 'role' => $role)); // proceed if no errors were detected: if ($update_username_result == false || $update_nickname_result == false) { // there was an error during registration, redirect and notify the user: $_SESSION["WPOA"]["RESULT"] = "Could not rename the username during registration. Please contact an admin or try again later."; header("Location: " . $_SESSION["WPOA"]["LAST_URL"]); exit; } elseif ($update_role_result == false) { // there was an error during registration, redirect and notify the user: $_SESSION["WPOA"]["RESULT"] = "Could not assign default user role during registration. Please contact an admin or try again later."; header("Location: " . $_SESSION["WPOA"]["LAST_URL"]); exit; } else { // registration was successful, the user account was created, proceed to login the user automatically... // associate the wordpress user account with the now-authenticated third party account: $this->wpoa_link_account($user_id); // attempt to login the new user (this could be error prone): $creds = array(); $creds['user_login'] = $username; $creds['user_password'] = $password; $creds['remember'] = true; $user = wp_signon( $creds, false ); // send a notification e-mail to the admin and the new user (we can also build our own email if necessary): if (!get_option('wpoa_suppress_welcome_email')) { //wp_mail($username, "New User Registration", "Thank you for registering!\r\nYour username: " . $username . "\r\nYour password: " . $password, $headers); wp_new_user_notification( $user_id, $password ); } // finally redirect the user back to the page they were on and notify them of successful registration: $_SESSION["WPOA"]["RESULT"] = "You have been registered successfully!"; header("Location: " . $_SESSION["WPOA"]["LAST_URL"]); exit; } ?> \ No newline at end of file +get_error_message(); header("Location: " . $_SESSION["WPOA"]["LAST_URL"]); exit; } // now try to update the username to something more permanent and recognizable: $username = "user" . $user_id; $update_username_result = $wpdb->update($wpdb->users, array('user_login' => $username, 'user_nicename' => $username, 'display_name' => $username), array('ID' => $user_id)); $update_nickname_result = update_user_meta($user_id, 'nickname', $username); // apply the custom default user role: $role = get_option('wpoa_new_user_role'); $update_role_result = wp_update_user(array('ID' => $user_id, 'role' => $role)); // proceed if no errors were detected: if ($update_username_result == false || $update_nickname_result == false) { // there was an error during registration, redirect and notify the user: $_SESSION["WPOA"]["RESULT"] = "Could not rename the username during registration. Please contact an admin or try again later."; header("Location: " . $_SESSION["WPOA"]["LAST_URL"]); exit; } elseif ($update_role_result == false) { // there was an error during registration, redirect and notify the user: $_SESSION["WPOA"]["RESULT"] = "Could not assign default user role during registration. Please contact an admin or try again later."; header("Location: " . $_SESSION["WPOA"]["LAST_URL"]); exit; } else { // registration was successful, the user account was created, proceed to login the user automatically... // associate the wordpress user account with the now-authenticated third party account: $this->wpoa_link_account($user_id); // attempt to login the new user (this could be error prone): $creds = array(); $creds['user_login'] = $username; $creds['user_password'] = $password; $creds['remember'] = true; $user = wp_signon( $creds, false ); // send a notification e-mail to the admin and the new user (we can also build our own email if necessary): if (!get_option('wpoa_suppress_welcome_email')) { //wp_mail($username, "New User Registration", "Thank you for registering!\r\nYour username: " . $username . "\r\nYour password: " . $password, $headers); wp_new_user_notification( $user_id, $password ); } // finally redirect the user back to the page they were on and notify them of successful registration: $_SESSION["WPOA"]["RESULT"] = "You have been registered successfully!"; header("Location: " . $_SESSION["WPOA"]["LAST_URL"]); exit; } ?> \ No newline at end of file diff --git a/wp-oauth-settings.php b/wp-oauth-settings.php index 0e34fa3..b5ef807 100644 --- a/wp-oauth-settings.php +++ b/wp-oauth-settings.php @@ -20,7 +20,7 @@ function wpoa_cc_security() { $points_max = 6; return floor(($points / $points_max) * 100); } - + // config check privacy function wpoa_cc_privacy() { $points = 0; @@ -31,7 +31,7 @@ function wpoa_cc_privacy() { $points_max = 1; return floor(($points / $points_max) * 100); } - + // config check user experience function wpoa_cc_ux() { $points = 0; @@ -44,7 +44,7 @@ function wpoa_cc_ux() { $points_max = 2; return floor(($points / $points_max) * 100); } - + // cache the config check ratings: $cc_security = wpoa_cc_security(); $cc_privacy = wpoa_cc_privacy(); @@ -75,10 +75,10 @@ function wpoa_cc_ux() {
Default Login Form / Page / Popup |
-
+
|
---|---|
Hide the WordPress login form: [?] | @@ -256,7 +256,7 @@ function wpoa_cc_ux() { |
Logo links to site: [?] | @@ -264,7 +264,7 @@ function wpoa_cc_ux() { |
Logo image: [?] | @@ -275,7 +275,7 @@ function wpoa_cc_ux() { |
Background image: [?] | @@ -286,13 +286,13 @@ function wpoa_cc_ux() { |
Custom Login Forms |
-
+
|
Custom form to show on the login screen: [?] | @@ -300,7 +300,7 @@ function wpoa_cc_ux() { |
Custom form to show on the user's profile page: [?] | @@ -308,7 +308,7 @@ function wpoa_cc_ux() { |
Custom form to show in the comments section: [?] | @@ -342,14 +342,14 @@ function wpoa_cc_ux() { |
Edit Design |
-
+
|
---|---|
Design name: [?] | @@ -357,7 +357,7 @@ function wpoa_cc_ux() { |
Icon set: [?] | @@ -368,7 +368,7 @@ function wpoa_cc_ux() { |
Show login buttons: [?] | @@ -380,7 +380,7 @@ function wpoa_cc_ux() { |
Show logout button: [?] | @@ -392,7 +392,7 @@ function wpoa_cc_ux() { |
Layout: [?] | @@ -405,7 +405,7 @@ function wpoa_cc_ux() { |
Login button prefix: [?] | @@ -413,7 +413,7 @@ function wpoa_cc_ux() { |
Logged out title: [?] | @@ -421,7 +421,7 @@ function wpoa_cc_ux() { |
Logged in title: [?] | @@ -429,7 +429,7 @@ function wpoa_cc_ux() { |
Logging in title: [?] | @@ -437,7 +437,7 @@ function wpoa_cc_ux() { |
Logging out title: [?] | @@ -445,14 +445,14 @@ function wpoa_cc_ux() { |
- + |
Instructions:
Enabled: | ++ /> + | +
---|---|
Client ID: | ++ ' /> + | +
Secret: | ++ ' /> + | +
Scopes: | ++ ' /> + | +
Authentication URL: | ++ ' /> + | +
Token URL: | ++ ' /> + | +
User URL: | ++ ' /> + | +
UserInfo element for unique ID (usually 'id' or 'username'): | ++ ' /> + | +
UserInfo element for preffered username (usually 'username' or 'preferred_username'): | ++ ' /> + | +
+ Instructions: +
Delete settings on uninstall: [?] | @@ -1029,4 +1132,4 @@ function wpoa_cc_ux() { - \ No newline at end of file + diff --git a/wp-oauth.php b/wp-oauth.php index d353e8c..fca6805 100644 --- a/wp-oauth.php +++ b/wp-oauth.php @@ -4,7 +4,7 @@ Plugin Name: WP-OAuth Plugin URI: http://github.com/perrybutler/wp-oauth Description: A WordPress plugin that allows users to login or register by authenticating with an existing Google, Facebook, LinkedIn, Github, Reddit or Windows Live account via OAuth 2.0. Easily drops into new or existing sites, integrates with existing users. -Version: 0.4.1 +Version: 0.4.1.1 Author: Perry Butler Author URI: http://glassocean.net License: GPL2 @@ -23,8 +23,21 @@ // ============== // set a version that we can use for performing plugin updates, this should always match the plugin version: - const PLUGIN_VERSION = "0.4.1"; - + const PLUGIN_VERSION = "0.4.1.1"; + static $WPOA_LOGIN_PROVIDERS = array( + "google" => "Google", + "facebook" => "Facebook", + "linkedin" => "LinkedIn", + "github" => "GitHub", + "itembase" => "itembase", + "reddit" => "Reddit", + "windowslive" => "Windows Live", + "paypal" => "PayPal", + "instagram" => "Instagram", + "battlenet" => "Battlenet", + "custom" => "Other" + ); + // singleton class pattern: protected static $instance = NULL; public static function get_instance() { @@ -81,6 +94,7 @@ public static function get_instance() { ), 'wpoa_suppress_welcome_email' => 0, // 0, 1 'wpoa_new_user_role' => 'contributor', // role + 'wpoa_new_user' => null, // default new user 'wpoa_google_api_enabled' => 0, // 0, 1 'wpoa_google_api_id' => '', // any string 'wpoa_google_api_secret' => '', // any string @@ -111,20 +125,27 @@ public static function get_instance() { 'wpoa_instagram_api_secret' => '', // any string 'wpoa_battlenet_api_enabled' => 0, // 0, 1 'wpoa_battlenet_api_id' => '', // any string - 'wpoa_battlenet_api_secret' => '', - // any string + 'wpoa_battlenet_api_secret' => '', // any string + 'wpoa_custom_api_enabled' => 0, // 0, 1 + 'wpoa_custom_api_id' => '', // any string + 'wpoa_custom_api_secret' => '', // any string + 'wpoa_custom_api_scope' => '', // any string + 'wpoa_custom_api_auth_url' => '', // any string + 'wpoa_custom_api_token_url' => '', // any string + 'wpoa_custom_api_user_url' => '', // any string + 'wpoa_custom_api_identity_id' => '', // any string + 'wpoa_custom_api_identity_preferred_username' => '', // any string 'wpoa_oauth_server_api_enabled' => 0, // 0, 1 'wpoa_oauth_server_api_id' => '', // any string 'wpoa_oauth_server_api_secret' => '', // any string 'wpoa_oauth_server_api_endpoint' => '', // any string 'wpoa_oauth_server_api_button_text' => '', // any string - 'wpoa_http_util' => 'curl', // curl, stream-context 'wpoa_http_util_verify_ssl' => 1, // 0, 1 'wpoa_restore_default_settings' => 0, // 0, 1 'wpoa_delete_settings_on_uninstall' => 0, // 0, 1 ); - + // when the plugin class gets created, fire the initialization: function __construct() { // hook activation and deactivation for the plugin: @@ -135,7 +156,7 @@ function __construct() { // hook init event to handle plugin initialization: add_action('init', array($this, 'init')); } - + // a wrapper for wordpress' get_option(), this basically feeds get_option() the setting's correct default value as specified at the top of this file: /* function wpoa_option($name) { @@ -144,15 +165,15 @@ function wpoa_option($name) { return $val; } */ - + // do something during plugin activation: function wpoa_activate() { } - + // do something during plugin deactivation: function wpoa_deactivate() { } - + // do something during plugin update: function wpoa_update() { $plugin_version = WPOA::PLUGIN_VERSION; @@ -167,7 +188,7 @@ function wpoa_update() { add_action('admin_notices', array($this, 'wpoa_update_notice')); } } - + // indicate to the admin that the plugin has been updated: function wpoa_update_notice() { $settings_link = "Settings Page"; // CASE SeNsItIvE filename! @@ -177,7 +198,7 @@ function wpoa_update_notice() { settings as $setting_name => $default_value) { @@ -188,7 +209,7 @@ function wpoa_add_missing_settings() { $added = add_option($setting_name, $default_value); } } - + // restores the default plugin settings: function wpoa_restore_default_settings() { foreach($this->settings as $setting_name => $default_value) { @@ -200,7 +221,7 @@ function wpoa_restore_default_settings() { } add_action('admin_notices', array($this, 'wpoa_restore_default_settings_notice')); } - + // indicate to the admin that the plugin has been updated: function wpoa_restore_default_settings_notice() { $settings_link = "Settings Page"; // CASE SeNsItIvE filename! @@ -213,9 +234,13 @@ function wpoa_restore_default_settings_notice() { // initialize the plugin's functionality by hooking into wordpress: function init() { + // restore default settings if necessary; this might get toggled by the admin or forced by a new version of the plugin: if (get_option("wpoa_restore_default_settings")) {$this->wpoa_restore_default_settings();} // hook the query_vars and template_redirect so we can stay within the wordpress context no matter what (avoids having to use wp-load.php) + + $this->wpoa_login_redirect_if_single_provider(); + add_filter('query_vars', array($this, 'wpoa_qvar_triggers')); add_action('template_redirect', array($this, 'wpoa_qvar_handlers')); // hook scripts and styles for frontend pages: @@ -246,7 +271,7 @@ function init() { add_filter('login_footer', array($this, 'wpoa_push_login_messages')); } } - + // init scripts and styles for use on FRONTEND PAGES: function wpoa_init_frontend_scripts_styles() { // here we "localize" php variables, making them available as a js variable in the browser: @@ -272,7 +297,7 @@ function wpoa_init_frontend_scripts_styles() { wp_enqueue_script('wpoa-script', plugin_dir_url( __FILE__ ) . 'wp-oauth.js', array()); wp_enqueue_style('wpoa-style', plugin_dir_url( __FILE__ ) . 'wp-oauth.css', array()); } - + // init scripts and styles for use on BACKEND PAGES: function wpoa_init_backend_scripts_styles() { // here we "localize" php variables, making them available as a js variable in the browser: @@ -298,7 +323,7 @@ function wpoa_init_backend_scripts_styles() { // load the default wordpress media screen: wp_enqueue_media(); } - + // init scripts and styles for use on the LOGIN PAGE: function wpoa_init_login_scripts_styles() { if (isset($_SESSION['WPOA']['RESULT'])) { @@ -332,25 +357,25 @@ function wpoa_init_login_scripts_styles() { wp_enqueue_script('wpoa-script', plugin_dir_url( __FILE__ ) . 'wp-oauth.js', array()); wp_enqueue_style('wpoa-style', plugin_dir_url( __FILE__ ) . 'wp-oauth.css', array()); } - + // add a settings link to the plugins page: function wpoa_settings_link($links) { $settings_link = "Settings"; // CASE SeNsItIvE filename! - array_unshift($links, $settings_link); - return $links; + array_unshift($links, $settings_link); + return $links; } - + // =============== // GENERIC HELPERS // =============== - + // adds basic http auth to a given url string: function wpoa_add_basic_auth($url, $username, $password) { $url = str_replace("https://", "", $url); $url = "https://" . $username . ":" . $password . "@" . $url; return $url; } - + // =================== // LOGIN FLOW HANDLING // =================== @@ -363,7 +388,28 @@ function wpoa_qvar_triggers($vars) { $vars[] = 'error_message'; return $vars; } - + + // Redirect users to the provider if there's only single provider (and login form is disabled) + function wpoa_login_redirect_if_single_provider() { + if ( $_SERVER['REQUEST_METHOD'] == 'GET' && (is_page( 'login' ) || $GLOBALS['pagenow'] === 'wp-login.php' || in_array( $_SERVER['PHP_SELF'], array( '/wp-login.php', '/wp-register.php' ) )) ) { + // We're on the login page! + // Check if we only have one provider + $count = 0; + $provider = ""; + foreach (self::$WPOA_LOGIN_PROVIDERS as $key => $value) { + if (get_option("wpoa_" . $key . "_api_enabled")) { + $count = $count + 1; + $provider = $key; + } + } + if ( $count == 1 && get_option("wpoa_hide_wordpress_login_form") == 1) { + $_SESSION['WPOA']['PROVIDER'] = $provider; + $this->wpoa_include_connector($provider); + return; + } + } + } + // handle the querystring triggers: function wpoa_qvar_handlers() { if (get_query_var('connect')) { @@ -379,7 +425,7 @@ function wpoa_qvar_handlers() { $this->wpoa_include_connector($provider); } } - + // load the provider script that is being requested by the user or being called back after authentication: function wpoa_include_connector($provider) { // normalize the provider name (no caps, no spaces): @@ -389,7 +435,7 @@ function wpoa_include_connector($provider) { // include the provider script: include 'login-' . $provider . '.php'; } - + // ======================= // LOGIN / LOGOUT HANDLING // ======================= @@ -407,13 +453,14 @@ function wpoa_match_wordpress_user($oauth_identity) { $user = get_user_by('id', $query_result); return $user; } - + // login (or register and login) a wordpress user based on their oauth identity: function wpoa_login_user($oauth_identity) { // store the user info in the user session so we can grab it later if we need to register the user: $_SESSION["WPOA"]["USER_ID"] = $oauth_identity["id"]; // try to find a matching wordpress user for the now-authenticated user's oauth identity: $matched_user = $this->wpoa_match_wordpress_user($oauth_identity); + $mapped_user = false; // handle the matched user if there is one: if ( $matched_user ) { // there was a matching wordpress user account, log it in now: @@ -424,6 +471,18 @@ function wpoa_login_user($oauth_identity) { do_action( 'wp_login', $user_login, $matched_user ); // after login, redirect to the user's last location $this->wpoa_end_login("Logged in successfully!"); + $mapped_user = true; + } else if(get_option("wpoa_new_user")!=null && get_option("wpoa_new_user") != '' && get_option("wpoa_new_user") != -1 && get_userdata(get_option("wpoa_new_user")) != false) { + $_SESSION["WPOA"]["USER_ID"] = get_option("wpoa_new_user"); + + $user_id = $_SESSION["WPOA"]["USER_ID"]; + $user_login = get_userdata($user_id)->user_login; + wp_set_current_user( $user_id, $user_login ); + wp_set_auth_cookie( $user_id ); + do_action( 'wp_login', $user_login, $matched_user ); + // after login, redirect to the user's last location + $this->wpoa_end_login("Logged in successfully as " . $user_login . "!"); + $mapped_user = true; } // handle the already logged in user if there is one: if ( is_user_logged_in() ) { @@ -434,16 +493,19 @@ function wpoa_login_user($oauth_identity) { $this->wpoa_link_account($user_id); // after linking the account, redirect user to their last url $this->wpoa_end_login("Your account was linked successfully with your third party authentication provider."); + return; } // handle the logged out user or no matching user (register the user): - if ( !is_user_logged_in() && !$matched_user ) { + if ( !is_user_logged_in() && !$mapped_user ) { // this person is not logged into a wordpress account and has no third party authentications registered, so proceed to register the wordpress user: + $_SESSION["WPOA"]["PREFERRED_USERNAME"] = $oauth_identity["preferred_username"]; include 'register.php'; + return; } // we shouldn't be here, but just in case... $this->wpoa_end_login("Sorry, we couldn't log you in. The login flow terminated in an unexpected way. Please notify the admin or try again later."); } - + // ends the login request by clearing the login state and redirecting the user to the desired page: function wpoa_end_login($msg) { $last_url = $_SESSION["WPOA"]["LAST_URL"]; @@ -476,7 +538,7 @@ function wpoa_end_login($msg) { wp_safe_redirect($redirect_url); die(); } - + // logout the wordpress user: // TODO: this is usually called from a custom logout button, but we could have the button call /wp-logout.php?action=logout for more consistency... function wpoa_logout_user() { @@ -485,7 +547,7 @@ function wpoa_logout_user() { session_destroy(); // destroy the php user session wp_logout(); // logout the wordpress user...this gets hooked and diverted to wpoa_end_logout() for final handling } - + // ends the logout request by redirecting the user to the desired page: function wpoa_end_logout() { $_SESSION["WPOA"]["RESULT"] = 'Logged out successfully.'; @@ -527,7 +589,7 @@ function wpoa_end_logout() { wp_safe_redirect($redirect_url); die(); } - + // links a third-party account to an existing wordpress user account: function wpoa_link_account($user_id) { if ($_SESSION['WPOA']['USER_ID'] != '') { @@ -558,7 +620,7 @@ function wpoa_unlink_account() { // wp-ajax requires death: die(); } - + // pushes login messages into the dom where they can be extracted by javascript: function wpoa_push_login_messages() { if (isset($_SESSION['WPOA']['RESULT'])) { @@ -567,7 +629,7 @@ function wpoa_push_login_messages() { } $_SESSION['WPOA']['RESULT'] = ''; } - + // clears the login state: function wpoa_clear_login_state() { unset($_SESSION["WPOA"]["USER_ID"]); @@ -577,7 +639,7 @@ function wpoa_clear_login_state() { unset($_SESSION["WPOA"]["EXPIRES_AT"]); //unset($_SESSION["WPOA"]["LAST_URL"]); } - + // =================================== // DEFAULT LOGIN SCREEN CUSTOMIZATIONS // =================================== @@ -586,7 +648,7 @@ function wpoa_clear_login_state() { function wpoa_logo_link() { return get_bloginfo('url'); } - + // show a custom login form on the default login screen: function wpoa_customize_login_screen() { $html = ""; @@ -601,7 +663,7 @@ function wpoa_customize_login_screen() { // =================================== // DEFAULT COMMENT FORM CUSTOMIZATIONS // =================================== - + // show a custom login form at the top of the default comment form: function wpoa_customize_comment_form_fields($fields) { $html = ""; @@ -613,7 +675,7 @@ function wpoa_customize_comment_form_fields($fields) { } return $fields; } - + // show a custom login form at the top of the default comment form: function wpoa_customize_comment_form() { $html = ""; @@ -628,7 +690,7 @@ function wpoa_customize_comment_form() { // ========================= // LOGIN / LOGOUT COMPONENTS // ========================= - + // shortcode which allows adding the wpoa login form to any post or page: function wpoa_login_form( $atts ){ $a = shortcode_atts( array( @@ -653,7 +715,7 @@ function wpoa_login_form( $atts ){ $html = $this->wpoa_login_form_content($a['design'], $a['icon_set'], $a['layout'], $a['button_prefix'], $a['align'], $a['show_login'], $a['show_logout'], $a['logged_out_title'], $a['logged_in_title'], $a['logging_in_title'], $a['logging_out_title'], $a['style'], $a['class']); return $html; } - + // gets the content to be used for displaying the login/logout form: function wpoa_login_form_content($design = '', $icon_set = 'icon_set', $layout = 'links-column', $button_prefix = '', $align = 'left', $show_login = 'conditional', $show_logout = 'conditional', $logged_out_title = 'Please login:', $logged_in_title = 'You are already logged in.', $logging_in_title = 'Logging in...', $logging_out_title = 'Logging out...', $style = '', $class = '') { // even though wpoa_login_form() will pass a default, we might call this function from another method so it's important to re-specify the default values // if a design was specified and that design exists, load the shortcode attributes from that design: @@ -702,7 +764,7 @@ function wpoa_login_form_content($design = '', $icon_set = 'icon_set', $layout = $html .= ""; return $html; } - + // generate and return the login buttons, depending on available providers: function wpoa_login_buttons($icon_set, $button_prefix) { // generate the atts once (cache them), so we can use it for all buttons without computing them each time: @@ -720,18 +782,10 @@ function wpoa_login_buttons($icon_set, $button_prefix) { 'button_prefix' => $button_prefix, ); // generate the login buttons for available providers: - // TODO: don't hard-code the buttons/providers here, we want to be able to add more providers without having to update this function... $html = ""; - $html .= $this->wpoa_login_button("google", "Google", $atts); - $html .= $this->wpoa_login_button("facebook", "Facebook", $atts); - $html .= $this->wpoa_login_button("linkedin", "LinkedIn", $atts); - $html .= $this->wpoa_login_button("github", "GitHub", $atts); - $html .= $this->wpoa_login_button("itembase", "itembase", $atts); - $html .= $this->wpoa_login_button("reddit", "Reddit", $atts); - $html .= $this->wpoa_login_button("windowslive", "Windows Live", $atts); - $html .= $this->wpoa_login_button("paypal", "PayPal", $atts); - $html .= $this->wpoa_login_button("instagram", "Instagram", $atts); - $html .= $this->wpoa_login_button("battlenet", "Battlenet", $atts); + foreach (self::$WPOA_LOGIN_PROVIDERS as $key => $value) { + $html .= $this->wpoa_login_button($key, $value, $atts); + } $html .= $this->wpoa_login_button( 'oauth_server' , get_option( 'wpoa_oauth_server_api_button_text' ), $atts ); if ($html == '') { $html .= 'Sorry, no login providers have been enabled.'; @@ -752,7 +806,7 @@ function wpoa_login_button($provider, $display_name, $atts) { } return $html; } - + // output the custom login form design selector: function wpoa_login_form_designs_selector($id = '', $master = false) { $html = ""; @@ -776,7 +830,7 @@ function wpoa_login_form_designs_selector($id = '', $master = false) { } return $html; } - + // returns a saved login form design as a shortcode atts string or array for direct use via the shortcode function wpoa_get_login_form_design($design_name, $as_string = false) { $designs_json = get_option('wpoa_login_form_designs'); @@ -799,7 +853,7 @@ function wpoa_get_login_form_design($design_name, $as_string = false) { } return $atts; } - + function wpoa_login_form_design_exists($design_name) { $designs_json = get_option('wpoa_login_form_designs'); $designs_array = json_decode($designs_json, true); @@ -816,7 +870,7 @@ function wpoa_login_form_design_exists($design_name) { return false; } } - + // shows the user's linked providers, used on the 'Your Profile' page: function wpoa_linked_accounts() { // get the current user: @@ -864,18 +918,18 @@ function wpoa_linked_accounts() { echo " | "; echo "
---|