2013-03-23 193 views
3

我正在创建一个网站.NET,它将为其用户提供特定的服务。让我们称之为service1.com。将来,将有service2.com,他们将共享数据库。我还希望通过提供Google,Facebook,Twitter +自定义注册登录(以防用户不在Google中)等方式进行用户友好认证,以便他们可以注册。我将使用DotNetOpenAuth库。所以场景与SO类似。OpenID提供商身份验证代理

现在Google存在即时问题:它提供different claimed identifier for different realm - 这意味着我不能将其用作用户的ID,但必须将电子邮件添加到图片以解析用户(like SO is doing)。

除此之外,它意味着我必须支持Facebook连接,Twitter和每个服务站点每增加登录选项。

于是我想出了OpenID的代理的想法:

  • 我创建OpenID提供商openid.service.com有自己单独的数据库
  • service1.com和service2.com是其依赖方和份额自己的数据库
  • openid.service.com可以在各种不同的方式验证用户:与openid.service.com (basic sign up like SO
    • 新帐户)
    • 的OpenID(如Gmail,雅虎,...)
    • Facebook连接
    • Twitter的
    • ...
  • 登录选项,并签署了形式将显示在iframe中每个服务的网站上(如SO注册是)
  • 一次openid.service.com通过任何选项验证用户它提供权利标识符依赖方回调

所以最终的结果会是这个样子:enter image description here

优点:

  • 服务可以使用从openid.service.com提供确定哪些用户登录声称标识符
  • 服务可以只需添加到所需的域
  • 添加更多的登录选项是微不足道的,因为openid.service.com处理它
  • 谷歌声称标识符不会改变,因为openid.service.com处理认证

缺点:

  • 认证的链较长(服务不与谷歌直接进行身份验证等)
  • ???

这是一个体面的方式来实现这样一个系统,是否还有其他缺点呢?

回答

2

是的,这是一个合理的方法来解决这个问题。其实我认为 StackOverflow做同样的事情。不使用OpenID的人们的自定义用户数据库也将在openid.service.com上,所以实际上他们也会在这种情况下使用OpenID,尽管他们不知道它。

有一点要注意的是在您的例子openid.service.com将能够断言,从谷歌和其他原声明的标识符,因为二级的RP将不会从你的中介接受的说法,因为它有对那些声称的ID没有权力。相反,你可以做的是在你的openid.service.com和你的每个辅助RP之间进行一次no-authentication OpenID。是的,OpenID实际上有一个流程,其中没有声明标识符从OP传递到仅限RP的扩展。因此,您可以使用DotNetOpenAuth FetchRequestFetchResponse分机来请求您的辅助RP和您的中央服务之间用户的实际claims_id。而辅助RP必须小心谨慎地接受来自中央RP的断言。

这里的辅助RP之间的代码的草图和您的中心之一:从openid.service.com

OpenIdRelyingParty rp; 
var request = rp.CreateRequest("https://openid.service.com/"); 
request.IsExtensionOnly = true; 
var fetchRequest = new FetchRequest(); 
fetchRequest.Attributes.AddRequired("http://openid.service.com/useridentity"); 
request.AddExtension(fetchRequest); 
request.RedirectToProvider(); 

步骤2的用户RP请求认证:openid.service

步骤1。 COM,作为OP,接收请求(作为一个OP是一个巨大的repsonsibility ......这是由所有帐户的一个非常不完整的样本。您应该参考OpenIdProvider samples that are available。)

OpenIdProvider op; 
IRequest request = op.GetRequest(); 
/// ... 
IAnonymousRequest anonRequest = request as IAnonymousRequest; 
if (anonRequest != null) { 
    // The key part for this sample snippet is that you make sure the RP asking 
    // is one of your own, since you're not following the typical OpenID flow. 
    if (!IsWhiteListedRealm(hostRequest.Realm)) { 
     anonRequest.IsApproved = false; // reject all RPs that aren't in the whitelist 
    } else { 
     // Perhaps here is where you'll start your double role as an RP 
     // to authenticate the user if there isn't already a FormsAuth cookie. 
    } 
} 

return op.PrepareResponse(request).AsActionResult() 

步骤3:辅助RP收到来自您的代理OpenID服务的响应。

OpenIdRelyingParty rp; 
var response = rp.GetResponse(); 
if (response != null) { 
    if (response.Provider.Uri.Authority != "openid.service.com") { 
     throw new Exception(); // only assertions from our own OP are trusted. 
    } 

    if (response.Status == AuthenticationStatus.ExtensionsOnly) { 
     var fetchResponse = response.GetExtension<FetchResponse>(); 
     string claimedId = fetchResponse.GetAttributeValue("http://openid.service.com/useridentity"); 
     FormsAuthentication.RedirectFromLoginPage(claimedId); 
    } 
} 

这些样品无法完成。上述内容并不适用于填补这些角色的网站的许多常规安全缓解措施。这仅仅是一个草图,概述了您的应用在特定情况下应采取的一些额外步骤。

+0

非常感谢您对我的问题和输入的检查!你的片段会非常方便! – 2013-03-24 21:36:16

+0

还有一件事情我不完全清楚 - 所以我将使用OpenID作为协议,它通过扩展将某种用户标识传递给RP。我必须为此实施全面的OP吗? (有发现机制等,就像在样本中...) – 2013-03-26 23:15:44

+1

好问题。由于你的OP永远不会声明一个声明的ID,你不需要从样本中设置user.aspx。但是您确实需要一个OP标识符,它是样本中OP主页返回的XRDS文档。 – 2013-03-27 02:26:52