google-apps-scriptoauth-2.0google-workspace-add-ons

Google Workspace Add-on for Calendar Conference Solution with OAuth2 integration fails on redirect with CORS


I have built a google workspace addon for calendar conference solution using app script and oauth2 library.

My oauth client code is:

return (
    OAuth2.createService("OAuthApp")
      // Set the endpoint URLs.
      .setAuthorizationBaseUrl(`${FRONTEND_DOMAIN}/auth/login`) // frontend api
      .setTokenUrl(`${BACKEND_DOMAIN}/v1.0/oauth/exchange-code-for-token`) // backend api

      // Set the client ID and secret.
      .setClientId(CLIENT_ID)
      .setClientSecret(CLIENT_SECRET)

      // Set the name of the callback function that should be invoked to
      // complete the OAuth flow.
      .setCallbackFunction("authCallback")

      // Set the property store where authorized tokens should be persisted.
      .setPropertyStore(PropertiesService.getUserProperties())
      .setCache(CacheService.getUserCache())
      .setLock(LockService.getUserLock())
  );

Where for setAuthorizationBaseUrl i have provided out frontend page to open login page for user to authenticate. When user authenticates successfully, backend redirects to the addon on https://script.google.com/macros/d/{SCRIPT_ID}/usercallback with auth code in params and status code 302.

However when i redirect the frontend to addon from backend i get this error in console:

Access to XMLHttpRequest at 'https://script.google.com/macros/d/{SCRIPT_ID}/usercallback?code=4611729c041e9d0f93506bcfa772707d' (redirected from 'https://{BACKEND_ENDPOINT}/oauth/verify-otp') from origin 'https://{FRONTEND_ENDPOINT}' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

My add on manifest is:

{
  "oauthScopes": [
    "https://www.googleapis.com/auth/calendar.addons.execute",
    "https://www.googleapis.com/auth/calendar.events.readonly",
    "https://www.googleapis.com/auth/calendar.addons.current.event.read",
    "https://www.googleapis.com/auth/calendar.addons.current.event.write",
    "https://www.googleapis.com/auth/script.external_request",
    "https://www.googleapis.com/auth/script.scriptapp"
  ],
  "addOns": {
    "common": {
      "homepageTrigger": {
        "enabled": false
      },
      "logoUrl": "https://lh3.googleusercontent.com/-WuPhRsFGKUc/XCng7m_FIxI/AAAAAAAAAGg/ASH4GCGDMs0d55OZQGCSIQHXjRAKnkeTQCLcBGAs/s400/jitsi-logo-96x96.png",
      "name": "Conference App"
    },
    "calendar": {
      "conferenceSolution": [
        {
          "id": 1,
          "name": "Private Meeting",
          "logoUrl": "https://lh3.googleusercontent.com/-WuPhRsFGKUc/XCng7m_FIxI/AAAAAAAAAGg/ASH4GCGDMs0d55OZQGCSIQHXjRAKnkeTQCLcBGAs/s400/jitsi-logo-96x96.png",
          "onCreateFunction": "createPrivateMeeting"
        }
      ],
      "currentEventAccess": "READ_WRITE"
    }
  },
  "timeZone": "America/New_York",
  "runtimeVersion": "V8",
  "dependencies": {
    "enabledAdvancedServices": [
      {
        "userSymbol": "Calendar",
        "serviceId": "calendar",
        "version": "v3"
      }
    ],
    "libraries": [
      {
        "userSymbol": "OAuth2",
        "version": "43",
        "libraryId": "1B7FSrk5Zi6L1rSxxTDgDEUsPzlukDsi4KGuTMorsTQHhGBzBkMun4iDF"
      }
    ]
  },
  "webapp": {
    "access": "ANYONE",
    "executeAs": "USER_ACCESSING"
  },
  "exceptionLogging": "STACKDRIVER"
}

From the network it seems the browser makes a preflight request when redirected from the backend to the google script and fails with cors error. I tried to change the Content-Type in headers to text/plain;charset=utf-8 to avoid the preflight request but the cors issue still persists.

I am expecting the popup to get redirect to addon and exchange the auth code for auth token.


Solution

  • The mistake i was making was redirecting the popup to appscript from backend. Instead of returning the redirect uri with auth code concatenated in response from the backend to the popup/frontend and frontend redirects which fixes the cors mismatch error.