19
19
import json
20
20
import os
21
21
import time
22
+ import unittest .mock
23
+ import datetime
22
24
23
25
from google .auth import crypt
24
26
from google .auth import jwt
25
27
import google .auth .exceptions
26
28
import google .oauth2 .id_token
29
+ from google .auth .jwt import _helpers as jwt_helpers
27
30
import pytest
28
31
from pytest_localserver import plugin
29
32
36
39
from tests import testutils
37
40
38
41
42
+ MOCK_CURRENT_TIME = 1500000000
39
43
MOCK_UID = 'user1'
40
44
MOCK_CREDENTIAL = credentials .Certificate (
41
45
testutils .resource_filename ('service_account.json' ))
@@ -105,16 +109,17 @@ def verify_custom_token(custom_token, expected_claims, tenant_id=None):
105
109
for key , value in expected_claims .items ():
106
110
assert value == token ['claims' ][key ]
107
111
108
- def _get_id_token (payload_overrides = None , header_overrides = None ):
112
+ def _get_id_token (payload_overrides = None , header_overrides = None , current_time = MOCK_CURRENT_TIME ):
109
113
signer = crypt .RSASigner .from_string (MOCK_PRIVATE_KEY )
110
114
headers = {
111
115
'kid' : 'mock-key-id-1'
112
116
}
117
+ now = int (current_time if current_time is not None else time .time ())
113
118
payload = {
114
119
'aud' : MOCK_CREDENTIAL .project_id ,
115
120
'iss' : 'https://securetoken.google.com/' + MOCK_CREDENTIAL .project_id ,
116
- 'iat' : int ( time . time ()) - 100 ,
117
- 'exp' : int ( time . time ()) + 3600 ,
121
+ 'iat' : now - 100 ,
122
+ 'exp' : now + 3600 ,
118
123
'sub' : '1234567890' ,
119
124
'admin' : True ,
120
125
'firebase' : {
@@ -127,12 +132,12 @@ def _get_id_token(payload_overrides=None, header_overrides=None):
127
132
payload = _merge_jwt_claims (payload , payload_overrides )
128
133
return jwt .encode (signer , payload , header = headers )
129
134
130
- def _get_session_cookie (payload_overrides = None , header_overrides = None ):
135
+ def _get_session_cookie (payload_overrides = None , header_overrides = None , current_time = MOCK_CURRENT_TIME ):
131
136
payload_overrides = payload_overrides or {}
132
137
if 'iss' not in payload_overrides :
133
138
payload_overrides ['iss' ] = 'https://session.firebase.google.com/{0}' .format (
134
139
MOCK_CREDENTIAL .project_id )
135
- return _get_id_token (payload_overrides , header_overrides )
140
+ return _get_id_token (payload_overrides , header_overrides , current_time = current_time )
136
141
137
142
def _instrument_user_manager (app , status , payload ):
138
143
client = auth ._get_client (app )
@@ -205,7 +210,7 @@ def env_var_app(request):
205
210
@pytest .fixture (scope = 'module' )
206
211
def revoked_tokens ():
207
212
mock_user = json .loads (testutils .resource ('get_user.json' ))
208
- mock_user ['users' ][0 ]['validSince' ] = str (int ( time . time ()) + 100 )
213
+ mock_user ['users' ][0 ]['validSince' ] = str (MOCK_CURRENT_TIME + 100 )
209
214
return json .dumps (mock_user )
210
215
211
216
@pytest .fixture (scope = 'module' )
@@ -218,7 +223,7 @@ def user_disabled():
218
223
def user_disabled_and_revoked ():
219
224
mock_user = json .loads (testutils .resource ('get_user.json' ))
220
225
mock_user ['users' ][0 ]['disabled' ] = True
221
- mock_user ['users' ][0 ]['validSince' ] = str (int ( time . time ()) + 100 )
226
+ mock_user ['users' ][0 ]['validSince' ] = str (MOCK_CURRENT_TIME + 100 )
222
227
return json .dumps (mock_user )
223
228
224
229
@@ -420,6 +425,17 @@ def test_unexpected_response(self, user_mgt_app):
420
425
421
426
class TestVerifyIdToken :
422
427
428
+ def setup_method (self , method ):
429
+ self .time_patch = unittest .mock .patch ('time.time' , return_value = MOCK_CURRENT_TIME )
430
+ self .time_patch .start ()
431
+ self .utcnow_patch = unittest .mock .patch .object (
432
+ jwt_helpers , 'utcnow' , return_value = datetime .datetime .utcfromtimestamp (MOCK_CURRENT_TIME ))
433
+ self .utcnow_patch .start ()
434
+
435
+ def teardown_method (self , method ):
436
+ self .time_patch .stop ()
437
+ self .utcnow_patch .stop ()
438
+
423
439
valid_tokens = {
424
440
'BinaryToken' : TEST_ID_TOKEN ,
425
441
'TextToken' : TEST_ID_TOKEN .decode ('utf-8' ),
@@ -435,15 +451,9 @@ class TestVerifyIdToken:
435
451
'EmptySubject' : _get_id_token ({'sub' : '' }),
436
452
'IntSubject' : _get_id_token ({'sub' : 10 }),
437
453
'LongStrSubject' : _get_id_token ({'sub' : 'a' * 129 }),
438
- 'FutureToken' : _get_id_token ({'iat' : int (time .time ()) + 1000 }),
439
- 'ExpiredToken' : _get_id_token ({
440
- 'iat' : int (time .time ()) - 10000 ,
441
- 'exp' : int (time .time ()) - 3600
442
- }),
443
- 'ExpiredTokenShort' : _get_id_token ({
444
- 'iat' : int (time .time ()) - 10000 ,
445
- 'exp' : int (time .time ()) - 30
446
- }),
454
+ 'FutureToken' : _get_id_token ({'iat' : MOCK_CURRENT_TIME + 1000 }),
455
+ 'ExpiredToken' : _get_id_token ({'iat' : MOCK_CURRENT_TIME - 10000 , 'exp' : MOCK_CURRENT_TIME - 3600 }),
456
+ 'ExpiredTokenShort' : _get_id_token ({'iat' : MOCK_CURRENT_TIME - 10000 , 'exp' : MOCK_CURRENT_TIME - 30 }),
447
457
'BadFormatToken' : 'foobar'
448
458
}
449
459
@@ -618,6 +628,17 @@ def test_certificate_request_failure(self, user_mgt_app):
618
628
619
629
class TestVerifySessionCookie :
620
630
631
+ def setup_method (self , method ):
632
+ self .time_patch = unittest .mock .patch ('time.time' , return_value = MOCK_CURRENT_TIME )
633
+ self .time_patch .start ()
634
+ self .utcnow_patch = unittest .mock .patch .object (
635
+ jwt_helpers , 'utcnow' , return_value = datetime .datetime .utcfromtimestamp (MOCK_CURRENT_TIME ))
636
+ self .utcnow_patch .start ()
637
+
638
+ def teardown_method (self , method ):
639
+ self .time_patch .stop ()
640
+ self .utcnow_patch .stop ()
641
+
621
642
valid_cookies = {
622
643
'BinaryCookie' : TEST_SESSION_COOKIE ,
623
644
'TextCookie' : TEST_SESSION_COOKIE .decode ('utf-8' ),
@@ -633,15 +654,9 @@ class TestVerifySessionCookie:
633
654
'EmptySubject' : _get_session_cookie ({'sub' : '' }),
634
655
'IntSubject' : _get_session_cookie ({'sub' : 10 }),
635
656
'LongStrSubject' : _get_session_cookie ({'sub' : 'a' * 129 }),
636
- 'FutureCookie' : _get_session_cookie ({'iat' : int (time .time ()) + 1000 }),
637
- 'ExpiredCookie' : _get_session_cookie ({
638
- 'iat' : int (time .time ()) - 10000 ,
639
- 'exp' : int (time .time ()) - 3600
640
- }),
641
- 'ExpiredCookieShort' : _get_session_cookie ({
642
- 'iat' : int (time .time ()) - 10000 ,
643
- 'exp' : int (time .time ()) - 30
644
- }),
657
+ 'FutureCookie' : _get_session_cookie ({'iat' : MOCK_CURRENT_TIME + 1000 }),
658
+ 'ExpiredCookie' : _get_session_cookie ({'iat' : MOCK_CURRENT_TIME - 10000 , 'exp' : MOCK_CURRENT_TIME - 3600 }),
659
+ 'ExpiredCookieShort' : _get_session_cookie ({'iat' : MOCK_CURRENT_TIME - 10000 , 'exp' : MOCK_CURRENT_TIME - 30 }),
645
660
'BadFormatCookie' : 'foobar' ,
646
661
'IDToken' : TEST_ID_TOKEN ,
647
662
}
@@ -792,6 +807,17 @@ def test_certificate_request_failure(self, user_mgt_app):
792
807
793
808
class TestCertificateCaching :
794
809
810
+ def setup_method (self , method ):
811
+ self .time_patch = unittest .mock .patch ('time.time' , return_value = MOCK_CURRENT_TIME )
812
+ self .time_patch .start ()
813
+ self .utcnow_patch = unittest .mock .patch .object (
814
+ jwt_helpers , 'utcnow' , return_value = datetime .datetime .utcfromtimestamp (MOCK_CURRENT_TIME ))
815
+ self .utcnow_patch .start ()
816
+
817
+ def teardown_method (self , method ):
818
+ self .time_patch .stop ()
819
+ self .utcnow_patch .stop ()
820
+
795
821
def test_certificate_caching (self , user_mgt_app , httpserver ):
796
822
httpserver .serve_content (MOCK_PUBLIC_CERTS , 200 , headers = {'Cache-Control' : 'max-age=3600' })
797
823
verifier = _token_gen .TokenVerifier (user_mgt_app )
@@ -810,6 +836,17 @@ def test_certificate_caching(self, user_mgt_app, httpserver):
810
836
811
837
class TestCertificateFetchTimeout :
812
838
839
+ def setup_method (self , method ):
840
+ self .time_patch = unittest .mock .patch ('time.time' , return_value = MOCK_CURRENT_TIME )
841
+ self .time_patch .start ()
842
+ self .utcnow_patch = unittest .mock .patch .object (
843
+ jwt_helpers , 'utcnow' , return_value = datetime .datetime .utcfromtimestamp (MOCK_CURRENT_TIME ))
844
+ self .utcnow_patch .start ()
845
+
846
+ def teardown_method (self , method ):
847
+ self .time_patch .stop ()
848
+ self .utcnow_patch .stop ()
849
+
813
850
timeout_configs = [
814
851
({'httpTimeout' : 4 }, 4 ),
815
852
({'httpTimeout' : None }, None ),
0 commit comments