@@ -2591,6 +2591,73 @@ describe('OAuth Authorization', () => {
25912591 expect ( body . get ( 'refresh_token' ) ) . toBe ( 'refresh123' ) ;
25922592 } ) ;
25932593
2594+ it ( 'does not hide token persistence failures after refresh succeeds' , async ( ) => {
2595+ mockFetch . mockImplementation ( url => {
2596+ const urlString = url . toString ( ) ;
2597+
2598+ if ( urlString . includes ( '/.well-known/oauth-protected-resource' ) ) {
2599+ return Promise . resolve ( {
2600+ ok : true ,
2601+ status : 200 ,
2602+ json : async ( ) => ( {
2603+ resource : 'https://api.example.com/mcp-server' ,
2604+ authorization_servers : [ 'https://auth.example.com' ]
2605+ } )
2606+ } ) ;
2607+ } else if ( urlString . includes ( '/.well-known/oauth-authorization-server' ) ) {
2608+ return Promise . resolve ( {
2609+ ok : true ,
2610+ status : 200 ,
2611+ json : async ( ) => ( {
2612+ issuer : 'https://auth.example.com' ,
2613+ authorization_endpoint : 'https://auth.example.com/authorize' ,
2614+ token_endpoint : 'https://auth.example.com/token' ,
2615+ response_types_supported : [ 'code' ] ,
2616+ code_challenge_methods_supported : [ 'S256' ]
2617+ } )
2618+ } ) ;
2619+ } else if ( urlString . includes ( '/token' ) ) {
2620+ return Promise . resolve ( {
2621+ ok : true ,
2622+ status : 200 ,
2623+ json : async ( ) => ( {
2624+ access_token : 'new-access123' ,
2625+ token_type : 'Bearer' ,
2626+ expires_in : 3600 ,
2627+ refresh_token : 'new-refresh123'
2628+ } )
2629+ } ) ;
2630+ }
2631+
2632+ return Promise . resolve ( { ok : false , status : 404 } ) ;
2633+ } ) ;
2634+
2635+ const saveError = new Error ( 'token store unavailable' ) ;
2636+ ( mockProvider . clientInformation as Mock ) . mockResolvedValue ( {
2637+ client_id : 'test-client' ,
2638+ client_secret : 'test-secret'
2639+ } ) ;
2640+ ( mockProvider . tokens as Mock ) . mockResolvedValue ( {
2641+ access_token : 'old-access' ,
2642+ refresh_token : 'refresh123'
2643+ } ) ;
2644+ ( mockProvider . saveTokens as Mock ) . mockRejectedValue ( saveError ) ;
2645+
2646+ await expect (
2647+ auth ( mockProvider , {
2648+ serverUrl : 'https://api.example.com/mcp-server'
2649+ } )
2650+ ) . rejects . toThrow ( 'token store unavailable' ) ;
2651+
2652+ expect ( mockProvider . saveTokens ) . toHaveBeenCalledWith (
2653+ expect . objectContaining ( {
2654+ access_token : 'new-access123' ,
2655+ refresh_token : 'new-refresh123'
2656+ } )
2657+ ) ;
2658+ expect ( mockProvider . redirectToAuthorization ) . not . toHaveBeenCalled ( ) ;
2659+ } ) ;
2660+
25942661 it ( 'skips default PRM resource validation when custom validateResourceURL is provided' , async ( ) => {
25952662 const mockValidateResourceURL = vi . fn ( ) . mockResolvedValue ( undefined ) ;
25962663 const providerWithCustomValidation = {
0 commit comments