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.

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)

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.