23

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?
Community
  • 1
  • 1
Gary
  • 821
  • 8
  • 20
  • You might want to check this [forum](https://groups.google.com/forum/#!msg/firebase-talk/wAcJFfQlFeg/IUuJXNcgDHgJ), it a bit old but it discussed some steps how to get the refresh token. Also a related [forum](https://groups.google.com/forum/#!topic/firebase-talk/ZPW3xtwn8g0) talks about the problem you've encountered. I'm not sure if there is any update regarding this, but I think you can apply the workaround in the said forum. Hope this helps. – Mr.Rebot Jan 01 '17 at 15:15
  • 2
    Thanks for the response and links. Those are a bit dated, especially the first one which I think is from before Google acquired Firebase. I didn't see a viable workaround, other than a vague comment to not use their Google auth and implement it myself from scratch on the server with a refresh token. :( I don't understand why Google would publically recommend using Firebase's Google Auth instead of the Identity Toolkit if it doesn't support extended auth to Google APIs, beyond a single hour. I hope someone from Google will respond and provide some definitive guidance. – Gary Jan 02 '17 at 00:18
  • 1
    Thank you so much for putting the details in the question, I am also looking solution for this. Have you found it? @Gary – Shajeel Afzal Jul 11 '20 at 22:59

2 Answers2

8

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.

bojeil
  • 29,642
  • 4
  • 69
  • 76
  • Thanks. I'm actually not doing either yet. It's a new app and I'm trying to do it the right way as of today. I read Google's message as, "use Firebase auth, not the old Identity Toolkit" So that is what I am trying to do. Also, my app needs a _redirect flow_ and the Identity Toolkit doesn't appear to have an official way to do that. Firebase Auth would be perfect if I could just figure out how to _refresh the access token_. – Gary Jan 01 '17 at 13:55
  • Unfortunately, gapi does not support redirect flow and Firebase does not refresh access tokens. As i explained, you need to use both APIs (gapi to refresh access tokens and Firebase Auth signInWithCredential). Please file a feature request at https://groups.google.com/forum/#!forum/firebase-talk to support refreshing OAuth tokens via Firebase. – bojeil Jan 03 '17 at 04:51
  • Do you happen to know if the feature request has been filed, so I could track it? I've searched, but couldn't find one. Thanks! – Vitali Kniazeu May 08 '17 at 12:26
  • I am not aware of any formal process for feature requests. Just go to the Forum link I provided and request that Firebase Auth support refreshing OAuth tokens. Explain the importance of this feature to developers and why it could be valuable. – bojeil May 09 '17 at 16:56
  • This doesn't seem to be working. The access token still gets invalid. However, lets say that internally the access token is refreshed. Can you tell us how to get that new Google Oauth2 Access Token? – gaurav414u May 15 '17 at 14:12
  • Does `gapi` itself refresh access token ? – Ajay S Jul 15 '17 at 09:38
  • It should refresh tokens. You should be able to get the access token: https://developers.google.com/api-client-library/javascript/reference/referencedocs#gapiauth2authresponse – bojeil Jul 15 '17 at 18:49
  • @bojeil so this means that we can get next google access token if old is expired at server side with the help of `gapi` and client won't have to do deal with it ? How it is different https://firebase.google.com/docs/reference/android/com/google/firebase/auth/FirebaseAuth.IdTokenListener.html#onIdTokenChanged(com.google.firebase.auth.FirebaseAuth) Is this firebase token ? – Ajay S Jul 17 '17 at 05:24
  • This is client side only (the Google access token refresh) though `GApi` does provide an offline mode for server side tokens. You would need to handle the refresh on your own for that. `onIdTokenChanged` is only for the Firebase ID token. – bojeil Jul 17 '17 at 07:37
  • @bojeil Ah then Do I need to keep sending access token from client to server periodically ? What do you mean by "`GApi` does provide an offline mode for server side tokens" ? Any example ? – Ajay S Jul 17 '17 at 15:18
  • 1
    If you need the access token on your server, you need the offline mode for `GApi`. Check here: https://developers.google.com/identity/sign-in/web/server-side-flow – bojeil Jul 17 '17 at 17:41
  • @bojeil Thank you so much :) – Ajay S Jul 18 '17 at 04:33
  • I am building a chrome extension and gapi.auth2 is not compatible with chrome extensions, someone has a solution? thanks – blinkofaneye Jul 07 '20 at 09:00
  • @blinkofaneye did you found solution for gapi and Chrome extensions? – rendom Apr 29 '21 at 02:51
-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

caitcoo0odes
  • 484
  • 1
  • 6
  • 17