Лучший способ реализовать единый вход со всеми основными поставщиками? - PullRequest
42 голосов
/ 31 октября 2010

Я уже провел много исследований по этой теме и сам реализовал множество решений.

Включая OpenID, Facebook Connect (используя старый API Rest и новый API Graph OAuth 2.0), войдите в системус твиттером (который, насколько я знаю, уже обновлен до полностью квалифицированного OpenID) и т. д. ...

Но то, чего мне не хватает, - это идеальное решение "все в одном".

Во время моего исследования я наткнулся на несколько интересных проектов:

Но я не хочуполагаться на внешнего поставщика, и я хотел бы также получить бесплатное решение, поэтому я не ограничен в реализации.

Я также видел разработчиков, внедряющих один сервис за другим, должным образом следуя инструкциям провайдеров.Работа и настройка моделей и таблиц базы данных для всего.

Конечно, это будет работать, но это куча работы и всегда требует разработки и изменений в вашем приложении и т. д.

То, что я ищуfor - это уровень абстракции , который переводит все сервисы в один стандарт, который может быть интегрирован в мой веб-сайт.После появления нового сервиса я хочу добавить только одну модель, которая работает с абстракцией этого конкретного провайдера, чтобы я мог легко интегрировать его в свое приложение.

Или, что еще лучше, найти уже существующее решение, которое я могу просто загрузить.

В идеале этот сервис абстракции должен размещаться независимо от моего приложения, поэтому его можно использовать для нескольких приложений и обновлять независимо.

Последнее из трех решений, представленных выше, выглядит многообещающим из этой концепции.Все просто перенесено на синтетический OpenID, и веб-сайт должен реализовать OpenID.

Через некоторое время я обнаружил Django socialauth , систему аутентификации на основе Python для Django Webframework.Но похоже, что он работает так, как описано выше, и я думаю, что это та же система входа в систему, которую использует Stackoverflow (или, по крайней мере, какой-то измененный форк ...).

Я скачал его и попытался настроить ипосмотрим, можно ли его настроить как автономное решение, но мне не повезло, так как я не очень разбираюсь в python.

Я бы хотел решение на основе PHP.

Так что после этого долгогоТекст мой вопрос точно таков:

  • Как бы вы внедрили SSO, есть ли лучшая идея, чем портировать все и иметь OpenID в качестве основы?
  • Каковы плюсы и минусы этого?
  • Знаете ли вы уже существующие решения?Предпочтительно с открытым исходным кодом.

Надеюсь, этот вопрос не слишком субъективен, заранее спасибо.

Обновление: я пришел к выводу, что создаем прокси / оболочку или как вы могли бы это назвать для Facebookпортировать его на OpenID, чтобы он стал конечной точкой / провайдером OpenID, было бы лучшим вариантом.Так что именно это я и сделал.

Пожалуйста, смотрите мой ответ ниже.

Я добавил награду, чтобы получить отзыв / обсуждение по ней.Маби, мой подход не так хорош, как я сейчас думаю!

Ответы [ 3 ]

13 голосов
/ 08 ноября 2010

Как оригинальный автор этого ответа, я хочу отметить, что считаю его Устаревшие . Поскольку большинство провайдеров решили использовать Oauth вместо Openid. Более новые сервисы Openid также, вероятно, будут использовать openid connect, основанный на oauth. Есть хорошие библиотеки, такие как, например: https://github.com/hybridauth/hybridauth

После обсуждения уже существующего ответа я подытожу:

Почти каждый крупный провайдер является openid-провайдером / конечной точкой, включая Google, Yahoo, Aol.

Некоторые из них требуют от пользователя указать имя пользователя для создания конечной точки openid. Некоторые из них (упомянутые выше) имеют URL-адреса обнаружения, где идентификатор пользователя автоматически возвращается, так что пользователю остается только щелкнуть. (Я был бы рад, если бы кто-то мог объяснить техническое обоснование)

Однако единственная боль в заднице - это Facebook, потому что у них есть Facebook, где они используют адаптированную версию OAuth для аутентификации.

Теперь то, что я сделал для своего проекта, - это установил провайдера openid, который аутентифицирует пользователя с помощью учетных данных моего приложения Facebook - так что пользователь подключается к моему приложению - и возвращает идентификатор пользователя, который выглядит следующим образом:

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

Я также настроил его на получение адреса электронной почты и имени и возвращал его как атрибуты AX.

Так что мой сайт просто должен реализовать opend id, и я в порядке:)

Я строю его на классах, которые вы можете найти здесь: http://gitorious.org/lightopenid

В моем файле index.php я просто называю это так:

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

и следующий исходный код 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;
    }    

}

Это просто первая рабочая версия (быстрая и грязная) Некоторые динамические вещи жестко запрограммированы на мои нужды. Это должно показать, как и что это можно сделать. Я счастлив, если кто-то поднимет и улучшит это или переписывает это или что-то еще:)

Ну, я считаю, что на этот вопрос ответили

но я добавляю награду только для обсуждения. Я хотел бы знать, что вы думаете о моем решении.

Я буду награждать награду лучшим ответом / комментарием рядом с этим.

5 голосов
/ 01 ноября 2010

OpenID будет вашим лучшим выбором для этого приложения.Поддерживается многими провайдерами:

  • Google
  • Yahoo
  • MyOpenID
  • AOL

The Onlyпроблема в том, что twitter еще не реализовал OpenID.Вероятно, это связано с тем, что они являются компанией, основанной на принципах пропритерии, поэтому они хотели найти «свое» решение.

Чтобы решить это решение, вы можете написать класс-оболочку, обеспечивающий совместимость с OpenID, но есть вероятность, что даже если у ваших пользователей нет учетной записи в Твиттере, они могут иметь Facebook, Google или Yahooучетная запись.

Facebook поддерживает oauth, поэтому вам придется перенести oauth на OpenID

Некоторые библиотеки PHP для OpenID можно найти здесь .

Теперь некоторыебыли заданы вопросы о том, что Facebook является oauth-провайдером.

Их адрес oauth: "https://graph.facebook.com/oauth/authorize"

Если вы все еще не верите мне, вы можете посмотреть этот файл javascript, где я получил этот URL. Если вы не верите этому файлу javascript, то обратите внимание, что он размещен в stackexchange, провайдере этого сайта. Теперь вы должны поверить в это.

2 голосов
/ 02 ноября 2012

Перенесемся на два года вперед, и ответ «OpenID - это ответ», похоже, отодвигается на второй план рядом крупных провайдеров. Кажется, что большинство крупных сторонних сайтов интеграции перешли на OAuth (обычно OAuth2). Кроме того, если вы не возражаете против использования OpenID / OAuth, теперь существует полное решение SSO, написанное на PHP (отказ от ответственности и полное раскрытие: этот продукт разработан и поддерживается мной под баннером CubicleSoft):

Сервер единой регистрации / клиент

Которого не было, когда этот вопрос был задан изначально. Он имеет либеральную лицензию (MIT или LGPL) и отвечает вашим требованиям быть уровнем абстракции. Проект, как правило, ориентирован на корпоративные входы, но в нем также есть входы для социальных сетей (Google и Facebook).

Возможно, вы также захотите взглянуть на HybridAuth , который ориентирован только на входы в социальные сети, но представляет собой скорее библиотеку, чем готовое решение, которое вы можете добавить на сервер и покончить с этим. Таким образом, есть еще немного работы, связанной с его настройкой. Это действительно зависит от того, что вы после.

Если вы довольны своим решением OpenID, то это здорово, но сегодня есть больше возможностей, чем было два года назад, и люди все еще находят эту тему.

...