一般说明
我使用DotNetOpenAuth实现了一个OP(OpenID提供程序(。我正在针对示例RP(信赖方(对其进行测试,例如Drupal的OpenID登录名和DotNetOpenAuth Samples
解决方案中的OpenIdRelyingPartyWebForms
项目。
问题是,据我所知,当浏览器反弹我的 OP 并将"成功的身份验证"请求(mode: id_res
、claimed_id: smth
等(发送回 RP 时,RP 不会尝试对 OP 执行服务器端请求并询问它是否实际对用户进行身份验证。我可以看到有一个从 OP 返回的openid.sig
签名,但同样,我不明白 RP 如何验证它,因为它没有与 OP 交换密钥。
所以问题是:OP 端是否有一些设置可以启用以使工作流程安全?
技术细节
我正在使用Wireshark来嗅探RP端的HTTP流量。没有HTTPS,所以我可以看到和阅读所有消息。下面你可以看到到底发生了什么。B = 浏览器,OP = OpenID 提供程序,RP = 信赖方。域名将替换为 *.example.com。
-
(B –> RP( 用户尝试访问信赖方上仅限成员的资源。他输入浏览器发布到 RP 的 OP 端点。
openid_identifier:http://OP.example.com/OpenId/Provider.aspx?xrds
-
(RP –> OP –> RP( RP 向我的 OP 发出服务器端请求,该请求返回 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/server</Type> <Type>http://openid.net/extensions/sreg/1.1</Type> <URI>http://OP.example.com/OpenId/Provider.aspx</URI> </Service> </XRD> </xrds:XRDS>
-
(RP –> B –> OP( 信赖方 302 将用户重定向到 OP 的
/OpenId/Provider.aspx?[params]
URL,其中参数如下:openid.claimed_id: http://specs.openid.net/auth/2.0/identifier_select openid.identity: http://specs.openid.net/auth/2.0/identifier_select openid.assoc_handle: {634730422000625000}{jkQC1Q==}{32} openid.return_to: http://RP.example.com/login.aspx?ReturnUrl=%2FMembersOnly%2FDefault.aspx&dnoa.receiver=ctl00_Main_OpenIdLogin1&dnoa.UsePersistentCookie=Session&dnoa.userSuppliedIdentifier=http%3A%2F%2FOP.example.com%2FOpenId%2FProvider.aspx%3Fxrds openid.realm: http://RP.example.com/ openid.mode: checkid_setup openid.ns: http://specs.openid.net/auth/2.0 openid.ns.sreg: http://openid.net/extensions/sreg/1.1 openid.sreg.policy_url: http://RP.example.com/PrivacyPolicy.aspx openid.sreg.required: email,gender,postcode,timezone
-
(OP –> B –> RP( 提供程序对用户进行身份验证,并使用以下 URL 参数将用户重定向回 RP
:ReturnUrl: /MembersOnly/Default.aspx dnoa.receiver: ctl00_Main_OpenIdLogin1 dnoa.UsePersistentCookie: Session dnoa.userSuppliedIdentifier: http://OP.example.com/OpenId/Provider.aspx?xrds openid.claimed_id: http://OP.example.com/OpenId/User.aspx/2925 openid.identity: http://OP.example.com/OpenId/User.aspx/2925 openid.sig: pWJ0ugjQATKGgRSW740bml9LDsSxFiJ+a9OLO6NlsvY= openid.signed: claimed_id,identity,assoc_handle,op_endpoint,return_to,response_nonce,ns.sreg,sreg.nickname,sreg.email openid.assoc_handle: {634730422000625000}{jkQC1Q==}{32} openid.op_endpoint: http://OP.example.com/OpenId/Provider.aspx openid.return_to: http://RP.example.com/login.aspx?ReturnUrl=%2FMembersOnly%2FDefault.aspx&dnoa.receiver=ctl00_Main_OpenIdLogin1&dnoa.UsePersistentCookie=Session&dnoa.userSuppliedIdentifier=http%3A%2F%2FOP.example.com%2FOpenId%2FProvider.aspx%3Fxrds openid.response_nonce: 2012-05-19T16:40:11ZSfsL4BK1 openid.mode: id_res openid.ns: http://specs.openid.net/auth/2.0 openid.ns.sreg: http://openid.net/extensions/sreg/1.1 openid.sreg.nickname: user@OP.example.com openid.sreg.email: user@OP.example.com
-
(RP –> OP(RP 对 OP 执行服务器端 HTTP 请求。没有传输任何数据,只是对先前获取的用户身份 URL 的 GET 请求。顺便说一下,它为什么要提出这个要求?
GET /OpenId/User.aspx/2925 HTTP/1.1
-
(OP –> RP(OP回复了另一个XRDS文档:
<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> <Type>http://openid.net/extensions/sreg/1.1</Type> <URI>http://OP.example.com/OpenId/Provider.aspx</URI> </Service> <Service priority="20"> <Type>http://openid.net/signon/1.0</Type> <Type>http://openid.net/extensions/sreg/1.1</Type> <URI>http://OP.example.com/OpenId/Provider.aspx</URI> </Service> </XRD> </xrds:XRDS>
-
(RP –> B(就是这样。用户已获得授权,RP 向他显示仅限成员的资源。
RP可以在有状态或无状态模式下运行(分别也称为智能模式和哑模式(。 查看每个网络流程图。
RP和 OP 之间存在一次性密钥交换,前提是 RP 在有状态模式下运行。 如果处于无状态模式,则在每次身份验证后,你将看到一条从 RP 到 OP 的消息,以验证断言的签名。
关于您对#5(对声明标识符的HTTP HEAD请求(的问题,这是DotNetOpenAuth RP检查OP对于它所断言的身份是否具有权威性。 由于它之前已拉取此 URL,因此缓存会启动并避免内容传输。
感觉很愚蠢,我错过了一些基本的东西——RP 和 OP 之间有一个密钥交换,但它只发生一次,然后密钥在两端缓存一段时间。
所以我的OpenID提供程序的实现被证明是安全的:)