@@ -217,8 +217,9 @@ describe('OAuth Authorization', () => {
217217 } ) ;
218218
219219 describe ( 'handleOAuthUnauthorized' , ( ) => {
220- it ( 'uses stored token scope, accumulated context scope, and resource metadata when reauthorizing ' , async ( ) => {
220+ it ( 'forces reauthorization with the full scope union instead of refreshing a narrower token ' , async ( ) => {
221221 const resourceMetadataUrl = new URL ( 'https://resource.example.com/custom-prm' ) ;
222+ const tokenEndpoint = 'https://auth.example.com/token' ;
222223 const provider : OAuthClientProvider = {
223224 get redirectUrl ( ) {
224225 return 'http://localhost:3000/callback' ;
@@ -230,7 +231,12 @@ describe('OAuth Authorization', () => {
230231 } ;
231232 } ,
232233 clientInformation : vi . fn ( ) . mockResolvedValue ( { client_id : 'test-client' } ) ,
233- tokens : vi . fn ( ) . mockResolvedValue ( { access_token : 'old-token' , token_type : 'Bearer' , scope : 'openid read' } ) ,
234+ tokens : vi . fn ( ) . mockResolvedValue ( {
235+ access_token : 'old-token' ,
236+ token_type : 'Bearer' ,
237+ refresh_token : 'refresh-token' ,
238+ scope : 'openid read'
239+ } ) ,
234240 saveTokens : vi . fn ( ) ,
235241 saveCodeVerifier : vi . fn ( ) ,
236242 codeVerifier : vi . fn ( ) ,
@@ -256,12 +262,21 @@ describe('OAuth Authorization', () => {
256262 Response . json ( {
257263 issuer : 'https://auth.example.com' ,
258264 authorization_endpoint : 'https://auth.example.com/authorize' ,
259- token_endpoint : 'https://auth.example.com/token' ,
265+ token_endpoint : tokenEndpoint ,
260266 response_types_supported : [ 'code' ] ,
261267 code_challenge_methods_supported : [ 'S256' ]
262268 } )
263269 ) ;
264270 }
271+ if ( urlString === tokenEndpoint ) {
272+ return Promise . resolve (
273+ Response . json ( {
274+ access_token : 'refreshed-token' ,
275+ token_type : 'Bearer' ,
276+ scope : 'openid read'
277+ } )
278+ ) ;
279+ }
265280 return Promise . reject ( new Error ( `Unexpected fetch: ${ urlString } ` ) ) ;
266281 } ) ;
267282
@@ -276,6 +291,7 @@ describe('OAuth Authorization', () => {
276291 ) . rejects . toBeInstanceOf ( UnauthorizedError ) ;
277292
278293 expect ( mockFetch . mock . calls [ 0 ] ?. [ 0 ] . toString ( ) ) . toBe ( resourceMetadataUrl . toString ( ) ) ;
294+ expect ( mockFetch . mock . calls . some ( ( [ url ] ) => url . toString ( ) === tokenEndpoint ) ) . toBe ( false ) ;
279295 const authorizationUrl = ( provider . redirectToAuthorization as Mock ) . mock . calls [ 0 ] ?. [ 0 ] as URL ;
280296 expect ( authorizationUrl . searchParams . get ( 'scope' ) ) . toBe ( 'openid read write' ) ;
281297 } ) ;
0 commit comments