在DotNetOpenAuth中强制使用不同的Attribute Exchange命名空间

时间:2012-10-24 14:29:05

标签: c# openid dotnetopenauth attribute-exchange

目前我正在使用OpenID(通过C#和DotNetOpenAuth)在App A(“他们的应用”)和App B(“我的应用”)之间创建单点登录功能。

我希望利用属性交换来获取其应用提供的数据。他们的API记录了AX请求的外观:

openid.ns.ax              = http://openid.net/srv/ax/1.0
openid.ax.type.studentids = http://theirapp.com/path/student-ids

请注意.ax命名空间。 That seems in line with OpenID's AX specs.

这就是我使用DotNetOpenAuth请求和获取属性as suggested by 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协议。

所以,在所有这些积累之后,我的问题是:

  1. 我需要将AX请求放在命名空间openid.ax中,而不是openid.alias3。我如何强制DotNetOpenAuth这样做?
  2. API要求请求的属性只是这样命名 - 在这种情况下,'student-ids'。上面,他们得到的默认名称如'alias1'。如何强制DotNetOpenAuth使用自定义名称标记属性?
  3. 谁在右边:需要openid.ax或DotNetOpenAuth的API不关心?

2 个答案:

答案 0 :(得分:2)

问题#1:

  

我需要将AX请求放在命名空间openid.ax中,而不是openid.alias3。我如何强制DotNetOpenAuth这样做?

DotNetOpenAuth不允许您强制使用特定扩展名的别名。要求特定的一个与OpenID 2.0规范相反。甚至是AX extension itself states this in section 1.1

  
    

openid.ns.<extension_alias>=http://openid.net/srv/ax/1.0

  
     

实际扩展名称空间别名应由组成消息的一方基于每个消息确定,以避免多个扩展之间的冲突。出于本文档的目的,属性交换服务的扩展名称空间别名将为“ax”。

问题#2:

  

API要求请求的属性就是这样命名的 - 在这种情况下,'student-ids'。上面,他们得到的默认名称如'alias1'。如何强制DotNetOpenAuth使用自定义名称标记属性?

就像您的第一个问题一样,DotNetOpenAuth没有为您提供强制单个属性的别名的方法,因为AX扩展不允许这些类型的要求。 URI中给出了属性的类型。该属性的别名可由依赖方定义,OpenID提供者应该查看属性的类型URI,并接受来自依赖方的任何别名。

问题#3:

  

谁在右边:要求openid.ax或DotNetOpenAuth的API不关心?

DotNetOpenAuth是正确的。如果您正在查看此学生ID交换的文档之间的别名差异以及DotNetOpenAuth是您看到的AX属性被忽略的问题的根本原因,那么问题在于执行不良OpenID提供程序正在服务器上运行。 OpenID提供商的糟糕实施非常可怕 - 不仅仅是因为糟糕的互操作,而是因为他们认为可能存在许多可能的安全问题,因为在正确实施规范时缺乏谨慎。

我建议您尝试使用Fiddler或其他一些HTTP嗅探器来拦截出站请求,修复所有别名以匹配文档建议它们应该是什么,并查看它是否解决了问题。如果是这样,OpenID提供程序应该被修复,您可以联系他们请求他们升级到他们正在使用的任何库的更新版本(希望单独将修复它)。如果“修复”别名解决了问题,那么您可以继续调查其他可能的互操作失败原因。

答案 1 :(得分:1)

感谢spamguy。我找到了解决这个问题的黑客,并将其发布在其他可能遇到PowerSchool OpenID提供商限制相同问题的其他人。

您需要使用DotNetOpenAuth正常构建请求,然后从请求中提取重定向响应。完成此操作后,您可以拉出Location标头并根据需要覆盖命名空间值。

此示例适用于MVC应用程序。如果您需要在WebForms应用程序中执行此操作,只需从方法中获取逻辑并将行return redirectResponse.AsActionResult();替换为redirectResponse.Send()。你需要将它包装在通常的try ... catch ...中,用于ThreadAbortExceptions。

使用的名称空间:

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的更改可能会破坏替换逻辑。