Skip to content

Commit ae82230

Browse files
committed
Add JWT_SECRET_KEY and JWT_PRIVATE_KEY
1 parent 6741215 commit ae82230

File tree

5 files changed

+47
-18
lines changed

5 files changed

+47
-18
lines changed

docs/options.rst

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,13 @@ General Options:
2323
takes a ``datetime.timedelta``, and defaults to 30 days
2424
``JWT_ALGORITHM`` Which algorithm to sign the JWT with. `See here <https://pyjwt.readthedocs.io/en/latest/algorithms.html>`_
2525
for the options. Defaults to ``'HS256'``.
26-
``JWT_PUBLIC_KEY`` The public key needed for RSA and ECDSA based signing algorithms.
27-
Has to be provided if any of ``RS*`` or ``ES*`` algorithms is used.
28-
PEM format expected.
26+
``JWT_SECRET_KEY`` The secret key needed for symmetric based signing algorithms,
27+
such as ``HS*``. If this is not set, we use the
28+
flask ``SECRET_KEY`` value instead.
29+
``JWT_PUBLIC_KEY`` The public key needed for asymmetric based signing algorithms,
30+
such as ``RS*`` or ``ES*``. PEM format expected.
31+
``JWT_PRIVATE_KEY`` The private key needed for asymmetric based signing algorithms,
32+
such as ``RS*`` or ``ES*``. PEM format expected.
2933
================================= =========================================
3034

3135

flask_jwt_extended/config.py

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ def is_asymmetric(self):
3333

3434
@property
3535
def encode_key(self):
36-
return self.secret_key
36+
return self.private_key if self.is_asymmetric else self.secret_key
3737

3838
@property
3939
def decode_key(self):
@@ -191,20 +191,31 @@ def blacklist_access_tokens(self):
191191

192192
@property
193193
def secret_key(self):
194-
key = current_app.config.get('SECRET_KEY', None)
194+
key = current_app.config['JWT_SECRET_KEY']
195195
if not key:
196-
raise RuntimeError('flask SECRET_KEY must be set')
196+
key = current_app.config.get('SECRET_KEY', None)
197+
if not key:
198+
raise RuntimeError('JWT_SECRET_KEY or flask SECRET_KEY '
199+
'must be set when using symmetric '
200+
'algorithm "{}"'.format(self.algorithm))
197201
return key
198202

199203
@property
200204
def public_key(self):
201-
key = None
202-
if self.algorithm in requires_cryptography:
203-
key = current_app.config.get('JWT_PUBLIC_KEY', None)
204-
if not key:
205-
raise RuntimeError('JWT_PUBLIC_KEY must be set to use '
206-
'asymmetric cryptography algorith '
207-
'"{crypto_algorithm}"'.format(crypto_algorithm=self.algorithm))
205+
key = current_app.config['JWT_PUBLIC_KEY']
206+
if not key:
207+
raise RuntimeError('JWT_PUBLIC_KEY must be set to use '
208+
'asymmetric cryptography algorithm '
209+
'"{}"'.format(self.algorithm))
210+
return key
211+
212+
@property
213+
def private_key(self):
214+
key = current_app.config['JWT_PRIVATE_KEY']
215+
if not key:
216+
raise RuntimeError('JWT_PRIVATE_KEY must be set to use '
217+
'asymmetric cryptography algorithm '
218+
'"{}"'.format(self.algorithm))
208219
return key
209220

210221
@property

flask_jwt_extended/jwt_manager.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,14 @@ def _set_default_configuration_options(app):
141141
# https://github.com/jpadilla/pyjwt/blob/master/jwt/api_jwt.py
142142
app.config.setdefault('JWT_ALGORITHM', 'HS256')
143143

144-
# must be set if using asymmetric cryptography algorithm (RS* or EC*)
144+
# Secret key to sign JWTs with. Only used if a symmetric algorithm is
145+
# used (such as the HS* algorithms). We will use the app secret key
146+
# if this is not set.
147+
app.config.setdefault('JWT_SECRET_KEY', None)
148+
149+
# Keys to sign JWTs with when use when using an asymmetric
150+
# (public/private key) algorithm, such as RS* or EC*
151+
app.config.setdefault('JWT_PRIVATE_KEY', None)
145152
app.config.setdefault('JWT_PUBLIC_KEY', None)
146153

147154
# Options for blacklisting/revoking tokens

tests/test_config.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,16 @@ def test_default_configs(self):
5151
self.assertEqual(config.blacklist_access_tokens, False)
5252

5353
self.assertEqual(config.secret_key, self.app.secret_key)
54-
self.assertEqual(config.public_key, None)
5554
self.assertEqual(config.encode_key, self.app.secret_key)
5655
self.assertEqual(config.decode_key, self.app.secret_key)
5756
self.assertEqual(config.cookie_max_age, None)
5857

5958
with self.assertRaises(RuntimeError):
6059
config.blacklist_store
60+
with self.assertRaises(RuntimeError):
61+
config.public_key
62+
with self.assertRaises(RuntimeError):
63+
config.private_key
6164

6265
def test_override_configs(self):
6366
sample_store = simplekv.memory.DictStore()
@@ -176,8 +179,11 @@ def test_invalid_config_options(self):
176179

177180
self.app.config['JWT_ALGORITHM'] = 'RS256'
178181
self.app.config['JWT_PUBLIC_KEY'] = None
182+
self.app.config['JWT_PRIVATE_KEY'] = None
179183
with self.assertRaises(RuntimeError):
180184
config.decode_key
185+
with self.assertRaises(RuntimeError):
186+
config.encode_key
181187

182188
def test_depreciated_options(self):
183189
self.app.config['JWT_CSRF_HEADER_NAME'] = 'Auth'
@@ -220,12 +226,13 @@ def test_special_config_options(self):
220226
self.assertEqual(config.csrf_protect, False)
221227

222228
def test_asymmetric_encryption_key_handling(self):
223-
self.app.secret_key = 'MOCK_RSA_PRIVATE_KEY'
229+
self.app.config['JWT_PRIVATE_KEY'] = 'MOCK_RSA_PRIVATE_KEY'
224230
self.app.config['JWT_PUBLIC_KEY'] = 'MOCK_RSA_PUBLIC_KEY'
225231
self.app.config['JWT_ALGORITHM'] = 'RS256'
226232

227233
with self.app.test_request_context():
228234
self.assertEqual(config.is_asymmetric, True)
229-
self.assertEqual(config.secret_key, 'MOCK_RSA_PRIVATE_KEY')
230235
self.assertEqual(config.encode_key, 'MOCK_RSA_PRIVATE_KEY')
231236
self.assertEqual(config.decode_key, 'MOCK_RSA_PUBLIC_KEY')
237+
self.assertEqual(config.private_key, 'MOCK_RSA_PRIVATE_KEY')
238+
self.assertEqual(config.public_key, 'MOCK_RSA_PUBLIC_KEY')

tests/test_protected_endpoints.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -846,8 +846,8 @@ class TestEndpointsWithAssymmetricCrypto(unittest.TestCase):
846846

847847
def setUp(self):
848848
self.app = Flask(__name__)
849-
self.app.secret_key = RSA_PRIVATE
850849
self.app.config['JWT_PUBLIC_KEY'] = RSA_PUBLIC
850+
self.app.config['JWT_PRIVATE_KEY'] = RSA_PRIVATE
851851
self.app.config['JWT_ALGORITHM'] = 'RS256'
852852
self.app.config['JWT_ACCESS_TOKEN_EXPIRES'] = timedelta(seconds=1)
853853
self.app.config['JWT_REFRESH_TOKEN_EXPIRES'] = timedelta(seconds=1)

0 commit comments

Comments
 (0)