.NET中的Firebase自定义身份验证提供了#34;自定义令牌格式不正确"

时间:2016-10-10 18:06:00

标签: asp.net-web-api firebase firebase-authentication

我们正在尝试设置自定义身份验证,以便Android应用程序可以利用我们现有的Auth系统来访问Firebase数据库。

移动应用程序针对.NET WebAPI端点进行身份验证。我们会在响应中发送一个firebase身份验证令牌,然后该应用可用于在Firebase SDK中进行身份验证。

根据文档,我们认为这很简单。使用Nuget的FirebaseTokenGenerator软件包,我们会从Firebase控制台中的密码生成此令牌>项目>管理>数据库>数据库秘密。

但是,当我们使用此处生成的令牌时,我们会看到此异常从Android SDK返回:

com.google.firebase.auth.FirebaseAuthInvalidCredentialsException: The custom token format is incorrect. Please check the documentation.
at com.google.android.gms.internal.zzafd.zzes(Unknown Source)
at com.google.android.gms.internal.zzafa$zzg.zza(Unknown Source)
at com.google.android.gms.internal.zzafl.zzet(Unknown Source)
at com.google.android.gms.internal.zzafl$zza.onFailure(Unknown Source)
at com.google.android.gms.internal.zzafg$zza.onTransact(Unknown Source)

查看文档让我更加困惑,因为不清楚问题可能是什么。似乎有很多候选解决方案,但我无法弄清楚哪个是正确的。以下是文档中讨论的一些内容:

  • 创建服务帐户,下载JWT json文件,包括.NET WebApi项目中的文件以及如何将其与FirebaseTokenGenerator一起使用
  • 使用第三方JWT库从秘密生成令牌

这两种策略似乎都是相同的,但似乎并没有任何关联。

我使用了错误的秘密吗?我是否需要在我的WebAPI项目上进行更多设置才能生成正确的令牌?

作为参考,这是生成我的令牌的方法:

public string GetSignedFirebaseAuthToken(Agent agent, DateTime expires)
{
    var tokenGenerator = new Firebase.TokenGenerator(BusinessLogicResources.FirebaseSecret);
    var authPayload = new Dictionary<string, object>()
    {
        { "uid", agent.AgentId.ToString() },
        { "UserName", agent.FullName },
        { "AgencyId", agent.AgencyId },
        { "AgencyName", agent.AgencyName }
    };
    return tokenGenerator.CreateToken(authPayload, new Firebase.TokenOptions(expires:expires));
}

更新 这是我用来构建我的firebase令牌的新代码。

public string GetSignedFirebaseAuthToken(Agent agent, DateTime expires)
    {
        // I set the expiry time to 3600 because this is the maximum number of seconds
        // allowed according the the Firebase documenation.
        var expiryTime = 3600;
        // This claims object contains some additional information that Telenotes would
        // like to track for each user of Firebase. This is used for reporting and
        // security rules in Firebase.
        var claims = new Dictionary<string, object>()
        {
            { "UserName", agent.FullName },
            { "AgencyId", agent.AgencyId.ToString() },
            { "AgencyName", agent.AgencyName }
        };
        // In order for the cryptography algorithms to be happy, I need to put our
        // keys into stream objects.
        var memoryStream = new MemoryStream();
        var streamWriter = new StreamWriter(memoryStream);
        streamWriter.Write(BusinessLogicResources.FirebaseSecret.Replace(@"\n", "\n"));
        streamWriter.Flush();
        memoryStream.Position = 0;
        var streamReader = new StreamReader(memoryStream);
        // BouncyCastle takes care of the cryptography stuff, so we'll hand our
        // secret over to BouncyCastle to read and encode.
        var bouncyCastleReader = new PemReader(streamReader);
        var rsaParams = (RsaPrivateCrtKeyParameters) bouncyCastleReader.ReadObject();
        // Now that the secret is packed up all nicely in rsaParams, I need to
        // put together the rest of the payload that Firebase needs in my auth token.
        var tokenPayload = new Dictionary<string, object>()
        {
            { "claims", claims },
            { "uid", agent.AgentId },
            { "iat", (DateTime.Now).SecondsSinceEpoch() },
            { "exp", (DateTime.Now).AddSeconds(expiryTime).SecondsSinceEpoch() },
            { "aud", BusinessLogicResources.FirebasePayloadAud },
            { "iss", BusinessLogicResources.FirebasePayloadISS },
            { "sub", BusinessLogicResources.FirebasePayloadSUB },
            { "alg", "RS256" }
        };

        // Lastly, we need to put it all together using JOSE JWT (see https://github.com/dvsekhvalnov/jose-jwt)
        // and BouncyCastle encoding magic.
        var rsaKey = DotNetUtilities.ToRSA(rsaParams);
        return JWT.Encode(tokenPayload, rsaKey, JwsAlgorithm.RS256);
    }

1 个答案:

答案 0 :(得分:1)

要理解的几个关键事项:

问题#1

我使用FirebaseTokenGenerator 2.0.0作为我项目的一部分。如果您查看the GitHub project,则会明确指出此程序包与Firebase 3.x.x不兼容。

因此,如果您尝试在.NET中使用现有的auth系统,则需要使用第三方将Firebase令牌放在一起。如何执行此操作的一个很好的示例可以在this post找到。

如果您不关心BouncyCastle或JOSE JWT(可帮助您根据Firebase密钥编码令牌的库),您可以查看Google提供的规范here,并找到另一种方法来实现这一切为你的系统工作。

问题#2

在上述过程中使用的正确令牌不是您的数据库密钥。 Firebase团队希望您使用服务帐户设置服务器。有关如何完成此操作的详细信息,请参见here

从这个过程中,您应该获得一个JSON文档(作为文件下载)。在此JSON文档中,您将找到名为“private_key_id”的属性。即使它看起来有点时髦("-----BEGIN PRIVATE KEY-----\n..."),但在上面提到的密钥生成过程中需要完整的东西。所以不需要任何字符串解析或类似的东西。您还需要该文档中的其他值,但这些详细信息将在已提供的链接中列出。

听起来事情不会永远存在,并且在接下来的几个月左右会出现一个很好的图书馆,以使这个过程更加直接。

相关问题