Skip to content

VerifyIDToken fails with INVALID_ARGUMENT: failed to verify token signature for valid Firebase ID token #715

@harpy-wings

Description

@harpy-wings

Description

When verifying a Firebase ID token generated by a Flutter Firebase Auth SDK, the Go Admin SDK consistently returns:

InvalidArgument desc = failed to verify token signature

Even though:

  • The token header contains a valid kid present in the keys fetched from
    https://www.googleapis.com/robot/v1/metadata/x509/[email protected]
  • The iss and aud in the payload match the Firebase project (demo-project-123456)
  • The token has a valid iat/exp and is not expired
  • The Admin SDK is initialized with the correct service account and ProjectID
  • System clock is correct
  • No emulator is used (FIREBASE_AUTH_EMULATOR_HOST unset)

Environment

  • SDK: firebase.google.com/go/v4
  • Go version: go1.25
  • OS/Env: (windows)
  • Project ID: demo-project-123456

Steps to reproduce

  1. Sign in to Firebase Auth from a Flutter mobile client using Google provider:

    final user = await FirebaseAuth.instance.signInWithCredential(credential);
    final token = await user.user?.getIdToken();
2. Send the idToken to the backend.

3. On the backend, verify with Go Admin SDK:
```go
package main

import (
    "context"
    "fmt"
    "log"

    firebase "firebase.google.com/go/v4"
    "google.golang.org/api/option"
)

func main() {
    ctx := context.Background()
    app, err := firebase.NewApp(ctx, &firebase.Config{ProjectID: "demo-project-123456"},
        option.WithCredentialsFile("service-account.json"))
    if err != nil {
        log.Fatal(err)
    }

    auth, err := app.Auth(ctx)
    if err != nil {
        log.Fatal(err)
    }

    token := "<PASTE_ID_TOKEN_HERE>"
    t, err := auth.VerifyIDToken(ctx, token)
    if err != nil {
        log.Fatalf("verify failed: %v", err)
    }
    fmt.Println("UID:", t.UID)
}
  1. Observe error:
    failed to verify token signature

Sample Token

Header

{
  "alg": "RS256",
  "kid": "e3ee7e028e3885a345ce07055f846862255a7046",
  "typ": "JWT"
}

Payload

{
  "name": "Mr Robot",
  "picture": "https://lh3.googl....",
  "iss": "https://securetoken.google.com/demo-project-123456",
  "aud": "demo-project-123456",
  "auth_time": 1757591071,
  "user_id": "demoUser12345",
  "sub": "demoUser12345",
  "iat": 1757591071,
  "exp": 1757594671,
  "email": "[email protected]",
  "email_verified": true,
  "firebase": {
    "identities": {
      "google.com": [
        "123456789..."
      ],
      "email": [
        "[email protected]"
      ]
    },
    "sign_in_provider": "google.com"
  }
}

Expected behavior

VerifyIDToken should successfully verify and return a parsed auth.Token struct with UID/email claims.

Actual behavior

Verification fails with: "INVALID_ARGUMENT" "failed to verify token signature"

Additional notes

  • We validated the token manually: base64-decoding header/payload shows correct structure.
  • The kid matches one of the keys in Google’s x509 JWKS endpoint.
  • No emulator is used, and project IDs match.
  • Same error reproduces in a minimal standalone program outside of our service.

and the execution hit
auth/token_verifier.go: 310

func (tv *tokenVerifier) verifySignatureWithKeys(ctx context.Context, token string, keys []*publicKey) bool {
	segments := strings.Split(token, ".")
	var h jwtHeader
	decode(segments[0], &h)

	verified := false
	for _, k := range keys {
		if h.KeyID == "" || h.KeyID == k.Kid {
			if verifyJWTSignature(segments, k) == nil {
				verified = true
				break
			}
		}
	}

	return verified
}

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions