Подтвердить что ты не робот

Лучший способ реализовать Single-Sign-On со всеми основными поставщиками?

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

Включая OpenID, Facebook Connect (используя старый API-интерфейс Rest API и новый API API OAuth 2.0), войдите в систему с помощью twitter (до сих пор до тех пор, пока я знаю), и т.д..

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

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

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

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

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

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

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

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

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

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

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

Мне бы понравилось решение на базе PHP.

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

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

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

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

См. мой ответ ниже.

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

4b9b3361

Ответ 1

Как оригинальный автор этого ответа, я хочу отметить, что я рассматриваю его как Устаревшие. Поскольку большинство провайдеров решило исключительно реализовать 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;
    }    

}

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

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

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

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

Ответ 2

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

  • Google
  • Yahoo
  • MyOpenID
  • AOL

Единственная проблема заключается в том, что twitter еще не реализовал OpenID. Вероятно, это связано с тем, что они являются фирмой, основанной на патентах, поэтому они хотели получить свое "собственное" решение.

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

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

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

Теперь возникли некоторые вопросы о том, что facebook является поставщиком oauth.

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

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

Ответ 3

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

Сервер/клиент с одиночным подключением

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

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

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