@@ -76,13 +76,18 @@ def _merge_jwt_claims(defaults, overrides):
7676
7777def  verify_custom_token (custom_token , expected_claims , tenant_id = None ):
7878    assert  isinstance (custom_token , bytes )
79-     token  =  google .oauth2 .id_token .verify_token (
80-         custom_token ,
81-         testutils .MockRequest (200 , MOCK_PUBLIC_CERTS ),
82-         _token_gen .FIREBASE_AUDIENCE )
79+     expected_email  =  MOCK_SERVICE_ACCOUNT_EMAIL 
80+     if  _is_emulated ():
81+         expected_email  =  _token_gen .AUTH_EMULATOR_EMAIL 
82+         token  =  jwt .decode (custom_token , verify = False )
83+     else :
84+         token  =  google .oauth2 .id_token .verify_token (
85+             custom_token ,
86+             testutils .MockRequest (200 , MOCK_PUBLIC_CERTS ),
87+             _token_gen .FIREBASE_AUDIENCE )
8388    assert  token ['uid' ] ==  MOCK_UID 
84-     assert  token ['iss' ] ==  MOCK_SERVICE_ACCOUNT_EMAIL 
85-     assert  token ['sub' ] ==  MOCK_SERVICE_ACCOUNT_EMAIL 
89+     assert  token ['iss' ] ==  expected_email 
90+     assert  token ['sub' ] ==  expected_email 
8691    if  tenant_id  is  None :
8792        assert  'tenant_id'  not  in token 
8893    else :
@@ -141,7 +146,15 @@ def _overwrite_iam_request(app, request):
141146    client  =  auth ._get_client (app )
142147    client ._token_generator .request  =  request 
143148
144- @pytest .fixture (scope = 'module' , params = [{'emulated' : False }, {'emulated' : True }]) 
149+ 
150+ def  _is_emulated ():
151+     emulator_host  =  os .getenv (EMULATOR_HOST_ENV_VAR , '' )
152+     return  emulator_host  and  '//'  not  in emulator_host 
153+ 
154+ 
155+ # These fixtures are set to the default function scope as the emulator environment variable bleeds 
156+ # over when in module scope. 
157+ @pytest .fixture (params = [{'emulated' : False }, {'emulated' : True }]) 
145158def  auth_app (request ):
146159    """Returns an App initialized with a mock service account credential. 
147160
@@ -157,7 +170,7 @@ def auth_app(request):
157170    firebase_admin .delete_app (app )
158171    monkeypatch .undo ()
159172
160- @pytest .fixture (scope = 'module' ,  params = [{'emulated' : False }, {'emulated' : True }]) 
173+ @pytest .fixture (params = [{'emulated' : False }, {'emulated' : True }]) 
161174def  user_mgt_app (request ):
162175    monkeypatch  =  testutils .new_monkeypatch ()
163176    if  request .param ['emulated' ]:
@@ -230,6 +243,12 @@ def test_invalid_params(self, auth_app, values):
230243            auth .create_custom_token (user , claims , app = auth_app )
231244
232245    def  test_noncert_credential (self , user_mgt_app ):
246+         if  _is_emulated ():
247+             # Should work fine with the emulator, so do a condensed version of 
248+             # test_sign_with_iam below. 
249+             custom_token  =  auth .create_custom_token (MOCK_UID , app = user_mgt_app ).decode ()
250+             self ._verify_signer (custom_token , _token_gen .AUTH_EMULATOR_EMAIL )
251+             return 
233252        with  pytest .raises (ValueError ):
234253            auth .create_custom_token (MOCK_UID , app = user_mgt_app )
235254
@@ -304,7 +323,7 @@ def test_sign_with_discovery_failure(self):
304323    def  _verify_signer (self , token , signer ):
305324        segments  =  token .split ('.' )
306325        assert  len (segments ) ==  3 
307-         body  =  json . loads ( base64 . b64decode ( segments [ 1 ]). decode () )
326+         body  =  jwt . decode (token ,  verify = False )
308327        assert  body ['iss' ] ==  signer 
309328        assert  body ['sub' ] ==  signer 
310329
@@ -406,14 +425,24 @@ class TestVerifyIdToken:
406425        'BadFormatToken' : 'foobar' 
407426    }
408427
409-     @pytest .mark .parametrize ('id_token' , valid_tokens .values (), ids = list (valid_tokens )) 
410-     def  test_valid_token (self , user_mgt_app , id_token ):
411-         _overwrite_cert_request (user_mgt_app , MOCK_REQUEST )
412-         claims  =  auth .verify_id_token (id_token , app = user_mgt_app )
428+     tokens_not_invalid_in_emulator  =  [
429+         'NoKid' ,
430+         'WrongKid' ,
431+         'FutureToken' ,
432+         'ExpiredToken' 
433+     ]
434+ 
435+     def  _assert_valid_token (self , id_token , app ):
436+         claims  =  auth .verify_id_token (id_token , app = app )
413437        assert  claims ['admin' ] is  True 
414438        assert  claims ['uid' ] ==  claims ['sub' ]
415439        assert  claims ['firebase' ]['sign_in_provider' ] ==  'provider' 
416440
441+     @pytest .mark .parametrize ('id_token' , valid_tokens .values (), ids = list (valid_tokens )) 
442+     def  test_valid_token (self , user_mgt_app , id_token ):
443+         _overwrite_cert_request (user_mgt_app , MOCK_REQUEST )
444+         self ._assert_valid_token (id_token , app = user_mgt_app )
445+ 
417446    def  test_valid_token_with_tenant (self , user_mgt_app ):
418447        _overwrite_cert_request (user_mgt_app , MOCK_REQUEST )
419448        claims  =  auth .verify_id_token (TEST_ID_TOKEN_WITH_TENANT , app = user_mgt_app )
@@ -458,8 +487,12 @@ def test_invalid_arg(self, user_mgt_app, id_token):
458487            auth .verify_id_token (id_token , app = user_mgt_app )
459488        assert  'Illegal ID token provided'  in  str (excinfo .value )
460489
461-     @pytest .mark .parametrize ('id_token' , invalid_tokens .values (), ids = list (invalid_tokens )) 
462-     def  test_invalid_token (self , user_mgt_app , id_token ):
490+     @pytest .mark .parametrize ('id_token_key' , list (invalid_tokens )) 
491+     def  test_invalid_token (self , user_mgt_app , id_token_key ):
492+         id_token  =  self .invalid_tokens [id_token_key ]
493+         if  _is_emulated () and  id_token_key  in  self .tokens_not_invalid_in_emulator :
494+             self ._assert_valid_token (id_token , user_mgt_app )
495+             return 
463496        _overwrite_cert_request (user_mgt_app , MOCK_REQUEST )
464497        with  pytest .raises (auth .InvalidIdTokenError ) as  excinfo :
465498            auth .verify_id_token (id_token , app = user_mgt_app )
@@ -469,6 +502,9 @@ def test_invalid_token(self, user_mgt_app, id_token):
469502    def  test_expired_token (self , user_mgt_app ):
470503        _overwrite_cert_request (user_mgt_app , MOCK_REQUEST )
471504        id_token  =  self .invalid_tokens ['ExpiredToken' ]
505+         if  _is_emulated ():
506+             self ._assert_valid_token (id_token , user_mgt_app )
507+             return 
472508        with  pytest .raises (auth .ExpiredIdTokenError ) as  excinfo :
473509            auth .verify_id_token (id_token , app = user_mgt_app )
474510        assert  isinstance (excinfo .value , auth .InvalidIdTokenError )
@@ -506,6 +542,10 @@ def test_custom_token(self, auth_app):
506542
507543    def  test_certificate_request_failure (self , user_mgt_app ):
508544        _overwrite_cert_request (user_mgt_app , testutils .MockRequest (404 , 'not found' ))
545+         if  _is_emulated ():
546+             # Shouldn't fetch certificates in emulator mode. 
547+             self ._assert_valid_token (TEST_ID_TOKEN , app = user_mgt_app )
548+             return 
509549        with  pytest .raises (auth .CertificateFetchError ) as  excinfo :
510550            auth .verify_id_token (TEST_ID_TOKEN , app = user_mgt_app )
511551        assert  'Could not fetch certificates'  in  str (excinfo .value )
@@ -540,20 +580,28 @@ class TestVerifySessionCookie:
540580        'IDToken' : TEST_ID_TOKEN ,
541581    }
542582
583+     cookies_not_invalid_in_emulator  =  [
584+         'NoKid' ,
585+         'WrongKid' ,
586+         'FutureCookie' ,
587+         'ExpiredCookie' 
588+     ]
589+ 
590+     def  _assert_valid_cookie (self , cookie , app , check_revoked = False ):
591+         claims  =  auth .verify_session_cookie (cookie , app = app , check_revoked = check_revoked )
592+         assert  claims ['admin' ] is  True 
593+         assert  claims ['uid' ] ==  claims ['sub' ]
594+ 
543595    @pytest .mark .parametrize ('cookie' , valid_cookies .values (), ids = list (valid_cookies )) 
544596    def  test_valid_cookie (self , user_mgt_app , cookie ):
545597        _overwrite_cert_request (user_mgt_app , MOCK_REQUEST )
546-         claims  =  auth .verify_session_cookie (cookie , app = user_mgt_app )
547-         assert  claims ['admin' ] is  True 
548-         assert  claims ['uid' ] ==  claims ['sub' ]
598+         self ._assert_valid_cookie (cookie , user_mgt_app )
549599
550600    @pytest .mark .parametrize ('cookie' , valid_cookies .values (), ids = list (valid_cookies )) 
551601    def  test_valid_cookie_check_revoked (self , user_mgt_app , cookie ):
552602        _overwrite_cert_request (user_mgt_app , MOCK_REQUEST )
553603        _instrument_user_manager (user_mgt_app , 200 , MOCK_GET_USER_RESPONSE )
554-         claims  =  auth .verify_session_cookie (cookie , app = user_mgt_app , check_revoked = True )
555-         assert  claims ['admin' ] is  True 
556-         assert  claims ['uid' ] ==  claims ['sub' ]
604+         self ._assert_valid_cookie (cookie , app = user_mgt_app , check_revoked = True )
557605
558606    @pytest .mark .parametrize ('cookie' , valid_cookies .values (), ids = list (valid_cookies )) 
559607    def  test_revoked_cookie_check_revoked (self , user_mgt_app , revoked_tokens , cookie ):
@@ -567,9 +615,7 @@ def test_revoked_cookie_check_revoked(self, user_mgt_app, revoked_tokens, cookie
567615    def  test_revoked_cookie_does_not_check_revoked (self , user_mgt_app , revoked_tokens , cookie ):
568616        _overwrite_cert_request (user_mgt_app , MOCK_REQUEST )
569617        _instrument_user_manager (user_mgt_app , 200 , revoked_tokens )
570-         claims  =  auth .verify_session_cookie (cookie , app = user_mgt_app , check_revoked = False )
571-         assert  claims ['admin' ] is  True 
572-         assert  claims ['uid' ] ==  claims ['sub' ]
618+         self ._assert_valid_cookie (cookie , app = user_mgt_app , check_revoked = False )
573619
574620    @pytest .mark .parametrize ('cookie' , INVALID_JWT_ARGS .values (), ids = list (INVALID_JWT_ARGS )) 
575621    def  test_invalid_args (self , user_mgt_app , cookie ):
@@ -578,8 +624,12 @@ def test_invalid_args(self, user_mgt_app, cookie):
578624            auth .verify_session_cookie (cookie , app = user_mgt_app )
579625        assert  'Illegal session cookie provided'  in  str (excinfo .value )
580626
581-     @pytest .mark .parametrize ('cookie' , invalid_cookies .values (), ids = list (invalid_cookies )) 
582-     def  test_invalid_cookie (self , user_mgt_app , cookie ):
627+     @pytest .mark .parametrize ('cookie_key' , list (invalid_cookies )) 
628+     def  test_invalid_cookie (self , user_mgt_app , cookie_key ):
629+         cookie  =  self .invalid_cookies [cookie_key ]
630+         if  _is_emulated () and  cookie_key  in  self .cookies_not_invalid_in_emulator :
631+             self ._assert_valid_cookie (cookie , user_mgt_app )
632+             return 
583633        _overwrite_cert_request (user_mgt_app , MOCK_REQUEST )
584634        with  pytest .raises (auth .InvalidSessionCookieError ) as  excinfo :
585635            auth .verify_session_cookie (cookie , app = user_mgt_app )
@@ -589,6 +639,9 @@ def test_invalid_cookie(self, user_mgt_app, cookie):
589639    def  test_expired_cookie (self , user_mgt_app ):
590640        _overwrite_cert_request (user_mgt_app , MOCK_REQUEST )
591641        cookie  =  self .invalid_cookies ['ExpiredCookie' ]
642+         if  _is_emulated ():
643+             self ._assert_valid_cookie (cookie , user_mgt_app )
644+             return 
592645        with  pytest .raises (auth .ExpiredSessionCookieError ) as  excinfo :
593646            auth .verify_session_cookie (cookie , app = user_mgt_app )
594647        assert  isinstance (excinfo .value , auth .InvalidSessionCookieError )
@@ -621,6 +674,10 @@ def test_custom_token(self, auth_app):
621674
622675    def  test_certificate_request_failure (self , user_mgt_app ):
623676        _overwrite_cert_request (user_mgt_app , testutils .MockRequest (404 , 'not found' ))
677+         if  _is_emulated ():
678+             # Shouldn't fetch certificates in emulator mode. 
679+             auth .verify_session_cookie (TEST_SESSION_COOKIE , app = user_mgt_app )
680+             return 
624681        with  pytest .raises (auth .CertificateFetchError ) as  excinfo :
625682            auth .verify_session_cookie (TEST_SESSION_COOKIE , app = user_mgt_app )
626683        assert  'Could not fetch certificates'  in  str (excinfo .value )
@@ -637,9 +694,11 @@ def test_certificate_caching(self, user_mgt_app, httpserver):
637694        verifier .cookie_verifier .cert_url  =  httpserver .url 
638695        verifier .id_token_verifier .cert_url  =  httpserver .url 
639696        verifier .verify_session_cookie (TEST_SESSION_COOKIE )
640-         assert  len (httpserver .requests ) ==  1 
697+         # No requests should be made in emulated mode 
698+         request_count  =  0  if  _is_emulated () else  1 
699+         assert  len (httpserver .requests ) ==  request_count 
641700        # Subsequent requests should not fetch certs from the server 
642701        verifier .verify_session_cookie (TEST_SESSION_COOKIE )
643-         assert  len (httpserver .requests ) ==  1 
702+         assert  len (httpserver .requests ) ==  request_count 
644703        verifier .verify_id_token (TEST_ID_TOKEN )
645-         assert  len (httpserver .requests ) ==  1 
704+         assert  len (httpserver .requests ) ==  request_count 
0 commit comments