firebase-admin-go icon indicating copy to clipboard operation
firebase-admin-go copied to clipboard

If `FIREBASE_AUTH_EMULATOR_HOST` is set, `VerifyIDToken` calls the Firebase Emulator, but shouldn't

Open arzonus opened this issue 2 years ago • 1 comments
trafficstars

[REQUIRED] Step 2: Describe your environment

  • Operating System version: no matter
  • Firebase SDK version: firebase.google.com/go/v4 v4.10.0
  • Library version: v4.10.0
  • Firebase Product: auth

[REQUIRED] Step 3: Describe the problem

I am working on functionality using AdminSDK to verify ID tokens by the VerifyIDToken function. I would like to write tests including calls of the method, but I found that the SDK tries to call a Firebase Emulator, which host is defined by FIREBASE_AUTH_EMULATOR_HOST variable.

I was surprised because I was sure VerifyIDToken shouldn't call the emulator to check user revocation. I found the place where the problem happens. Could you please describe the reason for this behavior or help me to avoid calls to the emulator?

Relevant Code:


// IDToken returns a valid ID token
func IDToken(uid string) (string, error) {
	const projectID = "project-id"

	var headers = map[string]interface{}{
		"alg": "none",
		"typ": "JWT",
	}

	jsonHeaders, err := json.Marshal(headers)
	if err != nil {
		return "", err
	}
	encodedHeaders := jwt.EncodeSegment(jsonHeaders)

	var claims = map[string]interface{}{
		"aud":       projectID,
		"iss":       "https://securetoken.google.com/" + projectID,
		"iat":       time.Now().Unix() - 100,
		"exp":       time.Now().Unix() + 3600,
		"auth_time": time.Now().Unix() - 100,
		"sub":       "1234567890",
		"uid":       uid,
	}

	jsonClaims, err := json.Marshal(claims)
	if err != nil {
		return "", err
	}
	encodedClaims := jwt.EncodeSegment(jsonClaims)

	return encodedHeaders + "." + encodedClaims + ".", nil
}

func check() {
  ctx := context.Background()
  token, _ := IDToken("uid")
  os.Setenv("FIREBASE_AUTH_EMULATOR_HOST", "localhost:9099")
  

  app, _ := firebase.NewApp(ctx, nil)
  auth, _ :=  app.Auth(ctx)
  t, err := auth.VerifyIDToken(ctx, token)
  if err != nil {
    fmt.Println(err)
  }
}

I get this error

failed to establish a connection: Post \"http://localhost:9099/identitytoolkit.googleapis.com/v1/projects/project-id/accounts:lookup\": dial tcp [::1]:9099: connect: connection refused"

Thank you!

arzonus avatar Feb 08 '23 16:02 arzonus

In https://pkg.go.dev/firebase.google.com/go/v4/auth#Client.VerifyIDToken

In non-emulator mode, this function does not make any RPC calls most of the time. The only time it makes an RPC call is when Google public keys need to be refreshed. These keys get cached up to 24 hours, and therefore the RPC overhead gets amortized over many invocations of this function.

This might mean that in emulator mode it is expected that it does RPC calls. I don't see a reason it should call the auth server since the JWT token contains the data.

lecajer avatar Nov 22 '24 22:11 lecajer