@@ -9,6 +9,7 @@ function FirebaseAuth () {
99 this . currentUser = null ;
1010 this . _auth = {
1111 listeners : [ ] ,
12+ idTokenListeners : [ ] ,
1213 completionListeners : [ ] ,
1314 users : [ ] ,
1415 uidCounter : 1
@@ -17,10 +18,10 @@ function FirebaseAuth () {
1718
1819FirebaseAuth . prototype . changeAuthState = function ( userData ) {
1920 this . _defer ( 'changeAuthState' , _ . toArray ( arguments ) , function ( ) {
20- if ( ! _ . isEqual ( this . currentUser , userData ) ) {
21- this . currentUser = _ . isObject ( userData ) ? userData : null ;
22- this . _triggerAuthEvent ( ) ;
23- }
21+ userData = _ . isObject ( userData ) ? userData : null ;
22+ const oldUser = _ . cloneDeep ( this . currentUser ) ;
23+ this . currentUser = userData ;
24+ this . _notify_state_listeners ( oldUser ) ;
2425 } ) ;
2526} ;
2627
@@ -47,6 +48,13 @@ FirebaseAuth.prototype.onAuthStateChanged = function (callback) {
4748 }
4849} ;
4950
51+ FirebaseAuth . prototype . onIdTokenChanged = function ( callback ) {
52+ const currentUser = this . currentUser ;
53+ this . _auth . idTokenListeners . push ( { fn : callback } ) ;
54+ callback . call ( null , _ . cloneDeep ( currentUser ) ) ;
55+ return ( ) => this . offAuth ( callback ) ;
56+ } ;
57+
5058FirebaseAuth . prototype . getUserByEmail = function ( email , onComplete ) {
5159 var err = this . _nextErr ( 'getUserByEmail' ) ;
5260 var self = this ;
@@ -100,6 +108,11 @@ FirebaseAuth.prototype.updateUser = function (newUser) {
100108 reject ( new Error ( 'Tried to update a nonexistent user' ) ) ;
101109 } else {
102110 self . _auth . users [ i ] = newUser . clone ( ) ;
111+ if ( this . currentUser && this . currentUser . uid === newUser . uid ) {
112+ const oldUser = this . currentUser . clone ( ) ;
113+ this . currentUser = self . _auth . users [ i ] ;
114+ this . _notify_state_listeners ( oldUser ) ;
115+ }
103116 resolve ( newUser ) ;
104117 }
105118 } ) ;
@@ -167,15 +180,14 @@ Object.keys(signinMethods)
167180 FirebaseAuth . prototype [ method ] = function ( ) {
168181 var self = this ;
169182 var user = getUser . apply ( this , arguments ) ;
170- var promise = new Promise ( function ( resolve , reject ) {
183+ return new Promise ( function ( resolve , reject ) {
171184 self . _authEvent ( method , function ( err ) {
172185 if ( err ) reject ( err ) ;
173186 self . currentUser = user ;
174187 resolve ( user ) ;
175188 self . _triggerAuthEvent ( ) ;
176189 } , true ) ;
177190 } ) ;
178- return promise ;
179191 } ;
180192 } ) ;
181193
@@ -218,6 +230,15 @@ FirebaseAuth.prototype._triggerAuthEvent = function () {
218230 listeners . forEach ( function ( parts ) {
219231 parts . fn . call ( parts . context , _ . cloneDeep ( user ) ) ;
220232 } ) ;
233+ this . _triggerIdTokenEvent ( ) ;
234+ } ;
235+
236+ FirebaseAuth . prototype . _triggerIdTokenEvent = function ( ) {
237+ var user = this . currentUser ;
238+ var listeners = _ . cloneDeep ( this . _auth . idTokenListeners ) ;
239+ listeners . forEach ( function ( parts ) {
240+ parts . fn . call ( parts . context , _ . cloneDeep ( user ) ) ;
241+ } ) ;
221242} ;
222243
223244FirebaseAuth . prototype . _getUser = function ( uid ) {
@@ -239,12 +260,11 @@ FirebaseAuth.prototype.onAuth = function (onComplete, context) {
239260} ;
240261
241262FirebaseAuth . prototype . offAuth = function ( onComplete , context ) {
242- var index = _ . findIndex ( this . _auth . listeners , function ( listener ) {
263+ function shouldRemove ( listener ) {
243264 return listener . fn === onComplete && listener . context === context ;
244- } ) ;
245- if ( index > - 1 ) {
246- this . _auth . listeners . splice ( index , 1 ) ;
247265 }
266+ [ this . _auth . listeners , this . _auth . idTokenListeners ]
267+ . forEach ( event => _ . remove ( event , shouldRemove ) ) ;
248268} ;
249269
250270FirebaseAuth . prototype . unauth = function ( ) {
@@ -256,7 +276,7 @@ FirebaseAuth.prototype.unauth = function () {
256276
257277FirebaseAuth . prototype . signOut = function ( ) {
258278 var self = this , updateuser = this . currentUser !== null ;
259- var promise = new Promise ( function ( resolve , reject ) {
279+ return new Promise ( function ( resolve , reject ) {
260280 self . _authEvent ( 'signOut' , function ( err ) {
261281 if ( err ) reject ( err ) ;
262282 self . currentUser = null ;
@@ -267,7 +287,6 @@ FirebaseAuth.prototype.signOut = function () {
267287 }
268288 } , true ) ;
269289 } ) ;
270- return promise ;
271290} ;
272291
273292FirebaseAuth . prototype . createUserWithEmailAndPassword = function ( email , password ) {
@@ -502,14 +521,54 @@ FirebaseAuth.prototype.setCustomUserClaims = function (uid, claims) {
502521 } ) ;
503522} ;
504523
524+ FirebaseAuth . prototype . _notify_state_listeners = function ( previousUser ) {
525+ const difference = scanDifference ( previousUser , this . currentUser ) ;
526+ if ( difference === 'different_user' ) {
527+ this . _triggerAuthEvent ( ) ;
528+ } else if ( difference === 'different_token' ) {
529+ this . _triggerIdTokenEvent ( ) ;
530+ } else if ( difference === 'same' ) {
531+ // do nothing
532+ } else {
533+ throw new Error ( 'Unexpected result from scanDifference' ) ;
534+ }
535+
536+ function scanDifference ( oldUser , newUser ) {
537+ if ( _ . isObject ( oldUser ) ) {
538+ if ( _ . isObject ( newUser ) ) {
539+ if ( _ . isEqual ( oldUser , newUser ) ) {
540+ return 'same' ;
541+ } else {
542+ return equalExceptToken ( oldUser , newUser ) ?
543+ 'different_token' : 'different_user' ;
544+ }
545+ } else {
546+ return 'different_user' ;
547+ }
548+ } else {
549+ return _ . isObject ( newUser ) ? 'different_user' : 'same' ;
550+ }
551+ }
552+
553+ function equalExceptToken ( user1 , user2 ) {
554+ const u1 = user1 . clone ( ) ;
555+ const u2 = user2 . clone ( ) ;
556+ delete u1 . _idtoken ;
557+ delete u1 . _tokenValidity ;
558+ delete u2 . _idtoken ;
559+ delete u2 . _tokenValidity ;
560+ return _ . isEqual ( u1 , u2 ) ;
561+ }
562+ } ;
563+
505564FirebaseAuth . prototype . _nextUid = function ( ) {
506565 return 'simplelogin:' + ( this . _auth . uidCounter ++ ) ;
507566} ;
508567
509568FirebaseAuth . prototype . _validateNewUid = function ( uid ) {
510569 if ( uid ) {
511570 var user = _ . find ( this . _auth . users , function ( user ) {
512- return user . uid == uid ;
571+ return user . uid === uid ;
513572 } ) ;
514573 if ( user ) {
515574 var err = new Error ( 'The provided uid is already in use by an existing user. Each user must have a unique uid.' ) ;
@@ -523,7 +582,7 @@ FirebaseAuth.prototype._validateNewUid = function (uid) {
523582FirebaseAuth . prototype . _validateExistingUid = function ( uid ) {
524583 if ( uid ) {
525584 var user = _ . find ( this . _auth . users , function ( user ) {
526- return user . uid == uid ;
585+ return user . uid === uid ;
527586 } ) ;
528587 if ( ! user ) {
529588 var err = new Error ( 'There is no existing user record corresponding to the provided identifier.' ) ;
0 commit comments