Skip to content

Commit

Permalink
changed authn interface
Browse files Browse the repository at this point in the history
  • Loading branch information
zcqian committed Dec 25, 2021
1 parent 0afa3e4 commit 76a6966
Showing 1 changed file with 41 additions and 17 deletions.
58 changes: 41 additions & 17 deletions biothings/web/auth/authn.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import abc
from typing import Iterable, Optional, Tuple, Type

from biothings.web.handlers import BaseHandler
from biothings.web.handlers import BaseAPIHandler


__all__ = [
Expand All @@ -11,9 +11,31 @@


class BioThingsAuthenticationProviderInterface(abc.ABC):
def __init__(self, handler: BaseHandler, **kwargs):
# we use the BioThings BaseHandler so that
# the interface has access to self.biothings
"""
Authentication Provider Interface for BioThings API Endpoints
BioThingsAuthnMixin depends on this interface. Any authentication for
the API endpoints is recommended to be implemented using this
interface.
A provider will be initialized with the API Handler calling it, so it will
have access to the request, and other related BioThings facilities.
Args:
handler: the BaseAPIHandler that invoked this provider
Attributes:
WWW_AUTHENTICATE_HEADER: string used for the 'WWW-Authenticate' Header.
If the handler returns a 401, this may be used to populate the
'WWW-Authenticate' Header. It should be None or one from the list
https://www.iana.org/assignments/http-authschemes/http-authschemes.xhtml
"""
WWW_AUTHENTICATE_HEADER: Optional[str] = None

def __init__(self, handler: BaseAPIHandler, **kwargs):
# we use the BioThings BaseAPIHandler so that:
# - the interface has access to self.handler.biothings
# - it is something only intended for programmatic access
super().__init__()
self.handler = handler

Expand All @@ -27,20 +49,8 @@ def get_current_user(self) -> Optional[dict]:
"""
raise NotImplementedError

def get_authenticate_header(self) -> Optional[str]:
"""
Return a string used for the 'WWW-Authenticate' Header
If the handler returns a 401, this is used
"""
# FIXME: need to figure out a way to support both Authorization header
# and non-authorization header methods
# the former should return a 401 and will need WWW-Authenticate
# while the latter (say cookie based) gets more freedom.
return None


class BioThingsAuthnMixin(BaseHandler):
class BioThingsAuthnMixin(BaseAPIHandler):
def get_current_user(self):
"""
Get the user from list of preconfigured authentication providers.
Expand All @@ -64,3 +74,17 @@ def get_current_user(self):
if user:
return user
return None

def get_www_authenticate_header(self) -> Optional[str]:
authenticators: \
Iterable[Tuple[Type[BioThingsAuthenticationProviderInterface], dict], ...] = \
getattr(
self,
'AUTHN_PROVIDERS',
self.biothings.config.AUTHN_PROVIDERS
)
for authenticator_cls, _ in authenticators:
header = authenticator_cls.WWW_AUTHENTICATE_HEADER
if header is not None:
return header
return None

0 comments on commit 76a6966

Please sign in to comment.