How to use the Firebase refreshToken to reauthenticate?

When you make call from a browser .getIdToken(true) will automatically refresh your token. Make call like this:

firebase.auth().currentUser.getIdToken(/ forceRefresh / true)
  .then(function(idToken) {
    
  }).catch(function(error) {

});

More info here https://firebase.google.com/docs/reference/js/firebase.User#getIdToken


** UPDATE ** this is also now documented in Firebase REST docs under Exchange a refresh token for an ID token section:

https://firebase.google.com/docs/reference/rest/auth/#section-refresh-token


Currently the only way I found to do this is here: https://developers.google.com/identity/toolkit/reference/securetoken/rest/v1/token

You must make an HTTP request:

POST https://securetoken.googleapis.com/v1/token?key=YOUR_KEY

Where YOUR_KEY can be found in the Google developers console > API Manager > Credentials. It's under the API Keys section.

Make sure request body is structured in the following format:

grant_type=refresh_token&refresh_token=REFRESH_TOKEN

Where REFRESH_TOKEN is the refresh token from Firebase user object when they signed in.

You must set the header Content-Type: application/json or you will get errors (e.g. "MISSING_GRANT_TYPE").

The POST call will return a new idToken (used to be called access_token)


I guess most people here are looking for a way to persist their authentication not in a browser but e.g. on a node backend. Turns out there actually is a way to do this:

  1. Trade the refresh-token for an access-token (using google's public api)
  2. Trade the access-token for a custom-token (using a firebase-function, see below)
  3. Login with custom-token

Here's the essence of the code:

const requestP = require('request-promise');
const fsP = require('fs').promises;

const refreshToken = await fsP.readFile('./refresh_token.txt');
const res = await requestP.post({
  headers: {'content-type': 'application/x-www-form-urlencoded'},
  url: 'https://securetoken.googleapis.com/v1/token?key=' + firebaseConf.apiKey,
  body: 'grant_type=refresh_token&refresh_token=' + refreshToken,
  json: true
});
const customToken = await requestP.post({
  headers: {'content-type': 'text/plain'},
  url: 'https://<yourFirebaseApp>.cloudfunctions.net/createCustomToken',
  body: {token: res.access_token},
  json: true
});
await firebaseApp.auth().signInWithCustomToken(customToken);

And the firebase function:

export const createCustomToken = functions.https.onRequest(async (request, response) => {
  response.set('Access-Control-Allow-Origin', '*');

  try {
      const token = JSON.parse(request.body).token;
      const decodedToken = await admin.auth().verifyIdToken(token);
      const customToken = await admin.auth().createCustomToken(decodedToken.uid);
      response.send(customToken);
  } catch(e) {
      console.log(e);
      response.sendStatus(500);
  }
});

// Create a callback which logs the current auth state
function authDataCallback(authData) {
  if (authData) {
    console.log("User " + authData['uid'] + " is logged with token" + authData['ie']);
  } else {
    console.log("User is logged out");
  }
}
// Register the callback to be fired every time auth state changes
var ref = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com");
ref.onAuth(authDataCallback);

Event onAuth will be called on page refresh, if user was logged out authData will be null, else not. You can find token in authdata['ie']. In the screenshot bellow I have printed the token after auth and authdata object, how you can see authData['ie'] and token are similar.

authdata.ie and token