Firebase .NET令牌验证 [英] Firebase .NET Token Verification

查看:241
本文介绍了Firebase .NET令牌验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用Firebase进行某些数据存储的项目,我们的客户端请求使用C#.NET实现服务器。我们正在服务器上设置REST端点,以便客户端能够与其进行通信(例如,触发只能在服务器上运行的算法)。



Firebase建议我们通过ID令牌来识别用户,如下所述:

由于没有官方的.NET Firebase服务器SDK支持令牌认证,所以我们使用第三方的JWT库来做到这一点: https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet



正如Firebase文档中所述,我们首先会生成sendin g给服务器一个令牌。在检查令牌中的几个不同的字段之后,我们使用 kid 字段从 https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com a>



我们一直在通过文档和StackOverflow进行长时间的挖掘,但是我们无法找到一种方法来使用这个公钥来做到这一点,由Firebase文档指定:


最后,请确保ID令牌由与令牌的kid声明相对应的私钥签名。从 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(); }

静态异步任务RunAsync(){
字符串encodedJwt =[TOKEN_TO_BE_VALIDATED];
// 1.获取Google签名密钥
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.配置验证参数
const string FirebaseProjectId =[FIREBASE_PROJECT_ID];
var parameters = new TokenValidationParameters {
ValidIssuer =https://securetoken.google.com/+ FirebaseProjectId,
ValidAudience = FirebaseProjectId,
IssuerSigningKeys = keys,
};
// 3.使用JwtSecurityTokenHandler来验证签名,颁发者,受众和生命周期
var handler = new JwtSecurityTokenHandler();
SecurityToken令牌;
ClaimsPrincipal principal = handler.ValidateToken(encodedJwt,parameters,out token);
var jwt =(JwtSecurityToken)token;
// 4.验证签名算法和其他适用的值
if(jwt.Header.Alg!= SecurityAlgorithms.RsaSha256){
抛出新SecurityTokenInvalidSignatureException(
令牌不是用期望的算法签名);


static Security CreateSecurityKeyFromPublicKey(string data){
return new X509SecurityKey(new X509Certificate2(Encoding.UTF8.GetBytes(data)));




$ b

示例程序的使用语句清单:

  using System; 
using System.Collections.Generic;
使用System.IdentityModel.Tokens.Jwt;
使用System.Linq;
使用System.Net.Http;
使用System.Security.Claims;
使用System.Security.Cryptography.X509Certificates;
使用System.Text;
使用System.Threading.Tasks;
使用Microsoft.IdentityModel.Tokens;


Working on a project that uses Firebase for some data storage, and our client requests that the server be implemented with C#.NET. We're setting up REST endpoints on the server so that the client is able to communicate with it for a few purposes (for example, triggering an algorithm to run which can only occur on the server).

Firebase recommends we identify users via an ID token, as noted here: https://firebase.google.com/docs/auth/server/verify-id-tokens#verify_id_tokens_using_a_third-party_jwt_library

Since there is no official .NET Firebase server SDK that supports token authentication, we've resorted to using a 3rd-party JWT library to do this: https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet

As specified in the Firebase documentation, we're first generating a sending a token to the server. After checking a few different fields in the token, we're using the kid field to grab the public key from https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com

We've been digging around through documentation and StackOverflow for a long time, but we can't find a way to use this public key to do this, as specified by the Firebase documentation:

Finally, ensure that the ID token was signed by the private key corresponding to the token's kid claim. Grab the public key from https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com and use a JWT library to verify the signature.

The Firebase documentation doesn't really offer any explanation for this, and neither does the documentation for the library we are using. So we've not been able to even get a basic idea as to how we could possibly verify the token was signed by a private key when all we are given is the public key.

What would be the best way to verify that the token was actually signed by the correct private key?

解决方案

You should be able to accomplish the token validation by doing something like the following, which leverages the System.IdentityModel.Tokens.Jwt Nuget package to perform most the validations:

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)));
  }
}

List of using statements for sample program:

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 .NET令牌验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆