Skip to content
This repository was archived by the owner on Feb 22, 2024. It is now read-only.

Commit 87d1a67

Browse files
committed
Add role check
If a ressource has a role specified the jwt should have at least this role If a list is specified, the jwt should have one (or several) of this role
1 parent c270841 commit 87d1a67

File tree

1 file changed

+35
-5
lines changed

1 file changed

+35
-5
lines changed

flask_jwt/__init__.py

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
'JWT_AUTH_USERNAME_KEY': 'username',
3434
'JWT_AUTH_PASSWORD_KEY': 'password',
3535
'JWT_ALGORITHM': 'HS256',
36+
'JWT_ROLE': 'role',
3637
'JWT_LEEWAY': timedelta(seconds=10),
3738
'JWT_AUTH_HEADER_PREFIX': 'JWT',
3839
'JWT_EXPIRATION_DELTA': timedelta(seconds=300),
@@ -141,7 +142,20 @@ def _default_jwt_error_handler(error):
141142
])), error.status_code, error.headers
142143

143144

144-
def _jwt_required(realm):
145+
def _force_iterable(input):
146+
"""Is role is just a string, for to an array """
147+
try:
148+
basestring
149+
except NameError:
150+
basestring = str
151+
if isinstance(input, basestring):
152+
return [input]
153+
if not hasattr(input, "__iter__"):
154+
return [input]
155+
return input
156+
157+
158+
def _jwt_required(realm, roles):
145159
"""Does the actual work of verifying the JWT data in the current request.
146160
This is done automatically for you by `jwt_required()` but you could call it manually.
147161
Doing so would be useful in the context of optional JWT access in your APIs.
@@ -163,17 +177,33 @@ def _jwt_required(realm):
163177

164178
if identity is None:
165179
raise JWTError('Invalid JWT', 'User does not exist')
166-
167-
168-
def jwt_required(realm=None):
180+
if roles:
181+
try:
182+
identity_role = getattr(identity, current_app.config['JWT_ROLE'])
183+
except AttributeError:
184+
try:
185+
identity_role = identity.get(current_app.config['JWT_ROLE'])
186+
except AttributeError:
187+
raise JWTError('Bad Request', 'Invalid credentials')
188+
if not identity_role:
189+
raise JWTError('Bad Request', 'Invalid credentials')
190+
identity_role = _force_iterable(identity_role)
191+
roles = _force_iterable(roles)
192+
if not identity_role or not set(roles).intersection(identity_role):
193+
raise JWTError('Bad Request', 'Invalid credentials')
194+
195+
196+
def jwt_required(realm=None, roles=None):
169197
"""View decorator that requires a valid JWT token to be present in the request
170198
171199
:param realm: an optional realm
200+
:param roles: an optional list of roles allowed,
201+
the role is pick in JWT_ROLE field of identity
172202
"""
173203
def wrapper(fn):
174204
@wraps(fn)
175205
def decorator(*args, **kwargs):
176-
_jwt_required(realm or current_app.config['JWT_DEFAULT_REALM'])
206+
_jwt_required(realm or current_app.config['JWT_DEFAULT_REALM'], roles)
177207
return fn(*args, **kwargs)
178208
return decorator
179209
return wrapper

0 commit comments

Comments
 (0)