如何在Forms身份验证中使用OAuth

时间:2014-05-21 21:54:12

标签: authentication oauth oauth-2.0 twitter-oauth facebook-oauth

将表单身份验证与OAuth身份验证相结合有哪些解决方案?

使用案例:

有一个网站,用户可以使用用户名密码进行登录,并且在他获得身份验证后,将提供一个令牌,从而可以访问该网站中的不同资源。应用程序一段时间。

现在产品负责人想要Facebook / Twitter / ...认证

可行的解决方案:

solution 1- AssServer tries to validate the Facebook ticket

edit sequence diagram

2 个答案:

答案 0 :(得分:11)

我们实际上是在我们的项目上做这件事。解决方案非常简单。这是主要观点

  • 请注意,OAuth规范建议不要在客户端上存储oauth bearer token。
  • 确保是向oauth提供商发出身份验证请求的应用服务器。不要在客户端进行此操作(授权步骤除外,因为您实际上没有选择权。)
  • 利用框架。让会员提供商处理身份验证票证。
  • 创建自定义成员资格提供程序,让它与第三方提供商一起管理身份验证过程。
  • 验证成功后,将令牌存储在会话中或具有用户身份的声明中。换句话说,保持服务器上的访问和刷新令牌。
  • 允许框架像通常那样
  • 生成身份验证票证
  • 在身份验证票证和会话cookie之间,您可以从会话/声明中检索访问令牌以进行资源请求。
  • 当关联第三方登录时,您显然必须使用访问令牌与提供商进行通话,以获取某些信息,例如Facebook用户ID。用它来链接你的内部用户和facebook用户。

需要考虑的其他事项:

  • 确保在退出时销毁会话。几个框架将清空cookie值,但会回收会话ID。确保会话ID不被回收。
  • 对任何需要会话信息的请求使用防伪令牌。这有助于确保会话cookie未被劫持。

现在,我认为这是一个重点:通常,对于像facebook和twitter这样的提供商,您使用授权流程,这意味着您必须使用他们的表单进行登录。他们处理它,而不是你。有一个用户名/密码"选项" (grant_type:密码)与OAuth 2.0,但我不知道这些提供商是否允许它,因为该流程不要求应用程序识别自己。

我觉得你差不多了。授权授权流程将是这样的: enter image description here

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

如果您仅仅使用它进行身份验证,那么您将无法使用该特定访问令牌向其资源服务器发出请求。我需要更多地了解您的架构。但是,通常,如果您有一个处理角色和身份的内部身份提供程序,您可以考虑使用联合身份提供程序,它可以将第三方令牌转换为您的内部格式,并将其与第三方令牌一起存储。这样,如果需要,您仍然可以向第三方发出请求,如果有意义的话,仍然需要在内部移动。如果这甚至是一个问题,请告诉我,我也会解释这条腿。

答案 1 :(得分:1)

表单身份验证通常会将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);

使用以下定义的GetFormsAuthCookie方法:

  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;
  }
相关问题