【问题标题】:Validate Google id token with C#使用 C# 验证 Google id 令牌
【发布时间】:2017-05-23 17:31:03
【问题描述】:

我目前正在创建一个用户可以通过其 Google 帐户登录的网络应用程序。这适用于客户端,但我也想保护 REST API 调用。为此,我通过“授权”标头随每个请求发送“Google id 令牌”。现在,我想在 C# 中验证传递的令牌是否有效。我发现有一个 .NET 库可以这样做,但我没有找到任何关于如何简单地验证令牌的明确文档。

谁有这方面的指点?

【问题讨论】:

    标签: c# google-api


    【解决方案1】:

    我的答案与上面的答案相同,但细节更多。

    using Google.Apis.Auth;
    using Google.Apis.Auth.OAuth2;
    
    GoogleJsonWebSignature.Payload payload = await GoogleJsonWebSignature.ValidateAsync(Token);
    ...
    

    有效负载对象包含您需要的所有信息。

    【讨论】:

    【解决方案2】:

    为了将来参考,Google.Apis.Auth 库会在内部检查以下验证,不需要额外的验证(通过设置或检查负载):

    • 错误的 jwt(空、空、太长、缺少签名)
    • 算法错误
    • 签名无效
    • 发行者无效
    • 签名时间无公差

    但是,以下内容需要开发人员输入才能进行验证。它们可以通过 GoogleJsonWebSignature.ValidationSettings 传递:

    • 观众
    • 托管域
    • 带有容差的签名时间

    来源:Google.Apis.Auth.Tests/GoogleJsonWebSignatureTests.cs

    According to the docs,必须通过使用 Google 的公钥验证签名来验证令牌。还要检查 aus、iss 和 exp 声明,以及 hd 声明(如果适用)。 因此只有 aus(和 hd)必须由开发人员明确测试。

    try
    {
       //...
       var validationSettings = new GoogleJsonWebSignature.ValidationSettings
       {
          Audience = new string[] { "[google-signin-client_id].apps.googleusercontent.com" }
       };
    
       var payload = await GoogleJsonWebSignature.ValidateAsync(idToken, validationSettings);
       //...
    }
    catch (InvalidJwtException ex)
    {
       //...
    }
    

    【讨论】:

      【解决方案3】:

      根据"Verify the integrity of the ID token" documentation,必须检查多项内容,才能使 id 令牌有效,而不仅仅是签名。

      其中之一是“ID 令牌是否等于 [...] 您应用的客户端 ID”。由于我们从未将客户端 ID 提供给 GoogleJsonWebSignature.ValidateAsync(token),因此我们似乎需要手动检查它。我假设它实际上只是检查签名,我们需要手动进行所有其他检查。

      我的第一次尝试:

      bool valid = true;
      try
      {
          GoogleJsonWebSignature.Payload payload = await GoogleJsonWebSignature.ValidateAsync(Token);
          if (!payload.Audience.Equals("YOUR_CLIENT_ID_1234567890.apps.googleusercontent.com"))
              valid = false;
          if (!payload.Issuer.Equals("accounts.google.com") && !payload.Issuer.Equals("https://accounts.google.com"))
              valid = false;
          if (payload.ExpirationTimeSeconds == null)            
              valid = false;            
          else
          {
              DateTime now = DateTime.Now.ToUniversalTime();
              DateTime expiration = DateTimeOffset.FromUnixTimeSeconds((long)payload.ExpirationTimeSeconds).DateTime;
              if (now > expiration)
              {
                  valid = false;
              }
          }
      }
      catch (InvalidJwtException e)
      {
          valid = false;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-12-27
        • 1970-01-01
        • 1970-01-01
        • 2020-07-25
        • 2015-06-27
        • 2019-06-28
        • 1970-01-01
        相关资源
        最近更新 更多