Search code examples
oauth-2.0google-oauthgoogle-api-js-client

google.accounts.oauth2 TokenClient, how to get refresh token


Using gapi my goal is to authenticate the user, then save their refresh token, which is to be later used for performing background tasks on the server side.

For this I have made a simple authentication component, excerpt of it is here:

<script src="https://accounts.google.com/gsi/client"></script>
<script src="https://apis.google.com/js/api.js"></script>
  const start = async () => {
    let gapiClient = await gapi.client.init({
      apiKey: API_KEY,
      discoveryDocs: ['https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest'],
    });

    console.log('gapiClient', gapiClient); // undefined

    let tokenClient = google.accounts.oauth2.initTokenClient({
      client_id: CLIENT_ID,
      scope: SCOPES,
      callback: '', // defined later
    });

    console.log('tokenClient', tokenClient);

    tokenClient.requestAccessToken({ prompt: 'consent' });

    tokenClient.callback = async (resp: { error?: any }) => {
      if (resp.error !== undefined) {
        throw resp;
      }
      console.log('resp', resp);
    };

  };

  gapi.load('client', start);

Now resp is logged as:

{
    "access_token": "xxxxxx",
    "token_type": "Bearer",
    "expires_in": 3599,
    "scope": "https://www.googleapis.com/auth/calendar.readonly"
}

This is not what is needed, as I would like a refresh token to later call the api for scheduled background tasks.

How could I use the tokenClient to authenticate the user and get a access / refresh token pair that I can use later with the appropriate scopes ?


Solution

  • It seems that you are using the implicit grant model (https://developers.google.com/identity/oauth2/web/guides/use-token-model) and what you need to use is the authorization code model (https://developers.google.com/identity/oauth2/web/guides/use-code-model). The last one is used to do offline API request (this meaning you don't need the user to be in the browser while you request to their APIs on their behalf, see https://developers.google.com/identity/oauth2/web/guides/choose-authorization-model#choosing_an_authorization_flow for more info on flow comparison).

    In the authorization code flow which you need to use, you will receive a code, then you have to send it to your backend, which can do a request as shown here https://developers.google.com/identity/protocols/oauth2/web-server#exchange-authorization-code to get the access and the refresh token. Here, you need to use the client id and secret you got from the Google Cloud Console.

    Hope this helps