Firebase 3:使用.net和c#创建自定义身份验证令牌

Ily*_*kin 13 c# asp.net-mvc firebase firebase-authentication

我正在尝试使用自定义令牌实施Firebase 3身份验证机制(如https:// firebase.google.com/docs/auth/server/create-custom-tokens中所述).

我的服务器是ASP.NET MVC Application.

因此,根据说明(https://firebase.google.com/docs/server/setup),我为Firebase应用程序创建了一个服务帐户,并生成了一个".p12"格式的密钥.

之后根据此处的说明(https://firebase.google.com/docs/auth/server/create-custom-tokens#create_custom_tokens_using_a_third-party_jwt_library)我尝试生成自定义令牌并使用之前收到的密钥对其进行签名步.对于令牌生成,我使用了Microsoft的SystemIdentityModel.Tokens.Jwt库,因此代码如下所示:

var now = DateTime.UtcNow;
var tokenHandler = new JwtSecurityTokenHandler();
var key = new X509AsymmetricSecurityKey(new X509Certificate2(p12path, p12pwd));
var signinCredentials = new SigningCredentials(key, "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256", "http://www.w3.org/2001/04/xmlenc#rsa-sha256");
Int32 nowInUnixTimestamp = (Int32)(now.Subtract(new DateTime(1970, 1, 1))).TotalSeconds;

var token = tokenHandler.CreateToken(
            issuer: serviceAccountEmail,
            audience: "https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit",                
            signingCredentials: signinCredentials,
            subject: new ClaimsIdentity(new Claim[]
                    {
                    new Claim("sub", serviceAccountEmail),
                    new Claim("iat", nowInUnixTimestamp.ToString()),
                    new Claim("exp", (nowInUnixTimestamp + (60*60)).ToString()),
                    new Claim("uid", uid)
                    })
            );

var tokenString = tokenHandler.WriteToken(token);
Run Code Online (Sandbox Code Playgroud)

然后尝试使用Firebase Javascript SDK在React Native应用程序中登录用户,其代码如下:

//omitting initialization code
firebase.auth().signInWithCustomToken(firebaseJWT).catch(function(error) {
            console.log('Error authenticating Firebase user. Code: ' + error.code + ' Message: ' + error.message);            
        });
Run Code Online (Sandbox Code Playgroud)

但Firebase的错误说:

验证Firebase用户时出错.代码:auth/invalid-custom-token消息:自定义标记格式不正确.请查看文档.

尝试为令牌到期控制添加不同的声明也没有帮助.

此外,我尝试使用"dvsekhvalnov/jose-jwt"库生成令牌,但无法使用"RS256"算法.

所以问题是:

关于我做错什么的任何建议?

Ell*_*eny 14

这个纯.NET解决方案适用于我,使用Org.BouncyCastle(https://www.nuget.org/packages/BouncyCastle/)和Jose.JWT(https://www.nuget.org/packages/jose-jwt /)库.

我按照以下步骤操作:

  • 在Firebase控制台中,单击项目名称旁边左上角的"cog"图标,然后单击"权限".
  • 在IAM和管理员页面,单击左侧的"服务帐户"
  • 点击顶部的"创建服务帐户",输入"服务帐户名称",在角色选择中选择"项目 - >编辑",勾选"提供新的私钥"复选框,然后选择JSON
  • 单击"创建"并下载服务帐户JSON文件并确保其安全.
  • 在合适的文本编辑器中打开服务帐户JSON文件,并将值放入以下代码中:

    // private_key from the Service Account JSON file
    public static string firebasePrivateKey=@"-----BEGIN PRIVATE KEY-----\nMIIE...\n...\n...\n...\n...\n...\n...\n...\n...\n...\n...\n...\n...\n...\n...\n...\n...\n...\n...\n...\n...\n...\n...\n...\n...\n...\n-----END PRIVATE KEY-----\n";
    
    // Same for everyone
    public static string firebasePayloadAUD="https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit";
    
    // client_email from the Service Account JSON file
    public static string firebasePayloadISS="serviceaccountname@projectname.iam.gserviceaccount.com";
    public static string firebasePayloadSUB="serviceaccountname@projectname.iam.gserviceaccount.com";
    
    // the token 'exp' - max 3600 seconds - see https://firebase.google.com/docs/auth/server/create-custom-tokens
    public static int firebaseTokenExpirySecs=3600;
    
    private static RsaPrivateCrtKeyParameters _rsaParams;
    private static object _rsaParamsLocker=new object();
    
    void Main() {
        // Example with custom claims
        var uid="myuserid";
        var claims=new Dictionary<string, object> {
            {"premium_account", true}
        };
        Console.WriteLine(EncodeToken(uid, claims));
    }
    
    public static string EncodeToken(string uid, Dictionary<string, object> claims) {
        // Get the RsaPrivateCrtKeyParameters if we haven't already determined them
        if (_rsaParams == null) {
            lock (_rsaParamsLocker) {
                if (_rsaParams == null) {
                    StreamReader sr = new StreamReader(GenerateStreamFromString(firebasePrivateKey.Replace(@"\n","\n")));
                    var pr = new Org.BouncyCastle.OpenSsl.PemReader(sr);
                    _rsaParams = (RsaPrivateCrtKeyParameters)pr.ReadObject();
                }
            }
        }
    
        var payload = new Dictionary<string, object> {
            {"claims", claims}
            ,{"uid", uid}
            ,{"iat", secondsSinceEpoch(DateTime.UtcNow)}
            ,{"exp", secondsSinceEpoch(DateTime.UtcNow.AddSeconds(firebaseTokenExpirySecs))}
            ,{"aud", firebasePayloadAUD}
            ,{"iss", firebasePayloadISS}
            ,{"sub", firebasePayloadSUB}
        };
    
        return Jose.JWT.Encode(payload, Org.BouncyCastle.Security.DotNetUtilities.ToRSA(_rsaParams), JwsAlgorithm.RS256);
    }
    
    private static long secondsSinceEpoch(DateTime dt) {
        TimeSpan t = dt - new DateTime(1970, 1, 1);
        return (long)t.TotalSeconds;
    }
    
    private static Stream GenerateStreamFromString(string s) {
        MemoryStream stream = new MemoryStream();
        StreamWriter writer = new StreamWriter(stream);
        writer.Write(s);
        writer.Flush();
        stream.Position = 0;
        return stream;
    }
    
    Run Code Online (Sandbox Code Playgroud)

为了在IIS中工作,我需要更改应用程序的池标识并将"加载用户配置文件"设置为true.