Budibase/budibase · error · Error

Microsoft OAuth response did not include an access token

Error message

Microsoft OAuth response did not include an access token

What it means

completeSharePointAuth requires an access_token from Microsoft's token exchange to authenticate subsequent SharePoint API calls. This error means the code exchange succeeded (HTTP 200) but the response body contained no access_token, so the OAuth flow cannot proceed.

Solutions

  1. Log the HTTP status and tokenPayload shape to see what Microsoft actually returned
  2. Verify the token request uses the correct endpoint (https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token), client_id, client_secret, and redirect_uri matching the app registration
  3. Retry the authorization flow; if the code was already redeemed, request a fresh code
Defensive patterns

Strategy: try-catch

Validate before calling

const res = await fetch(tokenEndpoint, { method: 'POST', body })
if (!res.ok) throw new Error(`Token endpoint returned ${res.status}`)
const payload = await res.json()
if (typeof payload.access_token !== 'string') throw new Error('No access_token in response: ' + JSON.stringify(Object.keys(payload)))

Type guard

function hasAccessToken(p: unknown): p is { access_token: string } {
  return typeof p === 'object' && p !== null && 'access_token' in p && typeof (p as { access_token: unknown }).access_token === 'string'
}

Try / catch

try {
  await completeSharePointAuth(params)
} catch (e) {
  if (e.message.includes('access token')) {
    // inspect raw token response and restart authorization flow with a fresh code
  }
}

Prevention

When it happens

Trigger: Microsoft's token endpoint returns an unexpected payload (e.g. an error-shaped JSON or empty body with 200) when completing the SharePoint OAuth code exchange.

Common situations: Misconfigured redirect URI causing an error response being parsed as a payload; wrong tenant/endpoint (v1 vs v2 token endpoint); network proxy returning an HTML error page with 200.

Related errors


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

Appendix: source

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

  })
  const tokenPayload = await tokenResponse.json()
  if (!tokenResponse.ok) {
    console.error("Microsoft OAuth token exchange failed", {
      appId,
      status: tokenResponse.status,
      error: tokenPayload?.error,
      hasDescription: !!tokenPayload?.error_description,
    })
    throw new Error("Failed to exchange Microsoft OAuth code")
  }

  const refreshToken = tokenPayload?.refresh_token
  const accessToken = tokenPayload?.access_token
  if (!refreshToken) {
    throw new Error("Microsoft OAuth response did not include a refresh token")
  }
  if (!accessToken) {
    throw new Error("Microsoft OAuth response did not include an access token")
  }

  const expiresIn = Number(tokenPayload?.expires_in || 0)
  const tokenType = tokenPayload?.token_type || "Bearer"
  const bearerToken = `${tokenType} ${accessToken}`
  let account = "unknown"

  try {
    const meResponse = await fetch(
      `${MICROSOFT_GRAPH_BASE}/me?$select=displayName,mail,userPrincipalName`,
      {
        headers: {
          Authorization: bearerToken,
        },
      }
    )
    if (meResponse.ok) {
      const mePayload = await meResponse.json()

View on GitHub (pinned to a81a902e9a)