火力地堡3:创建一个使用.NET和C#的自定义身份验证令牌 [英] Firebase 3: creating a custom authentication token using .net and c#
问题描述
我想使用自定义标记(如在描述的https:// firebase.google.com/docs/auth/server/create-custom-tokens)实施火力地堡3认证机制。
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 )我创建了一个服务帐户为我的火力地堡应用和生成的密钥在'的.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 )我试图生成自定义的令牌,并使用在上一步中收到的密钥进行签名。对于令牌生成我用微软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);
然后试图作出反应使用火力地堡的Javascript SDK本机应用程序,用下面的代码在用户登录:
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);
});
但是,从火力地堡说法得到了一个错误:
But got an error from Firebase saying:
错误验证火力地堡用户。代码:AUTH /无效的定制令牌消息:自定义令牌格式不正确。请检查文件。
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 /何塞 - 智威汤逊库令牌,但可以得到它与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.
我按照下列步骤操作:
- 在火力地堡控制台点击齿轮图标是左上角,旁边的项目名称,点击权限。
- 在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-----\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;
}
要得到这个工作在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.
这篇关于火力地堡3:创建一个使用.NET和C#的自定义身份验证令牌的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!