Firebase REST auth when creating token with node.js admin sdk

Ran picture Ran · Mar 21, 2017 · Viewed 7.2k times · Source

I know this issue was asked a lot here, but I still cannot seem to find the exact answer that can solve my problem.

I wish to access Firebase using REST calls, by adding an access_token param.

The access_token is created using the Node.js Admin SDK, using the following code:

var admin = require("firebase-admin");

var serviceAccount = require("./pk.json");

admin.initializeApp({
    credential: admin.credential.cert(serviceAccount),
    databaseURL: "https://XXX.firebaseio.com"
});

var uid = "1234";


admin.auth().createCustomToken(uid)
  .then(function(customToken) {
    // Send token back to client
    console.log("Token: "+customToken);
  })
  .catch(function(error) {
    console.log("Error creating custom token:", error);
  });

The problem is that if I take the token created from Node.js and use it my REST call, I get an Unauthorized request error.

I have read in some questions that people added the scope param when issuing the token, but have not found a way to do that with Node.js Admin SDK.

Google's docs are not so detailed with this issue. Any idea what I might try to resolve this one?

Answer

jwngr picture jwngr · Mar 21, 2017

The token you are using to authenticate to the Firebase REST API is not the correct type of token. You are using a Firebase Auth custom token, which can only be used to authenticate one of the Firebase client SDKs via the signInWithCustomToken() method as explained in Sign in using custom tokens on clients.

In order to authenticate to the Firebase REST API, you have two options: Firebase ID tokens (for user-based access) or Google OAuth2 access tokens (for admin access).

Authenticate with Firebase ID Tokens

See Retrieve ID tokens on the client for an explanation of how to retrieve access tokens in the various Firebase client SDKs. You can also exchange a Firebase custom token for an ID token and refresh token pair via an undocumented REST API:

Endpoint: https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyCustomToken?key=<API_KEY>

Method: POST

Request Body: { "token": <CUSTOM_TOKEN>, "returnSecureToken": true }

<API_KEY> is the same API key you get from your Firebase Console that you use in the Firebase clients. <CUSTOM_TOKEN> is a Firebase custom token.

Since ID tokens expire after an hour, you will need to use the refresh token to refresh them via this other undocumented REST API:

Endpoint: https://securetoken.googleapis.com/v1/token?key=<API_KEY>

Method: POST

Request Body: { "refresh_token": <REFRESH_TOKEN>, "grant_type": "refresh_token" }

<API_KEY> is the same API key as before. <REFRESH_TOKEN> is the refresh token from the previous API call.

Once you have an ID token, you can pass that to the REST API via the auth query parameter to authenticate a request. The request respects Firebase Security Rules as if the end user logged into the client was making the request.

Authenticate with Google Access Tokens

To authenticate with a Google OAuth2 access token, the first thing you need to do is get one. See Retrieving an access token for an explanation of how to do this. It only currently includes a Java example, but this is possible in many languages, including Node.js. Once you have an ID token, you can pass that to the REST API via the access_token query parameter to authenticate a request. The request will be made with admin access, overriding all Firebase Security Rules and granting full read and write access.