簡體   English   中英

Firebase .NET 令牌驗證

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM