Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
address comments
  • Loading branch information
icecrasher321 committed Mar 15, 2026
commit befc1ca01f6f6047df8e588f2bb4d67551175053
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import {
Tooltip,
} from '@/components/emcn'
import { useSession } from '@/lib/auth/auth-client'
import { writeOAuthReturnContext } from '@/lib/credentials/client-state'
import { consumeOAuthReturnContext, writeOAuthReturnContext } from '@/lib/credentials/client-state'
import {
getCanonicalScopesForProvider,
getProviderIdFromServiceId,
Expand Down Expand Up @@ -593,7 +593,10 @@ export function AddConnectorModal({ open, onOpenChange, knowledgeBaseId }: AddCo
{connectorConfig && connectorConfig.auth.mode === 'oauth' && connectorProviderId && (
<OAuthRequiredModal
isOpen={showOAuthModal}
onClose={() => setShowOAuthModal(false)}
onClose={() => {
consumeOAuthReturnContext()
setShowOAuthModal(false)
}}
provider={connectorProviderId}
toolName={connectorConfig.name}
requiredScopes={getCanonicalScopesForProvider(connectorProviderId)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import {
Tooltip,
} from '@/components/emcn'
import { cn } from '@/lib/core/utils/cn'
import { writeOAuthReturnContext } from '@/lib/credentials/client-state'
import { consumeOAuthReturnContext, writeOAuthReturnContext } from '@/lib/credentials/client-state'
import {
getCanonicalScopesForProvider,
getProviderIdFromServiceId,
Expand Down Expand Up @@ -475,7 +475,10 @@ function ConnectorCard({
{showOAuthModal && serviceId && providerId && (
<OAuthRequiredModal
isOpen={showOAuthModal}
onClose={() => setShowOAuthModal(false)}
onClose={() => {
consumeOAuthReturnContext()
setShowOAuthModal(false)
}}
provider={providerId as OAuthProvider}
toolName={connectorDef?.name ?? connector.connectorType}
requiredScopes={getCanonicalScopesForProvider(providerId)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,9 @@ export function IntegrationsManager() {
}),
})

const oauthPreCount = credentials.filter((c) => c.type === 'oauth').length
const oauthPreCount = credentials.filter(
(c) => c.type === 'oauth' && c.providerId === selectedOAuthService.providerId
).length
const returnOrigin = pendingReturnOriginRef.current
pendingReturnOriginRef.current = undefined

Expand Down Expand Up @@ -548,7 +550,9 @@ export function IntegrationsManager() {
}),
})

const oauthPreCount = credentials.filter((c) => c.type === 'oauth').length
const oauthPreCount = credentials.filter(
(c) => c.type === 'oauth' && c.providerId === selectedCredential.providerId
).length
writeOAuthReturnContext({
origin: 'integrations',
displayName: selectedCredential.displayName,
Expand Down
16 changes: 12 additions & 4 deletions apps/sim/hooks/use-oauth-return.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use client'

import { useEffect } from 'react'
import { useEffect, useRef } from 'react'
import { useParams, useRouter } from 'next/navigation'
import { toast } from '@/components/emcn'
import {
Expand All @@ -12,6 +12,7 @@ import { useNotificationStore } from '@/stores/notifications/store'

const OAUTH_CREDENTIAL_UPDATED_EVENT = 'oauth-credentials-updated'
const SETTINGS_RETURN_URL_KEY = 'settings-return-url'
const CONTEXT_MAX_AGE_MS = 15 * 60 * 1000

async function resolveOAuthMessage(ctx: OAuthReturnContext): Promise<string> {
if (ctx.reconnect) {
Expand All @@ -28,11 +29,12 @@ async function resolveOAuthMessage(ctx: OAuthReturnContext): Promise<string> {
providerId: string | null
}>

if (oauthCredentials.length > ctx.preCount) {
const forProvider = oauthCredentials.filter((c) => c.providerId === ctx.providerId)
if (forProvider.length > ctx.preCount) {
return `"${ctx.displayName}" credential connected successfully.`
}

const existing = oauthCredentials.find((c) => c.providerId === ctx.providerId)
const existing = forProvider[0]
return `This account is already connected as "${existing?.displayName || ctx.displayName}".`
} catch {
return `"${ctx.displayName}" credential connected successfully.`
Expand Down Expand Up @@ -61,15 +63,19 @@ export function useOAuthReturnRouter() {
const router = useRouter()
const params = useParams()
const workspaceId = params.workspaceId as string
const handledRef = useRef(false)

useEffect(() => {
if (handledRef.current) return
const ctx = readOAuthReturnContext()
if (!ctx) return
if (Date.now() - ctx.requestedAt > 15 * 60 * 1000) {
if (Date.now() - ctx.requestedAt > CONTEXT_MAX_AGE_MS) {
consumeOAuthReturnContext()
return
}

handledRef.current = true

if (ctx.origin === 'integrations') {
consumeOAuthReturnContext()
void (async () => {
Expand Down Expand Up @@ -110,6 +116,7 @@ export function useOAuthReturnForWorkflow(workflowId: string) {
if (!ctx || ctx.origin !== 'workflow') return
if (ctx.workflowId !== workflowId) return
consumeOAuthReturnContext()
if (Date.now() - ctx.requestedAt > CONTEXT_MAX_AGE_MS) return

void (async () => {
const message = await resolveOAuthMessage(ctx)
Expand All @@ -129,6 +136,7 @@ export function useOAuthReturnForKBConnectors(knowledgeBaseId: string) {
if (!ctx || ctx.origin !== 'kb-connectors') return
if (ctx.knowledgeBaseId !== knowledgeBaseId) return
consumeOAuthReturnContext()
if (Date.now() - ctx.requestedAt > CONTEXT_MAX_AGE_MS) return

void (async () => {
const message = await resolveOAuthMessage(ctx)
Expand Down
Loading