简体   繁体   English

Firebase 自定义身份验证错误:自定义令牌格式不正确

[英]Firebase Custom Auth Error: The custom token format is incorrect

I am generating token using JJWT library like this -我正在使用这样的 JJWT 库生成令牌 -

    final String issuer = "my-app-auth-server@my-app-797ab.iam.gserviceaccount.com";
    final String sub = "my-app-auth-server@my-app-797ab.iam.gserviceaccount.com";
    final String aud = "https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit";
    final String secret = "my-secret-key"   //only demo key , not real secret key that i am using



    final long iat = System.currentTimeMillis() / 1000L; // issued at claim
    final long exp = iat + 60L; // expires claim. In this case the token expires in 60 seconds

    final String jwtString = Jwts.builder()
                .claim("alg","HS256")
                .claim("iss", issuer)
                .claim("aud",aud)
                .claim("iat", iat)
                .claim("exp", exp)
                .claim("uid",number)
                .setSubject(sub)
                .signWith(SignatureAlgorithm.HS256, secret)
                .compact();

The secret key("my-secret-key") i am using is generated by Firebase , as stated here该密钥(“我的秘密钥匙”),我使用的是由火力地堡产生,如前所述这里

But i am getting this error when i am signing in Firebase with the token generated as above -但是当我使用如上生成的令牌登录 Firebase 时出现此错误 -

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)
                                                                         at android.os.Binder.execTransact(Binder.java:367)
                                                                         at dalvik.system.NativeStart.run(Native Method)

This is how it looks decoded -这是它的解码方式 -

在此处输入图片说明

Please help , Thanks in advance.请帮助,提前致谢。

my-secret-key is not a valid Base64 string. my-secret-key不是有效的 Base64 字符串。 Please read the JavaDoc for the signWith(SignatureAlgorithm, String) method:请阅读有关signWith(SignatureAlgorithm, String)方法的 JavaDoc:

/**
 * Signs the constructed JWT using the specified algorithm with the
 * specified key, producing a JWS.
 *
 * <p>This is a convenience method: the string argument is first
 * BASE64-decoded to a byte array and this resulting byte array is 
 * used to invoke {@link #signWith(SignatureAlgorithm, byte[])}.</p>
 *
 * @param alg the JWS algorithm to use to digitally sign the JWT, 
 *            thereby producing a JWS.
 * @param base64EncodedSecretKey the BASE64-encoded algorithm-specific 
 *        signing key to use to digitally sign the JWT.
 * @return the builder for method chaining.
 */
JwtBuilder signWith(SignatureAlgorithm alg, String base64EncodedSecretKey);

Cryptographic signatures are always computed with byte array keys - never strings.加密签名总是用字节数组键计算——而不是字符串。 You can get the UTF-8 bytes of a String, for example "my-secret-key".getBytes("UTF-8");您可以获取字符串的 UTF-8 字节,例如"my-secret-key".getBytes("UTF-8"); , but that only masks what could be a very problematic cryptographic weakness. ,但这只能掩盖可能是一个非常有问题的加密弱点。

Digital signature keys (again, byte arrays), should ideally never be based on simple strings like 'my secret' or 'my password'.数字签名密钥(再次,字节数组),理想情况下不应基于简单的字符串,如“我的秘密”或“我的密码”。 Or, at the very least, if a simple password should be used as a signing key, it is almost always better to send it through a key-derivation algorithm (like PBKDF2) and then use that resulting output as the signature key.或者,至少,如果一个简单的密码应该用作签名密钥,那么通过密钥派生算法(如 PBKDF2)发送它,然后将结果输出用作签名密钥几乎总是更好。 This ensures sufficient cryptographic entropy (randomness) that short, human-readable strings don't (and which are therefore risky).这确保了足够的密码熵(随机性),而短的、人类可读的字符串则没有(因此有风险)。

Signing keys should ideally always be:理想情况下,签名密钥应始终为:

  1. generated by a secure-random number generator or at the least created via a cryptographically secure key-derivation function and由安全随机数生成器生成或至少通过加密安全密钥派生函数创建,以及
  2. and this is important - of sufficient length for the hashing algorithm to be used.这很重要 - 对于要使用的散列算法有足够的长度。

Number 2 is why JJWT provides the MacProvider.generateKey method - to ensure you always have keys of sufficient strength for the algorithm chosen.第 2 点是 JJWT 提供MacProvider.generateKey方法的原因 - 确保您始终拥有用于所选算法的足够强度的密钥。 You can then easily base64 the result:然后,您可以轻松地对结果进行 base64:

SecretKey key = MacProvider.generateKey(SignatureAlgorithm.HS256);
String base64Encoded = TextCodec.BASE64.encode(key.getEncoded());

This is why JJWT expects Base64 by default - because if you do these best practices, you'll always end up with a byte array key (eg key.getEncoded()).这就是 JJWT 默认期望 Base64 的原因 - 因为如果您执行这些最佳实践,您将始终得到一个字节数组键(例如 key.getEncoded())。 And if you have a byte array key, the most common way to turn that into a string (eg for configuration) is to Base64-encode that byte array.如果您有一个字节数组键,将其转换为字符串(例如用于配置)的最常见方法是对该字节数组进行 Base64 编码。

Finally, note that TextCodec.BASE64.decode(myKey) does NOT produce the same byte array (key) as myKey.getBytes('UTF-8') .最后,请注意TextCodec.BASE64.decode(myKey)不会产生与myKey.getBytes('UTF-8')相同的字节数组(密钥myKey.getBytes('UTF-8') The latter is usually incorrect in cryptographic contexts.后者在加密上下文中通常是不正确的。

That means that my-secret-token-to-change-in-production.getBytes("UTF-8") might represent a weakened signing key, and as a result, shouldn't be used.这意味着 my-secret-token-to-change-in-production.getBytes("UTF-8") 可能代表弱化的签名密钥,因此不应使用。 I recommend dumping that current key and generating a new one with strong cryptographic guarantees as shown above (eg using JJWT) and ensuring your Node library base64-decodes your string correctly.我建议转储该当前密钥并生成一个具有强加密保证的新密钥,如上所示(例如使用 JJWT),并确保您的 Node 库 base64 正确解码您的字符串。

So, once you have a secure random generated byte array and Base64 that, then check the "secret base64 encoded" checkbox in the above tool, and it should work for you.所以,一旦你有一个安全的随机生成的字节数组和 Base64,然后检查上面工具中的“秘密 base64 编码”复选框,它应该适合你。

Since you are minting tokens in Java, you can make use of the official Firebase Java SDK which has token minting built-in.由于您是在 Java 中铸造令牌,因此您可以使用内置令牌铸造的官方 Firebase Java SDK。 Follow the instructions and code samples here to start creating custom tokens.按照此处的说明和代码示例开始创建自定义令牌。

I think your main problem is that you're creating a token with HS256 encryption but Firebase requires RS256, as noted here .我觉得你的主要问题是,你正在创建与HS256加密令牌,但火力地堡需要RS256,作为注意到这里 But if you use the official library, it will handle all of this for you.但是如果你使用官方库,它会为你处理所有这些。

I had a similar problem with a PHP JWT generator library and the solution was playing with the iat payload parameter.我在 PHP JWT 生成器库中遇到了类似的问题,解决方案是使用iat负载参数。 My server was some seconds in the future compared to google's one (the error message never told me that...).与谷歌的服务器相比,我的服务器在未来几秒钟内(错误消息从未告诉我......)。

I just defined the iat payload parameter 5 minutes in the past and boom, it worked.我刚刚在过去 5 分钟定义了iat有效载荷参数,然后就成功了。

Hope this will help.希望这会有所帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 自定义 Firebase 身份验证:令牌格式不正确错误 - Custom Firebase Auth: Token is not in proper format error com.google.firebase.auth.FirebaseAuthInvalidCredentialsException自定义令牌格式不正确。 请检查文档PHP-Laravel - com.google.firebase.auth.FirebaseAuthInvalidCredentialsException The custom token format is incorrect. Please check the documentation PHP-Laravel 使用JWT创建Firebase自定义身份验证令牌 - Create Firebase custom auth token using JWT Flutter:FirebaseAuth 令牌错误:自定义令牌格式不正确。 请检查文档 - Flutter: FirebaseAuth token error: The custom token format is incorrect. Please check the documentation Firebase身份验证:重新验证使用自定义令牌的用户 - Firebase Auth: Re-authenticate user who is using custom token Firebase 自定义身份验证与 Gigya - Firebase custom auth with Gigya Firebase自定义身份验证工作流程以执行自定义身份验证 - firebase custom auth workflow to do custom auth 发生内部错误 Firebase 自定义令牌身份验证 - Internal Error occurred Firebase Custom Token Authentication Firebase使用自定义令牌登录 - Firebase Sign in with custom token Firebase“请求没有身份验证令牌”错误 - Firebase “no auth token for request” Error
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM