Golang中Firebase Auth初始化失败问题求助
Firebase Auth初始化失败问题排查与解决
问题背景
我是Go语言新手,参考代码实现Firebase JWT令牌校验功能,运行程序时出现错误:
failed to init firebase auth 2 error initializing firebase auth (creating client): google: could not find default credentials. See https://cloud.google.com/docs/authentication/external/set-up-adc for more information
已编写的代码与配置如下:
main.go
package main import ( "log" "github.com/gin-gonic/gin" "package.com/components" "package.com/config" ) type Response struct { Message string `json:"message"` } func main() { client, err := config.InitAuth() if err != nil { log.Fatalln("failed to init firebase auth 2", err) } r := gin.Default() versioned := r.Group("/v1") versioned.Use(config.AuthJWT(client)) versioned.POST("/", func(c *gin.Context) { log.Println("created task") }) versioned.GET("/test", components.GetWorkouts) errRun := r.Run() if errRun != nil { log.Fatalln("failed to run Gin app") } }
fbauth.go
package config import ( "context" "os" firebase "firebase.google.com/go" "firebase.google.com/go/auth" "github.com/pkg/errors" "google.golang.org/api/option" ) var ( firebaseConfigFile = os.Getenv("FIREBASE_CONFIG_FILE") ) func InitAuth() (*auth.Client, error) { opt := option.WithCredentialsFile(firebaseConfigFile) app, err := firebase.NewApp(context.Background(), nil, opt) if err != nil { return nil, errors.Wrap(err, "error initializing firebase auth (create firebase app)") } client, errAuth := app.Auth(context.Background()) if errAuth != nil { return nil, errors.Wrap(errAuth, "error initializing firebase auth (creating client)") } return client, nil }
middleware.go
package config import ( "log" "net/http" "strings" "time" "firebase.google.com/go/auth" "github.com/gin-gonic/gin" "package.com/config/secrets" ) const ( authorizationHeader = "Authorization" apiKeyHeader = "X-API-Key" cronExecutedHeader = "X-Appengine-Cron" valName = "FIREBASE_ID_TOKEN" ) func AuthJWT(client *auth.Client) gin.HandlerFunc { return func(c *gin.Context) { startTime := time.Now() authHeader := c.Request.Header.Get(authorizationHeader) log.Println("authHeader", authHeader) token := strings.Replace(authHeader, "Bearer ", "", 1) idToken, err := client.VerifyIDToken(c, token) if err != nil { c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{ "code": http.StatusUnauthorized, "message": http.StatusText(http.StatusUnauthorized), }) return } log.Println("Auth time:", time.Since(startTime)) c.Set(valName, idToken) c.Next() } } func AuthAPIKey(secretId string) gin.HandlerFunc { return func(c *gin.Context) { key := c.Request.Header.Get(apiKeyHeader) secret, err := secrets.GetSecret(secretId) if err != nil { log.Println("failed to get secret") c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{ "code": http.StatusUnauthorized, "message": http.StatusText(http.StatusUnauthorized), }) return } if secret != key { log.Println("key doesnt match!") c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{ "code": http.StatusUnauthorized, "message": http.StatusText(http.StatusUnauthorized), }) return } c.Next() } } func AuthAppEngineCron() gin.HandlerFunc { return func(c *gin.Context) { cron := c.Request.Header.Get(cronExecutedHeader) if cron != "true" { log.Println("not invoked by cron - access denied") c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{ "code": http.StatusUnauthorized, "message": http.StatusText(http.StatusUnauthorized), }) return } c.Next() } }
.env配置
FIREBASE_CONFIG_FILE="./firebase.json" API_KEY_NAME="AIzaXXXXXXXXXX"
firebase.json配置
{ "type": "service_account", "project_id": "mobile-test", "private_key_id": "4870XXXXXXXXX", "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEGYE=\n-----END PRIVATE KEY-----\n", "client_email": "firebase-adminsdk-yqf07@mobile.iam.gserviceaccount.com", "client_id": "11590XXXXXX", "auth_uri": "https://accounts.google.com/o/oauth2/auth", "token_uri": "https://oauth2.googleapis.com/token", "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-yqf07%40wodhero-mobile.iam.gserviceaccount.com", "universe_domain": "googleapis.com" }
解决方案
这个错误核心是程序未正确读取到Firebase服务账号密钥文件,或文件路径无效,按以下步骤排查:
1. 确保环境变量正确加载
Go不会自动加载.env文件,需手动引入包处理:
- 安装依赖:
go get github.com/joho/godotenv - 在
main.go的main函数开头添加加载代码:
func main() { // 新增加载.env文件逻辑 err := godotenv.Load() if err != nil { log.Println("warning: 加载.env文件失败") } client, err := config.InitAuth() // 后续代码不变 }
2. 验证文件路径有效性
- 确认
firebase.json和.env在同一目录,程序运行的工作目录是项目根目录 - 可临时改用绝对路径测试,比如把
.env里的路径改成/home/yourname/projects/yourapp/firebase.json(替换为实际路径)
3. 检查文件权限
确保运行程序的用户有读取firebase.json的权限,Linux/macOS执行:
chmod 644 firebase.json
4. 确认服务账号密钥有效
- 检查
firebase.json中private_key格式正确,-----END PRIVATE KEY-----不能缺失 - 核对
project_id、client_email与Firebase控制台信息一致
5. 备选方案:直接通过环境变量传递密钥
若路径问题难排查,可将服务账号JSON内容设为环境变量GOOGLE_APPLICATION_CREDENTIALS,或在代码中直接加载JSON内容(不推荐硬编码密钥):
jsonContent := os.Getenv("FIREBASE_SERVICE_ACCOUNT_JSON") opt := option.WithCredentialsJSON([]byte(jsonContent)) app, err := firebase.NewApp(context.Background(), nil, opt)
内容的提问来源于stack exchange,提问作者Mathias
相关产品推荐
相关产品推荐

