Firebase .NET令牌验证

nol*_*int 7 c# jwt firebase firebase-authentication

处理使用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,因此我们使用第三方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文档实际上没有为此提供任何解释,我们正在使用的库的文档也没有.因此,当我们给出的所有内容都是公钥时,我们甚至无法获得关于如何验证令牌是否由私钥签名的基本想法.

验证令牌是否由正确的私钥实际签名的最佳方法是什么?

Joã*_*elo 7

您应该能够通过执行以下操作来完成令牌验证,该操作利用System.IdentityModel.Tokens.JwtNuget包执行大多数验证:

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)));
  }
}
Run Code Online (Sandbox Code Playgroud)

示例程序的使用声明列表:

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;
Run Code Online (Sandbox Code Playgroud)


Suy*_*Won 6

现在我们可以使用适用于 .NET 的 Firebase Admin SDK。

https://github.com/Firebase/firebase-admin-dotnet

var decoded = await FirebaseAuth.DefaultInstance.VerifyIdTokenAsync(idToken);
var uid = decoded.Uid;
Run Code Online (Sandbox Code Playgroud)