Source code for flask_resty.authentication
import flask
from . import context
from .exceptions import ApiError
# -----------------------------------------------------------------------------
def get_request_credentials():
return context.get("request_credentials")
def set_request_credentials(credentials):
context.set("request_credentials", credentials)
# -----------------------------------------------------------------------------
[docs]class AuthenticationBase:
"""Base class for API authentication components.
Authentication components are responsible for extracting the request
credentials, if any. They should raise a 401 if the credentials are
invalid, but should provide `None` for unauthenticated users.
Flask-RESTy provides an implementation using `JSON Web Tokens`_ but you
can use any authentication component by extending
:py:class:`AuthenticationBase` and implementing
:py:meth:`get_request_credentials`.
.. _JSON Web Tokens: https://jwt.io/
"""
[docs] def authenticate_request(self):
"""Store the request credentials in the
:py:class:`flask.ctx.AppContext`.
.. warning::
No validation is performed by Flask-RESTy. It is up to the
implementor to validate the request in
:py:meth:`get_request_credentials`.
"""
set_request_credentials(self.get_request_credentials())
[docs] def get_request_credentials(self):
"""Get the credentials for the current request.
Typically this is done by inspecting :py:data:`flask.request`.
.. warning::
Implementing classes **must** raise an exception on authentication
failure. A 401 Unauthorized :py:class:`ApiError` is recommended.
:return: The credentials for the current request.
"""
raise NotImplementedError()
# -----------------------------------------------------------------------------
[docs]class NoOpAuthentication:
"""An authentication component that provides no credentials."""
def authenticate_request(self):
pass
# -----------------------------------------------------------------------------
[docs]class HeaderAuthenticationBase(AuthenticationBase):
"""Base class for header authentication components.
These authentication components get their credentials from the
``Authorization`` request header. The Authorization header has the form::
Authorization: <scheme> <token>
This class also supports fallback to a query parameter, for cases where
API clients cannot set headers.
"""
#: Corresponds to the <scheme> in the Authorization request header.
header_scheme = "Bearer"
#: A fallback query parameter. The value of this query parameter will be
#: used as credentials if the Authorization request header is missing.
credentials_arg = None
[docs] def get_request_credentials(self):
token = self.get_request_token()
if token is None:
return None
return self.get_credentials_from_token(token)
def get_request_token(self):
authorization = flask.request.headers.get("Authorization")
if authorization is not None:
return self.get_token_from_authorization(authorization)
if self.credentials_arg is not None:
return flask.request.args.get(self.credentials_arg)
return None
def get_token_from_authorization(self, authorization):
try:
scheme, token = authorization.split()
except (AttributeError, ValueError) as e:
raise ApiError(401, {"code": "invalid_authorization"}) from e
if scheme.lower() != self.header_scheme.lower():
raise ApiError(401, {"code": "invalid_authorization.scheme"})
return token
[docs] def get_credentials_from_token(self, token):
"""Get the credentials from the token from the request.
:param str token: The token from the request headers or query.
:return: The credentials from the token.
"""
raise NotImplementedError()
[docs]class HeaderAuthentication(HeaderAuthenticationBase):
"""Header authentication component where the token is the credential.
This authentication component is useful for simple applications where the
token itself is the credential, such as when it is a fixed secret shared
between the client and the server that uniquely identifies the client.
"""
def get_credentials_from_token(self, token):
return token