{"record":{"id":"16ee9c2967ceabbd","repo":"Budibase/budibase","slug":"authentication-failed-with-microsoft-graph-verify","errorCode":null,"errorMessage":"Authentication failed with Microsoft Graph. Verify SharePoint application credentials and try again.","messagePattern":"Authentication failed with Microsoft Graph\\. Verify SharePoint application credentials and try again\\.","errorType":"http","errorClass":"HTTPError","httpStatus":401,"severity":"error","filePath":"packages/server/src/sdk/workspace/ai/knowledgeSources/sharepoint/connection.ts","lineNumber":243,"sourceCode":"      try {\n        const payload = (await response.json()) as {\n          error?: { code?: string; message?: string }\n        }\n        errorCode = payload?.error?.code || \"\"\n        errorDescription = payload?.error?.message || \"\"\n      } catch {\n        // noop\n      }\n      console.error(\"Failed to fetch SharePoint sites (app token)\", {\n        status: response.status,\n        errorCode,\n        hasErrorDescription: !!errorDescription,\n      })\n      let errorMessage = `Failed to fetch SharePoint sites (${response.status})`\n      if (response.status === 401) {\n        errorMessage =\n          \"Authentication failed with Microsoft Graph. Verify SharePoint application credentials and try again.\"\n        throw new HTTPError(errorMessage, 401)\n      } else if (response.status === 403) {\n        errorMessage =\n          \"Access denied by Microsoft Graph. Ensure SharePoint application permissions are granted.\"\n      } else if (response.status === 400 && errorDescription) {\n        errorMessage = `Microsoft Graph rejected the SharePoint search request: ${errorDescription}`\n      }\n      throw new HTTPError(errorMessage, 400)\n    }\n    return (await response.json()) as {\n      value?: Array<{\n        id?: string\n        displayName?: string\n        name?: string\n        webUrl?: string\n      }>\n      \"@odata.nextLink\"?: string\n    }\n  }","sourceCodeStart":225,"sourceCodeEnd":261,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/server/src/sdk/workspace/ai/knowledgeSources/sharepoint/connection.ts#L225-L261","documentation":"fetchSitesPage calls the Microsoft Graph /sites endpoint with a bearer token. A 401 response means the access token was rejected — expired, wrong tenant/audience, or issued from bad client credentials. The code translates this into a 401 HTTPError with an explicit message telling the user to verify the SharePoint application credentials.","triggerScenarios":"Graph returns HTTP 401 on the sites search request: expired/revoked bearer token, wrong clientSecret, token issued for the wrong tenant or audience, or clock skew in token caching.","commonSituations":"Rotated client secret not updated in the datasource config; Entra app registered in a different tenant than the sites being queried; cached OAuth2 token invalidated server-side; system clock drift causing premature token expiry.","solutions":["Verify the client ID and client secret in the datasource's OAuth2 auth config are current and correct.","Confirm the Entra app registration is in the same tenant as the SharePoint sites, and the token audience/scope is correct.","Clear the cached OAuth2 token so a fresh one is fetched on the next request.","Check server clock sync if tokens appear to expire instantly."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"const token = await getSharePointBearerToken(datasourceId, authConfigId)\nif (!token) {\n  throw new Error(\"No bearer token available; check SharePoint app credentials first\")\n}","typeGuard":null,"tryCatchPattern":"try {\n  await fetchSharePointSitesByDatasourceAuthConfig(datasourceId, authConfigId)\n} catch (err) {\n  if (err instanceof HTTPError && err.status === 401) {\n    // invalidate cached token, re-check client id/secret, then retry once\n  }\n  throw err\n}","preventionTips":["Keep the Entra client secret updated and monitor its expiry date.","Register the app in the same tenant as the target SharePoint sites.","Request the correct Graph scopes (e.g. Sites.Read.All) with application permissions.","Clear cached OAuth2 tokens after credential rotation."],"tags":["sharepoint","oauth2","authentication","http-401","microsoft-graph"],"backgroundTag":"auth-failed-401","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}