Наконец-то ПРАКТИЧНЫЙ способ интеграции Windows Live и SharePoint 2010 при помощи OAuth и SAML

Исходная статья опубликована в четверг, 1 марта 2012 г.

Многие уже говорили мне раньше об объединении SharePoint с Windows Live. На первый взгляд, идея кажется довольно удачной — в Windows Live миллионы пользователей, и все они для входа используют свой адрес электронной почты, а именно он часто используется в качестве идентификационного утверждения, это огромная масштабируемая служба, и в нашем распоряжении имеются различные инструкции о том, как это сделать — напрямую или через службу ACS (Access Control Service). Так почему же я так ворчу по поводу использования ее с SharePoint? Ну, те из вас, кто уже пытался делать это раньше, знают, что при объединении с Windows Live вам никогда не возвращается адрес электронной почты пользователя в качестве утверждения. Вы получаете только специальный идентификатор Windows Live, который называется PUID. Насколько я знаю, “PUID” должно означать “Practically GUID” (фактический GUID), поскольку это наиболее близко к тому, как он выглядит и применяется.

Например, как вы добавляете кого-либо на сайт при выполнении интеграции с Windows Live? Вам необходимо получить его PUID, а затем добавить PUID в группу или уровень разрешений SharePoint. А знаете ли вы хотя бы одного человека, которому известен его PUID (если это вы, то пора бы уже найти себе другое занятие в свободное время). Даже если вы каким-то чудом знаете свой PUID, много ли пользы вам это принесет, когда вы пытаетесь предоставить пользователям права в других семействах сайтов? Вы правда думаете, что кто-то еще может отличить вас в списке PUID (или средстве выбора людей, в зависимости от обстоятельств)? Конечно, нет! И это вызывает у меня еще больше сомнений.

Я подумал, а не попробовать ли более утопическое решение с использованием ACS. Служба ACS очень хороша в плане предоставления стандартных уловок таким поставщикам удостоверений, как Windows Live, Google, Yahoo и Facebook. В Facebook даже применяется немножко волшебства и фактически используется OAuth для проверки подлинности, а затем возвращается набор утверждений SAML. Это здорово! Так почему же нельзя сделать то же самое в Windows Live? Windows Live теперь поддерживает OAuth, так что, кажется, наконец появляется возможность сделать что-то стоящее. Но, как бы нам этого не хотелось, специалисты ACS не идут здесь нам на выручку. И на можно поставить точку во вступлении — наконец, я решил просто написать кое-что сам, и этому как раз и посвящена эта запись.

Итак, что нам нужно знать об OAuth? В отличие от PUID, который вы получаете при прямой интеграции с Windows Live, поддержка OAuth в Windows Live позволяет получить НАМНОГО больше информации о пользователе, в том числе — что бы вы думали? — его адрес электронной почты. Итак, общий план решения таков:

  1. Написать собственный поставщик удостоверений с использованием Windows Identity Foundation (WIF).
  2. Если пользователь, перенаправляемый в нашу службу STS, еще не прошел проверку подлинности, мы перенаправляем его снова в Windows Live. Для этого необходимо создать “приложение” для Windows Live, позже я поясню это подробнее.
  3. Как только пользователь проходит проверку подлинности, он перенаправляется обратно в нашу STS. По возвращении в строке запроса содержится маркер имени входа (login token), который можно обменять на маркер доступа (access token).
  4. Затем служба STS делает еще один запрос, адресованный Windows Live, с кодом входа и запрашивает маркер доступа.
  5. После получения маркера доступа она отправляет в Windows Live завершающий запрос с маркером доступа и запрашивает некоторую базовую информацию о пользователе (позже я поясню, что мы получаем в ответ).
  6. Получив информацию о пользователе из Windows Live, мы с помощью нашей собственной службы STS создаем набор утверждений SAML для пользователя и заполняем их информацией о пользователе. Затем выполняем переадресацию обратно в приложение, запросившее проверку подлинности, чтобы оно могло выполнить необходимые действия с маркерами SAML. В моем конкретном случае я тестировал мой проект STS с помощью как стандартного приложения ASP.NET, так и веб-приложения SharePoint 2010.

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

Создание сертификата для подписи маркера

Вам потребуется создать сертификат, который будет использоваться для подписания ваших маркеров SAML. Он ничем особенным не отличается от сертификата, который используется для подписания сертификатов, за исключением того, что у вас обязательно должен быть для него закрытый ключ. У меня установлены службы сертификации в домене, так что я просто открыл диспетчер IIS (IIS Manager) и выбрал команду для создания сертификата домена. Я выполнил указания мастера, и не успели вы оглянуться, как я уже получил новенький сертификат вместе с закрытым ключом. Для этого проекта я создал сертификат с названием livevbtoys. 

Как я буду объяснять в следующем разделе, когда запросы первоначально приходят в STS, пользователь является анонимным. Чтобы использовать сертификат для подписания маркеров SAML, необходимо предоставить процессу IIS доступ к закрытому ключу для этого сертификата. Когда анонимный запрос попадает в процесс IIS, удостоверением является сетевая служба (Network Service). Чтобы предоставить ей права на ключ, сделайте следующее:

  1. Запустите MMC
  2. Добавьте оснастку “Сертификаты” (Certificates). Выберите хранилище “Компьютер” (Computer) для локального компьютера.
  3. Откройте хранилище личных сертификатов (Personal) и найдите сертификат, созданный вами для подписания маркеров SAML. Если вы создали его так, как я описал выше, сертификат будет там по умолчанию. Если вы создаете его иным способом, возможно, его потребуется добавить в это хранилище.
  4. Щелкните правой кнопкой мыши сертификат и выберите “Управление закрытыми ключами” (Manage Private Keys).
  5. В списке пользователей, имеющих права на ключи, добавьте сетевую службу (Network Service) и предоставьте ей право “Чтение” (Read).

Имейте в виду, что если не сделать это правильно, то при попытке запуска приложения вы можете получить сообщение об ошибке, в котором говорится что-то типа “набор ключей не существует” (keyset does not exist). Это означает, что у процесса IIS недостаточно прав на закрытый ключ, поэтому он не может использовать ключ для подписания маркера SAML.

Установка приложения и необходимая сборка

Установка приложения в данном случае означает просто создание приложения ASP.NET в IIS, копирование фрагментов данных и проверку установленной версии WIF (должна быть последняя). Как только вы получите настроенное и работающее приложение на одном сервере, вам определенно тут же захочется добавить еще один или несколько серверов, чтобы получить отказоустойчивое решение. Но сейчас я буду говорить о настройке на одном сервере.

Не буду останавливаться на создании приложения ASP.NET в IIS. Это можно сделать с помощью Visual Studio, диспетчера IIS и т. п. 

ПРИМЕЧАНИЕ. Если вы воспользуетесь предоставленным здесь кодом и просто откроете проект в Visual Studio, он может пожаловаться на то, что узел или сайт не существует. Это потому, что используется имя моего сервера. Чтобы исправить это, проще всего вручную отредактировать файл WindowsLiveOauthSts.sln, изменив в нем значения https на реально существующие в вашей среде.

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

  1. Добавьте PassiveSTS.aspx в качестве документа по умолчанию в диспетчере IIS для веб-сайта STS.
  2. Измените параметры проверки подлинности для приложения в IIS таким образом, чтобы отключить все типы проверки подлинности, кроме анонимной.
  3. Служба STS должна работать через SSL, поэтому нужно получить для нее подходящий сертификат и обязательно обновить привязки на виртуальном сервере IIS, где используется пользовательское приложение STS.
  4. Не забудьте поместить отпечаток сертификата для подписи маркера в атрибут thumbprint элемента add в разделе trustedIssuers файла web.config проверяющей стороны (если вы НЕ используете SharePoint для тестирования). Если вы используете мастер добавления ссылки STS (Add STS Reference) в Visual Studio, он сделает это за вас.

Это вся настройка, которая необходима в IIS.

Изменение и построение пользовательского проекта STS

Приложенный zip-файл содержит проект Visual Studio 2010 с названием WindowsLiveOauthSts. После настройки IIS и обновления файла WindowsLiveOauthSts.sln, как описано выше, вам нужно успешно открыть проект в Visual Studio. В первую очередь вам следует изменить константы CLIENT_ID и CLIENT_SECRET в классе PassiveSTS.aspx.cs. Вы получаете их при создании нового приложения Windows Live. Я не собираюсь приводить пошаговые инструкции (поскольку в Windows Live есть люди, которые могут помочь вам с этим), так что просто укажу, куда можно пойти для создания приложения Windows Live: https://manage.dev.live.com/Applications/Index?wa=wsignin1.0. Кроме того, при создании приложения обязательно укажите в качестве домена перенаправления (Redirect Domain) место, где размещается ваш проект STS, например https://myserver.foo.com.

Теперь, когда у вас имеется собственный идентификатор и секрет, необходимо внести изменения в приложение:

  1. Измените константы CLIENT_ID и CLIENT_SECRET в классе PassiveSTS.aspx.cs.
  2. В файле web.config измените SigningCertificateName в разделе appSettings. Обратите внимание, что вам не обязательно изменять параметр IssuerName, но вы можете сделать это, если хотите.
  3. Измените сертификат для подписи маркера для документа FederationMetadata.xml в проекте STS. Выбрав сертификат, который собираетесь использовать, вы можете воспользоваться приложением test.exe, включенным в эту запись, чтобы получить значение строки для сертификата. Его нужно скопировать и вставить вместо двух значений элемента X509Certificate в файле federationmetadata.xml.

Есть еще одна важная вещь, на которую следует обратить внимание — в файле CustomSecurityTokenService.cs имеется опция задания значения true для переменной enableAppliesToValidation с последующим указанием списка URL-адресов, которые могут использовать эту пользовательскую службу STS. В моем случае я решил никак не ограничивать адреса, так что переменная имеет значение false. Если вы хотите ограничить использование STS, вам следует изменить это значение сейчас. После внесения всех этих изменений вы можете перекомпилировать приложение, и оно готово к работе.

И еще одно примечание — я включил также образец приложения ASP.NET, которое я использовал для тестирования при построении. Оно в проекте с названием LiveRP. Я не буду на нем останавливаться; достаточно сказать, что вот оно здесь на случай, если вы хотите поэкспериментировать с тестированием. Только не забудьте изменить отпечаток для сертификата подписи маркера STS, как описано выше.

Конфигурация SharePoint

Теперь для пользовательской службы STS все настроено и должно работать. Единственное, что осталось сделать — создать нового издателя (issuer) SPTrustedIdentityToken в SharePoint и настроить его использование в новом или уже имеющемся веб-приложении. Вам следует знать несколько вещей о настройке SPTrustedIdentityTokenIssuer; я сейчас приведу здесь код PowerShell, который я использовал для создания своего издателя, а затем дам пояснения.

$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2("c:\livevbtoys.cer")

New-SPTrustedRootAuthority -Name "SPS Live Token Signing Certificate" -Certificate $cert

 

$map = New-SPClaimTypeMapping -IncomingClaimType "https://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" -IncomingClaimTypeDisplayName "EmailAddress" -SameAsIncoming

$map2 = New-SPClaimTypeMapping -IncomingClaimType "https://blogs.technet.com/b/speschka/claims/id" -IncomingClaimTypeDisplayName "WindowsLiveID" -SameAsIncoming

$map3 = New-SPClaimTypeMapping -IncomingClaimType "https://blogs.technet.com/b/speschka/claims/full_name" -IncomingClaimTypeDisplayName "FullName" -SameAsIncoming

$map4 = New-SPClaimTypeMapping -IncomingClaimType "https://blogs.technet.com/b/speschka/claims/first_name" -IncomingClaimTypeDisplayName "FirstName" -SameAsIncoming

$map5 = New-SPClaimTypeMapping -IncomingClaimType "https://blogs.technet.com/b/speschka/claims/last_name" -IncomingClaimTypeDisplayName "LastName" -SameAsIncoming

$map6 = New-SPClaimTypeMapping -IncomingClaimType "https://blogs.technet.com/b/speschka/claims/link" -IncomingClaimTypeDisplayName "Link" -SameAsIncoming

$map7 = New-SPClaimTypeMapping -IncomingClaimType "https://blogs.technet.com/b/speschka/claims/gender" -IncomingClaimTypeDisplayName "Gender" -SameAsIncoming

$map8 = New-SPClaimTypeMapping -IncomingClaimType "https://blogs.technet.com/b/speschka/claims/locale" -IncomingClaimTypeDisplayName "Locale" -SameAsIncoming

$map9 = New-SPClaimTypeMapping -IncomingClaimType "https://blogs.technet.com/b/speschka/claims/updated_time" -IncomingClaimTypeDisplayName "WindowsLiveLastUpdatedTime" -SameAsIncoming

$map10 = New-SPClaimTypeMapping -IncomingClaimType "https://blogs.technet.com/b/speschka/claims/account" -IncomingClaimTypeDisplayName "AccountName" -SameAsIncoming

$map11 = New-SPClaimTypeMapping -IncomingClaimType "https://blogs.technet.com/b/speschka/claims/accesstoken" -IncomingClaimTypeDisplayName "WindowsLiveAccessToken" -SameAsIncoming

$realm = "https://spslive.vbtoys.com/_trust/"

$ap = New-SPTrustedIdentityTokenIssuer -Name "SpsLive" -Description "Window Live oAuth Identity Provider for SAML" -realm $realm -ImportTrustCertificate $cert -ClaimsMappings $map,$map2,$map3,$map4,$map5,$map6,$map7,$map8,$map9,$map10,$map11 -SignInUrl "https://spr200.vbtoys.com/WindowsLiveOauthSts/PassiveSTS.aspx" -IdentifierClaim "https://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"

На что здесь следует обратить внимание:

  1. Как я уже говорил выше, я создал сертификат с названием livevbtoys.cer для подписания моих маркеров, поэтому я добавил его в мой список SPTrustedRootAuthority, а затем связал с моим издателем маркера.
  2. Я создал сопоставления для всех утверждений, возвращаемых моей пользовательской службой STS. Как видите, это ГОРАЗДО БОЛЬШЕ И ЛУЧШЕ того, что вы могли бы получить при прямой интеграции с Windows Live. Хочу также заметить, что я включил здесь в качестве утверждения маркер доступа, полученный из Windows Live. Хотя он работает с Facebook, я не проводил тестирование, так что не могу с уверенностью сказать, позволит ли Windows Live использовать его повторно. Возможно, это будет темой другой записи в будущем.
  3. Значение $realm играет чрезвычайно важную роль. Оно должно указывать на корневой сайт вашего веб-приложения и включать каталог /_trust/. Если оно неправильное, то вы получите 500 ошибок из SharePoint при обратном перенаправлении после проверки подлинности.
  4. Параметр –SignInUrl при создании издателя маркера представляет абсолютный URL-адрес страницы PassiveSTS.aspx для моей пользовательской службы STS.

Ну, собственно, и все — после настройки вы по-прежнему используете стандартное средство поиска людей и поставщики утверждений, то есть у вас не будет возможностей поиска, на которые вы, возможно, рассчитываете. Вы предоставляете людям права с использованием адресов электронной почты, с помощью которых они входят в Windows Live. Вы можете расширить этот пример и использовать также поставщик утверждений Azure, о чем я писал здесь:  https://blogs.msdn.com/b/sharepoint_ru/archive/2012/03/07/the-azure-custom-claim-provider-for-sharepoint-project-part-1.aspx. Это значит, что вы могли бы с помощью этой STS выполнить проверку подлинности в Windows Live и получить в ответ подлинное утверждение SAML, а затем с помощью проекта настраиваемого поставщика утверждений Azure добавить прошедших проверку подлинности пользователей в хранилище каталогов Azure и средство выбора людей, где они будут доступны для выбора.

На картинках все видно. Вот что вы видите, когда в первый раз заходите на сайт SharePoint и выполняете проверку подлинности с помощью Windows Live:

При первом входе вас спрашивают, не возражаете ли вы против обмена информацией с пользовательским приложением STS. Тут нет ничего интересного — это стандартное представление разрешений OAuth. Вот так это выглядит; обратите внимание, здесь показаны данные, которые я запрашиваю в STS — вы можете запрашивать совершенно другой набор данных, если хотите. Вам только нужно с помощью Window Live OAuth SDK определить, что и как необходимо изменить:

После подтверждения происходит перенаправление обратно на сайт SharePoint. В данном примере я использую веб-часть SharePoint Claims, о которой говорил здесь:  https://blogs.technet.com/b/speschka/archive/2010/02/13/figuring-out-what-claims-you-have-in-sharepoint-2010.aspx. Здесь показаны все утверждения, полученные мной из Windows Live через OAuth, которые теперь имеются у меня в качестве утверждений SAML благодаря моему пользовательскому проекту STS, а также видно, что я вошел с помощью своего адреса электронной почты Windows Live, который я создал для этого проекта (на элементе управления входом в правом верхнем углу):

 

Это локализованная запись блога. Исходная статья доступна по ссылке: Finally A USEFUL Way to Federate With Windows Live and SharePoint 2010 Using OAuth and SAML