rest-firebase icon indicating copy to clipboard operation
rest-firebase copied to clipboard

Missing claim 'kid' in auth header.

Open jrasanen opened this issue 8 years ago • 23 comments

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.

jrasanen avatar May 27 '16 11:05 jrasanen

Hi, I'll check this tomorrow. In the mean time, could you please let me know if this is only for some latest setting, not that this breaks everything?

godfat avatar May 27 '16 18:05 godfat

Since I no longer use firebase, could you please let me know if this is the only thing we need to change? That is, the way to generate auth?

https://firebase.google.com/docs/auth/server#use_a_jwt_library

godfat avatar May 28 '16 02:05 godfat

I am using PHP-JWT to generate the token. Where does this kid go? Can anybody kindly help?

    "iss" => $service_email,
    "sub" => $service_email,
    "aud" => "https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit",
    "iat" => $now,
    "exp" => $now + (60 * 60),
    "uid" => $fbid,
    "claims" => array(
        'kid' => 'Key ID',
        'provider' => 'drupal',
    ),

Is it supposed to be inside claims or is it supposed to be at the same level as uid?

jigarius avatar Jun 02 '16 13:06 jigarius

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": "[email protected]",
  "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.

jrasanen avatar Jun 02 '16 15:06 jrasanen

@godfat thanks for the fix! I'll try to find time to test it tomorrow, it looks like it'll work.

Also reference for everybody: 2.4.X version of Firebase will be supported for some time according to devs.

jrasanen avatar Jun 02 '16 16:06 jrasanen

I am passing it as you described - It should work. However, it does not work :( It still gives me a 400 Bad Request saying Invalid claim 'kid' in auth header. And there is no documentation on kid in the Firebase Docs. Now I'm starting to get worried. Such a waste of time for such a simple thing. Thanks for the answer, buddy.

jigarius avatar Jun 02 '16 16:06 jigarius

@jrasanen I didn't figure out how to solve that kid issue for that commit and I can't find any document for that either :( Fortunately you found it! I'll try your approach in the next few days. Thanks!

Bottom line: As long as you could pass auth for rest-firebase, I guess it would still work for 3.0.

@jrm1987 Oh, sorry about that :( They said they would improve the doc.

godfat avatar Jun 02 '16 16:06 godfat

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.

godfat avatar Jun 03 '16 15:06 godfat

Some possible answers here and the required attributes (including the kid attribute) are described here

katowulf avatar Jun 14 '16 18:06 katowulf

@katowulf Thanks! I still don't get it though. Still getting {"error"=>"Invalid claim 'kid' in auth header."}

Questions:

  • Should I fill sub with uid? But actually I have no idea what's uid. Who is the user? I don't think I have any users in my testing project. How do I get any user id?
  • Should I also pass uid even with sub? We pass the same values for both of them?
  • It's not clear what's kid. Was that the private key (that pem) for this project?
  • Do we still pass claims?

godfat avatar Jun 15 '16 07:06 godfat

Firebase support team wrote me today that they are looking into the error and will inform when they have a solution. El 15 jun. 2016 2:21 a. m., "Lin Jen-Shin (godfat)" < [email protected]> escribió:

@katowulf https://github.com/katowulf Thanks! I still don't get it though. Still getting {"error"=>"Invalid claim 'kid' in auth header."}

Questions:

  • Should I fill sub with uid? But actually I have no idea what's uid. Who is the user? I don't think I have any users in my testing project. How do I get any user id?
  • Should I also pass uid even with sub? We pass the same values for both of them?
  • It's not clear what's kid. Was that the private key (that pem) for this project?
  • Do we still pass claims?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/CodementorIO/rest-firebase/issues/12#issuecomment-226108134, or mute the thread https://github.com/notifications/unsubscribe/AEFmUcEb6Rm4fzP66Afw1zomMhhbEU_rks5qL6fvgaJpZM4Ioawp .

jigarius avatar Jun 15 '16 12:06 jigarius

Meh, the code which I was using as a workaround stopped working and Google/Firebase started returning:

{
 "error": {
  "errors": [
   {
    "domain": "global",
    "reason": "invalid",
    "message": "INVALID_CUSTOM_TOKEN"
   }
  ],
  "code": 400,
  "message": "INVALID_CUSTOM_TOKEN"
 }
}

jrasanen avatar Jun 17 '16 08:06 jrasanen

Thanks for the update!!

I guess our best bet for now is just waiting, unless it's urgent to adopt...

godfat avatar Jun 17 '16 08:06 godfat

Waiting is good, too bad though. Firebase seriously needs a debug console, so devs can see what is happening on their side.

jrasanen avatar Jun 17 '16 08:06 jrasanen

Though, I just noticed poking Firebase that the tokens they return have "kid" attribute in JWT's header, not in payload/data: image

jrasanen avatar Jun 17 '16 08:06 jrasanen

Hi any update on the issue @breft did you got a response from firebase guys

bhuvangu avatar Aug 24 '16 07:08 bhuvangu

Original post: http://stackoverflow.com/questions/39117237/firebase-rest-with-auth-query-param-not-working From: FirebaseSupport team

Yes, creating custom tokens using FirebaseAuth.getInstance().createCustomToken(uid, additionalClaims) does not work with REST API. These tokens are designed to be used by client SDKs with signInWithCustomToken(token). Please note that "client to DB" REST requests are not supported right now due to changes in security model in the new Firebase (legacy Firebase supports it).

As you have pointed out, you need to follow this link in order to make an authenticated REST request. You should to use the access_token parameter, passing the token derived from the service account private key. This assumes you're scenario is "Server to DB" as you're using a service account.

To add custom claims using REST, you should use the auth_variable_override parameter. See here. Your request should now look like this with the added claim: {"uid":"6LiF16Dm0hNB9XO61UR1KM5Jeun2"}

$ curl "https://test-de98f.firebaseio.com/test.json?access_token=&auth_variable_override=%7B%22uid%22%3A%226LiF16Dm0hNB9XO61UR1KM5Jeun2%22%7D" {" 1213314":{"alanisawesome":"Alan Turing"}}

I do understand that the documentation you have pointed out needs to be improved and have raised this to our documentation team so that it could be prioritized appropriately. Though, I can't share any timelines as of the moment.

Hope this helps. Feel free to respond for any more issues or concerns.

bhuvangu avatar Aug 24 '16 15:08 bhuvangu

During the "verifyPassword" API use this parameter "returnSecureToken":true along with email and password. This worked for me. screen shot 2019-03-02 at 3 57 07 pm

rnanania avatar Mar 02 '19 21:03 rnanania

i am fetching the products for a specific user in this way:

Future<bool> fetchProducts() async {
    _isLoading = true;
    notifyListeners();
    try{
    final http.Response response = await http
        .get('https://flutter-products-d07d8.firebaseio.com/products.json?auth=${_authenticatedUser.token}');
        print(response.body);
      final List<Product> fetchProductList = [];
      final Map<String, dynamic> productListData = json.decode(response.body);
      if (productListData == null) {
        _isLoading = false;
        notifyListeners();
        return false;
      }
      productListData.forEach((String productId, dynamic productData) {
        final Product product = Product(
          id: productId,
          title: productData['title'],
          description: productData['description'],
          image: productData['image'],
          price: productData['price'],
          userEmail: productData['userEmail'],
          userId: productData['userId'],
        );
        fetchProductList.add(product);
      });
      _products = fetchProductList;
      _isLoading = false;
      notifyListeners();
      _selProductId = null;
      return true;
    }catch (error) {
      _isLoading = false;
      notifyListeners();
      return false;
    }
  }

but i am getting this response:

I/flutter (16571): "error" : "Invalid claim 'kid' in auth header: 'skIBNg' with iat: '1569414381'"

can any one help me please

SohaibKtb avatar Sep 27 '19 14:09 SohaibKtb

Any update on this issue

itzzmeakhi avatar Feb 25 '20 10:02 itzzmeakhi

Unfortunately, nothing from me

godfat avatar Feb 25 '20 11:02 godfat

Same with https://github.com/kreait/firebase-php/issues/169#issuecomment-366950404 There are 3 token type. But firebase only verify token from client app.

khuongphp avatar Apr 26 '20 11:04 khuongphp

I solved my this same type of error adding returnSecureToken: true in body object while logging with email and password and it works fine

bdmostafa avatar Jan 14 '22 13:01 bdmostafa