33
33
'JWT_AUTH_USERNAME_KEY' : 'username' ,
34
34
'JWT_AUTH_PASSWORD_KEY' : 'password' ,
35
35
'JWT_ALGORITHM' : 'HS256' ,
36
+ 'JWT_ROLE' : 'role' ,
36
37
'JWT_LEEWAY' : timedelta (seconds = 10 ),
37
38
'JWT_AUTH_HEADER_PREFIX' : 'JWT' ,
38
39
'JWT_EXPIRATION_DELTA' : timedelta (seconds = 300 ),
@@ -141,7 +142,20 @@ def _default_jwt_error_handler(error):
141
142
])), error .status_code , error .headers
142
143
143
144
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 ):
145
159
"""Does the actual work of verifying the JWT data in the current request.
146
160
This is done automatically for you by `jwt_required()` but you could call it manually.
147
161
Doing so would be useful in the context of optional JWT access in your APIs.
@@ -163,17 +177,33 @@ def _jwt_required(realm):
163
177
164
178
if identity is None :
165
179
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 ):
169
197
"""View decorator that requires a valid JWT token to be present in the request
170
198
171
199
: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
172
202
"""
173
203
def wrapper (fn ):
174
204
@wraps (fn )
175
205
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 )
177
207
return fn (* args , ** kwargs )
178
208
return decorator
179
209
return wrapper
0 commit comments