Skip to content

Commit 2b40750

Browse files
committed
Refactor jwt auth into authenticate_bearer_token() method on Client
The json web token authentication was buried inside determine user. Refactored to put this authenticate_bearer_token method so it can (hopefully) be overriden by an instance.
1 parent dea3a36 commit 2b40750

File tree

1 file changed

+51
-41
lines changed

1 file changed

+51
-41
lines changed

roundup/cgi/client.py

Lines changed: 51 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -952,6 +952,35 @@ def determine_language(self):
952952
language,
953953
tracker_home=self.instance.config["TRACKER_HOME"]))
954954

955+
def authenticate_bearer_token(self, challenge):
956+
''' authenticate the bearer token. Refactored from determine_user()
957+
to alow it to be overridden if needed.
958+
'''
959+
try: # will jwt import?
960+
import jwt
961+
except ImportError:
962+
# no support for jwt, this is fine.
963+
self.setHeader("WWW-Authenticate", "Basic")
964+
raise LoginError('Support for jwt disabled.')
965+
966+
secret = self.db.config.WEB_JWT_SECRET
967+
if len(secret) < 32:
968+
# no support for jwt, this is fine.
969+
self.setHeader("WWW-Authenticate", "Basic")
970+
raise LoginError('Support for jwt disabled by admin.')
971+
972+
try: # handle jwt exceptions
973+
token = jwt.decode(challenge, secret,
974+
algorithms=['HS256'],
975+
audience=self.db.config.TRACKER_WEB,
976+
issuer=self.db.config.TRACKER_WEB)
977+
except jwt.exceptions.InvalidTokenError as err:
978+
self.setHeader("WWW-Authenticate", "Basic, Bearer")
979+
self.make_user_anonymous()
980+
raise LoginError(str(err))
981+
982+
return(token)
983+
955984
def determine_user(self):
956985
"""Determine who the user is"""
957986
self.opendb('admin')
@@ -1011,48 +1040,29 @@ def determine_user(self):
10111040
# this is a no-op.
10121041
random_.seed("%s%s"%(password,time.time()))
10131042
elif scheme.lower() == 'bearer':
1014-
try: # will jwt import?
1015-
import jwt
1016-
from roundup.hyperdb import iter_roles
1017-
try: # handle jwt exceptions
1018-
secret = self.db.config.WEB_JWT_SECRET
1019-
if len(secret) < 32:
1020-
# no support for jwt, this is fine.
1021-
self.setHeader("WWW-Authenticate", "Basic")
1022-
raise LoginError('Support for jwt disabled by admin.')
1023-
token = jwt.decode(challenge, secret,
1024-
algorithms=['HS256'],
1025-
audience=self.db.config.TRACKER_WEB,
1026-
issuer=self.db.config.TRACKER_WEB)
1027-
except jwt.exceptions.InvalidTokenError as err:
1028-
self.setHeader("WWW-Authenticate", "Basic, Bearer")
1029-
self.make_user_anonymous()
1030-
raise LoginError(str(err))
1031-
1032-
# if we got here token is valid, use the role
1033-
# and sub claims.
1034-
try:
1035-
# make sure to str(token['sub']) the subject. As decoded
1036-
# by json, it is unicode which thows an error when used
1037-
# with 'nodeid in db' down the call chain.
1038-
user = self.db.user.get(str(token['sub']), 'username')
1039-
except IndexError:
1040-
raise LoginError("Token subject is invalid.")
1041-
1042-
# validate roles
1043-
all_rolenames = [ role[0] for role in self.db.security.role.items() ]
1044-
for r in token['roles']:
1045-
if r.lower() not in all_rolenames:
1046-
raise LoginError("Token roles are invalid.")
1043+
token = self.authenticate_bearer_token(challenge)
1044+
1045+
from roundup.hyperdb import iter_roles
1046+
1047+
# if we got here token is valid, use the role
1048+
# and sub claims.
1049+
try:
1050+
# make sure to str(token['sub']) the subject. As decoded
1051+
# by json, it is unicode which thows an error when used
1052+
# with 'nodeid in db' down the call chain.
1053+
user = self.db.user.get(str(token['sub']), 'username')
1054+
except IndexError:
1055+
raise LoginError("Token subject is invalid.")
1056+
1057+
# validate roles
1058+
all_rolenames = [ role[0] for role in self.db.security.role.items() ]
1059+
for r in token['roles']:
1060+
if r.lower() not in all_rolenames:
1061+
raise LoginError("Token roles are invalid.")
10471062

1048-
# will be used later to override the get_roles method
1049-
override_get_roles = \
1050-
lambda self: iter_roles(','.join(token['roles']))
1051-
1052-
except ImportError:
1053-
# no support for jwt, this is fine.
1054-
self.setHeader("WWW-Authenticate", "Basic")
1055-
raise LoginError('Support for jwt disabled.')
1063+
# will be used later to override the get_roles method
1064+
override_get_roles = \
1065+
lambda self: iter_roles(','.join(token['roles']))
10561066

10571067
# if user was not set by http authorization, try session lookup
10581068
if not user:

0 commit comments

Comments
 (0)