How to Refresh Google AccessToken in Firebase? #As

2019-03-25 10:28发布

问题:

I am attempting to build a web app that will be integrated with and installed into Google Drive. The user will be able to create and share my app's files in their drive. I am trying to write it using Firebase so I can leverage many of the great new features there. However, I'm having trouble getting the auth to work consistently across these two platforms.

This is a client-side only app (at least for now) so I can't use offline auth and refresh tokens.

Before Firebase auth, I would use the Google Identity Toolkit with gapi. This generally works fine, although it uses a popup flow which isn't mobile-friendly.

    gapi.signin2.render(elementId, {
        longtitle: true,
        width: 230,
        height: 50,
        theme: "dark"
    });

    var auth2 = gapi.auth2.init({
        client_id: CLIENT_ID,
        scope: SCOPES.join(" ")
    });

    auth2.isSignedIn.listen(signinChanged);
    auth2.currentUser.listen(userChanged);

Gapi is a bit clumsy, but it works. The access token can be obtained by calling

    gapi.auth2.getAuthInstance().currentUser.get().getAuthResponse(true));

As usual, the access token only lasts about an hour and then expires. The important thing is that we can just call GoogleUser.reloadAuthResponse() to get a refreshed access token. Note, that is a refreshed access token, not a refresh token!

So, in theory, I can just use that access token to authenticate with Firebase as described here, and have to just live with the popup flow, or try to hack around that.

All that said, Google says the Identity Toolkit is being replaced with Firebase Authentication and that new apps should use Firebase.

The newest version of Google Identity Toolkit has been released as Firebase Authentication. It includes upgraded client SDKs, open source UI libraries, session management and integrated email sending service for forgotten password flows.

New projects should use Firebase Authentication. To migrate an existing project from Identity Toolkit to Firebase Authentication, see the migration guide.

Quoted from: Google

Firebase has a straightforward API for auth with Google. I can get and store the AccessToken upon authentication. So it seems that is the way I should implement the auth, the new and improved Firebase way. Also, Firebase provides a nice redirect flow that works on mobile devices.

However, there is a huge problem...

This will get the Access Token.

    firebase.auth().getRedirectResult().then(function(result) {
      if (result.credential) {
        // This gives you a Google Access Token. You can use it to access the Google API.
        var token = result.credential.accessToken;
        // ...
      }

      // The signed-in user info.
      var user = result.user;
   })

The access token is available and I can use it to read/write to the drive, ...for an hour. Once that token expires, I can no longer do anything. The user is still logged into Firebase, so I can continue to use the Firebase services, but I would need to force the user to sign in again to access the drive. This won't do!

I'm looking for the equivalent of GoogleUser.reloadAuthResponse() in Firebase.

  • How can I do this?
  • What is the recommended way to build a web app that accesses both Firebase services and G Suite?
  • Are there any official examples?

回答1:

You are already using gapi to get the access token and refresh it every hour for your integration with google drive API. Stick to that. What you need to do is use the following API to sign to Firebase with the Google credential:

var cred = firebase.auth.GoogleAuthProvider.credential(null, gapiAccessToken); firebase.auth().signInWithCredential(cred).then(function(user) { // You are signed in to Firebase now and do not need to re-sign in again. ... });

You will now be signed in to Firebase while your access token continues to be refreshed via gapi. Firebase sessions are indefinite so you don't need to sign in again to Firebase.



回答2:

For anyone just trying to get a token for authenticated endpoint calls after using firebase google sign in (i.e. to google cloud endpoints), you can use:

var successCallback = function(firebaseIdJsonWebToken) {
   console.log("token: " + firebaseIdJsonWebToken);
}
var errorCallback = function(error) {
   console.log("error: " + error);
}
firebase.auth().currentUser.getIdToken().then(successCallback, errorCallback)

The firebase id token is a JWT and is different than the token in the credential from the signin redirect callback. The getIdToken() function will refresh the token if it is needed and return a valid token to the callback. The token in the credential from the signin redirect callback will expire in 1 hour as the OP said and cannot be refreshed without attempting to sign in again.

If you want to do authenticated endpoint calls using firebase google signin, use getIdToken(). Then follow instructions for google cloud endpoints with firebase auth