C# 在DotNetOpenAuth中强制使用不同的属性交换命名空间

C# 在DotNetOpenAuth中强制使用不同的属性交换命名空间,c#,openid,dotnetopenauth,attribute-exchange,C#,Openid,Dotnetopenauth,Attribute Exchange,目前我正在使用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

目前我正在使用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名称空间

这就是我如何使用DotNetOpenAuth请求和获取属性,以及大量其他来源:

FetchRequest ax = new FetchRequest();
ax.Attributes.AddRequired("http://theirapp.com/path/student-ids");
request.AddExtension(ax);

当回复完全忽略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?“别名3”来自哪里?那应该是“斧头”。我不知道我正在使用的应用程序是否对AX名称空间过于敏感,或者DotNetOpenAuth没有注意到强制的OpenID协议

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

  • 我需要我的AX请求位于名称空间openid.AX中,而不是openid.alias3中。我如何强制DotNetOpenAuth这样做
  • API要求请求的属性的名称正好如此——在本例中为“学生ID”。上面,他们得到了默认名称,如“alias1”。如何强制DotNetOpenAuth使用自定义名称标记属性
  • 谁在这里:要求openid.ax或DotNetOpenAuth不关心的API
  • 问题1:

    我需要我的AX请求位于名称空间openid.AX中,而不是openid.alias3中。我如何强制DotNetOpenAuth这样做

    DotNetOpenAuth不允许强制使用特定扩展名的别名。需要一个特定的接口与OpenID2.0规范相反。甚至

    openid.ns=http://openid.net/srv/ax/1.0

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

    问题2:

    API要求请求的属性的名称正好如此——在本例中为“学生ID”。上面,他们得到了默认名称,如“alias1”。如何强制DotNetOpenAuth使用自定义名称标记属性

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

    问题#3:

    谁在这里:要求openid.ax或DotNetOpenAuth不关心的API

    DotNetOpenAuth是正确的。如果您正在查看的有关此学生id交换的文档与DotNetOpenAuth之间的别名差异确实是您看到的AX属性被忽略的问题的根本原因,那么故障在于服务器上运行的OpenID提供程序的实现不佳。OpenID提供者的糟糕实现是非常可怕的——不仅仅是因为互操作性差,还因为它们表明在正确实现规范的过程中可能存在许多安全问题


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

    谢谢spamguy。我想出了一个解决这个问题的方法,并将它发布在这里,供其他可能遇到同样问题的人使用,因为PowerSchool的OpenID提供程序存在局限性

    您需要使用DotNetOpenAuth正常构建请求,然后从请求中提取重定向响应。一旦您有了这个,您就可以根据需要拉取位置头并覆盖名称空间值

    此示例适用于MVC应用程序。如果需要在WebForms应用程序中执行此操作,只需从方法中获取逻辑并替换行
    return redirectResponse.AsActionResult()带有
    重定向响应。发送()
    。你需要用通常的试一试…接住。。。对于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;
    
    黑客:


    请注意:这是一个脆弱的黑客。DNOA中的内部更改或FetchRequest的更改可能会破坏替换逻辑。

    后续:使用Fiddler尝试ax命名空间是个好主意。它最终证明了提供程序希望a)AX请求位于.AX中,b)显式命名的属性。他们坦白说,最终会有一个解决办法。在那之前我不知道我会做什么…+1谢谢安德鲁。如果没有你的回答,找到解决办法将是一条漫长的道路。如果可以的话,我会接受布兰登和你的回答。
    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();
    }