Skip to content

Commit dbd8da5

Browse files
authored
Caching Public Keys for ID Token and Cookie Verification (#150)
* Re-organizing auth unit tests * Moving _request to TokenVerifier class * Updated tests * Caching public certificates used to verify ID tokens and session cookies
1 parent c2f3ffe commit dbd8da5

File tree

4 files changed

+30
-5
lines changed

4 files changed

+30
-5
lines changed

firebase_admin/_token_gen.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import datetime
1818
import time
1919

20+
import cachecontrol
2021
import requests
2122
import six
2223
from google.auth import jwt
@@ -150,23 +151,24 @@ class TokenVerifier(object):
150151
"""Verifies ID tokens and session cookies."""
151152

152153
def __init__(self, app):
153-
self.request = transport.requests.Request()
154-
self._id_token_verifier = _JWTVerifier(
154+
session = cachecontrol.CacheControl(requests.Session())
155+
self.request = transport.requests.Request(session=session)
156+
self.id_token_verifier = _JWTVerifier(
155157
project_id=app.project_id, short_name='ID token',
156158
operation='verify_id_token()',
157159
doc_url='https://firebase.google.com/docs/auth/admin/verify-id-tokens',
158160
cert_url=ID_TOKEN_CERT_URI, issuer=ID_TOKEN_ISSUER_PREFIX)
159-
self._cookie_verifier = _JWTVerifier(
161+
self.cookie_verifier = _JWTVerifier(
160162
project_id=app.project_id, short_name='session cookie',
161163
operation='verify_session_cookie()',
162164
doc_url='https://firebase.google.com/docs/auth/admin/verify-id-tokens',
163165
cert_url=COOKIE_CERT_URI, issuer=COOKIE_ISSUER_PREFIX)
164166

165167
def verify_id_token(self, id_token):
166-
return self._id_token_verifier.verify(id_token, self.request)
168+
return self.id_token_verifier.verify(id_token, self.request)
167169

168170
def verify_session_cookie(self, cookie):
169-
return self._cookie_verifier.verify(cookie, self.request)
171+
return self.cookie_verifier.verify(cookie, self.request)
170172

171173

172174
class _JWTVerifier(object):

requirements.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
pylint == 1.6.4
22
pytest >= 3.0.6
33
pytest-cov >= 2.4.0
4+
pytest-localserver >= 0.4.1
45
tox >= 2.6.0
56

7+
cachecontrol >= 0.12.4
68
google-auth >= 1.3.0
79
google-cloud-firestore >= 0.27.0
810
google-cloud-storage >= 1.2.0

setup.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
long_description = ('The Firebase Admin Python SDK enables server-side (backend) Python developers '
3838
'to integrate Firebase into their services and applications.')
3939
install_requires = [
40+
'cachecontrol>=0.12.4',
4041
'google-auth>=1.3.0',
4142
'google-cloud-firestore>=0.27.0',
4243
'google-cloud-storage>=1.2.0',

tests/test_token_gen.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
from google.auth import jwt
2525
import google.oauth2.id_token
2626
import pytest
27+
from pytest_localserver import plugin
2728
import six
2829

2930
import firebase_admin
@@ -44,6 +45,9 @@
4445
INVALID_STRINGS = [None, '', 0, 1, True, False, list(), tuple(), dict()]
4546
INVALID_BOOLS = [None, '', 'foo', 0, 1, list(), tuple(), dict()]
4647

48+
# Fixture for mocking a HTTP server
49+
httpserver = plugin.httpserver
50+
4751

4852
def _merge_jwt_claims(defaults, overrides):
4953
defaults.update(overrides)
@@ -452,3 +456,19 @@ def test_certificate_request_failure(self, user_mgt_app):
452456
_overwrite_cert_request(user_mgt_app, testutils.MockRequest(404, 'not found'))
453457
with pytest.raises(exceptions.TransportError):
454458
auth.verify_session_cookie(TEST_SESSION_COOKIE, app=user_mgt_app)
459+
460+
461+
class TestCertificateCaching(object):
462+
463+
def test_certificate_caching(self, user_mgt_app, httpserver):
464+
httpserver.serve_content(MOCK_PUBLIC_CERTS, 200, headers={'Cache-Control': 'max-age=3600'})
465+
verifier = _token_gen.TokenVerifier(user_mgt_app)
466+
verifier.cookie_verifier.cert_url = httpserver.url
467+
verifier.id_token_verifier.cert_url = httpserver.url
468+
verifier.verify_session_cookie(TEST_SESSION_COOKIE)
469+
assert len(httpserver.requests) == 1
470+
# Subsequent requests should not fetch certs from the server
471+
verifier.verify_session_cookie(TEST_SESSION_COOKIE)
472+
assert len(httpserver.requests) == 1
473+
verifier.verify_id_token(TEST_ID_TOKEN)
474+
assert len(httpserver.requests) == 1

0 commit comments

Comments
 (0)