上下文:
我正在使用Firebase Admin SDK的Node Cloud Function来创建自定义令牌(在本地测试时通过模拟器)。该令牌被发送到React应用程序,在那里它被消费并转换为IdToken。然后,该令牌被尝试用作GolangREST服务器的auth令牌,我尝试使用Firebase Admin SDK对其进行验证
问题:
出于一些超出我推理的奇怪原因,每当我试图通过本地认证仿真器在本地仿真云函数中生成自定义firebase令牌时,"alg"
的头似乎总是"none"
。在部署该函数时,情况并非如此。
令牌生成示例代码:admin.auth().createCustomToken(request.body.username...
下面的屏幕截图表示TokenId的解码内容(当您使用生成的令牌登录并从获得的用户调用.getIdToken()
时会获得它)
这个特定的ID Token在有效载荷中缺少“kid”报头,使得它对Golang Admin SDK中的VerifyIDTokenAndCheckRevoked()
毫无用处(已经尝试过)。
并且也将使用自定义JWT验证器无效,因为“alg”是none
,并且默认情况下它是不允许的。(表示错误:token is unverifiable: 'none' signature type is not allowed
)以下代码表示自定义验证器:
func (s *authService) VerifyToken(ctx context.Context, token string) (*CustomClaims, error) {
var customClaims *CustomClaims
parsedToken, err := jwt.Parse(token, func(token *jwt.Token) (interface{}, error) {
// It doesn't work even with this validation commented...
if val, ok := token.Method.(*jwt.SigningMethodRSA); !ok {
return nil, fmt.Errorf("> Wrong signing method: %v", token.Method.Alg())
} else {
if val.Alg() != "RS256" {
return nil, fmt.Errorf("> Unexpected signing method: %v", val.Alg())
}
}
// In order to be able to decode the token manually, we need to give the private key to the Parse function
hmacSecret := []byte(os.Getenv("FIREBASE_CREDENTIALS_PRIVATE_KEY"))
return hmacSecret, nil
})
if err != nil {
if errors.Is(err, jwt.ErrTokenMalformed) {
return nil, fmt.Errorf("> Malformed authentication: %s", err.Error())
} else if errors.Is(err, jwt.ErrTokenExpired) || errors.Is(err, jwt.ErrTokenNotValidYet) {
return nil, fmt.Errorf("> Expired authentication token: %s", err.Error())
} else {
return nil, fmt.Errorf("> Something is wrong with the authentication: %s", err.Error())
}
}
if claims, ok := parsedToken.Claims.(jwt.MapClaims); ok && parsedToken.Valid {
byteClaims, err := json.Marshal(claims)
if err != nil {
return nil, err
}
err = json.Unmarshal(byteClaims, customClaims)
if err != nil {
return nil, err
}
return customClaims, nil
}
return nil, fmt.Errorf("> Something is wrong with the authentication claims")
/* Deprecated method due to custom token verification issue (no kid header) with Admin SDK*/
// client, err := s.app.Auth(ctx)
// if err != nil {
// return nil, err
// }
// authToken, err := client.VerifyIDTokenAndCheckRevoked(ctx, token)
// if err != nil {
// return nil, err
// }
}
是否有解决此阻塞的方法?
也许允许模拟器用正确的“alg”头来签署令牌,或者跳过自定义JWT验证器中的“alg”验证?
我看到过另一个类似的问题,但它没有解决方案:Firebase createCustomToken() returns an invalid token in local emulators
更新:
尝试创建自己的JWT令牌生成实现,但没有成功。看起来我能够生成一个完全工作的令牌,但是每当我想获取IdToken(firebase真正认证的令牌)时,它会被转换为一个非工作令牌,其中包含“alg”:“none”。
例如,我已经确定我在我这边做的一切都是正确的,但是Firebase IdToken生成器是导致问题的原因。
1条答案
按热度按时间gojuced71#
Firebase Auth Emulator不签署JWT令牌,这是设计使然。
参见: www.example.com
出于安全原因,身份验证模拟器会发出未签名的ID令牌,这些令牌仅被其他Firebase模拟器或Firebase Admin SDK(配置后)接受。
但您可以使用Admin SDK创建和验证令牌。
要使其与Admin SDK一起工作,您必须将模拟器主机的环境变量设置为模拟器url:
如果您从不同的主机/服务器使用Admin SDK模拟器,则必须在两端设置此变量以指向您的模拟器主机。