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.
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.