[英]Firebase .NET Token Verification
處理一個使用 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,我們求助於使用 3rd-party 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獲取公鑰
我們已經通過文檔和 StackOverflow 進行了很長時間的挖掘,但我們找不到使用此公鑰來執行此操作的方法,如 Firebase 文檔所指定的:
最后,確保 ID 令牌由與令牌的孩子聲明對應的私鑰簽名。 從https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com 獲取公鑰並使用 JWT 庫來驗證簽名。
Firebase 文檔並沒有真正對此提供任何解釋,我們正在使用的庫的文檔也沒有提供任何解釋。 因此,當我們得到的只是公鑰時,我們甚至無法獲得關於如何驗證令牌是否由私鑰簽名的基本想法。
驗證令牌實際上是由正確的私鑰簽名的最佳方法是什么?
您應該能夠通過執行以下操作來完成令牌驗證,它利用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 語句列表:
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;
現在我們可以使用 Firebase Admin SDK for .NET。
https://github.com/Firebase/firebase-admin-dotnet
var decoded = await FirebaseAuth.DefaultInstance.VerifyIdTokenAsync(idToken);
var uid = decoded.Uid;
如果你像我一樣使用另一個 Newtonsoft.JSON 庫並且不想導入微軟的庫,試試這個: https : //gist.github.com/saltyJeff/41029c9facf3ba6159ac019c1a85711a
使用Verify(string token)
異步驗證令牌是否有效:如果有效則返回用戶的唯一標識符,如果無效則返回 null。
使用 Startup.cs 中的以下代碼片段創建一個服務,該服務在服務器收到請求時自動驗證 JWT 令牌。 使用此代碼片段后,您必須在控制器類文件中使用 [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 請求。 該值應采用承載格式。 請查看 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
Firebase 確實缺乏對 c 銳化器的支持。 我為 C# 社區創建了一個 3rd 方令牌驗證庫。 https://github.com/gtaylor44/FirebaseAuth
大部分代碼基於 João Angelo 的回答。 我在響應標頭中使用 Cache-Control["max-age"] 屬性添加了 Web 請求的緩存,如 Firebase 所述,以提高性能。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.