Skip to content

Commit

Permalink
Merge pull request #142 from cognifloyd/multi_auth_docs
Browse files Browse the repository at this point in the history
Document Auth methods from #137
  • Loading branch information
prkumar authored Feb 19, 2019
2 parents 5cf85a4 + 5bb0f33 commit df75cb4
Show file tree
Hide file tree
Showing 4 changed files with 221 additions and 23 deletions.
44 changes: 44 additions & 0 deletions docs/source/dev/auth.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
.. _auth_methods:

Auth Methods
************


The ``auth`` parameter of the :py:class:`Consumer` constructor offers a way
to define an auth method to use for all requests.

.. code-block:: python
auth_method = SomeAuthMethod(...)
github = GitHub(BASE_URL, auth=auth_method)
BasicAuth
=========

.. autoclass:: uplink.auth.BasicAuth

ProxyAuth
=========

.. autoclass:: uplink.auth.ProxyAuth

BearerToken
===========

.. autoclass:: uplink.auth.BearerToken

MultiAuth
=========

.. autoclass:: uplink.auth.MultiAuth

ApiTokenParam
=============

.. autoclass:: uplink.auth.ApiTokenParam

ApiTokenHeader
==============

.. autoclass:: uplink.auth.ApiTokenHeader
3 changes: 2 additions & 1 deletion docs/source/dev/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ This guide details the classes and methods in Uplink's public API.
decorators.rst
types.rst
clients.rst
converters.rst
converters.rst
auth.rst
54 changes: 50 additions & 4 deletions docs/source/user/auth.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,50 @@ Authentication

This section covers how to do authentication with Uplink.

In v0.4, we added the :py:attr:`auth` parameter to the
:py:class:`uplink.Consumer` constructor which allowed for
sending HTTP Basic Authentication with all requests.

In v0.9, we added more auth methods which can be used in the
:py:attr:`auth` parameter of the :py:class:`uplink.Consumer`
constructor. If you are using an uplink-based API library,
the library might extend these methods with additional
API-specific auth methods.

Some common auth methods are described below, but for a
complete list of auth methods provided with Uplink, see
the :ref:`auth_methods` reference.

.. _basic_authentication:

Basic Authentication
--------------------

In v0.4, we added the :py:attr:`auth` parameter to the
:py:class:`uplink.Consumer` constructor.

Now it's simple to construct a consumer that uses HTTP Basic
It's simple to construct a consumer that uses HTTP Basic
Authentication with all requests:

.. code-block:: python
github = GitHub(BASE_URL, auth=("user", "pass"))
Proxy Authentication
--------------------

If you need to supply credentials for an intermediate proxy
in addition to the API's HTTP Basic Authentication, use
:py:class:`uplink.auth.MultiAuth` with :py:class:`uplink.auth.ProxyAuth`
and :py:class:`uplink.auth.BasicAuth`.

.. code-block:: python
from uplink.auth import BasicAuth, MultiAuth, ProxyAuth
auth_methods = MultiAuth(
ProxyAuth("proxy_user", "proxy_pass"),
BasicAuth("user", "pass")
)
github = GitHub(BASE_URL, auth=auth_methods)
Other Authentication
--------------------

Expand All @@ -43,6 +72,23 @@ through the consumer's :obj:`session <uplink.Consumer.session>` property:
self.session.params["access_token"] = access_token
...
As of v0.9, you can also supply these tokens via the :py:attr:`auth`
parameter of the :py:class:`uplink.Consumer` constructor. This is
like adding the token to the session (above) so that the token is
sent as part of every request.

.. code-block:: python
from uplink.auth import ApiTokenParam, ApiTokenHeader, BearerToken
# Passing a random auth query parameter
github = GitHub(BASE_URL, auth=ApiTokenParam("access_token", access_token))
# Passing a random auth header
github = GitHub(BASE_URL, auth=ApiTokenHeader("Access-Token", access_token))
# Passing a Bearer auth token
github = GitHub(BASE_URL, auth=BearerToken(access_token))
Using Auth Support for Requests and aiohttp
-------------------------------------------
Expand Down
143 changes: 125 additions & 18 deletions uplink/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,27 @@ def get_auth(auth_object=None):
class ApiTokenParam(object):
"""
Authorizes requests using a token or key in a query parameter.
Users should subclass this class to define which parameter is the token parameter.
Users may use this directly, or API library authors may subclass this
to predefine the query parameter name to use. If supplying query parameter
name on a subclass, define the ``_param`` property or attribute and
override ``__init__()`` without using ``super()``.
.. code-block:: python
# direct use
token_param = ApiTokenParam(QUERY_PARAM_NAME, TOKEN)
api_consumer = SomeApiConsumerClass(BASE_URL, auth=token_param)
# subclass in API library
class ExampleApiTokenParam(ApiTokenParam):
_param = "api-token"
def __init__(self, token):
self._param_value = token
# using the subclass
token_param = ExampleApiTokenParam(TOKEN)
api_consumer = SomeApiConsumerClass(BASE_URL, auth=token_param)
"""
def __init__(self, param, token):
self._param = param
Expand All @@ -43,20 +63,39 @@ def __call__(self, request_builder):
request_builder.info["params"][self._param] = self._param_value


# class ExampleApiTokenParam(ApiTokenParam):
# _param = "api-token"
# def __init__(self, token):
# self._param_value = token


class ApiTokenHeader(object):
"""
Authorizes requests using a token or key in a header.
Users should subclass this class to define which header is the token header.
The subclass may also, optionally, define a token prefix (such as in BearerToken)
_header and/or _prefix may be defined as class attributes on subclasses,
but should also override __init__() when they do so.
Users may use this directly, or API library authors may subclass this
to predefine the header name or a prefix to use. If supplying header name or prefix
in a subclass, define the ``_header`` and/or ``_prefix`` properties or attributes
and override ``__init__()`` without using ``super()``.
.. code-block:: python
# direct use
token_header = ApiTokenHeader(HEADER_NAME, TOKEN)
api_consumer = SomeApiConsumerClass(BASE_URL, auth=token_header)
# subclass in API library with a prefix
class ExampleApiTokenHeader(ApiTokenHeader):
_header = "X-Api-Token"
def __init__(self, token):
self._token = token
# subclass in API library with a prefix
class ExampleApiTokenHeader(ApiTokenHeader):
_header = "X-App-Id"
_prefix = "APP"
def __init__(self, token):
self._token = token
# using the subclass
token_header = ExampleApiTokenHeader(TOKEN)
api_consumer = SomeApiConsumerClass(BASE_URL, auth=token_header)
"""
_header = None
_prefix = None
Expand All @@ -78,7 +117,19 @@ def __call__(self, request_builder):


class BasicAuth(ApiTokenHeader):
"""Authorizes requests using HTTP Basic Authentication."""
"""
Authorizes requests using HTTP Basic Authentication.
There are two ways to use BasicAuth with a Consumer:
.. code-block:: python
# implicit BasicAuth
github = Github(BASE_URL, auth=(USER, PASS))
# explicit BasicAuth
github = GitHub(BASE_URL, auth=BasicAuth(USER, PASS))
"""

_header = "Authorization"

Expand All @@ -92,11 +143,37 @@ def _header_value(self):


class ProxyAuth(BasicAuth):
"""Authorizes requests with an intermediate HTTP proxy."""
"""
Authorizes requests with an intermediate HTTP proxy.
If both API auth and intermediate Proxy auth are required,
wrap ProxyAuth in MultiAuth:
.. code-block:: python
# only ProxyAuth
github = Github(BASE_URL, auth=ProxyAuth(PROXYUSER, PROXYPASS))
# both BasicAuth and ProxyAuth
auth_methods = MultiAuth(
BasicAuth(USER, PASS),
ProxyAuth(PROXYUSER, PROXYPASS)
)
github = GitHub(BASE_URL, auth=auth_methods)
"""
_header = "Proxy-Authorization"


class BearerToken(ApiTokenHeader):
"""
Authorizes requests using a Bearer Token.
.. code-block:: python
token = something_like_oauth_that_returns_a_token()
bearer = BearerToken(token)
api_consumer = SomeApiConsumerClass(BASE_URL, auth=bearer)
"""

_header = "Authorization"
_prefix = "Bearer"
Expand All @@ -108,16 +185,46 @@ def __init__(self, token):
class MultiAuth(object):
"""
Authorizes requests using multiple auth methods at the same time.
api_auth = MultiAuth(
BasicAuth(username, password),
ProxyAuth(proxy_user, proxy_pass)
This is useful for API users to supply both API credentials and
intermediary credentials (such as for a proxy).
.. code-block:: python
auth_methods = MultiAuth(
BasicAuth(USER, PASS),
ProxyAuth(PROXY_USER, PROXY_PASS)
)
api_consumer = SomeApiConsumerClass(
"https://my.base_url.com/",
auth=api_auth
api_consumer = SomeApiConsumerClass(BASE_URL, auth=auth_methods)
This may also be used if an API requires multiple Auth Tokens.
.. code-block:: python
auth_methods = MultiAuth(
BearerToken(API_TOKEN),
ApiTokenParam(QUERY_PARAMETER_NAME, QUERY_PARAMETER_VALUE),
ApiTokenHeader(API_HEADER_NAME, API_TOKEN_2)
)
api_consumer = SomeApiConsumerClass(BASE_URL, auth=auth_methods)
API library authors may find it more helpful to treat MultiAuth as
a list using ``append`` or ``extend`` to add aditional auth methods.
.. code-block:: python
auth_methods = MultiAuth()
auth_methods.append(BearerToken(API_TOKEN))
auth_methods.extend([
ApiTokenParam(QUERY_PARAMETER_NAME, QUERY_PARAMETER_VALUE),
ApiTokenHeader(API_HEADER_NAME, API_TOKEN_2)
])
api_consumer = SomeApiConsumerClass(BASE_URL, auth=auth_methods)
Mostly, this is useful for API users to supply intermediary credentials (such as for a proxy).
# looping over contained auth methods is also supported
for method in auth_methods:
print(method.__class__.__name__)
"""
def __init__(self, *auth_methods):
self._auth_methods = [get_auth(auth_method) for auth_method in auth_methods]
Expand Down

0 comments on commit df75cb4

Please sign in to comment.