@@ -760,6 +760,20 @@ describe('admin.auth', () => {
760760 safeDelete ( userRecord . uid ) ;
761761 }
762762 } ) ;
763+
764+ it ( 'A user with user record disabled is unable to sign in' , async ( ) => {
765+ const password = 'password' ;
766+ const email = 'updatedEmail@example.com' ;
767+ return admin . auth ( ) . updateUser ( updateUser . uid , { disabled : true , password, email } )
768+ . then ( ( ) => {
769+ return clientAuth ( ) . signInWithEmailAndPassword ( email , password ) ;
770+ } )
771+ . then ( ( ) => {
772+ throw new Error ( 'Unexpected success' ) ;
773+ } , ( error ) => {
774+ expect ( error ) . to . have . property ( 'code' , 'auth/user-disabled' ) ;
775+ } ) ;
776+ } ) ;
763777 } ) ;
764778
765779 it ( 'getUser() fails when called with a non-existing UID' , ( ) => {
@@ -833,53 +847,113 @@ describe('admin.auth', () => {
833847 } ) ;
834848 } ) ;
835849
836- it ( 'verifyIdToken() fails when called with an invalid token' , ( ) => {
837- return admin . auth ( ) . verifyIdToken ( 'invalid-token' )
838- . should . eventually . be . rejected . and . have . property ( 'code' , 'auth/argument-error' ) ;
839- } ) ;
850+ describe ( 'verifyIdToken()' , ( ) => {
851+ const uid = generateRandomString ( 20 ) . toLowerCase ( ) ;
852+ const email = uid + '@example.com' ;
853+ const password = 'password' ;
854+ const userData = {
855+ uid,
856+ email,
857+ emailVerified : false ,
858+ password,
859+ } ;
860+
861+ // Create the test user before running this suite of tests.
862+ before ( ( ) => {
863+ return admin . auth ( ) . createUser ( userData ) ;
864+ } ) ;
840865
841- if ( authEmulatorHost ) {
842- describe ( 'Auth emulator support' , ( ) => {
843- const uid = 'authEmulatorUser' ;
844- before ( ( ) => {
845- return admin . auth ( ) . createUser ( {
846- uid,
847- email : 'lastRefreshTimeUser@example.com' ,
848- password : 'p4ssword' ,
866+ // Sign out after each test.
867+ afterEach ( ( ) => {
868+ return clientAuth ( ) . signOut ( ) ;
869+ } ) ;
870+
871+ after ( ( ) => {
872+ return safeDelete ( uid ) ;
873+ } ) ;
874+
875+ it ( 'verifyIdToken() fails when called with an invalid token' , ( ) => {
876+ return admin . auth ( ) . verifyIdToken ( 'invalid-token' )
877+ . should . eventually . be . rejected . and . have . property ( 'code' , 'auth/argument-error' ) ;
878+ } ) ;
879+
880+ it ( 'verifyIdToken() fails with checkRevoked set to true and corresponding user disabled' , async ( ) => {
881+ const { user } = await clientAuth ( ) . signInWithEmailAndPassword ( email , password ) ;
882+ expect ( user ) . to . exist ;
883+ expect ( user ! . email ) . to . equal ( email ) ;
884+
885+ const idToken = await user ! . getIdToken ( ) ;
886+ let decodedIdToken = await admin . auth ( ) . verifyIdToken ( idToken , true ) ;
887+ expect ( decodedIdToken . uid ) . to . equal ( uid ) ;
888+ expect ( decodedIdToken . email ) . to . equal ( email ) ;
889+
890+ const userRecord = await admin . auth ( ) . updateUser ( uid , { disabled : true } ) ;
891+ expect ( userRecord . uid ) . to . equal ( uid ) ;
892+ expect ( userRecord . email ) . to . equal ( email ) ;
893+ expect ( userRecord . disabled ) . to . equal ( true ) ;
894+
895+ try {
896+ // If it is in emulator mode, a user-disabled error will be thrown.
897+ decodedIdToken = await admin . auth ( ) . verifyIdToken ( idToken , false ) ;
898+ expect ( decodedIdToken . uid ) . to . equal ( uid ) ;
899+ } catch ( error ) {
900+ if ( authEmulatorHost ) {
901+ expect ( error ) . to . have . property ( 'code' , 'auth/user-disabled' ) ;
902+ } else {
903+ throw error ;
904+ }
905+ }
906+
907+ try {
908+ await admin . auth ( ) . verifyIdToken ( idToken , true ) ;
909+ } catch ( error ) {
910+ expect ( error ) . to . have . property ( 'code' , 'auth/user-disabled' ) ;
911+ }
912+ } ) ;
913+
914+ if ( authEmulatorHost ) {
915+ describe ( 'Auth emulator support' , ( ) => {
916+ const uid = 'authEmulatorUser' ;
917+ before ( ( ) => {
918+ return admin . auth ( ) . createUser ( {
919+ uid,
920+ email : 'lastRefreshTimeUser@example.com' ,
921+ password : 'p4ssword' ,
922+ } ) ;
923+ } ) ;
924+ after ( ( ) => {
925+ return admin . auth ( ) . deleteUser ( uid ) ;
849926 } ) ;
850- } ) ;
851- after ( ( ) => {
852- return admin . auth ( ) . deleteUser ( uid ) ;
853- } ) ;
854927
855- it ( 'verifyIdToken() succeeds when called with an unsigned token' , ( ) => {
856- const unsignedToken = mocks . generateIdToken ( {
857- algorithm : 'none' ,
858- audience : projectId ,
859- issuer : 'https://securetoken.google.com/' + projectId ,
860- subject : uid ,
928+ it ( 'verifyIdToken() succeeds when called with an unsigned token' , ( ) => {
929+ const unsignedToken = mocks . generateIdToken ( {
930+ algorithm : 'none' ,
931+ audience : projectId ,
932+ issuer : 'https://securetoken.google.com/' + projectId ,
933+ subject : uid ,
934+ } ) ;
935+ return admin . auth ( ) . verifyIdToken ( unsignedToken ) ;
861936 } ) ;
862- return admin . auth ( ) . verifyIdToken ( unsignedToken ) ;
863- } ) ;
864937
865- it ( 'verifyIdToken() fails when called with a token with wrong project' , ( ) => {
866- const unsignedToken = mocks . generateIdToken ( { algorithm : 'none' , audience : 'nosuch' } ) ;
867- return admin . auth ( ) . verifyIdToken ( unsignedToken )
868- . should . eventually . be . rejected . and . have . property ( 'code' , 'auth/argument-error' ) ;
869- } ) ;
938+ it ( 'verifyIdToken() fails when called with a token with wrong project' , ( ) => {
939+ const unsignedToken = mocks . generateIdToken ( { algorithm : 'none' , audience : 'nosuch' } ) ;
940+ return admin . auth ( ) . verifyIdToken ( unsignedToken )
941+ . should . eventually . be . rejected . and . have . property ( 'code' , 'auth/argument-error' ) ;
942+ } ) ;
870943
871- it ( 'verifyIdToken() fails when called with a token that does not belong to a user' , ( ) => {
872- const unsignedToken = mocks . generateIdToken ( {
873- algorithm : 'none' ,
874- audience : projectId ,
875- issuer : 'https://securetoken.google.com/' + projectId ,
876- subject : 'nosuch' ,
944+ it ( 'verifyIdToken() fails when called with a token that does not belong to a user' , ( ) => {
945+ const unsignedToken = mocks . generateIdToken ( {
946+ algorithm : 'none' ,
947+ audience : projectId ,
948+ issuer : 'https://securetoken.google.com/' + projectId ,
949+ subject : 'nosuch' ,
950+ } ) ;
951+ return admin . auth ( ) . verifyIdToken ( unsignedToken )
952+ . should . eventually . be . rejected . and . have . property ( 'code' , 'auth/user-not-found' ) ;
877953 } ) ;
878- return admin . auth ( ) . verifyIdToken ( unsignedToken )
879- . should . eventually . be . rejected . and . have . property ( 'code' , 'auth/user-not-found' ) ;
880954 } ) ;
881- } ) ;
882- }
955+ }
956+ } ) ;
883957
884958 describe ( 'Link operations' , ( ) => {
885959 const uid = generateRandomString ( 20 ) . toLowerCase ( ) ;
@@ -1982,6 +2056,44 @@ describe('admin.auth', () => {
19822056 . should . eventually . be . rejected . and . have . property ( 'code' , 'auth/argument-error' ) ;
19832057 } ) ;
19842058 } ) ;
2059+
2060+ it ( 'fails with checkRevoked set to true and corresponding user disabled' , async ( ) => {
2061+ const expiresIn = 24 * 60 * 60 * 1000 ;
2062+ const customToken = await admin . auth ( ) . createCustomToken ( uid , { admin : true , groupId : '1234' } ) ;
2063+ const { user } = await clientAuth ( ) . signInWithCustomToken ( customToken ) ;
2064+ expect ( user ) . to . exist ;
2065+
2066+ const idToken = await user ! . getIdToken ( ) ;
2067+ const decodedIdTokenClaims = await admin . auth ( ) . verifyIdToken ( idToken ) ;
2068+ expect ( decodedIdTokenClaims . uid ) . to . be . equal ( uid ) ;
2069+
2070+ const sessionCookie = await admin . auth ( ) . createSessionCookie ( idToken , { expiresIn } ) ;
2071+ let decodedIdToken = await admin . auth ( ) . verifySessionCookie ( sessionCookie , true ) ;
2072+ expect ( decodedIdToken . uid ) . to . equal ( uid ) ;
2073+
2074+ const userRecord = await admin . auth ( ) . updateUser ( uid , { disabled : true } ) ;
2075+ // Ensure disabled field has been updated.
2076+ expect ( userRecord . uid ) . to . equal ( uid ) ;
2077+ expect ( userRecord . disabled ) . to . equal ( true ) ;
2078+
2079+ try {
2080+ // If it is in emulator mode, a user-disabled error will be thrown.
2081+ decodedIdToken = await admin . auth ( ) . verifySessionCookie ( sessionCookie , false ) ;
2082+ expect ( decodedIdToken . uid ) . to . equal ( uid ) ;
2083+ } catch ( error ) {
2084+ if ( authEmulatorHost ) {
2085+ expect ( error ) . to . have . property ( 'code' , 'auth/user-disabled' ) ;
2086+ } else {
2087+ throw error ;
2088+ }
2089+ }
2090+
2091+ try {
2092+ await admin . auth ( ) . verifySessionCookie ( sessionCookie , true ) ;
2093+ } catch ( error ) {
2094+ expect ( error ) . to . have . property ( 'code' , 'auth/user-disabled' ) ;
2095+ }
2096+ } ) ;
19852097 } ) ;
19862098
19872099 describe ( 'importUsers()' , ( ) => {
0 commit comments