{"record":{"id":"fbb64f9f0a21a1d0","repo":"Budibase/budibase","slug":"error-constructing-google-authentication-strategy","errorCode":null,"errorMessage":"Error constructing google authentication strategy: ${err}","messagePattern":"Error constructing google authentication strategy: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/backend-core/src/middleware/passport/sso/google.ts","lineNumber":72,"sourceCode":"    const { clientID, clientSecret } = config\n\n    if (!clientID || !clientSecret) {\n      throw new Error(\n        \"Configuration invalid. Must contain google clientID and clientSecret\"\n      )\n    }\n\n    const verify = buildVerifyFn(saveUserFn)\n    return new GoogleStrategy(\n      {\n        clientID: config.clientID,\n        clientSecret: config.clientSecret,\n        callbackURL: callbackUrl,\n      },\n      verify\n    )\n  } catch (err: any) {\n    throw new Error(`Error constructing google authentication strategy: ${err}`)\n  }\n}\n\nexport async function getCallbackUrl(config: GoogleInnerConfig) {\n  return ssoCallbackUrl(ConfigType.GOOGLE, config)\n}\n","sourceCodeStart":54,"sourceCodeEnd":79,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/backend-core/src/middleware/passport/sso/google.ts#L54-L79","documentation":"strategyFactory wraps construction of the passport Google OAuth2 strategy in a try/catch and rethrows any construction failure with this prefix. It means the underlying google-auth-library/passport-google-oauth20 constructor threw while being instantiated with the provided clientId, clientSecret and callbackURL. The original error text is appended so you can see the real cause.","triggerScenarios":"Calling strategyFactory with a malformed or missing clientId/clientSecret, an invalid callbackUrl shape, or a dependency-level failure inside new GoogleStrategy(config, verify) (e.g. missing constructor option required by the passport-google library version).","commonSituations":"SSO/Google OAuth provider configured in Budibase admin with an empty or wrong client secret; pasted config containing whitespace/newlines; upgrading passport-google-oauth20 so a previously-valid config option is rejected; callback URL not a valid absolute URL.","solutions":["Check the appended original error text in the message to identify the underlying cause","Verify the Google OAuth provider config (clientId, clientSecret, callbackUrl) in the admin SSO settings is complete and valid","Re-create the OAuth client credentials in Google Cloud Console, ensuring the authorized redirect URI matches the computed callback URL","Confirm the installed passport-google-oauth20 version matches what the config object expects"],"exampleFix":"// before\nawait strategyFactory({ config: { clientID: \"\", clientSecret: \"\", callbackURL: \"not-a-url\" } })\n// after\nawait strategyFactory({ config: { clientID: \"1234.apps.googleusercontent.com\", clientSecret: \"GOCSPX-xxxx\", callbackURL: \"https://app.example.com/api/global/auth/google/callback\" } })","handlingStrategy":"try-catch","validationCode":"function validateGoogleConfig(config) {\n  return Boolean(\n    config &&\n    typeof config.clientID === \"string\" && config.clientID.length > 0 &&\n    typeof config.clientSecret === \"string\" && config.clientSecret.length > 0 &&\n    typeof config.callbackURL === \"string\" &&\n    /^https?:\\/\\//.test(config.callbackURL)\n  )\n}","typeGuard":"function isGoogleConfig(config): config is { clientID: string; clientSecret: string; callbackURL: string } {\n  return typeof config?.clientID === \"string\" &&\n    typeof config?.clientSecret === \"string\" &&\n    typeof config?.callbackURL === \"string\"\n}","tryCatchPattern":"try {\n  const strategy = await strategyFactory({ config })\n} catch (err) {\n  if (String(err.message).startsWith(\"Error constructing google authentication strategy\")) {\n    // log err.message verbatim — the underlying cause is appended after the prefix\n  }\n}","preventionTips":["Validate clientId/clientSecret/callbackURL are non-empty and the callback is an absolute https URL before calling strategyFactory","Store SSO credentials through the admin UI rather than manual DB edits","Pin and test passport-google-oauth20 versions in CI after upgrades","Test the SSO login flow in staging whenever Google credentials are rotated"],"tags":["sso","oauth","configuration","passport"],"backgroundTag":"sso-provider-configuration-invalid","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}