Skip to content
Snippets Groups Projects
Unverified Commit 3067c1e2 authored by Timm Fitschen's avatar Timm Fitschen
Browse files

ENH: Authenticator decodes auth tokens now.

... for better support of user-provided auth tokens.
parent bc777965
No related branches found
No related tags found
No related merge requests found
......@@ -27,7 +27,7 @@ from abc import ABCMeta, abstractmethod, abstractproperty
import logging
from caosdb.connection.utils import urlencode
from caosdb.connection.interface import CaosDBServerConnection
from caosdb.connection.utils import parse_auth_token
from caosdb.connection.utils import parse_auth_token, auth_token_to_cookie
from caosdb.exceptions import LoginFailedException
# meta class compatible with Python 2 *and* 3:
......@@ -146,7 +146,7 @@ class AbstractAuthenticator(ABC):
-------
"""
if self.auth_token is not None:
headers['Cookie'] = self.auth_token
headers['Cookie'] = auth_token_to_cookie(self.auth_token)
class CredentialsAuthenticator(AbstractAuthenticator):
......
......@@ -30,10 +30,11 @@ except ImportError:
try: # pragma: no cover
# python3
from urllib.parse import (urlencode as _urlencode, quote as _quote,
urlparse, urlunparse)
urlparse, urlunparse, unquote as _unquote)
except ImportError: # pragma: no cover
# python2
from urllib import urlencode as _urlencode, quote as _quote
from urllib import (urlencode as _urlencode, quote as _quote, unquote as
_unquote)
from urlparse import urlparse, urlunparse
import re
......@@ -163,12 +164,59 @@ def check_python_ssl_version(hexversion):
"\nPython 3 version is smaller than 3.2. It is not does not fully support SSL encryption. Please update your Python to 2.7.9 or greater, or 3.2 or greater."
)
_PATTERN = re.compile(r"^SessionToken=([^;]*);.*$")
def unquote(string):
"""unquote.
Decode an urlencoded string into a plain text string.
"""
bts = _unquote(string)
if hasattr(bts, "decode"):
# python 2
return bts.decode("utf-8")
return bts
def parse_auth_token(cookie):
"""parse_auth_token.
Parse an auth token from a cookie.
Parameters
----------
cookie : str
A cookie with an urlencoded authtoken.
Returns
-------
str
An auth token string.
"""
auth_token = None
if cookie is not None:
try:
auth_token = re.compile(r";\s*.*$").split(cookie)[0]
except IndexError:
pass
if cookie is not None and _PATTERN.match(cookie):
auth_token = unquote(_PATTERN.split(cookie)[1])
return auth_token
def auth_token_to_cookie(auth_token):
"""auth_token_to_cookie.
Urlencode an auth token string and format it as a cookie.
Parameters
----------
auth_token : str
The plain auth token string.
Raises
------
TypeError
If the auth_token was None
Returns
-------
str
A cookie
"""
if auth_token is None:
raise TypeError("Parameter `auth_token` was None.")
return "SessionToken=" + quote(auth_token) + ";"
......@@ -259,8 +259,8 @@ def test_missing_auth_method():
def test_missing_password():
connection = configure_connection()
connection.configure(implementation=setup_two_resources,
password_method="plain", auth_token="test-auth-token")
assert connection.retrieve(["some"]).headers["Cookie"] == "test-auth-token"
password_method="plain", auth_token="[test-auth-token]")
assert connection.retrieve(["some"]).headers["Cookie"] == "SessionToken=%5Btest-auth-token%5D;"
connection.configure(implementation=setup_two_resources,
password_method="plain")
with raises(LoginFailedException):
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment