Search code examples
google-apigoogle-drive-apigoogle-oauthaccess-tokenauth0

Auth0 and Google API, access token expired, howto write files to Google Drive


I've written an online converter and integrated Auth0 to my website. What I'm trying to achieve is to auto-upload the converted file to the Google Drive of a logged in user. I set up Google oauth in Auth0 and everything seemed to work fine.

The problem is, Google's access_token expires after 60min and I don't have a refresh_token. Therefore, the user needs to log in via the Google Login-page again. That is not, what I want, because the user is in fact logged in way longer than just 60min on my site, but Google refuses API-calls (because the Google token expired).

I know I can request a refresh_token by setting access_type=offline but this will add the permission Have offline access. I don't want that, I just want to upload data to the user's Drive, if he clicked the convert button on my page. I don't want to ask the users for permissions I don't need. If I (as a user) would link my Google account on a similar page and the tool asks for offline access I wouldn't approve, to be honest - the permission sounds like the tool creator can do whatever he wants with your account whenever he wants... There are many tools out there that have write access to a user's Drive without asking for offline access and with one single login until the user revokes the permission. How is that done?

Is there a way to make Google API calls without asking for offline access and without forcing the user to approve the app (that is already approved by him) again and again every 60min?

Thanks in advance, phlo


Solution

  • I found the solution!

    Prerequirements

    1. Enable Use Auth0 instead of the IdP to do Single Sign On in your client's Dashboard
    2. Create a new Angular-route to handle the silent login callback (e.g. /sso)
    3. Add

      $rootScope.$on("$locationChangeStart", function() {
          if ($location.path().indexOf("sso") == -1) {
              authService.relogin(); //this is your own service
          }
      });
      

      to your run-function and set the callbackURL in angularAuth0Provider.init() to your new Angular-route (<YOUR_DOMAIN>/sso). Add this URL to your accepted callbacks in the Auth0 dashboard - this won't end in an infinite loop, because the locationChangeStart-event won't call authService.relogin() for this route

    4. Add $window.close(); to the controller of the Angular-route (/sso) to auto-close the popup
    5. Authenticate the user via Auth0 and save the timestamp and the Auth0-access_token somewhere

    On reload:

    Check, if the Auth0-token is still valid in authService.relogin(). If not, the user has to login again either way. If the token is valid and the Google token is about to expire (check this with the saved timestamp to prevent unnecessary API calls) check for SSO-data and login silently, if present

        /* ... */
        if (validToken && googleExpired) {
            angularAuth0.getSSOData(function (err, data) {
                var lastUsedConnection = data.lastUsedConnection;
                var connectionName = (_.isUndefined(lastUsedConnection) ? undefined : lastUsedConnection.name);
                var isGoogle = (_.isUndefined(connectionName) ? false : connectionName == "google-oauth2");
                if (!err && data.sso && isGoogle) {
                    authManager.authenticate();
                    localStorage.setItem("last-relogin", new Date().getTime());
                    angularAuth0.signin({
                        popup: true,
                        connection: data.lastUsedConnection.name
                    });
                }
            });
        }
    

    Now you will find a fresh Google access_token for this user (without asking for offline access)


    Resources: