11import { AuditAction , AuditResourceType , recordAudit } from '@sim/audit'
2- import {
3- resolvePrincipalSubject ,
4- type WorkflowExecutionDelegatedPrincipal ,
5- } from '@sim/auth/principal'
62import { createLogger } from '@sim/logger'
73import { getErrorMessage } from '@sim/utils/errors'
84import { type NextRequest , NextResponse } from 'next/server'
@@ -14,20 +10,15 @@ import {
1410import { getValidationErrorMessage , parseRequest } from '@/lib/api/server'
1511import { authorizeCredentialUse } from '@/lib/auth/credential-access'
1612import { AuthType , checkSessionOrInternalAuth } from '@/lib/auth/hybrid'
17- import { asOrchestrationError , statusForOrchestrationError } from '@/lib/core/orchestration/types'
1813import { generateRequestId } from '@/lib/core/utils/request'
1914import { withRouteHandler } from '@/lib/core/utils/with-route-handler'
15+ import { authenticateManagedOAuthDelegation } from '@/lib/credentials/application/managed-oauth-delegation'
16+ import { getCredential , getOAuthToken } from '@/lib/oauth/credential-service'
2017import {
21- authenticateManagedOAuthDelegation ,
22- InvalidManagedOAuthDelegationError ,
23- } from '@/lib/credentials/application/managed-oauth-delegation'
24- import { resolveManagedOAuthCredentialToken } from '@/lib/credentials/application/resolve-managed-oauth-token'
25- import { ManagedOAuthCredentialError } from '@/lib/credentials/managed-oauth'
26- import { getCredential , getOAuthToken , resolveOAuthAccountId } from '@/lib/oauth/credential-service'
27- import { completeOAuthCredentialToken , resolveCredentialToken } from '@/lib/oauth/token-resolution'
28- import { getCanonicalScopesForProvider } from '@/lib/oauth/utils'
18+ completeOAuthCredentialToken ,
19+ resolveCredentialAccessToken ,
20+ } from '@/lib/oauth/token-resolution'
2921import { captureServerEvent } from '@/lib/posthog/server'
30- import { getToolMetadata } from '@/tools/metadata'
3122
3223export const dynamic = 'force-dynamic'
3324
@@ -130,142 +121,21 @@ export const POST = withRouteHandler(async (request: NextRequest) => {
130121 }
131122 }
132123
133- const resolved = credentialId ? await resolveOAuthAccountId ( credentialId ) : null
134- if ( resolved ?. credentialType === 'managed_oauth' && resolved . credentialId ) {
135- const managedOAuthDelegation = parsed . data . headers ?. [ MANAGED_OAUTH_DELEGATION_HEADER ]
136- if ( ! managedOAuthDelegation ) {
137- return NextResponse . json (
138- {
139- code : 'MANAGED_CREDENTIAL_DELEGATION_REQUIRED' ,
140- error : 'Managed credentials can only be used by an authenticated workflow execution' ,
141- } ,
142- { status : 403 }
143- )
144- }
145-
146- let managedOAuthPrincipal : WorkflowExecutionDelegatedPrincipal
147- try {
148- managedOAuthPrincipal = await authenticateManagedOAuthDelegation (
149- managedOAuthDelegation ,
150- resolved . credentialId
151- )
152- } catch ( error ) {
153- if ( ! ( error instanceof InvalidManagedOAuthDelegationError ) ) throw error
154- return NextResponse . json (
155- {
156- code : 'MANAGED_CREDENTIAL_DELEGATION_INVALID' ,
157- error : error . message ,
158- } ,
159- { status : 401 }
160- )
161- }
162- if ( ! toolId ) {
163- return NextResponse . json (
164- {
165- code : 'MANAGED_CREDENTIAL_TOOL_REQUIRED' ,
166- error : 'A tool ID is required to use a managed credential' ,
167- } ,
168- { status : 400 }
169- )
170- }
171-
172- const toolMetadata = getToolMetadata ( toolId )
173- if ( ! toolMetadata ?. oauth ?. required ) {
174- logger . error ( `[${ requestId } ] Tool is not configured for managed OAuth` , { toolId } )
175- return NextResponse . json (
176- {
177- code : 'MANAGED_CREDENTIAL_TOOL_UNSUPPORTED' ,
178- error : 'This tool is not configured to use managed credentials' ,
179- } ,
180- { status : 500 }
181- )
182- }
183- const requiredScopes =
184- toolMetadata . oauth . requiredScopes ??
185- getCanonicalScopesForProvider ( toolMetadata . oauth . provider )
186- if ( requiredScopes . length === 0 ) {
187- logger . error ( `[${ requestId } ] Tool has no trusted OAuth scope policy` , {
188- toolId,
189- providerId : toolMetadata . oauth . provider ,
190- } )
191- return NextResponse . json (
192- {
193- code : 'MANAGED_CREDENTIAL_TOOL_UNSUPPORTED' ,
194- error : 'This tool is not configured to use managed credentials' ,
195- } ,
196- { status : 500 }
197- )
198- }
199-
200- try {
201- const result = await resolveManagedOAuthCredentialToken . execute ( {
202- principal : managedOAuthPrincipal ,
203- input : {
204- credentialId : resolved . credentialId ,
205- expectedProviderId : toolMetadata . oauth . provider ,
206- requiredScopes,
207- toolId,
208- } ,
209- request,
210- } )
211-
212- const managedOAuthSubject = resolvePrincipalSubject ( managedOAuthPrincipal )
213- if ( managedOAuthSubject ?. kind === 'sim_user' ) {
214- captureServerEvent (
215- managedOAuthSubject . userId ,
216- 'credential_used' ,
217- {
218- credential_type : 'managed_oauth' ,
219- provider_id : toolMetadata . oauth . provider ,
220- workspace_id : managedOAuthPrincipal . workspaceId ,
221- } ,
222- { groups : { workspace : managedOAuthPrincipal . workspaceId } }
223- )
224- }
225-
226- return NextResponse . json (
227- {
228- accessToken : result . accessToken ,
229- ...( result . idToken ? { idToken : result . idToken } : { } ) ,
230- } ,
231- { status : 200 }
232- )
233- } catch ( error ) {
234- if ( error instanceof ManagedOAuthCredentialError ) {
235- logger . warn ( `[${ requestId } ] Managed OAuth credential rejected` , {
236- credentialId : resolved . credentialId ,
237- code : error . code ,
238- } )
239- return NextResponse . json (
240- { code : error . code , error : error . message } ,
241- { status : error . statusCode }
242- )
243- }
244-
245- const orchestrationError = asOrchestrationError ( error )
246- if ( orchestrationError ) {
247- return NextResponse . json (
248- {
249- code : 'MANAGED_CREDENTIAL_UNAUTHORIZED' ,
250- error : orchestrationError . message ,
251- } ,
252- { status : statusForOrchestrationError ( orchestrationError . code ) }
253- )
254- }
255- throw error
256- }
257- }
258-
259- const auth = await checkSessionOrInternalAuth ( request , { requireWorkflowId : false } )
260- const result = await resolveCredentialToken ( auth , {
124+ const managedOAuthDelegation = parsed . data . headers ?. [ MANAGED_OAUTH_DELEGATION_HEADER ]
125+ const result = await resolveCredentialAccessToken ( {
261126 requestId,
262127 credentialId,
263128 workflowId : workflowId ?? undefined ,
129+ toolId,
264130 scopes,
265131 impersonateEmail,
266132 callerUserId,
267133 auditRequest : request ,
268- resolvedCredential : resolved ,
134+ authenticate : ( ) => checkSessionOrInternalAuth ( request , { requireWorkflowId : false } ) ,
135+ resolveManagedPrincipal : managedOAuthDelegation
136+ ? ( managedCredentialId : string ) =>
137+ authenticateManagedOAuthDelegation ( managedOAuthDelegation , managedCredentialId )
138+ : undefined ,
269139 } )
270140
271141 if ( ! result . ok ) {
0 commit comments