@@ -3504,6 +3504,39 @@ describe('(GHSA-5hmj-jcgp-6hff) Protected fields leak via LiveQuery afterEvent t
35043504 expect ( validatorSpy ) . toHaveBeenCalled ( ) ;
35053505 } ) ;
35063506
3507+ it ( 'rejects login with identical but expired authData when adapter rejects' , async ( ) => {
3508+ // Sign up with authData that is initially valid
3509+ const user = new Parse . User ( ) ;
3510+ await user . save ( {
3511+ authData : { testAdapter : { id : 'user_expired' , access_token : 'token_now_expired' } } ,
3512+ } ) ;
3513+ validatorSpy . calls . reset ( ) ;
3514+
3515+ // Simulate the token expiring on the provider side: the adapter now
3516+ // rejects the same token that was valid at signup time
3517+ validatorSpy . and . rejectWith (
3518+ new Parse . Error ( Parse . Error . SCRIPT_FAILED , 'Token expired' )
3519+ ) ;
3520+
3521+ // Attempt login with the exact same (now-expired) authData
3522+ const res = await request ( {
3523+ method : 'POST' ,
3524+ url : 'http://localhost:8378/1/users' ,
3525+ headers : {
3526+ 'Content-Type' : 'application/json' ,
3527+ 'X-Parse-Application-Id' : 'test' ,
3528+ 'X-Parse-REST-API-Key' : 'rest' ,
3529+ } ,
3530+ body : JSON . stringify ( {
3531+ authData : { testAdapter : { id : 'user_expired' , access_token : 'token_now_expired' } } ,
3532+ } ) ,
3533+ } ) . catch ( e => e ) ;
3534+
3535+ // Login must be rejected even though authData is identical to what's stored
3536+ expect ( res . status ) . toBe ( 400 ) ;
3537+ expect ( validatorSpy ) . toHaveBeenCalled ( ) ;
3538+ } ) ;
3539+
35073540 it ( 'skips validation on update when authData is a subset of stored data' , async ( ) => {
35083541 // Sign up with full authData
35093542 const user = new Parse . User ( ) ;
0 commit comments