Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Custom Tokens to make REST requests to FB DB as an admin

I'm migrating to the new database and 3.0 client libs. I'm updating the part which generates a custom auth token (on our server) to do a PATCH to update a resource in the Firebase DB.

These PATCH requests used to be made by our server to Firebase using admin claims based on this: https://www.firebase.com/docs/rest/guide/user-auth.htm

For the new DB, I'm generating the JWT token (using ruby-jwt) like this:

payload = {
  aud: "https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit",
  claims: custom_claims.merge({ admin: true }),
  exp: now_seconds + (60 * 60), # Maximum expiration time is one hour
  iat: now_seconds,
  iss: service_account_email,
  sub: service_account_email,
  uid: uid
}

JWT.encode(payload, private_key, "RS256")

A PATCH request with this token to the Firebase DB fails with: Missing claim 'kid' in auth header.

like image 389
Akshay Rawat Avatar asked May 25 '16 00:05

Akshay Rawat


People also ask

What is custom token authentication?

What Are Custom Authentication Tokens? An authentication token is some data, represented as a string or XML, that identifies an entity (user or process), such as an X509 client certificate. Typically, authentication tokens are designed to be used within specific security protocols.

How do I use authentication token in REST API?

Users of the REST API can authenticate by providing a user ID and password to the REST API login resource with the HTTP POST method. An LTPA token is generated that enables the user to authenticate future requests. This LTPA token has the prefix LtpaToken2 .


2 Answers

In the new Firebase you need to directly use a Service Account to create administrative access credentials. Here is a Node.js snippet that shows how to make a REST call to the Database:

// key.json is a service account key downloaded from the Firebase Console
var key = require('./key.json');

var google = require('googleapis');
var request = require('request');

var DATABASE_URL = 'https://<databaseName>.firebaseio.com';

var jwtClient = new google.auth.JWT(key.client_email, null, key.private_key, [
  'https://www.googleapis.com/auth/userinfo.email',
  'https://www.googleapis.com/auth/firebase.database'
]);

jwtClient.authorize(function(err, tokens) {
  request({
    url: DATABASE_URL + '/.json',
    method: 'GET',
    headers: {
      'Authorization': 'Bearer ' + tokens.access_token
    }
  }, function(err, resp) {
    console.log(resp.body);
  });
});

To do the same in Ruby, you might take a look at the googleauth gem for fetching the access token using Service Account credentials.

like image 198
Michael Bleigh Avatar answered Oct 01 '22 17:10

Michael Bleigh


Here is the equivalent of Michael Bleigh's answer using the ruby googleauth module:

require 'googleauth'

scopes = [ 'https://www.googleapis.com/auth/userinfo.email', 'https://www.googleapis.com/auth/firebase.database']
auth = ::Google::Auth.get_application_default(scopes)
auth_client = auth.dup
auth_client.sub = "[email protected]"
token = auth_client.fetch_access_token!

You will also need to set the GOOGLE_APPLICATION_CREDENTIALS environment variable to the path of your service account JSON file. the value for auth_client.sub comes from client_email in this JSON file.

Of course, as above, this is only valid in a server application you control.

Also, making the request to the firebase REST API is still an exercise for the reader.

references

  • https://developers.google.com/api-client-library/ruby/auth/service-accounts#authorizingrequests
  • https://developers.google.com/identity/protocols/application-default-credentials#whentouse
like image 39
Richard Stephens Avatar answered Oct 01 '22 19:10

Richard Stephens