Need help with fetching refresh_token from Google social login

I have an Angular 1.5 app using the Auth0 Angular SDK. My goal is to do authentication on the Angular app and then do automated tasks on a user’s google calendar server side (Using node).

So far I have everything working as far as using a hosted ‘Lock’ screen to authenticate using either username/password or Google. I am also able to successfully fetch an ‘access_token’ from Google from an identity object in the identities array on the object returned from the userinfo endpoint.

What I cannot get working for the life of me is for Auth0 to populate a refresh_token as part of the identity object. As I understand it (I could be incorrect) - all you have to do is add ‘access_type=offline’ to the params within the auth object.

I have read all of these articles, forum posts and more:

https://auth0.com/docs/libraries/lock/v10/configuration#params-object

I then made this change to my hosted lock code (small snippet shown):

.....
……
    **config.internalOptions.accessType = 'offline'**

    var lock = new Auth0Lock(config.clientID, config.auth0Domain, {
      auth: {
        redirectUrl: config.callbackURL,
        responseType: (config.internalOptions || {}).response_type ||
          (config.callbackOnLocationHash ? 'token' : 'code'),
        params: config.internalOptions,
            
      },
    …….
    …….

I have also tried:

 **config.internalOptions.access_type = 'offline'**

The end result is always the same. I get an identity object without a refresh_token like so:

identities:
   [ { user_id: '?????????585401352',
   provider: 'google-oauth2',
   connection: 'google-oauth2',
   isSocial: true,
   access_token: '??????????????????????????????????????????????????wP_BeLT-lL7ATxPZl-FTU2gEM',
   expires_in: 3600 } ],

I’ve been at this for days to no avail. It seems like Auth0 just refuses to put the result of the code exchange in the object for some reason. Contacted support and they asked me to read the above articles.

What else do I need to do or check to get the refresh_token populated within the google-oauth2 identity object?

Note that I do not actually use asterisks in the real code…

:wave: @hstevemcdonald Let’s see what we can do! I believe if we are calling for example authorize you can pass the parameter within that call, for example:

angularAuth0.authorize({
    ...
    accessType: "offline",
    ...
});

or within the Hosted Lock Page, setting the attributes inside the lockOptions.auth.params, this would look something like this:

 lockOptions.auth.params.access_type = 'offline';
 lockOptions.auth.params.approval_prompt = 'force';

You may also need to add approval_prompt=force if the user has already signed in with Google previously. This will force their approval for the refresh token again (since Google will only send it once).

You can then store the token in the user.app_metadata to persist it by using the Rule you mentioned (re-mentioning it here).

Please let me know if you continue to have issues or just to simply let me know if it worked :slight_smile:

@kimcodes Thank you so much for replying to my post! I apologize for the delay in trying this out.

In summary, neither option worked. Here is a snippet as an example for the hosted lock version:

var params = config.internalOptions;
params.access_type = 'offline';
params.approval_prompt = 'force';

var lock = new Auth0Lock(config.clientID, config.auth0Domain, {
  auth: {
    redirectUrl: config.callbackURL,
    responseType: (config.internalOptions || {}).response_type ||
      (config.callbackOnLocationHash ? 'token' : 'code'),
    params
  },

In troubleshooting this, I used Chrome debugger tools and watched the ‘Console’ and ‘Network’ tab to see what was happening. I noticed that when I click the Google login on the login page, it -does- seem to pass the ‘access_type’ and ‘approval_prompt’ params to auth0 correctly like so:

/authorize?client_id=00000000&response_type=token%20id_token&redirect_uri=0000000000000&connection=google-oauth2&nonce=000000000000000&sso=true&approval_prompt=force&_intstate=deprecated&_csrf=000000000000&audience=000000000000000&auth0Client=0000000000000000000&scope=openid&access_type=offline&protocol=oauth2

But the url that is generated for google is missing the ‘access_type=offline’ as shown below. Note than when I manually copy this url and then add ‘&access_type=offline’ to the query then it -does- work as expected and refresh_token is added to the google-oauth2 identity in the user profile.

/o/oauth2/auth?response_type=code&redirect_uri=000000000000&scope=email%20profile%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcalendar%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Ftasks&state=LR-WAR2cjtF_nQP5yZoCLmGJFLl-z_gl&client_id=0000000000000000

It really seems like something is being lost in passing extra params to the url generated for the google-oauth2 connection , or at the very least - when the google url is generated it is stripping out the ‘access_type’ param. Maybe this is a bug?

How do I force the access_type to ‘pass through’ and show when the Google oauth url is generated?

@hstevemcdonald no problem! Thank you for trying those out. Passing accessType: offline to the authorization request did not work? A similar issue with the Google refresh token was solved here. Can you share the code you are using to make the request?

@kimcodes

I am happy to report that I got this working by reviewing your suggested link here

webAuth.authorize({
connection: 'google-oauth2',
connection_scope: 'https://www.googleapis.com/auth/youtube.readonly,https://www.googleapis.com/auth/yt-analytics.readonly',
scope: 'openid profile',
accessType: 'offline',
approvalPrompt: 'force'

})

I had tried placing ‘accessType’ in this way before, but I had not included the scope or connection_scope. With all of these elements in place (approvalPrompt optional), it did work for me.

Thank you very much for your help!

@hstevemcdonald awesome! Glad we got it working :slight_smile: my pleasure.

Please let us know if you encounter any other issues while developing.

So basically the Lock js lib does not work correctly? It isn’t passing the extra params.

Hey there!

Sorry for such a delayed response! We’re doing our best in providing you with the best developer support experience out there but sometimes our bandwidth is just not enough for all the questions coming in. Sorry for the inconvenience!

Can you let us know if you still require further assistance from us?