【问题标题】:Crossplatform multiclient oauth2 API design跨平台多客户端 oauth2 API 设计
【发布时间】:2016-09-19 10:18:52
【问题描述】:

我正在使用 ASP.NET Web API 2 构建 RESTfull 后端。 FTM 我有三个客户端:AngularJs Web 应用程序、Android 和 iPhone 应用程序。

我需要通过 Google 和 Facebook 为他们所有人建立登录,并且需要您的帮助来设计它。

我的想法如下(以谷歌身份验证为例):

  1. 在 Google Developer Console 中,我创建 4“OAuth 2.0 客户端 ID”:

    • 对于 AngularJS 应用程序(类型 Web 应用程序,具有允许的来源)
    • 适用于 Android(Android 类型)
    • 对于 IO(类型 IO)
    • 用于 WEB API 后端(类型 Web 应用程序没有任何允许的来源)
  2. 每个客户都将与 Google 联系并提供其自己的库/api,以授权并请求用户同意所需的范围以及离线使用。以便 client 从 Google 接收到 authorization_code。

  3. 每个客户端都会调用web后端的GET方法ExternalLogin并发送authorization_code作为输入参数。

  4. Web 后端将(通过 Google API)将重新授权码交换到 access_token 并从 Google(通过 Google API)接收所有需要的用户信息。如果用户已经注册,请检查数据库(如果没有 - 应用程序将创建一个帐户),然后发出 本地访问令牌,该令牌应该用于对 Web 后端的所有进一步调用。

好处很简单:

  • 简单的流程,每个客户端都一样
  • 为每个客户端登录/注册的单一方法
  • 收集用户数据的逻辑在一个地方(Web 后端) - 所以如果我们需要从用户那里收集额外的数据,我们只需要在后端进行更改。 客户只需将范围添加到同意屏幕。

我的问题是:

  • 以下流程是否正确且足够稳定?它也适用于 Facebook 身份验证吗?
  • FTM 我被困在第 4 步。AngularJs 获得了带有其 ClientId 的授权代码。 Web 后端正在尝试将此授权代码交换为 access_token 与另一个 ClientId(Web 后端在 Google 开发人员控制台中有自己的 ClientId,请阅读上文)我收到一个错误:未授权客户端。奇怪,导致谷歌开发者控制台中同一个“项目”中的所有 ClientID。有没有办法让它发挥作用?

【问题讨论】:

  • 注意:使用来自您的 AngualrJS 应用程序的客户端 ID 进行身份验证的用户将无法通过 Android 访问。客户端 id、秘密、刷新令牌是他们不混合的一组。
  • @DaImTo 感谢您的评论。我需要用户通过 Android/AngularJS/IOS ClientId 进行身份验证,然后将 authentication_code 传递给后端,并可以使用 Web-Backend ClientId 访问用户数据并传递 authentication_code。你觉得这行不通?
  • 使用 Web 凭据创建的刷新令牌将无法使用移动应用程序的凭据进行刷新。如果您使用 Android/AngularJS/IOS 请求访问用户,则需要使用 Android/AngularJS/IOS 凭据来获取访问权限。你不能仅仅因为它们是在同一个项目下创建的就混合它们。
  • @z0omie 但是为什么你认为你应该独立注册 4 个应用程序呢?我不知道移动应用程序,但是您不能将 OAuth 集成到您的 WebAPI 后端并让它处理所有与令牌相关的部分。在您的所有客户端上,您将直接访问您为 OAuth 创建的 API 端点。通过这样做,您的最终用户不必授权您的所有应用程序,这也将改善用户体验。例如 - dzone.com/articles/…

标签: oauth-2.0 asp.net-web-api2 cross-platform google-oauth


【解决方案1】:

流程几乎没有问题,除了一个例外:您需要为实际的客户端应用程序设置客户端 ID(因此是 Authorized JavaScript origins),而不是后端。

Facebook 至少在后端几乎相同(只是用于验证的库不同),抽象出通用提供程序接口应该没有问题。

至于验证server side 上 ID 令牌的完整性 - 在 Google 的端点上执行 GET 以验证此令牌,让他们担心验证算法: https://www.googleapis.com/oauth2/v3/tokeninfo?id_token={0}

这可能是这样的:

private const string GoogleApiTokenInfoUrl = "https://www.googleapis.com/oauth2/v3/tokeninfo?id_token={0}";

public ProviderUserDetails GetUserDetails(string providerToken)
{
    var httpClient = new MonitoredHttpClient();
    var requestUri = new Uri(string.Format(GoogleApiTokenInfoUrl, providerToken));

    HttpResponseMessage httpResponseMessage;
    try
    {
        httpResponseMessage = httpClient.GetAsync(requestUri).Result;
    }
    catch (Exception ex)
    {
        return null;
    }

    if (httpResponseMessage.StatusCode != HttpStatusCode.OK)
    {
        return null;
    }

    var response = httpResponseMessage.Content.ReadAsStringAsync().Result;
    var googleApiTokenInfo = JsonConvert.DeserializeObject<GoogleApiTokenInfo>(response);

    if (!SupportedClientsIds.Contains(googleApiTokenInfo.aud))
    {
        Log.WarnFormat("Google API Token Info aud field ({0}) not containing the required client id", googleApiTokenInfo.aud);
        return null;
    }

    return new ProviderUserDetails
    {
        Email = googleApiTokenInfo.email,
        FirstName = googleApiTokenInfo.given_name,
        LastName = googleApiTokenInfo.family_name,
        Locale = googleApiTokenInfo.locale,
        Name = googleApiTokenInfo.name,
        ProviderUserId = googleApiTokenInfo.sub
    };
}

【讨论】:

    【解决方案2】:

    您应该查看Firebase Auth(从Google Identity Toolkit 重命名)。这将使您非常轻松,您所要做的就是在后端接受一个令牌。

    请注意,您不需要使用 Firebase 数据库来使用 Firebase 身份验证。

    【讨论】:

      猜你喜欢
      • 2010-11-27
      • 1970-01-01
      • 2017-08-02
      • 2017-08-12
      • 1970-01-01
      • 2017-08-11
      • 1970-01-01
      • 2017-02-09
      • 2016-07-30
      相关资源
      最近更新 更多