【问题标题】:Google Identity Toolkit API in C#C# 中的 Google 身份工具包 API
【发布时间】:2019-12-18 15:55:56
【问题描述】:

一些背景资料

我正在使用 C# 在 Unity 中构建游戏。由于我使用的是 Firebase,而现成的 Unity Firebase SDK 在我的情况下无法工作1,因此我通过 C# 的 HttpClient 类(@987654329 附带)与 Firebase's REST API 进行交互@)。

我目前正在努力使用 Firebase 身份验证 API。对于那些不熟悉 OAuth API 的人,当我调用注册或登录端点时,我会同时获得一个 ID 令牌 和一个 刷新令牌。 ID 令牌过期;刷新令牌没有。当 ID 令牌过期时,我必须调用另一个端点,称为 Token Exchange,以使用我的刷新令牌获取新的 ID 令牌。

1 有传言称Google Identity Toolkit C# library,但我找到它的搜索返回的第一个结果导致 404 错误而不是文档。 ????

什么工作

按照Firebase guides 和底层Identity Toolkit guides,到目前为止,我已经成功地将令牌交换端点与来自bash 的cURL 命令连接起来:

curl 'https://securetoken.googleapis.com/v1/token?key=[MY FIREBASE API KEY]' \
-H 'Content-Type: application/x-www-form-urlencoded' \
--data 'grant_type=refresh_token&refresh_token=[MY REFRESH TOKEN]'

当然,我将 [MY FIREBASE API KEY] 替换为我的 Firebase Web API 密钥,并将 [MY REFRESH TOKEN] 替换为从登录/注册端点返回的刷新令牌。

然而,尽管我做了很多尝试,我还是无法在 C# 中复制这个 cURL 命令!

我的失败尝试

1.

这是我原来的无效代码。

public async Task<bool> ExchangeToken()
    {
        FormUrlEncodedContent body = new FormUrlEncodedContent(new Dictionary<string, string>() {
            {"grant_type", "refresh_token" },
            {"refresh_token", Uri.EscapeDataString(user.refreshToken) }
        });
        HttpRequestMessage message = new HttpRequestMessage(HttpMethod.Post, "https://securetoken.googleapis.com/v1/token?key=" + apiKey);
        message.Content = body;
        message.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/x-www-form-urlencoded"));
        HttpResponseMessage res = await client.SendAsync(message);
    }

不幸的是,我收到了这个401 (Unauthorized) 错误响应:

{
  "error": {
    "code": 401,
    "message": "Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.",
    "status": "UNAUTHENTICATED"
  }
}

这很奇怪,考虑到我从应该是等效的 cURL 命令得到 2XX (OK) 响应...

2.

感谢我刚刚发现的 very nice website,我能够将我的 cURL 命令“转换”为 C# 代码。然而,这并没有奏效。我得到了与尝试 #1 完全相同的错误。

public async Task<bool> ExchangeToken()
    {
        using (var request = new HttpRequestMessage(new HttpMethod("POST"), "https://securetoken.googleapis.com/v1/token?key=[I WOULD INSERT MY KEY HERE]"))
        {
            request.Content = new StringContent("grant_type=refresh_token&refresh_token=[INSERT REFRESH TOKEN HERE]", Encoding.UTF8, "application/x-www-form-urlencoded");

            var res = await client.SendAsync(request);
        }
    }

可能的线索

  1. 我对所有其他端点的所有其他请求都有效。有两个显着的区别:1) API 在技术上不是 Firebase 的,而是 Google Identity Toolkit 的。 2)这是我使用的唯一一个使用Content-Type 标头的application/x-www-form-urlencoded 而不是application/json 的端点。

我的问题/TL;DR

如何使用 C# 与 Google Identity Toolkit API 的 Token Exchange 端点交互? (虽然我目前正在使用 HttpClient 类,但我完全愿意接受其他解决方案!它们只需要与 Unity3D 兼容。)

提前致谢!

【问题讨论】:

    标签: c# firebase http oauth google-identity-toolkit


    【解决方案1】:

    Google 希望您使用 Firebase 进行身份验证。虽然 Firebase 没有 Google 提供的 .NET 客户端 SDK,但有 other options

    如果您不使用 Firebase 并自己使用 oAuth/OpenID Connect 端点执行必要的任务,那也可以。有一个Google .NET SDK 可以帮助您解决这个问题……一点点。 SDK 列出了 SDK“支持”的 Google API; Google Cloud Identity v1v1beta API 都在列表中。因此,您可以通过此 .NET SDK 调用 Google Cloud Identity 端点。您确实必须了解各种身份验证流程的含义,而在 Firebase 中,大部分机制都是从您作为应用开发人员那里抽象出来的。

    【讨论】:

    • 您好,非常感谢您的回答。事实上,我使用的 REST API 是官方支持的 Firebase 服务接口方法(请参阅 firebase.google.com/docs/reference/rest/auth)。我会看看 .NET SDK 并可能联系 firebase。
    【解决方案2】:

    在玩了一会儿代码之后,我记得我在我的HttpClient 上设置了默认授权:

    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", idToken);
    

    这包含在所有其他 API 调用中,因为它们需要使用 ID 令牌进行身份验证。但是,这似乎使令牌交换端点感到困惑;它必须1)查找授权标头,然后 2)使用消息内容中提供的刷新令牌。


    如何解决此问题

    1. 不要在HttpClient 上设置默认标头(应该为所有您的 HTTP 请求重用该标头),请执行以下操作:
    var req = new HttpRequestMessage(/* HttpMethod enum value, endpoint URL/IP */);
    req.Headers.Authorization = new AuthenticationHeaderValue("Bearer", user.idToken); //Set the authorization per-request, not globally
    var res = await client.SendAsync(req);
    
    1. 然后只需调用令牌交换端点!

    来自Firebase REST API Documentation

    您可以通过向 securetoken.googleapis.com 端点发出 HTTP POST 请求来刷新 Firebase ID 令牌。

    https://securetoken.googleapis.com/v1/token?key=[API_KEY]

    只需在正文中提供一个refresh_token 参数(以及带有值refresh_token 的强制性grant_type)。 请勿提供授权标头。


    希望这对遇到同样问题的人有所帮助!

    【讨论】:

      【解决方案3】:

      作为替代方案,您还可以使用 https://github.com/google/apis-client-generator 从发现文档生成 c# 客户端。我在生成我的时遇到了一些命名冲突,但在解决了这些冲突之后它就可以工作了。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-12-31
        • 2015-06-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多