2010-10-31 13 views
42

Ho già fatto molte ricerche su questo argomento e ho implementato molte soluzioni da solo.Il modo migliore per implementare l'accesso Single Sign-On con tutti i principali fornitori?

Includendo OpenID, Facebook Connect (utilizzando la vecchia API Rest e la nuova API Graph OAuth 2.0), Accedi con Twitter (che è stato aggiornato a OpenID completamente qualificato ormai per quanto ne so) e così via. ..

Ma quello che mi manca ancora è la perfetta soluzione tutto in uno.

Durante la mia ricerca ho inciampato su alcuni progetti interessanti:

Ma io non voglio fare affidamento su un fornitore esterno e vorrei come una soluzione gratuita, quindi non sono limitato nell'implementazione.

Ho visto anche sviluppatori che implementano un servizio dopo l'altro seguendo diligentemente le istruzioni dei provider e impostando modelli e tabelle di database per tutto.

Naturalmente questo funziona, ma è un casino di lavoro e ha sempre bisogno di sviluppo e cambiamenti nella vostra applicazione ecc

Quello che sto cercando è un livello di astrazione che prende tutti i servizi là fuori per uno standard che può essere integrato nel mio sito web. Quando viene visualizzato un nuovo servizio, voglio solo aggiungere un modello che si occupa dell'astrazione di quel fornitore specifico in modo da poterlo integrare senza problemi nella mia applicazione.

O meglio, trovare una soluzione già esistente che posso semplicemente scaricare.

Idealmente questo servizio di astrazione sarebbe ospitato in modo indipendente dalla mia applicazione in modo che possa essere utilizzato per diverse applicazioni ed essere aggiornato indipendentemente.

L'ultima delle 3 soluzioni sopra sembra promettente dal concetto. Tutto è appena trasferito a un OpenID sintetico e l'intestazione del sito Web deve implementare OpenID.

Dopo un po 'ho trovato Django socialauth, un sistema di autenticazione basato su python per il Webframework di Django. Ma sembra che funzioni come descritto sopra e penso che questo sia lo stesso sistema di login che StackOverflow utilizza (o almeno qualche fork modificato ...).

L'ho scaricato e ho provato a configurarlo e vedere se poteva essere impostato come soluzione autonoma, ma non ho avuto fortuna, perché non lo sono neanche per Python.

Mi piacerebbe una soluzione basata su PHP.

Così, dopo questo lungo testo la mia domanda è proprio:

  • Come ti implementare SSO, qualche idea migliore di porting tutto e hanno OpenID come base?
  • Quali sono i pro e i contro di ciò?
  • Conosci qualche soluzione già esistente? Preferibilmente open source.

Spero che questa domanda non sia troppo soggettiva, grazie in anticipo.

Aggiornamento: Ho concluso che la creazione di un proxy/wrapper o di quello che si potrebbe chiamare per Facebook, per portarlo su un OpenID in modo che diventi un endpoint/provider OpenID sarebbe l'opzione migliore. Così esattamente quello che ho fatto.

Si prega di vedere la mia risposta qui sotto.

Ho aggiunto la taglia per ottenere feedback/discussioni su di essa. Maby il mio approccio non è così buono come penso che sia attualmente!

+0

ho modificato la mia classe un po 'e corretto alcuni bug! lo metterà su github o qualcosa del genere quando è fatto, favorisce la domanda per ottenere l'aggiornamento. –

+0

Non credo che questa domanda sia abbastanza non costruttiva da essere chiusa. – markus

+1

nevermind @ markus-tharkun, mi sento come se effettivamente aiutarmi a vicenda è diventato irrilevante in SO. è più simile a un regime con le sue definizioni di ciò che fa e non fa una buona domanda e il desiderio di dare la caccia a tutti gli altri e umiliare l'interrogante in modo che non possa mai più tornare. –

risposta

13

Come autore originale di questa risposta, voglio sottolineare che considero come obsoleto. Poiché la maggior parte dei provider ha deciso di implementare esclusivamente Oauth anziché Openid. I nuovi servizi Openid utilizzeranno probabilmente anche openid connect, che è basato su oauth. Ci sono buone biblioteche, come ad esempio:

Dopo la discussione della risposta già esistente che riassumo:

Quasi tutti i principali provider è un provider OpenID/endpoint tra cui Google, Yahoo, Aol.

Alcuni di essi richiedono all'utente di specificare il nome utente per la costruzione dell'endpoint aperto. Alcuni di questi (quelli sopra menzionati) hanno URL di individuazione, in cui l'ID utente viene automaticamente restituito in modo che l'utente debba solo fare clic. (sarei felice se qualcuno potesse spiegare lo sfondo tecnico)

Tuttavia l'unico dolore nel culo è Facebook, perché hanno la loro connessione Facebook dove usano una versione adattata di OAuth per l'autenticazione.

Ora quello che ho fatto per il mio progetto è di creare un provider OpenID che autentica l'utente con le credenziali di mio facebook applicazione - in modo che l'utente si connette alla mia domanda - e restituisce un ID utente che assomiglia:

http://my-facebook-openid-proxy-subdomain.mydomain.com/?id=facebook-user-id 

L'ho anche configurato per recuperare indirizzo e-mail e nome e restituirlo come attributi AX.

Quindi il mio sito web deve solo implementare opend id e sto bene :)

ho costruire su di classi si possono trovare qui: http://gitorious.org/lightopenid

Nel mio file index.php ho appena lo chiamo come questo:

<?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(); 
?> 

e il codice sorgente di FacebookProvider.php segue:

<?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; 
    }  

} 

E 'solo una prima versione funzionante (veloce e sporca) Alcune cose dinamiche sono hardcoded per le mie esigenze. Dovrebbe mostrare come e che può essere fatto. Sono felice se qualcuno prende e lo migliora o ri scrive o qualunque :)

Beh io considero questa domanda ha risposto

ma aggiungo una taglia solo per ottenere la discussione. Mi piacerebbe sapere cosa pensi della mia soluzione.

assegnerò la taglia alla migliore risposta/commento accanto a questa.

+1

Potrebbe essere più sicuro archiviare l'appid come una stringa: questo è un grande intero pericoloso grosso '$ op-> appid = '148906418456860'; ' –

+0

true;) comune" errore ".. comunque tendo a lanciare un'eccezione" please upgrade a 64 bit ": P –

+0

penso che probabilmente vale la pena ricordare che al momento in cui questa risposta è stata creata era Giustamente, tuttavia, il corso della storia voleva che Oauth fosse il vincitore su Openid ... quindi probabilmente sarebbe meglio concentrarsi su questo. –

5

OpenID sta per essere la soluzione migliore per questa applicazione. Esso è supportato da molti, i fornitori:

  • Google
  • Yahoo
  • myOpenID
  • AOL

L'unico problema è che twitter non ha ancora attuato OpenID. Ciò è probabilmente dovuto al fatto che si tratta di una società basata sulla proprietà, quindi volevano la loro soluzione "propria".

Per risolvere questa soluzione, è possibile scrivere una classe wrapper per garantire la compatibilità con OpenID, ma è possibile che anche se gli utenti non dispongono di un account Twitter, potrebbero disporre di un account Facebook, Google o Yahoo.

Facebook Supporta OAuth, in modo da avere alla porta OAuth per OpenID

Alcune librerie PHP per OpenID può essere trovato here.

Ora, alcune domande sono state sollevate su Facebook essendo un fornitore oauth.

loro URL OAuth è "https://graph.facebook.com/oauth/authorize"

Se ancora non mi credi, allora si può guardare this file JavaScript, dove ho ottenuto l'URL. Se non si ritiene che il file javascript, si noti che è ospitato da stackexchange, il fornitore di questo sito. Ora devi credere che.

+0

Maby I trascura qualcosa ma quando si tratta di Facebook e OpenID mi sembra che l'unica possibilità sia quella di collegare un account OpenId al proprio account Facebook. Quello che voglio è che le persone possano autenticarsi sul mio sito con il loro account Facebook. Non ho trovato NESSUNA risorsa su questo? Mamma puoi indicarmi la direzione giusta o fornirmi un link? –

+0

Facebook è un fornitore OpenID. Ho inserito un link nella risposta, se guardi l'elenco dei fornitori, facebook è un link. – xaav

+0

Ho modificato la domanda per rendere più chiaro su Facebook – xaav

2

Avanti veloce di due anni e la risposta di "OpenID è la risposta" sembra cadere lungo la strada da un certo numero di grandi fornitori. La maggior parte dei principali siti di integrazione di terze parti sembra essere passata ad alcuni aspetti di OAuth (di solito OAuth2). Inoltre, se non vi dispiace non usando OpenID/OAuth, c'è una soluzione ormai completa SSO scritto in PHP (Clausola di full disclosure: Questo prodotto è sviluppato e mantenuto da solo sotto la bandiera CubicleSoft):

Single Sign-On Server/Client

Quale non esisteva quando inizialmente veniva posta questa domanda. Ha una licenza liberale (MIT o LGPL) e soddisfa il tuo requisito di essere un livello di astrazione. Il progetto tende a focalizzarsi sugli accessi aziendali, ma ha anche alcuni inserimenti sui social media nel mix (Google e Facebook).

Si potrebbe anche voler guardare a HybridAuth, che si concentra solo su accessi di social media ma è più di una libreria di una soluzione predefinita che si può gettare su un server e fare con esso. Quindi c'è un po 'di lavoro in più nella configurazione. Dipende davvero da cosa stai cercando.

Se siete soddisfatti della vostra soluzione OpenID, allora grandioso, ma oggi ci sono più opzioni rispetto a due anni fa e la gente sta ancora trovando questo thread.

+0

Grazie per aver postato la tua risposta! Si prega di leggere attentamente le [FAQ sulla promozione di sé] (http://stackoverflow.com/faq#promotion) attentamente. In particolare si noti che * è * richiesto * di pubblicare una dichiarazione di non responsabilità ogni volta che si collega al proprio sito/prodotto, * e * che la ragione principale per cui si è presenti qui non dovrebbe essere la promozione del/i prodotto/i/sito web. –

Problemi correlati