Example #1
0
 public function ProcessFrontend()
 {
     global $sso_rng, $sso_provider, $sso_settings, $sso_session_info;
     $redirect_uri = BB_GetRequestHost() . SSO_ROOT_URL . "/index.php?sso_provider=" . urlencode($sso_provider) . "&sso_google_action=signin";
     if (isset($_REQUEST["sso_google_action"]) && $_REQUEST["sso_google_action"] == "signin") {
         // Recover the language settings.
         if (!isset($sso_session_info["sso_google_info"])) {
             $this->DisplayError(BB_Translate("Unable to authenticate the request."));
             return;
         }
         $url = BB_GetRequestHost() . SSO_ROOT_URL . "/index.php?sso_provider=" . urlencode($sso_provider) . "&sso_google_action=signin2";
         if (isset($_REQUEST["state"])) {
             $url .= "&state=" . urlencode($_REQUEST["state"]);
         }
         if (isset($_REQUEST["code"])) {
             $url .= "&code=" . urlencode($_REQUEST["code"]);
         }
         if (isset($_REQUEST["error"])) {
             $url .= "&error=" . urlencode($_REQUEST["error"]);
         }
         $url .= "&lang=" . urlencode($sso_session_info["sso_google_info"]["lang"]);
         header("Location: " . $url);
     } else {
         if (isset($_REQUEST["sso_google_action"]) && $_REQUEST["sso_google_action"] == "signin2") {
             // Validate the token.
             if (!isset($_REQUEST["state"]) || !isset($sso_session_info["sso_google_info"]) || $_REQUEST["state"] !== $sso_session_info["sso_google_info"]["token"]) {
                 $this->DisplayError(BB_Translate("Unable to authenticate the request."));
                 return;
             }
             // Check for token expiration.
             if (CSDB::ConvertFromDBTime($sso_session_info["sso_google_info"]["expires"]) < time()) {
                 $this->DisplayError(BB_Translate("Verification token has expired."));
                 return;
             }
             if (isset($_REQUEST["error"])) {
                 if ($_REQUEST["error"] == "access_denied") {
                     $message = BB_Translate("The request to sign in with Google was denied.");
                 } else {
                     $message = BB_Translate("The error message returned was '%s'.", $_REQUEST["error"]);
                 }
                 $this->DisplayError(BB_Translate("Sign in failed.  %s", $message));
                 return;
             }
             if (!isset($_REQUEST["code"])) {
                 $this->DisplayError(BB_Translate("Sign in failed.  Authorization code missing."));
                 return;
             }
             // Get an access token from the authorization code.
             require_once SSO_ROOT_PATH . "/" . SSO_SUPPORT_PATH . "/http.php";
             require_once SSO_ROOT_PATH . "/" . SSO_SUPPORT_PATH . "/web_browser.php";
             $url = "https://accounts.google.com/o/oauth2/token";
             $options = array("postvars" => array("code" => $_REQUEST["code"], "client_id" => $sso_settings["sso_google"]["client_id"], "client_secret" => $sso_settings["sso_google"]["client_secret"], "redirect_uri" => $redirect_uri, "grant_type" => "authorization_code"));
             $web = new WebBrowser();
             $result = $web->Process($url, "auto", $options);
             if (!$result["success"]) {
                 $this->DisplayError(BB_Translate("Sign in failed.  Error retrieving URL for Google access token.  %s", $result["error"]));
             } else {
                 if ($result["response"]["code"] != 200) {
                     $this->DisplayError(BB_Translate("Sign in failed.  The Google access token server returned:  %s", $result["response"]["code"] . " " . $result["response"]["meaning"]));
                 } else {
                     // Get the access token.
                     $data = @json_decode($result["body"], true);
                     if ($data === false || !isset($data["access_token"])) {
                         $this->DisplayError(BB_Translate("Sign in failed.  Error retrieving access token from Google."));
                     } else {
                         // Get the user's profile information.
                         $url = "https://www.googleapis.com/oauth2/v1/userinfo?access_token=" . urlencode($data["access_token"]);
                         $result = $web->Process($url);
                         if (!$result["success"]) {
                             $this->DisplayError(BB_Translate("Sign in failed.  Error retrieving URL for Google profile information.  %s", $result["error"]));
                         } else {
                             if ($result["response"]["code"] != 200) {
                                 $this->DisplayError(BB_Translate("Sign in failed.  The Google profile information server returned:  %s", $result["response"]["code"] . " " . $result["response"]["meaning"]));
                             } else {
                                 $profile = @json_decode($result["body"], true);
                                 if ($profile === false) {
                                     $this->DisplayError(BB_Translate("Sign in failed.  Error retrieving profile information from Google."));
                                 }
                                 $origprofile = $profile;
                                 // Remove unverified e-mail addresses.
                                 if (!isset($profile["verified_email"]) || !$profile["verified_email"]) {
                                     unset($profile["verified_email"]);
                                     unset($profile["email"]);
                                 }
                                 // Convert most profile fields into strings.
                                 foreach ($profile as $key => $val) {
                                     if (is_string($val)) {
                                         continue;
                                     }
                                     if (is_bool($val)) {
                                         $val = (string) (int) $val;
                                     } else {
                                         if (is_numeric($val)) {
                                             $val = (string) $val;
                                         } else {
                                             if (is_object($val) && isset($val->id) && isset($val->name)) {
                                                 $val = $val->name;
                                             }
                                         }
                                     }
                                     $profile[$key] = $val;
                                 }
                                 $mapinfo = array();
                                 foreach (self::$fieldmap as $key => $info) {
                                     $key2 = $sso_settings["sso_google"]["map_" . $key];
                                     if ($key2 != "" && isset($profile[$key])) {
                                         $mapinfo[$key2] = $profile[$key];
                                     }
                                 }
                                 SSO_ActivateUser($profile["id"], serialize($origprofile), $mapinfo);
                                 // Only falls through on account lockout or a fatal error.
                                 $this->DisplayError(BB_Translate("User activation failed."));
                             }
                         }
                     }
                 }
             }
         } else {
             // Create internal data packet.
             $token = $sso_rng->GenerateString();
             $sso_session_info["sso_google_info"] = array("lang" => isset($_REQUEST["lang"]) ? $_REQUEST["lang"] : "", "token" => $token, "expires" => CSDB::ConvertToDBTime(time() + 30 * 60));
             if (!SSO_SaveSessionInfo()) {
                 $this->DisplayError(BB_Translate("Unable to save session information."));
                 return;
             }
             // Calculate the required scope.
             $scope = array("https://www.googleapis.com/auth/userinfo.profile" => true);
             foreach (self::$fieldmap as $key => $info) {
                 if ($info["extra"] != "" && $sso_settings["sso_google"]["map_" . $key] != "") {
                     $scope[$info["extra"]] = true;
                 }
             }
             // Get the login redirection URL.
             $options = array("response_type" => "code", "client_id" => $sso_settings["sso_google"]["client_id"], "redirect_uri" => $redirect_uri, "scope" => implode(" ", array_keys($scope)), "state" => $token);
             $options2 = array();
             foreach ($options as $key => $val) {
                 $options2[] = urlencode($key) . "=" . urlencode($val);
             }
             $url = "https://accounts.google.com/o/oauth2/auth?" . implode("&", $options2);
             SSO_ExternalRedirect($url);
         }
     }
 }
Example #2
0
 public function ProcessFrontend()
 {
     global $sso_settings, $sso_rng, $sso_provider, $sso_target_url, $sso_session_info, $sso_session_id, $sso_db;
     if (isset($sso_session_info["setlogin_result"]) && !isset($_REQUEST["tryagain"])) {
         // Check the secret.
         if (!isset($_REQUEST["sso_setlogin_secret"]) || !isset($sso_session_info["setlogin_info"]) || $_REQUEST["sso_setlogin_secret"] !== $sso_session_info["setlogin_info"]["secret"]) {
             $this->DisplayError(BB_Translate("Unable to authenticate the request."));
             return;
         }
         // Should be nearly impossible to get here since browser redirects are executed almost immediately.
         if (CSDB::ConvertFromDBTime($sso_session_info["setlogin_info"]["expires"]) < time()) {
             $this->DisplayError(BB_Translate("Verification token has expired."));
             return;
         }
         // The user is signed in.  Activate the account.
         $sso_db_sso_remote_users = SSO_DB_PREFIX . "p_sso_remote_users";
         try {
             $id = $sso_db->GetOne("SELECT", array("id", "FROM" => "?", "WHERE" => "remote_id = ? AND user_id = ?"), $sso_db_sso_remote_users, $this->info["row"]->id, $sso_session_info["setlogin_result"]["user_id"]);
             if ($id === false) {
                 $sso_db->Query("INSERT", array($sso_db_sso_remote_users, array("remote_id" => $this->info["row"]->id, "user_id" => $sso_session_info["setlogin_result"]["user_id"], "created" => CSDB::ConvertToDBTime(time())), "AUTO INCREMENT" => "id"));
                 $id = $sso_db->GetInsertID();
             }
             $mapinfo = $sso_session_info["setlogin_result"]["protected_fields"];
             $mapinfo[$sso_settings["sso_remote"]["map_remote_id"]] = $this->info["row"]->id;
             SSO_ActivateUser($id, serialize($sso_session_info["setlogin_info"]), $mapinfo, false, $this->info["row_info"]["automate"]);
             // Only falls through on account lockout or a fatal error.
             $this->DisplayError(BB_Translate("User activation failed."));
         } catch (Exception $e) {
             $this->DisplayError("A database error has occurred.  Most likely cause:  Bad SQL query.");
         }
     } else {
         // Check the API key information.
         $info = unserialize($this->info["apirow"]->info);
         if ($info["type"] != "remote") {
             $this->DisplayError(BB_Translate("The target client API key is not a remote API key."));
             return;
         }
         if ($info["url"] == "") {
             $this->DisplayError(BB_Translate("The target client API key URL is missing."));
             return;
         }
         // Set up the session so that the endpoint works.
         unset($sso_session_info["setlogin_result"]);
         $token = $sso_rng->GenerateString();
         $sso_session_info["setlogin_info"] = array("provider" => $sso_provider, "apikey_id" => $this->info["apirow"]->id, "redirect_url" => BB_GetRequestHost() . $sso_target_url, "token" => $token, "secret" => $sso_rng->GenerateString(), "expires" => CSDB::ConvertToDBTime(time() + 30 * 60));
         if (!SSO_SaveSessionInfo()) {
             $this->DisplayError(BB_Translate("Unable to save session information."));
             return;
         }
         // Redirect to the remote host.
         $url = $info["url"] . (strpos($info["url"], "?") === false ? "?" : "&") . "from_sso_server=1&sso_setlogin_id=" . urlencode($sso_session_id[1]) . "&sso_setlogin_token=" . urlencode($token) . (isset($_REQUEST["lang"]) ? "&sso_lang=" . urlencode($_REQUEST["lang"]) : "");
         SSO_ExternalRedirect($url);
     }
 }
Example #3
0
    public function ProcessFrontend()
    {
        global $sso_provider, $sso_settings, $sso_target_url, $sso_header, $sso_footer, $sso_providers, $sso_selectors_url;
        require_once SSO_ROOT_PATH . "/" . SSO_PROVIDER_PATH . "/" . $sso_provider . "/facebook.php";
        $facebook = new SSO_FacebookSDK(array("appId" => $sso_settings["sso_facebook"]["app_id"], "secret" => $sso_settings["sso_facebook"]["app_secret"]));
        $id = $facebook->getUser();
        if ($id) {
            try {
                // Calculate the required fields.
                $fields = array("id" => true, "first_name" => true, "last_name" => true);
                foreach (self::$fieldmap as $key => $info) {
                    if ($sso_settings["sso_facebook"]["map_" . $key] != "" && !isset($info["pseudo"])) {
                        $fields[isset($info["parent"]) ? $info["parent"] : $key] = true;
                    }
                }
                $profile = $facebook->api("/me", "GET", array("fields" => implode(",", array_keys($fields))));
            } catch (FacebookApiException $e) {
                // Fall through here to go to the next step.
                $id = 0;
                $exceptionmessage = $e->getMessage();
            }
        }
        if (isset($_REQUEST["sso_facebook_action"]) && $_REQUEST["sso_facebook_action"] == "signin") {
            if ($id) {
                // Create a fake username based on available information.
                if ($sso_settings["sso_facebook"]["map_username"] != "") {
                    if (isset($profile["email"])) {
                        $profile["username"] = (string) @substr($profile["email"], 0, strpos($profile["email"], "@"));
                    } else {
                        if (isset($profile["first_name"]) && isset($profile["last_name"])) {
                            $profile["username"] = $profile["first_name"] . @substr($profile["last_name"], 0, 1);
                        } else {
                            if (isset($profile["name"])) {
                                $name = explode(" ", $name);
                                $profile["username"] = $name[0] . @substr($name[count($name) - 1], 0, 1);
                            } else {
                                $profile["username"] = (string) $id;
                            }
                        }
                    }
                    $profile["username"] = preg_replace('/\\s+/', "_", trim(preg_replace('/[^a-z0-9]/', " ", strtolower((string) $profile["username"]))));
                }
                // Check username blacklist.
                $message = "";
                if (isset($profile["username"])) {
                    $blacklist = explode("\n", str_replace("\r", "\n", $sso_settings["sso_facebook"]["username_blacklist"]));
                    foreach ($blacklist as $word) {
                        $word = trim($word);
                        if ($word != "" && stripos($profile["username"], $word) !== false) {
                            $message = BB_Translate("Username contains a blocked word.");
                            break;
                        }
                    }
                }
                // Check e-mail domain blacklist.
                if (isset($profile["email"])) {
                    define("CS_TRANSLATE_FUNC", "BB_Translate");
                    require_once SSO_ROOT_PATH . "/" . SSO_SUPPORT_PATH . "/smtp.php";
                    $email = SMTP::MakeValidEmailAddress($profile["email"]);
                    if (!$email["success"]) {
                        $message = BB_Translate("Invalid e-mail address.  %s", $email["error"]);
                    } else {
                        $domain = strtolower(substr($email["email"], strrpos($email["email"], "@") + 1));
                        $y = strlen($domain);
                        $baddomains = explode("\n", strtolower($sso_settings["sso_facebook"]["email_bad_domains"]));
                        foreach ($baddomains as $baddomain) {
                            $baddomain = trim($baddomain);
                            if ($baddomain != "") {
                                $y2 = strlen($baddomain);
                                if ($domain == $baddomain || $y < $y2 && substr($domain, $y - $y2 - 1, 1) == "." && substr($domain, $y - $y2) == $baddomain) {
                                    $message = BB_Translate("E-mail address is in a blacklisted domain.");
                                    break;
                                }
                            }
                        }
                    }
                }
                if ($message == "") {
                    // Fix birthday to be in international format YYYY-MM-DD.
                    if (isset($profile["birthday"])) {
                        $birthday = explode("/", $profile["birthday"]);
                        $year = array_pop($birthday);
                        array_unshift($birthday, $year);
                        $profile["birthday"] = implode("-", $birthday);
                    }
                    // Convert most profile fields into strings.
                    foreach ($profile as $key => $val) {
                        if (is_string($val)) {
                            continue;
                        }
                        if (is_bool($val)) {
                            $val = (string) (int) $val;
                        } else {
                            if (is_numeric($val)) {
                                $val = (string) $val;
                            } else {
                                if (is_object($val) && isset($val->id) && isset($val->name)) {
                                    $val = $val->name;
                                }
                            }
                        }
                        $profile[$key] = $val;
                    }
                    // Convert specialized fields into strings.
                    if (isset($profile["age_range"])) {
                        $profile["age_range"] = trim($item->min . "-" . $item->max);
                    }
                    if (isset($profile["education"])) {
                        $items = array();
                        foreach ($profile["education"] as $item) {
                            $items[] = trim($item->year . " " . $item->type . " " . $item->school->name);
                        }
                        $profile["education"] = implode("\n", $items);
                    }
                    if (isset($profile["work"])) {
                        $items = array();
                        foreach ($profile["work"] as $item) {
                            $items[] = trim($item->employer . ", " . $item->location . ", " . $item->position);
                        }
                        $profile["work"] = implode("\n", $items);
                    }
                    $mapinfo = array();
                    foreach (self::$fieldmap as $key => $info) {
                        $key2 = $sso_settings["sso_facebook"]["map_" . $key];
                        if ($key2 != "" && isset($profile[$key])) {
                            $mapinfo[$key2] = $profile[$key];
                        }
                    }
                    // Process specialized fields.
                    if (isset($profile["birthday"])) {
                        $birthday = explode("-", $profile["birthday"]);
                        $key = "birthday_year";
                        $key2 = $sso_settings["sso_facebook"]["map_" . $key];
                        if ($key2 != "") {
                            $mapinfo[$key2] = $birthday[0];
                        }
                        $key = "birthday_month";
                        $key2 = $sso_settings["sso_facebook"]["map_" . $key];
                        if ($key2 != "") {
                            $mapinfo[$key2] = $birthday[1];
                        }
                        $key = "birthday_day";
                        $key2 = $sso_settings["sso_facebook"]["map_" . $key];
                        if ($key2 != "") {
                            $mapinfo[$key2] = $birthday[2];
                        }
                    }
                    SSO_ActivateUser($profile["id"], serialize($profile), $mapinfo);
                    // Only falls through on account lockout or a fatal error.
                    $message = BB_Translate("User activation failed.");
                }
            } else {
                if (isset($_REQUEST["error"]) && $_REQUEST["error"] == "access_denied") {
                    $message = BB_Translate("The request to sign in with Facebook was denied.");
                } else {
                    if (isset($_REQUEST["error_description"])) {
                        $message = BB_Translate($_REQUEST["error_description"]);
                    } else {
                        $message = BB_Translate("An unknown error occurred.  %s", $exceptionmessage);
                    }
                }
            }
            $message = BB_Translate("Sign in failed.  %s", $message);
            echo $sso_header;
            SSO_OutputHeartbeat();
            ?>
<div class="sso_main_wrap">
<div class="sso_main_wrap_inner">
	<div class="sso_main_messages_wrap">
		<div class="sso_main_messages">
			<div class="sso_main_messageerror"><?php 
            echo htmlspecialchars($message);
            ?>
</div>
		</div>
	</div>

	<div class="sso_main_info"><a href="<?php 
            echo htmlspecialchars($sso_target_url);
            ?>
"><?php 
            echo htmlspecialchars(BB_Translate("Try again"));
            ?>
</a><?php 
            if (count($sso_providers) > 1) {
                ?>
 | <a href="<?php 
                echo htmlspecialchars($sso_selectors_url);
                ?>
"><?php 
                echo htmlspecialchars(BB_Translate("Select another sign in method"));
                ?>
</a><?php 
            }
            ?>
</div>
</div>
</div>
<?php 
            echo $sso_footer;
        } else {
            // Calculate the required scope.
            $scope = array();
            foreach (self::$fieldmap as $key => $info) {
                if ($info["extra"] != "" && $sso_settings["sso_facebook"]["map_" . $key] != "") {
                    $scope[$info["extra"]] = true;
                }
            }
            // Get the login redirection URL.
            $options = array("scope" => implode(",", array_keys($scope)), "redirect_uri" => BB_GetRequestHost() . $sso_target_url . "&sso_facebook_action=signin");
            $url = $facebook->getLoginUrl($options);
            SSO_ExternalRedirect($url);
        }
    }
Example #4
0
function SSO_ValidateUser()
{
    global $sso_rng, $sso_db, $sso_db_user_sessions, $sso_db_temp_sessions, $sso_session_info, $sso_apirow, $sso_sessionrow, $sso_sessionrow2, $sso_ipaddr, $sso_settings;
    try {
        // Browser gets a token representing the new session in the temporary session.
        $sso_session_info["new_id2"] = $sso_rng->GenerateString();
        $sso_db->Query("UPDATE", array($sso_db_temp_sessions, array("info" => serialize($sso_session_info)), "WHERE" => "id = ?"), $sso_sessionrow->id);
        // Validate the session.
        $sso_db->Query("UPDATE", array($sso_db_user_sessions, array("updated" => CSDB::ConvertToDBTime(time()), "info" => serialize(array("validated" => true, "ipaddr" => $sso_ipaddr["ipv6"]))), "WHERE" => "id = ?"), $sso_sessionrow2->id);
        // Build the redirect.
        $redirect = str_replace(array("\r", "\n"), "", base64_decode($sso_session_info["url"]));
        $redirect .= (strpos($redirect, "?") === false ? "?" : "&") . "from_sso_server=1&sso_id=" . urlencode($sso_session_info["new_id2"]) . "&sso_id2=" . urlencode($_REQUEST["sso_id"]);
        // Set the namespace cookie.
        if (isset($sso_settings[""]["namespacekey2"])) {
            $namespaces = SSO_LoadNamespaces(true);
            $namespaces[$sso_apirow->namespace] = $_COOKIE["sso_server_id2"];
            $data = serialize($namespaces);
            $data = base64_encode(Blowfish::CreateDataPacket($data, pack("H*", $sso_settings[""]["namespacekey"]), array("prefix" => $sso_rng->GenerateString(), "mode" => "CBC", "iv" => pack("H*", $sso_settings[""]["namespaceiv"]), "key2" => pack("H*", $sso_settings[""]["namespacekey2"]), "iv2" => pack("H*", $sso_settings[""]["namespaceiv2"]), "lightweight" => true)));
            SetCookieFixDomain("sso_server_ns", $data, 0, "", "", SSO_IsSSLRequest(), true);
        }
        // Set the exposed namespace cookie if the option is enabled.
        if (isset($sso_settings[""]["expose_namespaces"]) && $sso_settings[""]["expose_namespaces"] && isset($sso_settings[""]["namespacekey4"])) {
            $namespaces = SSO_LoadNamespaces(false);
            $namespaces[$sso_apirow->namespace] = $sso_sessionrow2->id;
            $data = serialize($namespaces);
            $data = base64_encode(Blowfish::CreateDataPacket($data, pack("H*", $sso_settings[""]["namespacekey3"]), array("prefix" => $sso_rng->GenerateString(), "mode" => "CBC", "iv" => pack("H*", $sso_settings[""]["namespaceiv3"]), "key2" => pack("H*", $sso_settings[""]["namespacekey4"]), "iv2" => pack("H*", $sso_settings[""]["namespaceiv4"]), "lightweight" => true)));
            $host = str_replace(array("http://", "https://"), "", BB_GetRequestHost());
            SetCookieFixDomain("sso_server_ns2", $data, 0, "/", $host, false, true);
        }
        // Redirect back to the client.
        SSO_ExternalRedirect($redirect, true);
    } catch (Exception $e) {
        // Don't do anything here.  Just catch the database exception and let the code fall through.
        // It should be nearly impossible to get here in the first place.
    }
    return false;
}