【发布时间】:2017-05-23 17:31:03
【问题描述】:
我目前正在创建一个用户可以通过其 Google 帐户登录的网络应用程序。这适用于客户端,但我也想保护 REST API 调用。为此,我通过“授权”标头随每个请求发送“Google id 令牌”。现在,我想在 C# 中验证传递的令牌是否有效。我发现有一个 .NET 库可以这样做,但我没有找到任何关于如何简单地验证令牌的明确文档。
谁有这方面的指点?
【问题讨论】:
标签: c# google-api
我目前正在创建一个用户可以通过其 Google 帐户登录的网络应用程序。这适用于客户端,但我也想保护 REST API 调用。为此,我通过“授权”标头随每个请求发送“Google id 令牌”。现在,我想在 C# 中验证传递的令牌是否有效。我发现有一个 .NET 库可以这样做,但我没有找到任何关于如何简单地验证令牌的明确文档。
谁有这方面的指点?
【问题讨论】:
标签: c# google-api
我的答案与上面的答案相同,但细节更多。
using Google.Apis.Auth;
using Google.Apis.Auth.OAuth2;
GoogleJsonWebSignature.Payload payload = await GoogleJsonWebSignature.ValidateAsync(Token);
...
有效负载对象包含您需要的所有信息。
【讨论】:
为了将来参考,Google.Apis.Auth 库会在内部检查以下验证,不需要额外的验证(通过设置或检查负载):
但是,以下内容需要开发人员输入才能进行验证。它们可以通过 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)
{
//...
}
【讨论】:
根据"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;
}
【讨论】: