diff --git a/CHANGELOG.md b/CHANGELOG.md index 9fadcf22d..ab841e434 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fixed issue where using multiple identity providers of the same type (e.g., gitlab) would result in unexpected behaviours. [#1177](https://github.com/sourcebot-dev/sourcebot/pull/1177) - Fixed a race condition where large repositories could be indexed twice within a single reindex interval. [#1298](https://github.com/sourcebot-dev/sourcebot/pull/1298) - Upgraded `shell-quote` to `^1.8.4`. [#1299](https://github.com/sourcebot-dev/sourcebot/pull/1299) +- [EE] Fixed MCP OAuth connectors (e.g. Atlassian) rejecting authorization when `offline_access` was not enabled. When adding a connector, the scopes dialog now pre-selects `offline_access` (admins can untick it) and warns when it is the only selected scope. [#1292](https://github.com/sourcebot-dev/sourcebot/pull/1292) ## [5.0.1] - 2026-06-04 diff --git a/docs/docs/features/ask/connectors.mdx b/docs/docs/features/ask/connectors.mdx index 2d743519a..bf472beb6 100644 --- a/docs/docs/features/ask/connectors.mdx +++ b/docs/docs/features/ask/connectors.mdx @@ -56,6 +56,8 @@ Owners can configure which OAuth scopes users authorize when connecting to a con Sourcebot checks the connector for discoverable scopes and shows them as options. You can also add custom scopes. +When you select scopes, most providers grant only what you request, so include the resource scopes the connector's tools need. +
+ +`offline_access` is pre-selected when you add a connector that offers it because token refresh requires it. You can deselect it to opt out of refresh tokens, but users will need to re-authenticate every time their access token expires. Some connectors, such as Atlassian, reject authorization entirely without it. +For more information, see the [OpenID Connect `offline_access` documentation](https://openid.net/specs/openid-connect-core-1_0.html#OfflineAccess). + + ## Tool Permissions Owners can configure how Ask Sourcebot may use each tool exposed by a connector. Changes take effect immediately and do not require users to re-authenticate. @@ -121,4 +128,3 @@ You can see all available connectors on this page. After you connect one, you ca
- diff --git a/packages/web/src/app/(app)/settings/workspaceAskAgent/workspaceAskAgentPage.tsx b/packages/web/src/app/(app)/settings/workspaceAskAgent/workspaceAskAgentPage.tsx index 08879ee85..f71ed904b 100644 --- a/packages/web/src/app/(app)/settings/workspaceAskAgent/workspaceAskAgentPage.tsx +++ b/packages/web/src/app/(app)/settings/workspaceAskAgent/workspaceAskAgentPage.tsx @@ -22,16 +22,17 @@ import { Label } from "@/components/ui/label"; import { Separator } from "@/components/ui/separator"; import { Skeleton } from "@/components/ui/skeleton"; import { Textarea } from "@/components/ui/textarea"; +import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"; import { checkMcpServerDynamicClientRegistration, createMcpServer, createStaticOAuthMcpServer, deleteMcpServer, updateMcpServerOAuthScopes } from "@/ee/features/chat/mcp/actions"; import { ConnectMcpButton } from "@/ee/features/chat/mcp/components/connectMcpButton"; import { ConnectorCard } from "@/ee/features/chat/mcp/components/connectorCard"; import { useMcpToolMetadata } from "@/ee/features/chat/mcp/hooks/useMcpToolMetadata"; import { invalidateMcpConfigurationQueries, mcpQueryKeys } from "@/ee/features/chat/mcp/queryKeys"; -import { buildMcpOAuthScopeEntries, getMcpRequestedOAuthScopes, normalizeMcpRequestedOAuthScopes } from "@/ee/features/chat/mcp/oauthScopeUtils"; +import { buildMcpOAuthScopeEntries, getMcpRequestedOAuthScopes, normalizeMcpRequestedOAuthScopes, OFFLINE_ACCESS_SCOPE } from "@/ee/features/chat/mcp/oauthScopeUtils"; import { pluralize } from "@/features/chat/mcp/utils"; import { cn, isServiceError } from "@/lib/utils"; import { useQuery, useQueryClient } from "@tanstack/react-query"; -import { AlertTriangleIcon, CableIcon, CopyIcon, KeyRoundIcon, Loader2, MoreHorizontalIcon, PlusIcon, Trash2Icon, WrenchIcon } from "lucide-react"; +import { AlertTriangleIcon, CableIcon, CopyIcon, InfoIcon, KeyRoundIcon, Loader2, MoreHorizontalIcon, PlusIcon, Trash2Icon, WrenchIcon } from "lucide-react"; import { PrefabConnectorPopover } from "@/ee/features/chat/mcp/components/prefabConnectorPopover"; import Markdown from "react-markdown"; import { getStaticOAuthDescription, type PrefabMcpServer } from "@/ee/features/chat/mcp/prefabMcpServers"; @@ -89,6 +90,11 @@ function OAuthScopesInput({ const [oauthScopeSearchInput, setOAuthScopeSearchInput] = useState(""); const selectedOAuthScopeSet = new Set(selectedOAuthScopes); const requestedOAuthScopes = getMcpRequestedOAuthScopes(selectedOAuthScopes, customOAuthScopeInput); + const hasDiscoveredResourceScopes = discoveredOAuthScopes.some((scope) => scope !== OFFLINE_ACCESS_SCOPE); + const isOfflineAccessOnly = requestedOAuthScopes.length === 1 + && requestedOAuthScopes[0] === OFFLINE_ACCESS_SCOPE + && hasDiscoveredResourceScopes; + const isNoScopesSelected = requestedOAuthScopes.length === 0 && hasDiscoveredResourceScopes; const filteredOAuthScopes = useMemo(() => { const query = oauthScopeSearchInput.trim().toLowerCase(); if (!query) { @@ -154,6 +160,18 @@ function OAuthScopesInput({ aria-label={`Request ${scope}`} /> {scope} + {scope === OFFLINE_ACCESS_SCOPE && ( + + + event.preventDefault()}> + + + + + Required for refresh tokens. Without this scope, users must re-authenticate whenever their access token expires, and some connectors reject authorization entirely. + + + )} {onRemoveOAuthScope && (