Authentication 如何将OAuth与Forms auth一起使用

Authentication 如何将OAuth与Forms auth一起使用,authentication,oauth,oauth-2.0,twitter-oauth,facebook-oauth,Authentication,Oauth,Oauth 2.0,Twitter Oauth,Facebook Oauth,有什么解决方案可以将表单身份验证与OAuth身份验证相结合 用例: 有一个网站,用户将使用用户名和密码登录,并在其验证后提供令牌,从而在一段时间内访问应用程序中的不同资源 现在产品所有者想要的是Facebook/Twitter/。。。Auth 可行的解决方案: Forms auth通常会将cookie发送给经过身份验证的用户,因此您可以执行相同的操作,并发送与Forms auth发送的cookie完全相同的cookie 因此,在从提供程序成功完成OAuth回调后,您可以执行如下操作: //

有什么解决方案可以将表单身份验证与OAuth身份验证相结合

用例: 有一个网站,用户将使用用户名和密码登录,并在其验证后提供令牌,从而在一段时间内访问应用程序中的不同资源

现在产品所有者想要的是Facebook/Twitter/。。。Auth

可行的解决方案:


Forms auth通常会将cookie发送给经过身份验证的用户,因此您可以执行相同的操作,并发送与Forms auth发送的cookie完全相同的cookie

因此,在从提供程序成功完成OAuth回调后,您可以执行如下操作:

  // here, we are called on a successful OAuth auth, so 
  // let's do Forms login by ourselves
  HttpCookie authCookie = GetFormsAuthCookie(email, true, true);
  context.Response.Cookies.Add(authCookie);
  private static HttpCookie GetAuthCookie(string userName, bool createPersistentCookie, bool httpOnly)
  {
      FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(2, userName, DateTime.Now, DateTime.Now.Add(FormsAuthentication.Timeout), createPersistentCookie, "SocialEmailLogin", FormsAuthentication.FormsCookiePath);
      string encryptedTicket = FormsAuthentication.Encrypt(ticket);
      if (encryptedTicket == null)
          throw new Exception("Obviously, something went wrong here. That shouldn't happen.");

      HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
      cookie.HttpOnly = httpOnly;
      cookie.Path = FormsAuthentication.FormsCookiePath;

      if (FormsAuthentication.RequireSSL)
      {
          cookie.Secure = true;
      }

      if (FormsAuthentication.CookieDomain != null)
      {
          cookie.Domain = FormsAuthentication.CookieDomain;
      }

      if (ticket.IsPersistent)
      {
          cookie.Expires = ticket.Expiration;
      }
      return cookie;
  }
使用如下定义的GetFormsAuthCookie方法:

  // here, we are called on a successful OAuth auth, so 
  // let's do Forms login by ourselves
  HttpCookie authCookie = GetFormsAuthCookie(email, true, true);
  context.Response.Cookies.Add(authCookie);
  private static HttpCookie GetAuthCookie(string userName, bool createPersistentCookie, bool httpOnly)
  {
      FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(2, userName, DateTime.Now, DateTime.Now.Add(FormsAuthentication.Timeout), createPersistentCookie, "SocialEmailLogin", FormsAuthentication.FormsCookiePath);
      string encryptedTicket = FormsAuthentication.Encrypt(ticket);
      if (encryptedTicket == null)
          throw new Exception("Obviously, something went wrong here. That shouldn't happen.");

      HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
      cookie.HttpOnly = httpOnly;
      cookie.Path = FormsAuthentication.FormsCookiePath;

      if (FormsAuthentication.RequireSSL)
      {
          cookie.Secure = true;
      }

      if (FormsAuthentication.CookieDomain != null)
      {
          cookie.Domain = FormsAuthentication.CookieDomain;
      }

      if (ticket.IsPersistent)
      {
          cookie.Expires = ticket.Expiration;
      }
      return cookie;
  }

我们实际上是在我们的项目上做这件事的。解决办法非常简单。以下是要点

  • 请记住,OAuth规范建议不要在客户机上存储OAuth承载令牌
  • 确保是应用服务器向oauth提供程序发出身份验证请求。不要从客户端执行此操作(授权步骤除外,因为您实际上没有选择权)
  • 利用框架。让成员资格提供者处理身份验证票证
  • 创建您的自定义成员资格提供商,并让它与您的第三方提供商一起管理身份验证过程
  • 一旦身份验证成功,将令牌存储在会话中或具有用户标识的声明中。换句话说,在服务器上保留访问和刷新令牌
  • 允许框架像通常一样生成身份验证票证
  • 在身份验证票证和会话cookie之间,您可以从会话/声明中检索访问令牌以进行资源请求
  • 当关联第三方登录时,您显然必须使用访问令牌打电话给提供商,以获取一些信息,如facebook用户id。使用该信息将您的内部用户与facebook用户链接
其他需要考虑的事项:

  • 确保在注销时销毁会话。几个框架将清空cookie值,但会回收会话id。请确保会话id未被回收
  • 在任何需要会话信息的请求中使用防伪令牌,而会话信息应该包括所有内容。这将帮助您确保会话cookie未被劫持
现在,我认为这是一个重要的观点:通常,对于facebook和twitter这样的提供商,您使用授权流,这意味着您必须使用他们的表单登录。是他们处理的,不是你。OAuth 2.0中有一个用户名/密码“选项”(grant_type:password),但我不知道这些提供者是否允许,因为该流不需要应用程序识别自己

我想你差不多明白了。授权授予流如下所示:

密码授予流程基本相同,但没有重定向和授权步骤。您只需使用自己的表单登录,并让服务器使用密码授予类型向提供者发出身份验证请求


如果您只是将其用于身份验证,那么就不会使用特定的访问令牌向其资源服务器发出请求。我需要更多地了解您的体系结构才能说得更多。但是,一般来说,如果您有一个处理角色和身份的内部身份提供者,您可以考虑一个联邦身份提供者,它可以将第三方令牌转换为内部格式,并将其与第三方令牌一起存储。这样,如果需要,您仍然可以向第三方提出请求,如果有意义,您仍然可以在内部移动所需的内容。如果这是一个问题,请让我知道,我也会解释这个问题。

我要寻找的答案可能是高水平的,与高水平的流程更相关。如果恶意请求错误地通知我OAuth提供程序对用户进行了身份验证,您如何提出保护措施?请加强您的问题。你想要什么根本不清楚。如果您正在研究如何保护oauth,您可以选择包含大量输入的标准:您是正确的,安全部分有点范围蠕变,但我的问题是“有什么解决方案可以将表单身份验证与oauth身份验证相结合?”。我看不出您的答案提供了新的解决方案,您只是为底部的部分“这是您的身份验证单APPTK1234”提供了一个实现。您是说不需要验证提供商提供的票据吗?或者验证是唯一的选择?难道没有可能在客户机/服务器上暗示不同流的解决方案吗?(注意:当我说form auth时,我指的是用户/密码,而不是.Net FormsAuthentication)另外,为了您自己的利益,我想指出,OAuth提供程序不颁发票证,而是颁发令牌;两件不同的事情。此外,用户名/密码在OAuth领域中不是“formauth”。我相信您要查找的只是密码授予类型或“资源所有者密码凭据授予”(规范第4.3节)。我认为这两件事有助于减少混乱和模棱两可,也有助于你的搜索。