Il modo migliore per implementare il Single-Sign-On con tutti i principali fornitori?

Ho già fatto molte ricerche su questo argomento e ho implementato molte soluzioni da solo.

Compresi 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 sono incappato in alcuni progetti interessanti:

  • Janrain (ex RPX) – una soluzione commerciale
  • Gigya: una soluzione gratuita ma ospitata esternamente con javascript e restiamo a capo
  • AnyOpenID – una soluzione gratuita per i clienti, commerciale per i siti web

Ma non voglio fare affidamento su un fornitore esterno e vorrei anche 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 templates e tabelle di database per tutto.

Ovviamente questo functionrà, ma è un carico di lavoro e ha sempre bisogno di sviluppo e cambiamenti nella tua applicazione, ecc.

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

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

Idealmente questo servizio di astrazione verrebbe ospitato in modo indipendente dalla mia applicazione in modo che possa essere utilizzato per diverse applicazioni e possa 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 authentication basato su python per Django Webframework. Ma sembra che funzioni come descritto sopra e penso che questo sia lo stesso sistema di login che StackOverflow utilizza (o alless 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.

Quindi, dopo questo lungo text, la mia domanda è precisamente:

  • Come implementereste SSO, un'idea migliore del porting di tutto e di avere 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 potresti call per Facebook, portrlo 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 get feedback / discussioni su di essa. Maby il mio approccio non è così buono come penso che sia attualmente!

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

Dopo la discussione della risposta già esistente riassumo:

Quasi tutti i principali provider sono openid provider / endpoint inclusi Google, Yahoo, Aol.

Alcuni di essi richiedono all'utente di specificare il nome utente per build l'endpoint openid. Alcuni di essi (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 il background tecnico)

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

Ora quello che ho fatto per il mio progetto è quello di creare un provider openid che autentica l'utente con le credenziali della mia applicazione facebook – così l'utente si connette alla mia applicazione – e restituisce un id utente che assomiglia a:

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

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

Quindi il mio sito web deve solo implementare id di apertura e sto bene 🙂

Lo costruisco sulle classi che puoi trovare qui: http://gitorious.org/lightopenid

Nel mio file index.php lo chiamo così:

 <?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 (ie 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 = arrays( '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 = arrays_merge($requested_attributes['required'],$requested_attributes['optional']); $attributes = arrays(); 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; } } 

È 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 raccoglie e migliora o ri scrive o qualsiasi altra cosa 🙂

Bene, considero la risposta a questa domanda

ma aggiungo una taglia solo per avere discussioni. Mi piacerebbe sapere cosa pensi della mia soluzione.

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

OpenID sarà la soluzione migliore per questa applicazione. È supportto da molti fornitori:

  • Google
  • Yahoo
  • myOpenID
  • AOL

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

Per risolvere questa soluzione, potresti scrivere una class wrapper per fornire compatibilità con OpenID, ma la possibilità è che anche se i tuoi utenti non hanno un account Twitter, potrebbero avere un account Facebook, Google o Yahoo.

Facebook support oauth, quindi dovrai portrlo su OpenID

Alcune librerie PHP per OpenID possono essere trovate qui .

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

Il loro URL oauth è "https://graph.facebook.com/oauth/authorize&quot;

Se ancora non mi credi, allora puoi guardare questo file javascript, where ho trovato quell'URL. Se non si ritiene che il file javascript, si noti che è ospitato da stackexchange, il fornitore di questo sito. Ora devi credere che.

Avanti veloce di due anni e la risposta di "OpenID è la risposta" sembra cadere sul ciglio di 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 ti dispiace NON usare OpenID / OAuth, c'è una soluzione SSO ora completa scritta in PHP (Disclaimer e completa divulgazione: questo prodotto è sviluppato e gestito da me stesso sotto il banner di CubicleSoft):

Single Sign-On Server / Client

Che 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).

Potresti anche voler guardare a HybridAuth , che è focalizzato solo sui social sign in ma è più una libreria che una soluzione predefinita che puoi gettare su un server e farla con esso. Quindi c'è un po 'di lavoro in più nella configuration. Dipende davvero da cosa stai cercando.

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