@@ -92,7 +92,6 @@ const INTERNAL_AUTH = { success: true, userId: 'user-1', authType: 'internal_jwt
9292describe ( 'resolveCredentialToken' , ( ) => {
9393 beforeEach ( ( ) => {
9494 vi . clearAllMocks ( )
95- mockResolveOAuthAccountId . mockResolvedValue ( null )
9695 } )
9796
9897 it ( 'fails closed when the credential is not authorized' , async ( ) => {
@@ -103,6 +102,7 @@ describe('resolveCredentialToken', () => {
103102
104103 const result = await resolveCredentialToken ( INTERNAL_AUTH , {
105104 requestId : 'req-1' ,
105+ resolvedCredential : null ,
106106 credentialId : 'cred-1' ,
107107 } )
108108
@@ -124,7 +124,7 @@ describe('resolveCredentialToken', () => {
124124
125125 const result = await resolveCredentialToken (
126126 { success : true , authType : 'internal_jwt' } ,
127- { requestId : 'req-1' , credentialId : 'cred-1' }
127+ { requestId : 'req-1' , credentialId : 'cred-1' , resolvedCredential : null }
128128 )
129129
130130 expect ( result ) . toEqual ( { ok : false , status : 403 , error : 'Authentication required' } )
@@ -147,6 +147,7 @@ describe('resolveCredentialToken', () => {
147147
148148 const result = await resolveCredentialToken ( INTERNAL_AUTH , {
149149 requestId : 'req-1' ,
150+ resolvedCredential : null ,
150151 credentialId : 'cred-1' ,
151152 workflowId : 'wf-1' ,
152153 } )
@@ -177,6 +178,7 @@ describe('resolveCredentialToken', () => {
177178
178179 const result = await resolveCredentialToken ( INTERNAL_AUTH , {
179180 requestId : 'req-1' ,
181+ resolvedCredential : null ,
180182 credentialId : 'cred-1' ,
181183 } )
182184
@@ -201,6 +203,7 @@ describe('resolveCredentialToken', () => {
201203 await expect (
202204 resolveCredentialToken ( INTERNAL_AUTH , {
203205 requestId : 'req-1' ,
206+ resolvedCredential : null ,
204207 credentialId : 'cred-1' ,
205208 } )
206209 ) . resolves . toEqual ( {
@@ -231,6 +234,7 @@ describe('resolveCredentialToken', () => {
231234 await expect (
232235 resolveCredentialToken ( INTERNAL_AUTH , {
233236 requestId : 'req-1' ,
237+ resolvedCredential : null ,
234238 credentialId : 'cred-1' ,
235239 } )
236240 ) . resolves . toEqual ( {
@@ -251,6 +255,7 @@ describe('resolveCredentialToken', () => {
251255
252256 const result = await resolveCredentialToken ( INTERNAL_AUTH , {
253257 requestId : 'req-1' ,
258+ resolvedCredential : null ,
254259 credentialId : 'cred-1' ,
255260 } )
256261
@@ -259,34 +264,26 @@ describe('resolveCredentialToken', () => {
259264 } )
260265
261266 it ( 'authorizes service-account credentials before minting a token' , async ( ) => {
262- mockResolveOAuthAccountId . mockResolvedValue ( {
263- credentialType : 'service_account' ,
264- credentialId : 'sa-1' ,
265- providerId : 'google' ,
266- workspaceId : 'ws-1' ,
267- accountId : '' ,
268- usedCredentialTable : true ,
269- } )
270267 mockAuthorizeCredentialUseForAuth . mockResolvedValue ( { ok : false , error : 'Unauthorized' } )
271268
272269 const result = await resolveCredentialToken ( INTERNAL_AUTH , {
273270 requestId : 'req-1' ,
274271 credentialId : 'cred-1' ,
272+ resolvedCredential : {
273+ credentialType : 'service_account' ,
274+ credentialId : 'sa-1' ,
275+ providerId : 'google' ,
276+ workspaceId : 'ws-1' ,
277+ accountId : '' ,
278+ usedCredentialTable : true ,
279+ } ,
275280 } )
276281
277282 expect ( result ) . toEqual ( { ok : false , status : 403 , error : 'Unauthorized' } )
278283 expect ( mockResolveServiceAccountToken ) . not . toHaveBeenCalled ( )
279284 } )
280285
281286 it ( 'surfaces the classified service-account failure code' , async ( ) => {
282- mockResolveOAuthAccountId . mockResolvedValue ( {
283- credentialType : 'service_account' ,
284- credentialId : 'sa-1' ,
285- providerId : 'atlassian' ,
286- workspaceId : 'ws-1' ,
287- accountId : '' ,
288- usedCredentialTable : true ,
289- } )
290287 mockAuthorizeCredentialUseForAuth . mockResolvedValue ( { ok : true , requesterUserId : 'user-1' } )
291288 mockResolveServiceAccountToken . mockRejectedValue (
292289 new TokenServiceAccountValidationError ( 'invalid_credentials' , 401 )
@@ -295,6 +292,14 @@ describe('resolveCredentialToken', () => {
295292 const result = await resolveCredentialToken ( INTERNAL_AUTH , {
296293 requestId : 'req-1' ,
297294 credentialId : 'cred-1' ,
295+ resolvedCredential : {
296+ credentialType : 'service_account' ,
297+ credentialId : 'sa-1' ,
298+ providerId : 'atlassian' ,
299+ workspaceId : 'ws-1' ,
300+ accountId : '' ,
301+ usedCredentialTable : true ,
302+ } ,
298303 } )
299304
300305 expect ( result ) . toEqual ( {
@@ -308,6 +313,7 @@ describe('resolveCredentialToken', () => {
308313 it ( 'rejects a malformed impersonation subject before touching the credential' , async ( ) => {
309314 const result = await resolveCredentialToken ( INTERNAL_AUTH , {
310315 requestId : 'req-1' ,
316+ resolvedCredential : null ,
311317 credentialId : 'cred-1' ,
312318 impersonateEmail : 'not-an-email' ,
313319 } )
@@ -378,6 +384,27 @@ describe('resolveCredentialAccessToken', () => {
378384 } )
379385 } )
380386
387+ it ( 'treats an empty impersonation subject as absent' , async ( ) => {
388+ mockAuthorizeCredentialUseForAuth . mockResolvedValue ( {
389+ ok : true ,
390+ requesterUserId : 'user-1' ,
391+ credentialOwnerUserId : 'owner-1' ,
392+ workspaceId : 'ws-1' ,
393+ resolvedCredentialId : 'account-1' ,
394+ } )
395+ mockGetCredential . mockResolvedValue ( { providerId : 'google' } )
396+ mockRefreshTokenIfNeeded . mockResolvedValue ( { accessToken : 'fresh' , refreshed : false } )
397+
398+ const result = await resolveCredentialAccessToken ( {
399+ requestId : 'req-1' ,
400+ credentialId : 'cred-1' ,
401+ impersonateEmail : '' ,
402+ authenticate,
403+ } )
404+
405+ expect ( result ) . toEqual ( { ok : true , token : { accessToken : 'fresh' , idToken : undefined } } )
406+ } )
407+
381408 it ( 'rejects a managed credential when no delegation resolver is wired' , async ( ) => {
382409 mockResolveOAuthAccountId . mockResolvedValue ( MANAGED_RESOLVED )
383410
0 commit comments