Skip to content

Commit

Permalink
WIP: rework required_scopes checking
Browse files Browse the repository at this point in the history
  • Loading branch information
Ruwann committed Feb 23, 2022
1 parent 40d9dad commit 8d7bdda
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 18 deletions.
8 changes: 3 additions & 5 deletions connexion/operations/secure.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,31 +75,29 @@ def security_decorator(self):
return self._api.security_handler_factory.security_passthrough

auth_funcs = []
required_scopes = None
for security_req in self.security:
if not security_req:
auth_funcs.append(self._api.security_handler_factory.verify_none())
continue

sec_req_funcs = {}
oauth = False
for scheme_name, scopes in security_req.items():
for scheme_name, required_scopes in security_req.items():
security_scheme = self.security_schemes[scheme_name]

if security_scheme['type'] == 'oauth2':
if oauth:
logger.warning("... multiple OAuth2 security schemes in AND fashion not supported", extra=vars(self))
break
oauth = True
required_scopes = scopes
token_info_func = self._api.security_handler_factory.get_tokeninfo_func(security_scheme)
scope_validate_func = self._api.security_handler_factory.get_scope_validate_func(security_scheme)
if not token_info_func:
logger.warning("... x-tokenInfoFunc missing", extra=vars(self))
break

sec_req_funcs[scheme_name] = self._api.security_handler_factory.verify_oauth(
token_info_func, scope_validate_func)
token_info_func, scope_validate_func, required_scopes)

# Swagger 2.0
elif security_scheme['type'] == 'basic':
Expand Down Expand Up @@ -159,7 +157,7 @@ def security_decorator(self):
else:
auth_funcs.append(self._api.security_handler_factory.verify_multiple_schemes(sec_req_funcs))

return functools.partial(self._api.security_handler_factory.verify_security, auth_funcs, required_scopes)
return functools.partial(self._api.security_handler_factory.verify_security, auth_funcs)

def get_mimetype(self):
return DEFAULT_MIMETYPE
Expand Down
29 changes: 16 additions & 13 deletions connexion/security/security_handler_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,10 +173,10 @@ def get_auth_header_value(request):
raise OAuthProblem(description='Invalid authorization header')
return auth_type.lower(), value

def verify_oauth(self, token_info_func, scope_validate_func):
def verify_oauth(self, token_info_func, scope_validate_func, required_scopes):
check_oauth_func = self.check_oauth_func(token_info_func, scope_validate_func)

def wrapper(request, required_scopes):
def wrapper(request):
auth_type, token = self.get_auth_header_value(request)
if auth_type != 'bearer':
return self.no_value
Expand All @@ -188,7 +188,7 @@ def wrapper(request, required_scopes):
def verify_basic(self, basic_info_func):
check_basic_info_func = self.check_basic_auth(basic_info_func)

def wrapper(request, required_scopes):
def wrapper(request):
auth_type, user_pass = self.get_auth_header_value(request)
if auth_type != 'basic':
return self.no_value
Expand All @@ -198,7 +198,7 @@ def wrapper(request, required_scopes):
except Exception:
raise OAuthProblem(description='Invalid authorization header')

return check_basic_info_func(request, username, password, required_scopes=required_scopes)
return check_basic_info_func(request, username, password)

return wrapper

Expand All @@ -221,7 +221,7 @@ def get_cookie_value(cookies, name):
def verify_api_key(self, api_key_info_func, loc, name):
check_api_key_func = self.check_api_key(api_key_info_func)

def wrapper(request, required_scopes):
def wrapper(request):

def _immutable_pop(_dict, key):
"""
Expand Down Expand Up @@ -252,7 +252,7 @@ def _immutable_pop(_dict, key):
if api_key is None:
return self.no_value

return check_api_key_func(request, api_key, required_scopes=required_scopes)
return check_api_key_func(request, api_key)

return wrapper

Expand All @@ -263,11 +263,11 @@ def verify_bearer(self, token_info_func):
"""
check_bearer_func = self.check_bearer_token(token_info_func)

def wrapper(request, required_scopes):
def wrapper(request):
auth_type, token = self.get_auth_header_value(request)
if auth_type != 'bearer':
return self.no_value
return check_bearer_func(request, token, required_scopes=required_scopes)
return check_bearer_func(request, token)

return wrapper

Expand All @@ -281,10 +281,10 @@ def verify_multiple_schemes(self, schemes):
:rtype: types.FunctionType
"""

def wrapper(request, required_scopes):
def wrapper(request):
token_info = {}
for scheme_name, func in schemes.items():
result = func(request, required_scopes)
result = func(request)
if result is self.no_value:
return self.no_value
token_info[scheme_name] = result
Expand All @@ -299,7 +299,7 @@ def verify_none():
:rtype: types.FunctionType
"""

def wrapper(request, required_scopes):
def wrapper(request):
return {}

return wrapper
Expand All @@ -320,6 +320,9 @@ def wrapper(request, *args, required_scopes=None):
if need_to_add_required_scopes:
kwargs[self.required_scopes_kw] = required_scopes
token_info = func(*args, **kwargs)
# TODO: Multiple OAuth schemes defined in OR fashion
# This currently doesn't work because if the first one doesn't apply, it will raise an error
# and the second OAuth security func is never checked
if token_info is self.no_value:
return self.no_value
if token_info is None:
Expand Down Expand Up @@ -362,12 +365,12 @@ def wrapper(request, token, required_scopes):
return wrapper

@classmethod
def verify_security(cls, auth_funcs, required_scopes, function):
def verify_security(cls, auth_funcs, function):
@functools.wraps(function)
def wrapper(request):
token_info = cls.no_value
for func in auth_funcs:
token_info = func(request, required_scopes)
token_info = func(request)
if token_info is not cls.no_value:
break

Expand Down

0 comments on commit 8d7bdda

Please sign in to comment.