Budibase/budibase · error · Error

Microsoft OAuth authorization failed

Error message

Microsoft OAuth authorization failed

What it means

When Microsoft redirects back with an error query parameter (e.g. access_denied), the controller logs the error and description and throws this generic Error. It abstracts the provider-side failure so the caller only sees that authorization did not succeed.

Solutions

  1. Check server logs for the accompanying 'Microsoft OAuth authorization failed' entry to see the actual oauthError and description.
  2. Re-run the flow and approve the consent prompt; request admin consent in Azure AD for required scopes.
  3. Reduce/correct requested scopes to those the tenant permits (include offline_access so a refresh token is issued).
Defensive patterns

Strategy: try-catch

Validate before calling

const oauthError = new URL(callbackUrl).searchParams.get('error')
if (oauthError) {
  const desc = new URL(callbackUrl).searchParams.get('error_description')
  throw new Error(`OAuth rejected by Microsoft: ${oauthError} - ${desc}`)
}

Try / catch

try {
  await completeSharePointAuth(ctx)
} catch (e) {
  if (e.message === 'Microsoft OAuth authorization failed') {
    // inspect server logs for oauthError (e.g. access_denied) and guide user to consent
  } else throw e
}

Prevention

When it happens

Trigger: User denies consent on the Microsoft consent screen; Azure AD returns error=invalid_scope, access_denied, or similar; conditional-access/tenant policies block the app.

Common situations: App lacks admin consent for required SharePoint permissions; user cancels the consent dialog; requested scopes (e.g. Sites.ReadWrite.All, offline_access) not granted for the tenant.

Related errors


AI-assisted analysis of Budibase/budibase@a81a902e9a (2026-08-29). Data as JSON: /api/errors/82057c91cb49cb54. Report an issue: GitHub.

Appendix: source

Thrown at packages/server/src/api/controllers/ai/sharepointAuth.ts:121

    typeof statePayload?.appId === "string" ? statePayload.appId.trim() : ""
  if (
    !statePayload ||
    !stateAppId ||
    statePayload.provider !== MICROSOFT_PROVIDER
  ) {
    throw new Error("Microsoft OAuth state is invalid or expired")
  }
  const appId = stateAppId

  const oauthError = String(ctx.query.error || "").trim()
  if (oauthError) {
    const description = String(ctx.query.error_description || "").trim()
    console.error("Microsoft OAuth authorization failed", {
      appId,
      error: oauthError,
      hasDescription: !!description,
    })
    throw new Error("Microsoft OAuth authorization failed")
  }

  const code = String(ctx.query.code || "").trim()
  if (!code) {
    throw new Error(
      "Microsoft OAuth callback is missing the authorization code"
    )
  }

  const { clientId, clientSecret, tenantId } = getMicrosoftConfig()
  const platformUrl = await configs.getPlatformUrl({ tenantAware: false })
  const callbackUrl = `${platformUrl}/api/agent/knowledge-sources/sharepoint/callback`
  const tokenEndpoint = `https://login.microsoftonline.com/${tenantId}/oauth2/v2.0/token`

  const tokenResponse = await fetch(tokenEndpoint, {
    method: "POST",
    headers: {
      "Content-Type": "application/x-www-form-urlencoded",

View on GitHub (pinned to a81a902e9a)