Digest Authentication
In this example, a new custom authenticator will be made re-using
the out-of-the-box AuthBasic
authenticator and a Request’s digest
authencation object.
See HTTPDigestAuth
Finally, we will test it the newly created authenticator against
a test endpoint that requires Digest Authentication. See RFC 7616
The first step is understanding the AuthBasic
authenticator. Below is the
implementation of the authenticator. It is using HTTPBasicAuth
from the
Requests library.
from silo.auth import Authenticator, add_auth
@add_auth
class AuthBasic(Authenticator):
"""AuthBasic encapsulates the authentication lifecycle for BasicAuth.
username, password and debug are the expected keys for AuthBasic.
Debug is used for logging requests to stderr for debug purposes.
:param Authenticator Authenticator: Parent ABC Class
:param silo.apps.collection.credential.Credential credentials: credentials retrieved
from em7/UCF
"""
def __init__(self, credentials):
"""Constructor method"""
Authenticator.__init__(self, credentials)
self.auth = HTTPBasicAuth(credentials.fields["username"], credentials.fields["password"])
self.cred_filter = CredentialFilter(credentials)
self.cred_filter.update_secret_from_auth(self.auth)
def check_if_authenticated(self):
"""
Required for ABC implementation. This is a return True.
This is due to the fact that we will essentially authenticate
on every resource request.
:return: True
:rtype: boolean
"""
return True
def check_result(self, result):
"""
Provides a check on the returned response from the REST request that was made.
Used in HTTPRequest to trigger a retry on an unsuccessful request.
:param response result: Response object after making a REST call
:return: If request was successful or not, True -> Success, False -> Fail
:rtype: boolean
"""
return http_check_result(result)
def authenticate(self):
"""
Authenticate is a no-op for BasicAuth
"""
return True
def modify_request(self, res):
"""Function to apply authorization impl to Request Session
:param session res: Request to be updated with credentials
:type res: [type]
"""
res.auth = self.auth
return True
@staticmethod
def build(credentials):
"""Build method to be called by get_authmethod in low_code"""
return AuthBasic(credentials)
@staticmethod
def get_name():
return "AuthBasic"
@staticmethod
def get_desc():
return "Basic Authentication for HTTP"
The following changes are needed to change the authenticator from HTTPBasicAuth
to the HTTPDigestAuth
and allow use to use this new authenticator. This
authenticator will rely on reusing methods from AuthBasic
, but switches
out the underlying Requests authenticator.
from requests import HTTPDigestAuth
self.auth = HTTPDigestAuth(credentials.fields["username"], credentials.fields["password"])
@staticmethod
def get_name():
return "AuthDigest"
Putting It All Together
Below is the new authenticator and a test endpoint to verify its functionality.
Snippet
from silo.auth import AuthBasic, add_auth
from requests.auth import HTTPDigestAuth
@add_auth
class AuthDigest(AuthBasic):
"""AuthDigest encapsulates the authentication lifecycle for DigestAuth.
username and password are the expected credential keys for AuthDigest.
Debug is used for logging requests to stderr for debug purposes.
:param Authenticator Authenticator: Parent ABC Class
:param silo.apps.collection.credential.Credential credentials: credentials retrieved
from em7/UCF
"""
def __init__(self, credentials, **kwargs):
"""Constructor method"""
AuthBasic.__init__(self, credentials)
self.auth = HTTPDigestAuth(credentials.fields["username"], credentials.fields["password"])
@staticmethod
def build(credentials, **kwargs):
"""Build method to be called by get_authmethod in low_code"""
return AuthDigest(credentials, **kwargs)
@staticmethod
def get_name():
return "AuthDigest"
@staticmethod
def get_desc():
return "Digest Authentication for HTTP"
Snippet Argument
low_code:
version: 2
steps:
- http:
url: "https://www.httpbin.org/digest-auth/auth/sfuser/sfpassword"
- json
Credential
Authentication Override:
AuthDigest
Username:
sfuser
Password:
sfpassword
The expected return is a 200 status code and the following output.
{"authenticated": True, "user": "sfuser"}