构建OpenId提供程序时,我遇到了一个奇怪的问题,只有Stack Exchange站点会接受它。
Discovery工作得很好,并且我正在发送(对我来说像是)一个有效的响应。
奇妙的是,没有合规性测试*告诉我什么是错的,也没有大多数网站提供登录通过OpenId给你任何有用的错误信息。Stack Overflow给出了一些,但它似乎是唯一接受我断言的依赖方,所以……是的。
无论如何,如果我尝试登录(例如)Typepad,我最终会重定向到像
这样的url
https://www.typepad.com/secure/services/signin/openid?openid-check=1&archetype.quickreg=1&tos_locale=en_US&portal=typepad&oic.time=1303249620-9db5665031c9c6b36031&openid.claimed_id=https://example/user/8c481fb7-1b5c-4e50-86b5-xxxxxxxxx&openid.identity=https://example/user/8c481fb7-1b5c-4e50-86b5-xxxxxxxxx&openid.sig=hoaxQrsN4BBg6H8kp50NoQwpHmcO96BBe+jB3oOP2UA=&openid.signed=claimed_id,identity,assoc_handle,op_endpoint,return_to,response_nonce,ns.alias3,alias3.mode&openid.assoc_handle={634388464235195799}{oqMrOA==}{32}&openid.op_endpoint=https://example/openid/provider&openid.return_to=https://www.typepad.com/secure/services/signin/openid?openid-check=1&archetype.quickreg=1&tos_locale=en_US&portal=typepad&oic.time=1303249620-9db5665031c9c6b36031&openid.response_nonce=2011-04-19T21:47:03Z1aa4NZ48&openid.mode=id_res&openid.ns=http://specs.openid.net/auth/2.0&openid.ns.alias3=http://openid.net/srv/ax/1.0&openid.alias3.mode=fetch_response
为了(稍微)更容易阅读而跳出来:
openid-check=1
archetype.quickreg=1
tos_locale=en_US
portal=typepad
oic.time=1303249620-9db5665031c9c6b36031
openid.claimed_id=https://example/user/8c481fb7-1b5c-4e50-86b5-xxxxxxxxx
openid.identity=https://example/user/8c481fb7-1b5c-4e50-86b5-xxxxxxxxx
openid.sig=hoaxQrsN4BBg6H8kp50NoQwpHmcO96BBe+jB3oOP2UA=
openid.signed=claimed_id,identity,assoc_handle,op_endpoint,return_to,response_nonce,ns.alias3,alias3.mode
openid.assoc_handle={634388464235195799}{oqMrOA==}{32}
openid.op_endpoint=https://example/openid/provider
openid.return_to=https://www.typepad.com/secure/services/signin/openid?openid-check=1
archetype.quickreg=1
tos_locale=en_US
portal=typepad
oic.time=1303249620-9db5665031c9c6b36031
openid.response_nonce=2011-04-19T21:47:03Z1aa4NZ48
openid.mode=id_res
openid.ns=http://specs.openid.net/auth/2.0
openid.ns.alias3=http://openid.net/srv/ax/1.0
openid.alias3.mode=fetch_response
这是给用户的XRDS(因为发现似乎没问题)。
<?xml version="1.0" encoding="UTF-8"?>
<xrds:XRDS
xmlns:xrds="xri://$xrds"
xmlns:openid="http://openid.net/xmlns/1.0"
xmlns="xri://$xrd*($v*2.0)">
<XRD>
<Service priority="10">
<Type>http://specs.openid.net/auth/2.0/signon</Type>
<LocalID>https://example/user/8c481fb7-1b5c-4e50-86b5-xxxxxxxxx</LocalID>
<Type>http://openid.net/extensions/sreg/1.1</Type>
<Type>http://axschema.org/contact/email</Type>
<URI>https://example/openid/provider</URI>
</Service>
<Service priority="20">
<Type>http://openid.net/signon/1.0</Type>
<Type>http://openid.net/extensions/sreg/1.1</Type>
<Type>http://axschema.org/contact/email</Type>
<URI>https://example/openid/provider</URI>
</Service>
</XRD>
</xrds:XRDS>
如果您深入研究TypePad的html,您会发现以下错误消息
<!-- Error Code: unexpected_url_redirect -->
…这就是为什么我用他们作为例子。有点没用,但还是有意义的。
这段代码很大程度上基于与dotNetOpenAuth一起发布的示例MVC项目,SendAssertion的实现是我怀疑事情不太好。
protected ActionResult SendAssertion(IAuthenticationRequest authReq)
{
// Not shown: redirect to a prompt if needed
if (authReq.IsDirectedIdentity)
{
authReq.LocalIdentifier = Current.LoggedInUser.GetClaimedIdentifier();
}
if (!authReq.IsDelegatedIdentifier)
{
authReq.ClaimedIdentifier = authReq.LocalIdentifier;
}
authReq.IsAuthenticated = this.UserControlsIdentifier(authReq);
if (authReq.IsAuthenticated.Value)
{
// User can setup an alias, but we don't actually want relying parties to store that since it can change over time
authReq.ClaimedIdentifier = Current.LoggedInUser.GetClaimedIdentifier();
authReq.LocalIdentifier = Current.LoggedInUser.GetClaimedIdentifier();
// Not shown: responding to AX and SREG requests
}
var req = OpenIdProvider.PrepareResponse(authReq);
var ret = req.AsActionResult();
return ret;
}
很抱歉,这是一个如此庞大的信息转储,但我没有很多要继续,因此不能真正缩小到一些简单的。
所以我想最终的问题是……知道我哪里做错了吗?
*好的,这里有一些测试。但没人说"啊哈,这个坏了"
这里有一大堆其他陷阱,它们都不属于dotNetOpenAuth。
- 这整个事情是强制SSL,并重定向所有HTTP流量进来。
- …除了所有HTTP流量重定向到
/
,这破坏了发现
- …除了所有HTTP流量重定向到
- HTML发现被破坏。
- 虽然,理论上,依赖方可以做所有的发现使用头在实践中几乎每个人开始解析HTML的某个点。
一些依赖方修改了OpenId 1.1和2.0规范 - 这与#2有点重叠,但一些依赖方非常乐意用头(OpenId 2.0)做发现,但随后在返回的HTML中寻找
openid.server
。
dotNetOpenAuth作为(显然是少数)OpenId库之一,可以在header上完成整个OpenId舞蹈,工作得很好,巧合的是