rest-firebase: Missing claim 'kid' in auth header.

On Firebase 3.0 I get an error "Missing claim 'kid' in auth header."

Apparently now Firebase requires private key’s id supplied with claims.

About this issue

  • Original URL
  • State: open
  • Created 8 years ago
  • Comments: 23 (7 by maintainers)

Commits related to this issue

Most upvoted comments

It didn’t work for me either. However, I tried to put a kid into JWT header, then Firebase would give me:

{"error"=>"Invalid claim 'kid' in auth header."}

I tried to give private_key_id, project_id, client_id, but none of them worked. Oh silly kid. Please stop kidding me.

For future reference.

I got Firebase 3.0 working like this:

You get this service account manifest JSON through Google’s IAM console.

{
  "type": "service_account",
  "project_id": "..redacted..",
  "private_key_id": "..redacted..",
  "private_key": "-----BEGIN PRIVATE KEY-----\n...redacted...\n-----END PRIVATE KEY-----\n",
  "client_email": "firebase@example.gserviceaccount.com",
  "client_id": "12340000000000000000",
  "auth_uri": "https://accounts.google.com/o/oauth2/auth",
  "token_uri": "https://accounts.google.com/o/oauth2/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/..."
}
def generate_web_token(uid, claims)
  # Parses Google's `service_account` JSON file into an array
  service_data = get_service_data()

  private_key = OpenSSL::PKey::RSA.new(service_data['private_key'])

  service_account_email = service_data['client_email']
  now_seconds = Time.now.to_i

  payload = {
    iss: service_account_email,
    sub: service_account_email,
    aud: 'https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit',
    iat: now_seconds,
    exp: now_seconds + (60 * 60),
    uid: uid,
    claims: claims,
    kid: data['private_key_id']
  }

  private_key = OpenSSL::PKey::RSA.new(service_data['private_key'])

  # Generate JWT
  JWT.encode(payload, private_key, 'RS256')
end

My other findings:

  • For what I tested, as for now Firebase ignores the exp parameter and sets/forces it to 1 hour, regardless what you put there, I tried to get it to 30 min but when you read the token back after authenticating, it’s 3600 seconds.
  • To get the real reason why token did not work, monitor for POST XHR to endpoint 'https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyCustomToken?key=...' in your browser’s dev tools. If the token was OK, it returns when it expires (3600 seconds) and a refreshToken (couldn’t find what this is for).
  • Make sure your frontend api key matches the domain you have whitelisted on Firebase’s panel. (CREDENTIAL_MISMATCH error returned by that verifyCustomToken post call if domain doesn’t match to what you initialize in initializeApp)

Hope this helps.