@@ -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,23 @@ 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+         'WrongKid' ,
430+         'FutureToken' ,
431+         'ExpiredToken' 
432+     ]
433+ 
434+     def  _assert_valid_token (self , id_token , app ):
435+         claims  =  auth .verify_id_token (id_token , app = app )
413436        assert  claims ['admin' ] is  True 
414437        assert  claims ['uid' ] ==  claims ['sub' ]
415438        assert  claims ['firebase' ]['sign_in_provider' ] ==  'provider' 
416439
440+     @pytest .mark .parametrize ('id_token' , valid_tokens .values (), ids = list (valid_tokens )) 
441+     def  test_valid_token (self , user_mgt_app , id_token ):
442+         _overwrite_cert_request (user_mgt_app , MOCK_REQUEST )
443+         self ._assert_valid_token (id_token , app = user_mgt_app )
444+ 
417445    def  test_valid_token_with_tenant (self , user_mgt_app ):
418446        _overwrite_cert_request (user_mgt_app , MOCK_REQUEST )
419447        claims  =  auth .verify_id_token (TEST_ID_TOKEN_WITH_TENANT , app = user_mgt_app )
@@ -458,8 +486,12 @@ def test_invalid_arg(self, user_mgt_app, id_token):
458486            auth .verify_id_token (id_token , app = user_mgt_app )
459487        assert  'Illegal ID token provided'  in  str (excinfo .value )
460488
461-     @pytest .mark .parametrize ('id_token' , invalid_tokens .values (), ids = list (invalid_tokens )) 
462-     def  test_invalid_token (self , user_mgt_app , id_token ):
489+     @pytest .mark .parametrize ('id_token_key' , list (invalid_tokens )) 
490+     def  test_invalid_token (self , user_mgt_app , id_token_key ):
491+         id_token  =  self .invalid_tokens [id_token_key ]
492+         if  _is_emulated () and  id_token_key  in  self .tokens_not_invalid_in_emulator :
493+             self ._assert_valid_token (id_token , user_mgt_app )
494+             return 
463495        _overwrite_cert_request (user_mgt_app , MOCK_REQUEST )
464496        with  pytest .raises (auth .InvalidIdTokenError ) as  excinfo :
465497            auth .verify_id_token (id_token , app = user_mgt_app )
@@ -469,6 +501,9 @@ def test_invalid_token(self, user_mgt_app, id_token):
469501    def  test_expired_token (self , user_mgt_app ):
470502        _overwrite_cert_request (user_mgt_app , MOCK_REQUEST )
471503        id_token  =  self .invalid_tokens ['ExpiredToken' ]
504+         if  _is_emulated ():
505+             self ._assert_valid_token (id_token , user_mgt_app )
506+             return 
472507        with  pytest .raises (auth .ExpiredIdTokenError ) as  excinfo :
473508            auth .verify_id_token (id_token , app = user_mgt_app )
474509        assert  isinstance (excinfo .value , auth .InvalidIdTokenError )
@@ -506,6 +541,10 @@ def test_custom_token(self, auth_app):
506541
507542    def  test_certificate_request_failure (self , user_mgt_app ):
508543        _overwrite_cert_request (user_mgt_app , testutils .MockRequest (404 , 'not found' ))
544+         if  _is_emulated ():
545+             # Shouldn't fetch certificates in emulator mode. 
546+             self ._assert_valid_token (TEST_ID_TOKEN , app = user_mgt_app )
547+             return 
509548        with  pytest .raises (auth .CertificateFetchError ) as  excinfo :
510549            auth .verify_id_token (TEST_ID_TOKEN , app = user_mgt_app )
511550        assert  'Could not fetch certificates'  in  str (excinfo .value )
@@ -540,20 +579,27 @@ class TestVerifySessionCookie:
540579        'IDToken' : TEST_ID_TOKEN ,
541580    }
542581
582+     cookies_not_invalid_in_emulator  =  [
583+         'WrongKid' ,
584+         'FutureCookie' ,
585+         'ExpiredCookie' 
586+     ]
587+ 
588+     def  _assert_valid_cookie (self , cookie , app , check_revoked = False ):
589+         claims  =  auth .verify_session_cookie (cookie , app = app , check_revoked = check_revoked )
590+         assert  claims ['admin' ] is  True 
591+         assert  claims ['uid' ] ==  claims ['sub' ]
592+ 
543593    @pytest .mark .parametrize ('cookie' , valid_cookies .values (), ids = list (valid_cookies )) 
544594    def  test_valid_cookie (self , user_mgt_app , cookie ):
545595        _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' ]
596+         self ._assert_valid_cookie (cookie , user_mgt_app )
549597
550598    @pytest .mark .parametrize ('cookie' , valid_cookies .values (), ids = list (valid_cookies )) 
551599    def  test_valid_cookie_check_revoked (self , user_mgt_app , cookie ):
552600        _overwrite_cert_request (user_mgt_app , MOCK_REQUEST )
553601        _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' ]
602+         self ._assert_valid_cookie (cookie , app = user_mgt_app , check_revoked = True )
557603
558604    @pytest .mark .parametrize ('cookie' , valid_cookies .values (), ids = list (valid_cookies )) 
559605    def  test_revoked_cookie_check_revoked (self , user_mgt_app , revoked_tokens , cookie ):
@@ -567,9 +613,7 @@ def test_revoked_cookie_check_revoked(self, user_mgt_app, revoked_tokens, cookie
567613    def  test_revoked_cookie_does_not_check_revoked (self , user_mgt_app , revoked_tokens , cookie ):
568614        _overwrite_cert_request (user_mgt_app , MOCK_REQUEST )
569615        _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' ]
616+         self ._assert_valid_cookie (cookie , app = user_mgt_app , check_revoked = False )
573617
574618    @pytest .mark .parametrize ('cookie' , INVALID_JWT_ARGS .values (), ids = list (INVALID_JWT_ARGS )) 
575619    def  test_invalid_args (self , user_mgt_app , cookie ):
@@ -578,8 +622,12 @@ def test_invalid_args(self, user_mgt_app, cookie):
578622            auth .verify_session_cookie (cookie , app = user_mgt_app )
579623        assert  'Illegal session cookie provided'  in  str (excinfo .value )
580624
581-     @pytest .mark .parametrize ('cookie' , invalid_cookies .values (), ids = list (invalid_cookies )) 
582-     def  test_invalid_cookie (self , user_mgt_app , cookie ):
625+     @pytest .mark .parametrize ('cookie_key' , list (invalid_cookies )) 
626+     def  test_invalid_cookie (self , user_mgt_app , cookie_key ):
627+         cookie  =  self .invalid_cookies [cookie_key ]
628+         if  _is_emulated () and  cookie_key  in  self .cookies_not_invalid_in_emulator :
629+             self ._assert_valid_cookie (cookie , user_mgt_app )
630+             return 
583631        _overwrite_cert_request (user_mgt_app , MOCK_REQUEST )
584632        with  pytest .raises (auth .InvalidSessionCookieError ) as  excinfo :
585633            auth .verify_session_cookie (cookie , app = user_mgt_app )
@@ -589,6 +637,9 @@ def test_invalid_cookie(self, user_mgt_app, cookie):
589637    def  test_expired_cookie (self , user_mgt_app ):
590638        _overwrite_cert_request (user_mgt_app , MOCK_REQUEST )
591639        cookie  =  self .invalid_cookies ['ExpiredCookie' ]
640+         if  _is_emulated ():
641+             self ._assert_valid_cookie (cookie , user_mgt_app )
642+             return 
592643        with  pytest .raises (auth .ExpiredSessionCookieError ) as  excinfo :
593644            auth .verify_session_cookie (cookie , app = user_mgt_app )
594645        assert  isinstance (excinfo .value , auth .InvalidSessionCookieError )
@@ -621,6 +672,10 @@ def test_custom_token(self, auth_app):
621672
622673    def  test_certificate_request_failure (self , user_mgt_app ):
623674        _overwrite_cert_request (user_mgt_app , testutils .MockRequest (404 , 'not found' ))
675+         if  _is_emulated ():
676+             # Shouldn't fetch certificates in emulator mode. 
677+             auth .verify_session_cookie (TEST_SESSION_COOKIE , app = user_mgt_app )
678+             return 
624679        with  pytest .raises (auth .CertificateFetchError ) as  excinfo :
625680            auth .verify_session_cookie (TEST_SESSION_COOKIE , app = user_mgt_app )
626681        assert  'Could not fetch certificates'  in  str (excinfo .value )
@@ -637,9 +692,11 @@ def test_certificate_caching(self, user_mgt_app, httpserver):
637692        verifier .cookie_verifier .cert_url  =  httpserver .url 
638693        verifier .id_token_verifier .cert_url  =  httpserver .url 
639694        verifier .verify_session_cookie (TEST_SESSION_COOKIE )
640-         assert  len (httpserver .requests ) ==  1 
695+         # No requests should be made in emulated mode 
696+         request_count  =  0  if  _is_emulated () else  1 
697+         assert  len (httpserver .requests ) ==  request_count 
641698        # Subsequent requests should not fetch certs from the server 
642699        verifier .verify_session_cookie (TEST_SESSION_COOKIE )
643-         assert  len (httpserver .requests ) ==  1 
700+         assert  len (httpserver .requests ) ==  request_count 
644701        verifier .verify_id_token (TEST_ID_TOKEN )
645-         assert  len (httpserver .requests ) ==  1 
702+         assert  len (httpserver .requests ) ==  request_count 
0 commit comments