google-apps-scriptgoogle-api-nodejs-client

How to use Gmail add-on access token for Google API


Initially, I created a Gmail add-on in Apps Script:

function buildAddOn(e) {
  var accessToken = e.messageMetadata.accessToken;
  GmailApp.setCurrentMessageAccessToken(accessToken);
  var messageId = e.messageMetadata.messageId;
  var message = GmailApp.getMessageById(messageId);
  ...
}

Now, I want to move from AppScript to JavaScript (Gmail Add-on in other language), and using Google API (googleapis) to get message & attachment metadata information :

import Hapi from "@hapi/hapi";
import { google } from "googleapis";

const port = 3023;

const init = async () => {
  const server = Hapi.server({
    port: port,
    host: "localhost",
  });

  server.route({
    method: "POST",
    path: "/",
    handler: async (request, h) => {

      const { payload } = request;
      const { gmail } = payload;

      const gmailAPI = google.gmail({
        version: "v1",
        headers: {
          // Here I want to use the access token coming from the Gmail add-on client
          Authorization: `Bearer ${gmail.accessToken}`,
        },
      });

      try {
        // Here I want to get info about the current message is opened in Gmail while the add-on is active 
        const res = await gmailAPI.users.messages.get({
          userId: "me",
          id: gmail.messageId,
        });
        console.log(res.data);
      } catch (e) {
        console.log(e.response.data);
      }

This is the payload coming from Gmail add-on client (Gmail web):

{
  commonEventObject: { hostApp: 'GMAIL', platform: 'WEB' },
  gmail: {
    messageId: 'msg-f:1762895788594548046',
    threadId: 'thread-f:1762895788594548046',
    accessToken: 'XXXYYYZZZ' // changing value for security
  },
  authorizationEventObject: {
    userOAuthToken: 'GGGYYYJJJ', // changing value for security
    systemIdToken: 'FFFHHHCCC' // changing value for security
  }
}

This is the error:

{
  error: {
    code: 401,
    message: 'Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.',
    errors: [ [Object] ],
    status: 'UNAUTHENTICATED'
  }
}

These are the scopes for the Add-on:

"oauthScopes": [
  "https://www.googleapis.com/auth/gmail.addons.execute",
  "https://mail.google.com/",
  "https://www.googleapis.com/auth/gmail.metadata", 
  "https://www.googleapis.com/auth/gmail.readonly"
]

Question: How can I replicate successfully GmailApp.setCurrentMessageAccessToken(accessToken) using the access_token coming from Gmail client to Gmail add-on backend so I can get metadata about the current opened mail


Solution

  • To create a Gmail API service you need to use an OAuthToken and you can use the one that comes in the payload, try this modification:

          const { payload } = request;
          const { authorizationEventObject } = payload;
    
          const gmailAPI = google.gmail({
            version: "v1",
            headers: {
              // Here I want to use the access token coming from the Gmail add-on client
              Authorization: `Bearer ${authorizationEventObject.userOAuthToken}`,
            },
          });
    
    

    There is an example in this link from Google Developers.