Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use the Firebase refreshToken to reauthenticate?

I use the JS library call firebase.auth().signInWithEmailAndPassword(email, password) and get back a User object. The User object contains a refreshToken.

I use curl 'https://docs-examples.firebaseio.com/rest/saving-data/auth-example.json?auth=TOKEN' to make calls to Firebase.

The token will eventually expire. In order to make it look like the application (iOS and macOS) has persistent login, I want to refresh the token, how do I do that with using either the REST or JS library? I can't find any calls in the documentation that allow me to use the refreshToken to get a new token.

like image 560
kgaidis Avatar asked Jul 06 '16 20:07

kgaidis


People also ask

What is Refreshtoken Firebase?

Firebase ID tokens are short lived and last for an hour; the refresh token can be used to retrieve new ID tokens. Refresh tokens expire only when one of the following occurs: The user is deleted. The user is disabled. A major account change is detected for the user.

How do you reAuthenticate a Firebase flutter?

When you want to change sensitive informations on Firebase you need to re-authenticate first to your account using your current credentials then you can update it. Currently flutter has no reAuthenticate method for Firebase so you need to call signInWithEmailAndPassword or any other signIn method.

Can I use Firebase just for authentication?

Yes, you can use Firebase for auth only and link it to your own database. You'll have to use the Firebase Admin SDK in your backend. Check out the set up guide.


3 Answers

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

like image 64
Yevgen Avatar answered Oct 17 '22 05:10

Yevgen


** 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)

like image 51
kgaidis Avatar answered Oct 17 '22 06:10

kgaidis


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);
  }
});
like image 13
Martin Cremer Avatar answered Oct 17 '22 05:10

Martin Cremer