Skip to content

Commit 6098e00

Browse files
committed
chore: address CR
1 parent 5584e5d commit 6098e00

File tree

7 files changed

+82
-40
lines changed

7 files changed

+82
-40
lines changed

firebase_admin/__about__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
"""About information (version, etc) for Firebase Admin SDK."""
1616

17-
__version__ = '6.2.1'
17+
__version__ = '6.2.0'
1818
__title__ = 'firebase_admin'
1919
__author__ = 'Firebase'
2020
__license__ = 'Apache License 2.0'

firebase_admin/__init__.py

+5-6
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@
2929

3030
_DEFAULT_APP_NAME = '[DEFAULT]'
3131
_FIREBASE_CONFIG_ENV_VAR = 'FIREBASE_CONFIG'
32-
_CONFIG_VALID_KEYS = ['clockSkewInSeconds', 'databaseAuthVariableOverride', 'databaseURL',
33-
'httpTimeout', 'projectId', 'storageBucket']
32+
_CONFIG_VALID_KEYS = ['databaseAuthVariableOverride', 'databaseURL', 'httpTimeout', 'projectId',
33+
'storageBucket']
3434

3535
def initialize_app(credential=None, options=None, name=_DEFAULT_APP_NAME):
3636
"""Initializes and returns a new App instance.
@@ -49,10 +49,9 @@ def initialize_app(credential=None, options=None, name=_DEFAULT_APP_NAME):
4949
credential: A credential object used to initialize the SDK (optional). If none is provided,
5050
Google Application Default Credentials are used.
5151
options: A dictionary of configuration options (optional). Supported options include
52-
``clockSkewInSeconds``, ``databaseURL``, ``storageBucket``, ``projectId``,
53-
``databaseAuthVariableOverride``, ``serviceAccountId`` and ``httpTimeout``. If
54-
``httpTimeout`` is not set, the SDK uses a default timeout of 120 seconds. If
55-
``clockSkewInSeconds`` is not set, 0 is used when verifying a token or cookie.
52+
``databaseURL``, ``storageBucket``, ``projectId``, ``databaseAuthVariableOverride``,
53+
``serviceAccountId`` and ``httpTimeout``. If ``httpTimeout`` is not set, the SDK uses
54+
a default timeout of 120 seconds.
5655
5756
name: Name of the app (optional).
5857
Returns:

firebase_admin/_auth_client.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ def create_custom_token(self, uid, developer_claims=None):
9292
return self._token_generator.create_custom_token(
9393
uid, developer_claims, tenant_id=self.tenant_id)
9494

95-
def verify_id_token(self, id_token, check_revoked=False, clock_skew_in_seconds=0):
95+
def verify_id_token(self, id_token, check_revoked=False, clock_skew_seconds=0):
9696
"""Verifies the signature and data for the provided JWT.
9797
9898
Accepts a signed token string, verifies that it is current, was issued
@@ -102,7 +102,8 @@ def verify_id_token(self, id_token, check_revoked=False, clock_skew_in_seconds=0
102102
id_token: A string of the encoded JWT.
103103
check_revoked: Boolean, If true, checks whether the token has been revoked or
104104
the user disabled (optional).
105-
clock_skew_in_seconds: The number of seconds to tolerate when checking the token
105+
clock_skew_seconds: The number of seconds to tolerate when checking the token.
106+
Must be between 0-60. Defaults to 0.
106107
107108
Returns:
108109
dict: A dictionary of key-value pairs parsed from the decoded JWT.
@@ -125,7 +126,7 @@ def verify_id_token(self, id_token, check_revoked=False, clock_skew_in_seconds=0
125126
raise ValueError('Illegal check_revoked argument. Argument must be of type '
126127
' bool, but given "{0}".'.format(type(check_revoked)))
127128

128-
verified_claims = self._token_verifier.verify_id_token(id_token, clock_skew_in_seconds)
129+
verified_claims = self._token_verifier.verify_id_token(id_token, clock_skew_seconds)
129130
if self.tenant_id:
130131
token_tenant_id = verified_claims.get('firebase', {}).get('tenant')
131132
if self.tenant_id != token_tenant_id:

firebase_admin/_token_gen.py

+11-6
Original file line numberDiff line numberDiff line change
@@ -289,11 +289,11 @@ def __init__(self, app):
289289
invalid_token_error=InvalidSessionCookieError,
290290
expired_token_error=ExpiredSessionCookieError)
291291

292-
def verify_id_token(self, id_token, clock_skew_in_seconds=0):
293-
return self.id_token_verifier.verify(id_token, self.request, clock_skew_in_seconds)
292+
def verify_id_token(self, id_token, clock_skew_seconds=0):
293+
return self.id_token_verifier.verify(id_token, self.request, clock_skew_seconds)
294294

295-
def verify_session_cookie(self, cookie, clock_skew_in_seconds=0):
296-
return self.cookie_verifier.verify(cookie, self.request, clock_skew_in_seconds)
295+
def verify_session_cookie(self, cookie, clock_skew_seconds=0):
296+
return self.cookie_verifier.verify(cookie, self.request, clock_skew_seconds)
297297

298298

299299
class _JWTVerifier:
@@ -313,7 +313,7 @@ def __init__(self, **kwargs):
313313
self._invalid_token_error = kwargs.pop('invalid_token_error')
314314
self._expired_token_error = kwargs.pop('expired_token_error')
315315

316-
def verify(self, token, request, clock_skew_in_seconds=0):
316+
def verify(self, token, request, clock_skew_seconds=0):
317317
"""Verifies the signature and data for the provided JWT."""
318318
token = token.encode('utf-8') if isinstance(token, str) else token
319319
if not isinstance(token, bytes) or not token:
@@ -328,6 +328,11 @@ def verify(self, token, request, clock_skew_in_seconds=0):
328328
'or set your Firebase project ID as an app option. Alternatively set the '
329329
'GOOGLE_CLOUD_PROJECT environment variable.'.format(self.operation))
330330

331+
if clock_skew_seconds < 0 or clock_skew_seconds > 60:
332+
raise ValueError(
333+
'Illegal clock_skew_seconds value: {0}. Must be between 0 and 60, inclusive.'
334+
.format(clock_skew_seconds))
335+
331336
header, payload = self._decode_unverified(token)
332337
issuer = payload.get('iss')
333338
audience = payload.get('aud')
@@ -394,7 +399,7 @@ def verify(self, token, request, clock_skew_in_seconds=0):
394399
request=request,
395400
audience=self.project_id,
396401
certs_url=self.cert_url,
397-
clock_skew_in_seconds=clock_skew_in_seconds)
402+
clock_skew_in_seconds=clock_skew_seconds)
398403
verified_claims['uid'] = verified_claims['sub']
399404
return verified_claims
400405
except google.auth.exceptions.TransportError as error:

firebase_admin/auth.py

+7-7
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ def create_custom_token(uid, developer_claims=None, app=None):
191191
return client.create_custom_token(uid, developer_claims)
192192

193193

194-
def verify_id_token(id_token, app=None, check_revoked=False, clock_skew_in_seconds=0):
194+
def verify_id_token(id_token, app=None, check_revoked=False, clock_skew_seconds=0):
195195
"""Verifies the signature and data for the provided JWT.
196196
197197
Accepts a signed token string, verifies that it is current, and issued
@@ -202,8 +202,8 @@ def verify_id_token(id_token, app=None, check_revoked=False, clock_skew_in_secon
202202
app: An App instance (optional).
203203
check_revoked: Boolean, If true, checks whether the token has been revoked or
204204
the user disabled (optional).
205-
clock_skew_in_seconds: The number of seconds to tolerate when checking the token.
206-
205+
clock_skew_seconds: The number of seconds to tolerate when checking the token.
206+
Must be between 0-60. Defaults to 0.
207207
Returns:
208208
dict: A dictionary of key-value pairs parsed from the decoded JWT.
209209
@@ -219,7 +219,7 @@ def verify_id_token(id_token, app=None, check_revoked=False, clock_skew_in_secon
219219
"""
220220
client = _get_client(app)
221221
return client.verify_id_token(
222-
id_token, check_revoked=check_revoked, clock_skew_in_seconds=clock_skew_in_seconds)
222+
id_token, check_revoked=check_revoked, clock_skew_seconds=clock_skew_seconds)
223223

224224

225225
def create_session_cookie(id_token, expires_in, app=None):
@@ -245,7 +245,7 @@ def create_session_cookie(id_token, expires_in, app=None):
245245
return client._token_generator.create_session_cookie(id_token, expires_in)
246246

247247

248-
def verify_session_cookie(session_cookie, check_revoked=False, app=None, clock_skew_in_seconds=0):
248+
def verify_session_cookie(session_cookie, check_revoked=False, app=None, clock_skew_seconds=0):
249249
"""Verifies a Firebase session cookie.
250250
251251
Accepts a session cookie string, verifies that it is current, and issued
@@ -256,7 +256,7 @@ def verify_session_cookie(session_cookie, check_revoked=False, app=None, clock_s
256256
check_revoked: Boolean, if true, checks whether the cookie has been revoked or the
257257
user disabled (optional).
258258
app: An App instance (optional).
259-
clock_skew_in_seconds: The number of seconds to tolerate when checking the cookie
259+
clock_skew_seconds: The number of seconds to tolerate when checking the cookie
260260
261261
Returns:
262262
dict: A dictionary of key-value pairs parsed from the decoded JWT.
@@ -274,7 +274,7 @@ def verify_session_cookie(session_cookie, check_revoked=False, app=None, clock_s
274274
client = _get_client(app)
275275
# pylint: disable=protected-access
276276
verified_claims = client._token_verifier.verify_session_cookie(
277-
session_cookie, clock_skew_in_seconds)
277+
session_cookie, clock_skew_seconds)
278278
if check_revoked:
279279
client._check_jwt_revoked_or_disabled(
280280
verified_claims, RevokedSessionCookieError, 'session cookie')

integration/test_auth.py

+36-9
Original file line numberDiff line numberDiff line change
@@ -164,20 +164,25 @@ def test_session_cookies_with_tolerance(api_key):
164164
dev_claims = {'premium' : True, 'subscription' : 'silver'}
165165
custom_token = auth.create_custom_token('user3', dev_claims)
166166
id_token = _sign_in(custom_token, api_key)
167-
expires_in = datetime.timedelta(seconds=300)
167+
expires_in = datetime.timedelta(seconds=3)
168168
session_cookie = auth.create_session_cookie(id_token, expires_in=expires_in)
169-
time.sleep(300)
169+
time.sleep(4)
170170
# expect this to fail because the cookie is expired
171171
with pytest.raises(auth.ExpiredSessionCookieError):
172172
auth.verify_session_cookie(session_cookie)
173173

174174
# expect this to succeed because we're within the tolerance
175-
claims = auth.verify_session_cookie(session_cookie, check_revoked=False, tolerance=2)
175+
claims = auth.verify_session_cookie(session_cookie, check_revoked=False, clock_skew_seconds=2)
176176
assert claims['uid'] == 'user3'
177177
assert claims['premium'] is True
178178
assert claims['subscription'] == 'silver'
179179
assert claims['iss'].startswith('https://session.firebase.google.com')
180180

181+
with pytest.raises(ValueError):
182+
auth.verify_session_cookie(session_cookie, clock_skew_seconds=-1)
183+
with pytest.raises(ValueError):
184+
auth.verify_session_cookie(session_cookie, clock_skew_seconds=61)
185+
181186
def test_session_cookie_error():
182187
expires_in = datetime.timedelta(days=1)
183188
with pytest.raises(auth.InvalidIdTokenError):
@@ -601,12 +606,12 @@ def test_verify_id_token_tolerance(new_user, api_key):
601606
# Verify the ID token with a tolerance of 0 seconds. This should
602607
# raise an exception because the token is expired.
603608
with pytest.raises(auth.InvalidIdTokenError) as excinfo:
604-
auth.verify_id_token(expired_id_token, check_revoked=False, clock_skew_in_seconds=0)
609+
auth.verify_id_token(expired_id_token, check_revoked=False, clock_skew_seconds=0)
605610
assert str(excinfo.value) == 'The Firebase ID token is expired.'
606611

607612
# Verify the ID token with a tolerance of 2 seconds. This should
608613
# not raise an exception because the token is within the tolerance.
609-
auth.verify_id_token(expired_id_token, check_revoked=False, clock_skew_in_seconds=2)
614+
auth.verify_id_token(expired_id_token, check_revoked=False, clock_skew_seconds=2)
610615

611616
def test_verify_id_token_disabled(new_user, api_key):
612617
custom_token = auth.create_custom_token(new_user.uid)
@@ -649,17 +654,39 @@ def test_verify_session_cookie_revoked(new_user, api_key):
649654
assert claims['iat'] * 1000 >= user.tokens_valid_after_timestamp
650655

651656
def test_verify_session_cookie_tolerance(new_user, api_key):
652-
expired_session_cookie = auth.create_session_cookie(_sign_in(auth.create_custom_token(new_user.uid), api_key), expires_in=datetime.timedelta(seconds=300))
653-
time.sleep(300)
657+
expired_session_cookie = auth.create_session_cookie(
658+
_sign_in(auth.create_custom_token(new_user.uid), api_key),
659+
expires_in=datetime.timedelta(seconds=3)
660+
)
661+
time.sleep(3)
654662
# Verify the session cookie with a tolerance of 0 seconds. This should
655663
# raise an exception because the cookie is expired.
656664
with pytest.raises(auth.InvalidSessionCookieError) as excinfo:
657-
auth.verify_session_cookie(expired_session_cookie, check_revoked=False, clock_skew_in_seconds=0)
665+
auth.verify_session_cookie(expired_session_cookie, check_revoked=False, clock_skew_seconds=0)
658666
assert str(excinfo.value) == 'The Firebase session cookie is expired.'
659667

660668
# Verify the session cookie with a tolerance of 2 seconds. This should
661669
# not raise an exception because the cookie is within the tolerance.
662-
auth.verify_session_cookie(expired_session_cookie, check_revoked=False, clock_skew_in_seconds=2)
670+
auth.verify_session_cookie(expired_session_cookie, check_revoked=False, clock_skew_seconds=2)
671+
672+
def test_verify_session_cookie_clock_skew_seconds_range(new_user, api_key):
673+
expired_session_cookie = auth.create_session_cookie(
674+
_sign_in(auth.create_custom_token(new_user.uid), api_key),
675+
expires_in=datetime.timedelta(seconds=3)
676+
)
677+
# Verify the session cookie with a tolerance of 0 seconds. This should
678+
# raise an exception because the cookie is expired.
679+
with pytest.raises(ValueError) as excinfo:
680+
auth.verify_session_cookie(expired_session_cookie, check_revoked=False, clock_skew_seconds=-1)
681+
assert str(excinfo.value) == 'clock_skew_seconds must be between 0 and 60.'
682+
with pytest.raises(ValueError) as excinfo:
683+
auth.verify_session_cookie(expired_session_cookie, check_revoked=False, clock_skew_seconds=61)
684+
assert str(excinfo.value) == 'clock_skew_seconds must be between 0 and 60.'
685+
686+
# Verify the session cookie with a tolerance of 2 seconds. This should
687+
# not raise an exception because the cookie is within the tolerance.
688+
auth.verify_session_cookie(expired_session_cookie, check_revoked=False, clock_skew_seconds=2)
689+
663690

664691
def test_verify_session_cookie_disabled(new_user, api_key):
665692
custom_token = auth.create_custom_token(new_user.uid)

tests/test_token_gen.py

+18-8
Original file line numberDiff line numberDiff line change
@@ -440,14 +440,19 @@ class TestVerifyIdToken:
440440
'iat': int(time.time()) - 10000,
441441
'exp': int(time.time()) - 3600
442442
}),
443+
'ExpiredTokenShort': _get_id_token({
444+
'iat': int(time.time()) - 10000,
445+
'exp': int(time.time()) - 30
446+
}),
443447
'BadFormatToken': 'foobar'
444448
}
445449

446450
tokens_accepted_in_emulator = [
447451
'NoKid',
448452
'WrongKid',
449453
'FutureToken',
450-
'ExpiredToken'
454+
'ExpiredToken',
455+
'ExpiredTokenShort',
451456
]
452457

453458
def _assert_valid_token(self, id_token, app):
@@ -557,17 +562,17 @@ def test_expired_token(self, user_mgt_app):
557562

558563
def test_expired_token_with_tolerance(self, user_mgt_app):
559564
_overwrite_cert_request(user_mgt_app, MOCK_REQUEST)
560-
id_token = self.invalid_tokens['ExpiredToken']
565+
id_token = self.invalid_tokens['ExpiredTokenShort']
561566
if _is_emulated():
562567
self._assert_valid_token(id_token, user_mgt_app)
563568
return
564569
claims = auth.verify_id_token(id_token, app=user_mgt_app,
565-
clock_skew_in_seconds=3700)
570+
clock_skew_seconds=60)
566571
assert claims['admin'] is True
567572
assert claims['uid'] == claims['sub']
568573
with pytest.raises(auth.ExpiredIdTokenError) as excinfo:
569574
auth.verify_id_token(id_token, app=user_mgt_app,
570-
clock_skew_in_seconds=3500)
575+
clock_skew_seconds=20)
571576

572577
def test_project_id_option(self):
573578
app = firebase_admin.initialize_app(
@@ -633,6 +638,10 @@ class TestVerifySessionCookie:
633638
'iat': int(time.time()) - 10000,
634639
'exp': int(time.time()) - 3600
635640
}),
641+
'ExpiredCookieShort': _get_session_cookie({
642+
'iat': int(time.time()) - 10000,
643+
'exp': int(time.time()) - 30
644+
}),
636645
'BadFormatCookie': 'foobar',
637646
'IDToken': TEST_ID_TOKEN,
638647
}
@@ -641,7 +650,8 @@ class TestVerifySessionCookie:
641650
'NoKid',
642651
'WrongKid',
643652
'FutureCookie',
644-
'ExpiredCookie'
653+
'ExpiredCookie',
654+
'ExpiredCookieShort',
645655
]
646656

647657
def _assert_valid_cookie(self, cookie, app, check_revoked=False):
@@ -731,17 +741,17 @@ def test_expired_cookie(self, user_mgt_app):
731741

732742
def test_expired_cookie_with_tolerance(self, user_mgt_app):
733743
_overwrite_cert_request(user_mgt_app, MOCK_REQUEST)
734-
cookie = self.invalid_cookies['ExpiredCookie']
744+
cookie = self.invalid_cookies['ExpiredCookieShort']
735745
if _is_emulated():
736746
self._assert_valid_cookie(cookie, user_mgt_app)
737747
return
738748
claims = auth.verify_session_cookie(cookie, app=user_mgt_app, check_revoked=False,
739-
clock_skew_in_seconds=7200)
749+
clock_skew_seconds=59)
740750
assert claims['admin'] is True
741751
assert claims['uid'] == claims['sub']
742752
with pytest.raises(auth.ExpiredSessionCookieError) as excinfo:
743753
auth.verify_session_cookie(cookie, app=user_mgt_app, check_revoked=False,
744-
clock_skew_in_seconds=3500)
754+
clock_skew_seconds=29)
745755

746756
def test_project_id_option(self):
747757
app = firebase_admin.initialize_app(

0 commit comments

Comments
 (0)