Firebase 3:使用 .net 和 c# 创建自定义身份验证令牌 [英] Firebase 3: creating a custom authentication token using .net and c#

查看:22
本文介绍了Firebase 3:使用 .net 和 c# 创建自定义身份验证令牌的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to implement Firebase 3 Authentication mechanism using Custom Tokens (as described at https:// firebase.google.com/docs/auth/server/create-custom-tokens).

我的服务器是 ASP.NET MVC 应用程序.

My server is ASP.NET MVC Application.

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

So according to the instructions (https://firebase.google.com/docs/server/setup) I've created a service account for my Firebase application and generated a key in '.p12' format.

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

After that according to instructions here (https://firebase.google.com/docs/auth/server/create-custom-tokens#create_custom_tokens_using_a_third-party_jwt_library) I tried to generate a custom token and sign it using the key received on the previous step. For token generation I used SystemIdentityModel.Tokens.Jwt library from Microsoft, so the code looks like the following:

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

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

Then tried to sign in user in React Native application using Firebase Javascript SDK, with the following code:

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

但从 Firebase 收到一条错误消息:

But got an error from Firebase saying:

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

Error authenticating Firebase user. Code: auth/invalid-custom-token Message: The custom token format is incorrect. Please check the documentation.

尝试为令牌过期控制添加不同的声明也无济于事.

Experimenting with adding different claims for token expiration control didn't help either.

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

Also I tried to generate tokens with "dvsekhvalnov/jose-jwt" library but can't get it working with "RS256" algorithm.

所以问题:

对我做错了什么有什么建议吗?

推荐答案

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

This pure .NET solution works for me, using the Org.BouncyCastle (https://www.nuget.org/packages/BouncyCastle/) and Jose.JWT (https://www.nuget.org/packages/jose-jwt/) libraries.

我按照以下步骤操作:

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

  • In the Firebase console click the 'cog' icon which is top left, next to the project name, and click 'Permissions'.
  • At the IAM and Admin page, click 'Service Accounts' on the left
  • Click 'Create Service Account' at the top, enter a 'Service Account Name', select 'Project->Editor' in the Role selection, tick the 'Furnish a new private key' checkbox and select JSON
  • Click 'Create' and download the Service Account JSON file and keep it safe.
  • Open the Service Account JSON file in a suitable text editor and put the values into the following code:

// private_key from the Service Account JSON file
public static string firebasePrivateKey=@"-----BEGIN PRIVATE KEY-----
MIIE...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
-----END PRIVATE KEY-----
";

// 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(@"
","
")));
                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;
}

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

To get this working in IIS I needed to change the application's pool identity and set the "load user profile" setting to true.

这篇关于Firebase 3:使用 .net 和 c# 创建自定义身份验证令牌的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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