Firebase .NET 令牌验证
Posted
技术标签:
【中文标题】Firebase .NET 令牌验证【英文标题】:Firebase .NET Token Verification 【发布时间】:2017-02-17 17:02:52 【问题描述】:正在处理使用 Firebase 进行一些数据存储的项目,我们的客户要求使用 C#.NET 实现服务器。我们正在服务器上设置 REST 端点,以便客户端能够出于一些目的与其通信(例如,触发只能在服务器上运行的算法)。
Firebase 建议我们通过 ID 令牌识别用户,如下所述:https://firebase.google.com/docs/auth/server/verify-id-tokens#verify_id_tokens_using_a_third-party_jwt_library
由于没有支持令牌身份验证的官方 .NET Firebase 服务器 SDK,我们采用了第 3 方 JWT 库来执行此操作:https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet
如 Firebase 文档中所述,我们首先生成一个向服务器发送令牌。检查令牌中的几个不同字段后,我们使用kid
字段从https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com 获取公钥
我们一直在研究文档和 *** 很长时间,但我们找不到使用此公钥的方法,如 Firebase 文档所述:
最后,确保 ID 令牌由与令牌的 Kid 声明对应的私钥签名。从https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com 获取公钥并使用 JWT 库来验证签名。
Firebase 文档并没有对此提供任何解释,我们正在使用的库的文档也没有提供任何解释。因此,当我们得到的只是公钥时,我们甚至无法获得关于如何验证令牌是否由私钥签名的基本概念。
验证令牌是否确实由正确的私钥签名的最佳方法是什么?
【问题讨论】:
【参考方案1】:在 Startup.cs 中使用以下代码 sn-p 创建一个服务,该服务在收到对服务器的请求时自动验证 JWT 令牌。使用此代码 sn-p 后,您必须在控制器类文件中使用 [ApiController] 上方的 [Authorize] 属性来强制程序进行身份验证,然后才能访问该特定控制器类中的操作方法。
public void ConfigureServices(IServiceCollection services)
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options =>
options.Authority = "https://securetoken.google.com/<PROJECT ID>";
options.TokenValidationParameters = new TokenValidationParameters
ValidIssuer = "https://securetoken.google.com/<PROJECT ID>",
ValidateIssuer = true,
ValidateAudience = true,
ValidAudience = "<PROJECT ID>",
ValidateLifetime = true
;
);
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
app.UseAuthentication();
编辑>你应该如何将令牌发送到服务器。
如您所见,您必须发送带有 Authorization 标头的 Post/Get 请求。该值应为 Bearer 格式。请查看 firebase 文档以了解如何从经过身份验证的用户中提取令牌 ID。
https://firebase.google.com/docs/reference/node/firebase.auth.Auth#signinwithemailandpassword https://firebase.google.com/docs/reference/node/firebase.auth#usercredential https://firebase.google.com/docs/reference/node/firebase.User#getidtoken
【讨论】:
这对你有用吗?我不断收到 401。是否需要额外的 firebase 设置? 是的,它对我有用 :) 401 是未经授权的错误,这意味着令牌未经过验证。您必须将令牌作为承载令牌发送到服务器,这意味着标头应该具有授权标签,并且值应该是承载现在我们可以使用适用于 .NET 的 Firebase Admin SDK。
https://github.com/Firebase/firebase-admin-dotnet
var decoded = await FirebaseAuth.DefaultInstance.VerifyIdTokenAsync(idToken);
var uid = decoded.Uid;
【讨论】:
更多信息firebase.googleblog.com/2018/08/…【参考方案3】:Firebase 确实缺乏对 c 锐化器的支持。我为 C# 社区创建了第 3 方令牌验证库。 https://github.com/gtaylor44/FirebaseAuth
大部分代码都基于 João Angelo 的回答。我已经使用 Cache-Control["max-age"] 属性在响应标头中添加了 Web 请求的缓存,如 Firebase 所记录的那样,以获得更好的性能。
【讨论】:
【参考方案4】:如果您像我一样使用另一个 Newtonsoft.JSON 库并且不想导入 Microsoft 库,请试试这个:https://gist.github.com/saltyJeff/41029c9facf3ba6159ac019c1a85711a
使用Verify(string token)
异步验证令牌是否有效:如果有效则返回用户的唯一标识符,如果无效则返回null。
【讨论】:
【参考方案5】:您应该能够通过执行以下操作来完成令牌验证,该操作利用System.IdentityModel.Tokens.Jwt
Nuget 包来执行大部分验证:
class Program
static HttpClient client = new HttpClient();
static void Main() RunAsync().Wait();
static async Task RunAsync()
string encodedJwt = "[TOKEN_TO_BE_VALIDATED]";
// 1. Get Google signing keys
client.BaseAddress = new Uri("https://www.googleapis.com/robot/v1/metadata/");
HttpResponseMessage response = await client.GetAsync(
"x509/securetoken@system.gserviceaccount.com");
if (!response.IsSuccessStatusCode) return;
var x509Data = await response.Content.ReadAsAsync<Dictionary<string, string>>();
SecurityKey[] keys = x509Data.Values.Select(CreateSecurityKeyFromPublicKey).ToArray();
// 2. Configure validation parameters
const string FirebaseProjectId = "[FIREBASE_PROJECT_ID]";
var parameters = new TokenValidationParameters
ValidIssuer = "https://securetoken.google.com/" + FirebaseProjectId,
ValidAudience = FirebaseProjectId,
IssuerSigningKeys = keys,
;
// 3. Use JwtSecurityTokenHandler to validate signature, issuer, audience and lifetime
var handler = new JwtSecurityTokenHandler();
SecurityToken token;
ClaimsPrincipal principal = handler.ValidateToken(encodedJwt, parameters, out token);
var jwt = (JwtSecurityToken)token;
// 4.Validate signature algorithm and other applicable valdiations
if (jwt.Header.Alg != SecurityAlgorithms.RsaSha256)
throw new SecurityTokenInvalidSignatureException(
"The token is not signed with the expected algorithm.");
static SecurityKey CreateSecurityKeyFromPublicKey(string data)
return new X509SecurityKey(new X509Certificate2(Encoding.UTF8.GetBytes(data)));
示例程序的使用语句列表:
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Net.Http;
using System.Security.Claims;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
using Microsoft.IdentityModel.Tokens;
【讨论】:
获取 SecurityTokenSIgnatureKeyNotFoundException。将深入研究这一点,感谢您的起点!如果我让它与这个解决方案一起工作,我会继续接受答案。 如果您提供的安全密钥都不匹配 JWT 声明使用的安全密钥,就会发生这种情况。如果您解码jwt.io 中的令牌,您可能会在标题中找到kid
属性。该值应与从 Google 获得的列表中返回的证书之一匹配。如果不是,则说明异常。
我已经实施了您的解决方案并遇到了同样的异常。我已经根据googleapis.com/robot/v1/metadata/x509/… 的证书检查了我的令牌的孩子,它与 4 个证书之一匹配。四个证书被加载到密钥数组中,但在验证时会抛出 SecurityTokenSIgnatureKeyNotFoundException。有什么想法吗?
请注意,为此我必须安装一个额外的 Nuget 包,否则 ReadAsAsync<>
不会被识别为有效方法。 Install-package Microsoft.AspNet.WebApi.Client
nuget.org/packages/Microsoft.AspNet.WebApi.Client
我正在寻找一种类似的方法来验证 Azure APIM 中的 firebase 令牌,使用带有 JWKS 和颁发者密钥的 validate-jwt 策略?以上是关于Firebase .NET 令牌验证的主要内容,如果未能解决你的问题,请参考以下文章
使用 apollo-client + firebase auth 刷新令牌
如何在 Flutter 应用程序中更新 Firebase 令牌并存储它?