簡體   English   中英

Firebase 自定義身份驗證錯誤:自定義令牌格式不正確

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

我正在使用這樣的 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();

該密鑰(“我的秘密鑰匙”),我使用的是由火力地堡產生,如前所述這里

但是當我使用如上生成的令牌登錄 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)

這是它的解碼方式 -

在此處輸入圖片說明

請幫助,提前致謝。

my-secret-key不是有效的 Base64 字符串。 請閱讀有關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);

加密簽名總是用字節數組鍵計算——而不是字符串。 您可以獲取字符串的 UTF-8 字節,例如"my-secret-key".getBytes("UTF-8"); ,但這只能掩蓋可能是一個非常有問題的加密弱點。

數字簽名密鑰(再次,字節數組),理想情況下不應基於簡單的字符串,如“我的秘密”或“我的密碼”。 或者,至少,如果一個簡單的密碼應該用作簽名密鑰,那么通過密鑰派生算法(如 PBKDF2)發送它,然后將結果輸出用作簽名密鑰幾乎總是更好。 這確保了足夠的密碼熵(隨機性),而短的、人類可讀的字符串則沒有(因此有風險)。

理想情況下,簽名密鑰應始終為:

  1. 由安全隨機數生成器生成或至少通過加密安全密鑰派生函數創建,以及
  2. 這很重要 - 對於要使用的散列算法有足夠的長度。

第 2 點是 JJWT 提供MacProvider.generateKey方法的原因 - 確保您始終擁有用於所選算法的足夠強度的密鑰。 然后,您可以輕松地對結果進行 base64:

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

這就是 JJWT 默認期望 Base64 的原因 - 因為如果您執行這些最佳實踐,您將始終得到一個字節數組鍵(例如 key.getEncoded())。 如果您有一個字節數組鍵,將其轉換為字符串(例如用於配置)的最常見方法是對該字節數組進行 Base64 編碼。

最后,請注意TextCodec.BASE64.decode(myKey)不會產生與myKey.getBytes('UTF-8')相同的字節數組(密鑰myKey.getBytes('UTF-8') 后者在加密上下文中通常是不正確的。

這意味着 my-secret-token-to-change-in-production.getBytes("UTF-8") 可能代表弱化的簽名密鑰,因此不應使用。 我建議轉儲該當前密鑰並生成一個具有強加密保證的新密鑰,如上所示(例如使用 JJWT),並確保您的 Node 庫 base64 正確解碼您的字符串。

所以,一旦你有一個安全的隨機生成的字節數組和 Base64,然后檢查上面工具中的“秘密 base64 編碼”復選框,它應該適合你。

由於您是在 Java 中鑄造令牌,因此您可以使用內置令牌鑄造的官方 Firebase Java SDK。 按照此處的說明和代碼示例開始創建自定義令牌。

我覺得你的主要問題是,你正在創建與HS256加密令牌,但火力地堡需要RS256,作為注意到這里 但是如果你使用官方庫,它會為你處理所有這些。

我在 PHP JWT 生成器庫中遇到了類似的問題,解決方案是使用iat負載參數。 與谷歌的服務器相比,我的服務器在未來幾秒鍾內(錯誤消息從未告訴我......)。

我剛剛在過去 5 分鍾定義了iat有效載荷參數,然后就成功了。

希望這會有所幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM