Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
'use client'

import { useMemo } from 'react'
import { Check } from 'lucide-react'
import { Button, Modal, ModalBody, ModalContent, ModalFooter, ModalHeader } from '@/components/emcn'
import { client } from '@/lib/auth/auth-client'
Expand Down Expand Up @@ -315,14 +316,28 @@ export function OAuthRequiredModal({
}
}

const displayScopes = requiredScopes.filter(
(scope) => !scope.includes('userinfo.email') && !scope.includes('userinfo.profile')
const newScopesSet = useMemo(
() =>
new Set(
(newScopes || []).filter(
(scope) => !scope.includes('userinfo.email') && !scope.includes('userinfo.profile')
)
),
[newScopes]
)
const newScopesSet = new Set(
(newScopes || []).filter(

const displayScopes = useMemo(() => {
const filtered = requiredScopes.filter(
(scope) => !scope.includes('userinfo.email') && !scope.includes('userinfo.profile')
)
)
return filtered.sort((a, b) => {
const aIsNew = newScopesSet.has(a)
const bIsNew = newScopesSet.has(b)
if (aIsNew && !bIsNew) return -1
if (!aIsNew && bIsNew) return 1
return 0
})
}, [requiredScopes, newScopesSet])

const handleConnectDirectly = async () => {
try {
Expand Down
73 changes: 37 additions & 36 deletions apps/sim/lib/auth/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,28 +110,20 @@ export const auth = betterAuth({
account: {
create: {
before: async (account) => {
// Only one credential per (userId, providerId) is allowed
// If user reconnects (even with a different external account), replace the existing one
const existing = await db.query.account.findFirst({
where: and(
eq(schema.account.userId, account.userId),
eq(schema.account.providerId, account.providerId),
eq(schema.account.accountId, account.accountId)
eq(schema.account.providerId, account.providerId)
),
})

if (existing) {
logger.warn(
'[databaseHooks.account.create.before] Duplicate account detected, updating existing',
{
existingId: existing.id,
userId: account.userId,
providerId: account.providerId,
accountId: account.accountId,
}
)

await db
.update(schema.account)
.set({
accountId: account.accountId,
accessToken: account.accessToken,
refreshToken: account.refreshToken,
idToken: account.idToken,
Expand Down Expand Up @@ -733,17 +725,17 @@ export const auth = betterAuth({
scopes: ['login', 'data'],
responseType: 'code',
redirectURI: `${getBaseUrl()}/api/auth/oauth2/callback/wealthbox`,
getUserInfo: async (tokens) => {
getUserInfo: async (_tokens) => {
try {
logger.info('Creating Wealthbox user profile from token data')

const uniqueId = `wealthbox-${Date.now()}`
const uniqueId = 'wealthbox-user'
const now = new Date()

return {
id: uniqueId,
name: 'Wealthbox User',
email: `${uniqueId.replace(/[^a-zA-Z0-9]/g, '')}@wealthbox.user`,
email: `${uniqueId}@wealthbox.user`,
emailVerified: false,
createdAt: now,
updatedAt: now,
Expand Down Expand Up @@ -1655,33 +1647,42 @@ export const auth = betterAuth({
redirectURI: `${getBaseUrl()}/api/auth/oauth2/callback/slack`,
getUserInfo: async (tokens) => {
try {
logger.info('Creating Slack bot profile from token data')
const response = await fetch('https://slack.com/api/auth.test', {
headers: {
Authorization: `Bearer ${tokens.accessToken}`,
},
})

// Extract user identifier from tokens if possible
let userId = 'slack-bot'
if (tokens.idToken) {
try {
const decodedToken = JSON.parse(
Buffer.from(tokens.idToken.split('.')[1], 'base64').toString()
)
if (decodedToken.sub) {
userId = decodedToken.sub
}
} catch (e) {
logger.warn('Failed to decode Slack ID token', { error: e })
}
if (!response.ok) {
logger.error('Slack auth.test failed', {
status: response.status,
statusText: response.statusText,
})
return null
}

const uniqueId = `${userId}-${Date.now()}`
const now = new Date()
const data = await response.json()

if (!data.ok) {
logger.error('Slack auth.test returned error', { error: data.error })
return null
}

const teamId = data.team_id || 'unknown'
const userId = data.user_id || data.bot_id || 'bot'
const teamName = data.team || 'Slack Workspace'

const uniqueId = `${teamId}-${userId}`

logger.info('Slack credential identifier', { teamId, userId, uniqueId, teamName })

return {
id: uniqueId,
name: 'Slack Bot',
email: `${uniqueId.replace(/[^a-zA-Z0-9]/g, '')}@slack.bot`,
name: teamName,
email: `${teamId}-${userId}@slack.bot`,
emailVerified: false,
createdAt: now,
updatedAt: now,
createdAt: new Date(),
updatedAt: new Date(),
}
} catch (error) {
logger.error('Error creating Slack bot profile:', { error })
Expand Down Expand Up @@ -1722,7 +1723,7 @@ export const auth = betterAuth({
const data = await response.json()
const now = new Date()

const userId = data.user_id || `webflow-${Date.now()}`
const userId = data.user_id || 'user'
const uniqueId = `webflow-${userId}`

return {
Expand Down
Loading