Skip to content

Commit a3cee80

Browse files
committed
Add function for getting full (raw) jwt in a protected endpoint
This allows you to use 'get_raw_jwt()' in any jwt protected endpoint (jwt_required, fresh_jwt_required, refresh_jwt_required). Refs #22
1 parent 04abf6e commit a3cee80

File tree

4 files changed

+52
-3
lines changed

4 files changed

+52
-3
lines changed

examples/blacklist.py

+12-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
from flask_jwt_extended import JWTManager, jwt_required, \
77
get_jwt_identity, revoke_token, unrevoke_token, \
88
get_stored_tokens, get_all_stored_tokens, create_access_token, \
9-
create_refresh_token, jwt_refresh_token_required, get_stored_token
9+
create_refresh_token, jwt_refresh_token_required, \
10+
get_raw_jwt, get_stored_token
1011

1112

1213
# Setup flask
@@ -55,6 +56,16 @@ def refresh():
5556
return jsonify(ret), 200
5657

5758

59+
# Endpoint for revoking a token when logging out
60+
@app.route('/logout', method=['POST'])
61+
@jwt_required
62+
def login():
63+
jwt = get_raw_jwt()
64+
jti = jwt['jti']
65+
revoke_token(jti)
66+
return jsonify({"msg": "Successfully logged out"}), 200
67+
68+
5869
# Endpoint for listing tokens that have the same identity as you
5970
@app.route('/auth/tokens', methods=['GET'])
6071
@jwt_required

flask_jwt_extended/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22
from .utils import (jwt_required, fresh_jwt_required, jwt_refresh_token_required,
33
create_refresh_token, create_access_token, get_jwt_identity,
44
get_jwt_claims, set_access_cookies, set_refresh_cookies,
5-
unset_jwt_cookies)
5+
unset_jwt_cookies, get_raw_jwt)
66
from .blacklist import (revoke_token, unrevoke_token, get_stored_tokens,
77
get_all_stored_tokens, get_stored_token)

flask_jwt_extended/utils.py

+11
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,14 @@ def get_jwt_claims():
4141
return getattr(ctx_stack.top, 'jwt_user_claims', {})
4242

4343

44+
def get_raw_jwt():
45+
"""
46+
Returns the python dictionary which has all of the data in this JWT. If no
47+
JWT is currently present, and empty dict is returned
48+
"""
49+
return getattr(ctx_stack.top, 'jwt', {})
50+
51+
4452
def _create_csrf_token():
4553
return str(uuid.uuid4())
4654

@@ -235,6 +243,7 @@ def wrapper(*args, **kwargs):
235243
# the various endpoints that is using this decorator
236244
ctx_stack.top.jwt_identity = jwt_data['identity']
237245
ctx_stack.top.jwt_user_claims = jwt_data['user_claims']
246+
ctx_stack.top.jwt = jwt_data
238247
return fn(*args, **kwargs)
239248
return wrapper
240249

@@ -270,6 +279,7 @@ def wrapper(*args, **kwargs):
270279
# the various endpoints that is using this decorator
271280
ctx_stack.top.jwt_identity = jwt_data['identity']
272281
ctx_stack.top.jwt_user_claims = jwt_data['user_claims']
282+
ctx_stack.top.jwt = jwt_data
273283
return fn(*args, **kwargs)
274284
return wrapper
275285

@@ -297,6 +307,7 @@ def wrapper(*args, **kwargs):
297307
# Save the jwt in the context so that it can be accessed later by
298308
# the various endpoints that is using this decorator
299309
ctx_stack.top.jwt_identity = jwt_data['identity']
310+
ctx_stack.top.jwt = jwt_data
300311
return fn(*args, **kwargs)
301312
return wrapper
302313

tests/test_protected_endpoints.py

+28-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
get_jwt_identity, set_refresh_cookies, set_access_cookies, unset_jwt_cookies
1111
from flask_jwt_extended import JWTManager, create_refresh_token, \
1212
jwt_refresh_token_required, create_access_token, fresh_jwt_required, \
13-
jwt_required
13+
jwt_required, get_raw_jwt
1414

1515

1616
class TestEndpoints(unittest.TestCase):
@@ -280,6 +280,7 @@ def claims():
280280
'claims': get_jwt_claims()
281281
})
282282

283+
283284
# Login
284285
response = self.client.post('/auth/login')
285286
data = json.loads(response.get_data(as_text=True))
@@ -290,6 +291,32 @@ def claims():
290291
self.assertEqual(status, 200)
291292
self.assertEqual(data, {'username': 'test', 'claims': {'foo': 'bar'}})
292293

294+
def test_jwt_raw_token(self):
295+
# Endpoints that uses get raw tokens and returns the keys
296+
@self.app.route('/claims')
297+
@jwt_required
298+
def claims():
299+
jwt = get_raw_jwt()
300+
claims_keys = [claim for claim in jwt]
301+
return jsonify(claims_keys), 200
302+
303+
# Login
304+
response = self.client.post('/auth/login')
305+
data = json.loads(response.get_data(as_text=True))
306+
access_token = data['access_token']
307+
308+
# Test our custom endpoint
309+
status, data = self._jwt_get('/claims', access_token)
310+
self.assertEqual(status, 200)
311+
self.assertIn('exp', data)
312+
self.assertIn('iat', data)
313+
self.assertIn('nbf', data)
314+
self.assertIn('jti', data)
315+
self.assertIn('identity', data)
316+
self.assertIn('fresh', data)
317+
self.assertIn('type', data)
318+
self.assertIn('user_claims', data)
319+
293320
def test_different_headers(self):
294321
response = self.client.post('/auth/login')
295322
data = json.loads(response.get_data(as_text=True))

0 commit comments

Comments
 (0)