Najlepszy sposób na wdrożenie jednokrotnego logowania ze wszystkimi głównymi dostawcami?

Zrobiłem już wiele badań na ten temat i sam wdrożyłem wiele rozwiązań.

Facebook OpenID (OpenID), Facebook Connect (przy użyciu starego API Rest i nowego API Graph OAuth 2.0), Zaloguj się za pomocą Twittera (który został zaktualizowany do w pełni kwalifikowanego OpenID o ile wiem), i tak dalej...

Ale wciąż brakuje mi idealnego rozwiązania "wszystko w jednym".

Podczas moich badań natknąłem się na kilka ciekawych projektów:

Ale nie chcę polegać na zewnętrznym dostawcy i chciałbym również darmowe rozwiązanie, więc nie jestem ograniczony w implementacji.

Widziałem też deweloperów wdrażających jedną usługę po drugiej, sumiennie podążających za dostawcami instrukcje i konfigurowanie modeli i tabel baz danych dla wszystkiego.

Oczywiście, że to zadziała, ale jest to gówno pracy i zawsze wymaga rozwoju i zmian w aplikacji itp.

To, czego szukam, to warstwa abstrakcji, która przenosi wszystkie usługi do jednego standardu, który można zintegrować z moją stroną internetową. Gdy pojawi się nowa usługa, chcę dodać tylko jeden model, który zajmuje się abstrakcją tego konkretnego dostawcy, dzięki czemu mogę bezproblemowo Zintegruj go z moją aplikacją.

Lub lepiej, znaleźć już istniejące rozwiązanie, które mogę po prostu dowonload.

Najlepiej, aby ta usługa abstrakcji była hostowana niezależnie od mojej aplikacji, więc może być używana w kilku aplikacjach i być aktualizowana niezależnie.

Ostatnie z 3 powyższych rozwiązań wygląda obiecująco z koncepcji. Wszystko OpenID OpenID jest po prostu przeportowany na syntetyczny, a strona jut musi zaimplementować OpenID.

Po chwili znalazłem Django socialauth-System Uwierzytelniania oparty na Pythonie dla Webframework Django. Ale wygląda na to, że działa jak opisano powyżej i myślę, że jest to ten sam system logowania, którego używa Stackoverflow (lub przynajmniej jakiś zmodyfikowany fork...).

Pobrałem go i próbowałem go skonfigurować i sprawdzić, czy można go skonfigurować jako samodzielne rozwiązanie, ale nie miałem szczęścia, ponieważ nie jestem tak zainteresowany Pythonem.

Chciałbym rozwiązanie oparte na PHP.

Więc po tym długim tekście moje pytanie brzmi:

  • Jak zaimplementowałbyś SSO, lepszy pomysł niż portowanie wszystkiego i posiadanie OpenID jako podstawy?
  • Jakie są tego plusy i minusy?
  • czy znasz jakieś już istniejące rozwiązania? Preferuje open source.

Mam nadzieję, że to pytanie nie jest zbyt subiektywne, z góry dziękuję.

Update: Facebook OpenID to OpenID, który pozwala na tworzenie proxy / wrappera lub Jak to można nazwać na Facebooku, aby portować go do OpenID, aby stał się OpenID najlepszym rozwiązaniem byłby punkt końcowy / dostawca. Więc dokładnie to zrobiłem.

Proszę zobaczyć moją odpowiedź poniżej.

Dodałem bounty, aby uzyskać opinie/dyskusję na ten temat. Maby moje podejście nie jest tak dobre, jak obecnie myślę, że jest!

Author: sobbe, 2010-10-31

3 answers

Jako autor tej odpowiedzi chcę zauważyć, że uważam ją za nieaktualne . Ponieważ większość dostawców zdecydowała się na wyłącznie wdrożenie Oauth zamiast Openid. Nowsze usługi Openid będą również prawdopodobnie używać OpenID connect, który jest oparty na oauth. Istnieją dobre biblioteki, takie jak na przykład: https://github.com/hybridauth/hybridauth

Po omówieniu już istniejącej odpowiedzi podsumowuję:

Prawie każdy główny dostawca jest OpenID dostawca / punkt końcowy, w tym Google, Yahoo, AOL.

Niektóre z nich wymagają od użytkownika podania nazwy użytkownika do zbudowania punktu końcowego openid. Niektóre z nich (te wymienione powyżej) mają adresy URL do wykrywania, gdzie identyfikator użytkownika jest zwracany automatycznie, tak że użytkownik musi tylko kliknąć. (byłbym zadowolony, gdyby ktoś mógł wyjaśnić tło techniczne)

Facebook Facebook connect jest jedynym wrzodem na tyłku, ponieważ mają swój Facebook connect, gdzie używają zaadaptowanej wersji OAuth do uwierzytelniania. Facebook - OpenID, który uwierzytelnia użytkownika za pomocą danych uwierzytelniających mojej aplikacji na Facebooku - dzięki czemu użytkownik zostanie połączony z moją aplikacją - i zwróci identyfikator użytkownika, który wygląda następująco:]}
http://my-facebook-openid-proxy-subdomain.mydomain.com/?id=facebook-user-id

Skonfigurowałem go również do pobierania adresu e-mail i nazwy i zwracania go jako atrybuty AX.

Więc moja strona musi tylko zaimplementować opend id i jest dobrze:)

Buduję je na klasach, które można znaleźć tutaj: http://gitorious.org/lightopenid

W moim indeksie.plik php nazywam tak:
<?php
require 'LightOpenIDProvider.php';
require 'FacebookProvider.php';
$op = new FacebookProvider;
$op->appid = 148906418456860; // your facebook app id
$op->secret = 'mysecret'; // your facebook app secret
$op->baseurl = 'http://fbopenid.2xfun.com'; // needs to be allowed by facebook
$op->server();
?>

I Kod źródłowy FacebookProvider.php:

<?php
class FacebookProvider extends LightOpenIDProvider
{
    public $appid = "";
    public $appsecret = "";
    public $baseurl = "";

    // i have really no idea what this is for. just copied it from the example.
    public $select_id = true;

    function __construct() {

        $this->baseurl = rtrim($this->baseurl,'/'); // no trailing slash as it will be concatenated with
                                                    // request uri wich has leading slash

        parent::__construct();

        # If we use select_id, we must disable it for identity pages,
        # so that an RP can discover it and get proper data (i.e. without select_id)
        if(isset($_GET['id'])) {
            // i have really no idea what happens here. works with or without! just copied it from the example.
            $this->select_id = false;
        }
    }

    function setup($identity, $realm, $assoc_handle, $attributes)
    {
        // here we should check the requested attributes and adjust the scope param accordingly
        // for now i just hardcoded email
        $attributes = base64_encode(serialize($attributes));    

        $url = "https://graph.facebook.com/oauth/authorize?client_id=".$this->appid."&redirect_uri=";

        $redirecturl = urlencode($this->baseurl.$_SERVER['REQUEST_URI'].'&attributes='.$attributes);
        $url .= $redirecturl;
        $url .= "&display=popup";
        $url .= "&scope=email";
        header("Location: $url");
        exit();        

    }

    function checkid($realm, &$attributes)
    {
        // try authenticating
        $code = isset($_GET["code"]) ? $_GET["code"] : false;
        if(!$code) {
            // user has not authenticated yet, lets return false so setup redirects him to facebook
            return false;
        }

        // we have the code parameter set so it looks like the user authenticated
        $url = "https://graph.facebook.com/oauth/access_token?client_id=148906418456860&redirect_uri=";

        $redirecturl = ($this->baseurl.$_SERVER['REQUEST_URI']);
        $redirecturl = strstr($redirecturl, '&code', true);
        $redirecturl = urlencode($redirecturl);     
        $url .= $redirecturl;
        $url .= "&client_secret=".$this->secret;
        $url .= "&code=".$code;
        $data = $this->get_data($url);

        parse_str($data,$data);

        $token = $data['access_token'];

        $data = $this->get_data('https://graph.facebook.com/me?access_token='.urlencode($token));
        $data = json_decode($data);

        $id = $data->id;
        $email = $data->email;
        $attribute_map = array(
            'namePerson/friendly' => 'name', // we should parse the facebook link to get the nickname
            'contact/email' => 'email',
        );

        if($id > 0) {

            $requested_attributes = unserialize(base64_decode($_GET["attributes"]));

            // lets be nice and return everything we can
            $requested_attributes = array_merge($requested_attributes['required'],$requested_attributes['optional']);
            $attributes = array();
            foreach($requested_attributes as $requsted_attribute) {
                if(!isset($data->{$attribute_map[$requsted_attribute]})) {
                    continue; // unknown attribute
                }
                $attributes[$requsted_attribute] = $data->{$attribute_map[$requsted_attribute]};    
            }

            // yeah authenticated!
            return $this->serverLocation . '?id=' . $id ;
        }
        die('login failed'); // die so we dont retry bouncing back to facebook
        return false;
    }
    function get_data($url) { 
      $ch = curl_init();
      $timeout = 5;
      curl_setopt($ch,CURLOPT_URL,$url);
      curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
      curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,$timeout);
      $data = curl_exec($ch);
      curl_close($ch);
      return $data;
    }    

}

To tylko pierwsza działająca wersja (szybka i brudna) Niektóre dynamiczne rzeczy są zakodowane na twardo do moich potrzeb. To powinno pokazać, jak i że można to zrobić. Cieszę się, że ktoś to podniósł i poprawił, albo przepisał czy coś :)

Cóż uważam to pytanie za odpowiedź

Ale dodaję bounty tylko do dyskusja. Chciałbym wiedzieć, co sądzisz o moim rozwiązaniu.

Przyznam nagrodę za najlepszą odpowiedź / komentarz obok tej.

 13
Author: The Surrican,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-14 12:12:17

OpenID będzie najlepszym rozwiązaniem dla tej aplikacji. Jest obsługiwany przez wielu, dostawców:

  • Google
  • Yahoo
  • MyOpenID
  • AOL

Jedyny problem polega na tym, że twitter nie zaimplementował jeszcze OpenID. Prawdopodobnie wynika to z faktu, że są firmą opartą na własności, więc chcieli swojego "własnego" rozwiązania.

Aby rozwiązać To rozwiązanie, możesz napisać klasę wrapper, która zapewni kompatybilność z OpenID, ale szansa jest taka, że nawet jeśli użytkownicy nie mają konta na Twitterze, mogą mieć konto Facebook, Google lub Yahoo.

Facebook wspiera OpenID, więc będziesz musiał portować oauth, aby OpenID

Niektóre biblioteki PHP dla OpenID można znaleźć tutaj .

Teraz pojawiły się pytania o to, że facebook jest dostawcą oauth.

Ich OAuth URL to "https://graph.facebook.com/oauth/authorize"

Jeśli nadal mnie Nie wierzysz, możesz spojrzeć na ten plik javascript, skąd mam ten adres URL. Jeśli nie wierzysz w ten plik javascript, zwróć uwagę, że jest on hostowany przez stackexchange, dostawcę tej witryny. Teraz musisz w to uwierzyć.

 5
Author: xaav,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-11-02 21:19:09

Przewiń do przodu o dwa lata i odpowiedź "OpenID jest odpowiedzią" wydaje się spadać na uboczu przez wielu dużych dostawców. Większość głównych witryn integracyjnych innych firm wydaje się przenieść na jakiś smak OAuth (Zwykle OAuth2). Ponadto, jeśli nie masz nic przeciwko Nie używaniu OpenID/OAuth, istnieje teraz kompletne rozwiązanie SSO napisane w PHP (Zastrzeżenie i pełne ujawnienie: ten produkt jest rozwijany i utrzymywany przez mnie pod szyldem CubicleSoft): {]}

Single Logowanie Serwer / Klient

Które nie istniały, gdy to pytanie zostało pierwotnie zadane. Posiada liberalną licencję (MIT lub LGPL) i spełnia Twoje wymagania bycia warstwą abstrakcji. Projekt koncentruje się głównie na logowaniu w przedsiębiorstwie, ale ma też pewne wpisy w mediach społecznościowych (Google i Facebook).

Możesz również spojrzeć na HybridAuth , który koncentruje się tylko na social media sign ins, ale jest bardziej biblioteką niż gotowym rozwiązaniem, które możesz można wrzucić na serwer i z tym skończyć. Jest więc trochę więcej pracy związanej z jego skonfigurowaniem. To naprawdę zależy od tego, czego szukasz.

Jeśli jesteś zadowolony z rozwiązania OpenID, to świetnie, ale obecnie jest więcej opcji niż dwa lata temu i ludzie wciąż znajdują ten wątek.

 2
Author: CubicleSoft,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-21 14:32:48