Форсирование другого пространства имен Attribute Exchange в DotNetOpenAuth
В настоящее время я использую OpenID (через C# и DotNetOpenAuth) для создания функции единого входа между приложением A ("их приложение") и приложением B ("мое приложение").
Я хочу использовать обмен атрибутами для сбора данных, которые предлагает их приложение. Их API документирует, как должны выглядеть AX-запросы:
openid.ns.ax = http://openid.net/srv/ax/1.0
openid.ax.type.studentids = http://theirapp.com/path/student-ids
Обратите внимание на пространство имен.ax. Это похоже на спецификации AX OpenID.
Вот как я использую DotNetOpenAuth для запроса и получения атрибутов, как это было предложено SO и несколькими другими источниками:
FetchRequest ax = new FetchRequest();
ax.Attributes.AddRequired("http://theirapp.com/path/student-ids");
request.AddExtension(ax);
а также
string sIDs = String.Empty;
if (fetch != null)
sIDs = fetch.GetAttributeValue("http://theirapp.com/path/student-ids");
Я был смущен, когда ответы вернулись полностью игнорируя запросы AX. После просмотра параметров строки запроса, которые мы отправляли, я думаю, что это на самом деле не их вина:
openid.ns:http://specs.openid.net/auth/2.0
openid.ns.alias3:http://openid.net/srv/ax/1.0
openid.alias3.required:alias1
openid.alias3.mode:fetch_request
openid.alias3.type.alias1:http://theirapp.com/path/student-ids
openid.alias3.count.alias1:1
Какого черта, DotNetOpenAuth? Откуда появился alias3? Это должен быть "топор". Я не могу сказать, является ли приложение, с которым я работаю, слишком анальным по поводу пространств имен AX, или DotNetOpenAuth не обращает внимания на обязательный протокол OpenID.
Итак, после всего этого, мои вопросы:
- Мне нужно, чтобы мои запросы AX находились в пространстве имен openid.ax, а не openid.alias3. Как заставить DotNetOpenAuth сделать это?
- API требует, чтобы запрошенные свойства были названы именно так - в данном случае "идентификаторы ученика". Выше они получают имена по умолчанию, такие как "alias1". Как заставить DotNetOpenAuth помечать свойства пользовательскими именами?
- Кто здесь прав: API, требующий openid.ax или DotNetOpenAuth за то, что он не заботится?
2 ответа
Спасибо спамгуй. Я понял, как обойти эту проблему, и выкладываю ее здесь для других, которые могут столкнуться с той же проблемой с ограничениями OpenID-провайдера PowerSchool.
Вам необходимо построить запрос с помощью DotNetOpenAuth, а затем извлечь ответ перенаправления из запроса. Получив это, вы можете извлечь заголовок Location и перезаписать значения пространства имен по мере необходимости.
Этот пример для приложения MVC. Если вам нужно сделать это в приложении WebForms, просто возьмите логику из метода и замените строку return redirectResponse.AsActionResult();
с redirectResponse.Send()
, Вам нужно будет обернуть это в обычную попытку... поймать... для исключений ThreadAbortException.
Используемые пространства имен:
using System;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Mvc;
using System.Web.Security;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OpenId;
using DotNetOpenAuth.OpenId.Extensions.AttributeExchange;
using DotNetOpenAuth.OpenId.RelyingParty;
взломать:
const string NS_DCID = "http://powerschool.com/entity/id";
const string NS_USERTYPE = "http://powerschool.com/entity/type";
static readonly OpenIdRelyingParty openid = new OpenIdRelyingParty();
private ActionResult SubmitOpenIdRequest(string openid_identifier)
{
var request = openid.CreateRequest(openid_identifier);
var ax = new FetchRequest();
// any modification to the following attributes will require a corresponding change in the string replacement hack
ax.Attributes.AddRequired(NS_DCID);
ax.Attributes.AddRequired(NS_USERTYPE);
request.AddExtension(ax);
var redirectResponse = request.RedirectingResponse;
// PowerSchool is violating the attribute exchange specification, requiring specific namespaces and elements to function
// Need to overwrite the values generated by OpenID to patch PowerSchool's incorrect provider implementation
redirectResponse.Headers["Location"] = redirectResponse.Headers["Location"]
.Replace("openid.ns.alias3", "openid.ns.ax")
.Replace("openid.alias3.required=dcid%2Calias2", "openid.ax.required=dcid%2Cusertype")
.Replace("openid.alias3.mode", "openid.ax.mode")
.Replace("openid.alias3.type.alias1", "openid.ax.type.dcid")
.Replace("openid.alias3.count.alias1", "openid.ax.count.dcid")
.Replace("openid.alias3.type.alias2", "openid.ax.type.usertype")
.Replace("openid.alias3.count.alias2", "openid.ax.count.usertype");
return redirectResponse.AsActionResult();
}
Будьте осторожны: это хрупкий взлом. Внутренние изменения в DNOA или изменения в FetchRequest могут нарушить логику замены.
Вопрос 1:
Мне нужно, чтобы мои запросы AX находились в пространстве имен openid.ax, а не openid.alias3. Как заставить DotNetOpenAuth сделать это?
DotNetOpenAuth не позволяет вводить псевдоним определенного расширения. Требование конкретного противоречит спецификации OpenID 2.0. Даже само расширение AX заявляет об этом в разделе 1.1.
openid.ns.<extension_alias>=http://openid.net/srv/ax/1.0
Фактический псевдоним пространства имен расширения должен определяться для каждого сообщения стороной, составляющей сообщения, таким образом, чтобы избежать конфликтов между несколькими расширениями. Для целей этого документа псевдоним пространства имен расширения для службы обмена атрибутами будет "ax".
Вопрос 2:
API требует, чтобы запрошенные свойства были названы именно так - в данном случае "идентификаторы ученика". Выше они получают имена по умолчанию, такие как "alias1". Как заставить DotNetOpenAuth помечать свойства пользовательскими именами?
Как и в случае с вашим первым вопросом, DotNetOpenAuth не позволяет вам принудительно использовать псевдонимы отдельных атрибутов, поскольку расширение AX не учитывает эти типы требований. Тип атрибута указан в URI. Псевдоним этого атрибута определяется проверяющей стороной, и поставщик OpenID должен просматривать URI типа атрибута и принимать любой псевдоним, полученный от проверяющей стороны.
Вопрос № 3:
Кто здесь прав: API, требующий openid.ax или DotNetOpenAuth за то, что он не заботится?
DotNetOpenAuth правильно. Если на самом деле различия в псевдонимах между документацией, которую вы просматриваете для этого обмена студентами, и тем, что DotNetOpenAuth являются основной причиной проблемы, которую вы видите с игнорируемыми атрибутами AX, то ошибка заключается в плохой реализации Поставщик OpenID запускается на сервере. Плохие реализации поставщиков OpenID очень страшны - не только из-за плохого взаимодействия, но и потому, что они предполагают, что могут быть любые из многих возможных проблем безопасности, а также из-за отсутствия осторожности при правильной реализации спецификации.
Я предлагаю вам попробовать использовать Fiddler или какой-либо другой HTTP-сниффер для перехвата исходящего запроса, исправить все псевдонимы, чтобы они соответствовали тому, что, согласно документам, должно быть, и посмотреть, решит ли это проблему. Если это так, поставщик OpenID должен быть исправлен, и вы можете связаться с ним, чтобы попросить его обновить его до более новой версии той библиотеки, которую они используют (надеюсь, что это поможет исправить это). Если "исправление" псевдонимов не устраняет проблему, вы можете перейти к изучению других возможных причин сбоя взаимодействия.