Coder Social home page Coder Social logo

django-rest-framework-httpsignature's Introduction

django-rest-framework-httpsignature

https://travis-ci.org/etoccalino/django-rest-framework-httpsignature.png?branch=master

Provides HTTP Signature support for Django REST framework. The HTTP Signature package provides a way to achieve origin authentication and message integrity for HTTP messages. Similar to Amazon's HTTP Signature scheme, used by many of its services. The HTTP Signature specification is currently an IETF draft.

Installing the package via the repository:

pip install djangorestframework-httpsignature

Older version of pip don't support the Wheel format (which is how httpsig is distributed). The problem manifests when installing the requirements, pip will complain that it cannot find a httpsig. In such cases, pip needs to be upgraded:

pip install --upgrade pip

Another possible problem: while installing via python setup.py install you may encounter:

No local packages or download links found for httpsig
error: Could not find suitable distribution for Requirement.parse('httpsig')

If that is the case, use pip install httpsig to install the httpsig package and retry python setup.py install.

To run the tests for the packages, use the following command on the repository root directory:

python manage.py test

To authenticate HTTP requests via HTTP signature, you need to:

  1. Install this package in your Django project, as instructed in Installation.

  2. Add rest_framework_httpsignature to your settings.py INSTALLED_APPS.

  3. In your app code, extend the SignatureAuthentication class, as follows:

    # my_api/auth.py
    
    from rest_framework_httpsignature.authentication import SignatureAuthentication
    
    class MyAPISignatureAuthentication(SignatureAuthentication):
        # The HTTP header used to pass the consumer key ID.
        # Defaults to 'X-Api-Key'.
        API_KEY_HEADER = 'X-Api-Key'
    
        # A method to fetch (User instance, user_secret_string) from the
        # consumer key ID, or None in case it is not found.
        def fetch_user_data(self, api_key):
            # ...
            # example implementation:
            try:
                user = User.objects.get(api_key=api_key)
                return (user, user.secret)
            except User.DoesNotExist:
                return None
    
  4. Configure Django REST framework to use you authentication class; e.g.:

    # my_project/settings.py
    
    # ...
    REST_FRAMEWORK = {
        'DEFAULT_AUTHENTICATION_CLASSES': (
           'my_api.auth.MyAPISignatureAuthentication',
        ),
        'DEFAULT_PERMISSION_CLASSES': (
            'rest_framework.permissions.IsAuthenticated',
        )
    }
    # The above will force HTTP signature for all requests.
    # ...
    

You can also use another algorithm that is provided by httpsig package:

class MyAPISignatureAuthentication(SignatureAuthentication):
    API_KEY_HEADER = 'X-Api-Key'
    ALGORITHM = 'rsa-256'

    def fetch_user_data(self, api_key):
        try:
            user = User.objects.get(api_key=api_key)
            fpath = user.private_key
            with open(fpath, 'rb') as fobj:
                secret = fobj.read()
            return (user, secret)
        except User.DoesNotExist:
            return (None, None)

Currently supported throught httpsig are: rsa-sha1, rsa-sha256, rsa-sha512, hmac-sha1, hmac-sha256, hmac-sha512

  • The REQUIREMENTS.txt file is fairly strict. It is very possible that previous versions of Django and Django REST framework are supported.
  • Since HTTP Signature uses a HTTP header for the request date and time, the authentication class could deal with request expiry.

Assuming the setup detailed in Usage, a project running on localhost:8000 could be probed with cURL as follows:

~$ SSS=Base64(Hmac(SECRET, "Date: Mon, 17 Feb 2014 06:11:05 GMT", SHA256))
~$ curl -v -H 'Date: "Mon, 17 Feb 2014 06:11:05 GMT"' -H 'Authorization: Signature keyId="my-key",algorithm="hmac-sha256",headers="date",signature="SSS"'

And for a much less painful example, check out the httpsig package documentation to use requests and httpsig.

django-rest-framework-httpsignature's People

Contributors

benctamas avatar entequak avatar etoccalino avatar kouk avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

django-rest-framework-httpsignature's Issues

Installation problem

Hi!

I'm having trouble installing this package using pip 1.5.6 (latest stable) for python 2.7.6. Basically the dependency stated in this packages' requirements.txt file is not being fetched

-e git+https://github.com/digitalbazaar/py-http-signature

but rather getting to pypy and getting the latest stable version of http-signature, 0.1.4 , which doesn't work with django-rest-framework-httpsignature.

For the record, when I deploy my django app on amazon beanstalk it works fine, but they have pip 1.4.1 ... don't know if it's related.

This is the pip install log for this

$ pip install djangorestframework-httpsignature -v -v -v
Downloading/unpacking djangorestframework-httpsignature
Getting page https://pypi.python.org/simple/djangorestframework-httpsignature/
URLs to search for versions for djangorestframework-httpsignature:

  • https://pypi.python.org/simple/djangorestframework-httpsignature/
    Analyzing links from page https://pypi.python.org/simple/djangorestframework-httpsignature/
    Found link https://pypi.python.org/packages/source/d/djangorestframework-httpsignature/djangorestframework-httpsignature-0.1.3.tar.gz#md5=6ddaa2ab64965a7132a1d4c6b3cdbf60 (from https://pypi.python.org/simple/djangorestframework-httpsignature/), version: 0.1.3
    Downloading djangorestframework-httpsignature-0.1.3.tar.gz
    Downloading from URL https://pypi.python.org/packages/source/d/djangorestframework-httpsignature/djangorestframework-httpsignature-0.1.3.tar.gz#md5=6ddaa2ab64965a7132a1d4c6b3cdbf60 (from https://pypi.python.org/simple/djangorestframework-httpsignature/)
    Running setup.py (path:/opt/python2.7/venv/project/build/djangorestframework-httpsignature/setup.py) egg_info for package djangorestframework-httpsignature
    Running command python setup.py egg_info
    running egg_info
    creating pip-egg-info/djangorestframework_httpsignature.egg-info
    writing requirements to pip-egg-info/djangorestframework_httpsignature.egg-info/requires.txt
    writing pip-egg-info/djangorestframework_httpsignature.egg-info/PKG-INFO
    writing top-level names to pip-egg-info/djangorestframework_httpsignature.egg-info/top_level.txt
    writing dependency_links to pip-egg-info/djangorestframework_httpsignature.egg-info/dependency_links.txt
    writing manifest file 'pip-egg-info/djangorestframework_httpsignature.egg-info/SOURCES.txt'
    warning: manifest_maker: standard file '-c' not found

    reading manifest file 'pip-egg-info/djangorestframework_httpsignature.egg-info/SOURCES.txt'
    reading manifest template 'MANIFEST.in'
    writing manifest file 'pip-egg-info/djangorestframework_httpsignature.egg-info/SOURCES.txt'
    Source in /opt/python2.7/venv/project/build/djangorestframework-httpsignature has version 0.1.3, which satisfies requirement djangorestframework-httpsignature
    Requirement already satisfied (use --upgrade to upgrade): Django==1.6.2 in /opt/python2.7/venv/project/lib/python2.7/site-packages (from djangorestframework-httpsignature)
    Requirement already satisfied (use --upgrade to upgrade): djangorestframework==2.3.12 in /opt/python2.7/venv/project/lib/python2.7/site-packages (from djangorestframework-httpsignature)
    Requirement already satisfied (use --upgrade to upgrade): pycrypto==2.6.1 in /opt/python2.7/venv/project/lib/python2.7/site-packages (from djangorestframework-httpsignature)
    Downloading/unpacking http-signature (from djangorestframework-httpsignature)
    Getting page https://pypi.python.org/simple/http_signature/
    URLs to search for versions for http-signature (from djangorestframework-httpsignature):

  • https://pypi.python.org/simple/http_signature/
    Analyzing links from page https://pypi.python.org/simple/http_signature/
    Found link https://pypi.python.org/packages/source/h/http_signature/http_signature-0.1.0.tar.gz#md5=b03ef22b20f4a068d5227189d2338086 (from https://pypi.python.org/simple/http_signature/), version: 0.1.0
    Found link https://pypi.python.org/packages/source/h/http_signature/http_signature-0.1.1.tar.gz#md5=7aeb690573c6f3af27ffab6217557ec4 (from https://pypi.python.org/simple/http_signature/), version: 0.1.1
    Found link https://pypi.python.org/packages/source/h/http_signature/http_signature-0.1.2.tar.gz#md5=8a07a47e6de505739be9df110e8b18a2 (from https://pypi.python.org/simple/http_signature/), version: 0.1.2
    Found link https://pypi.python.org/packages/source/h/http_signature/http_signature-0.1.3.tar.gz#md5=27a8512b9b8325fd668aea20ea13418a (from https://pypi.python.org/simple/http_signature/), version: 0.1.3
    Found link https://pypi.python.org/packages/source/h/http_signature/http_signature-0.1.4.tar.gz#md5=015061846254bd5d8c5dbc2913985153 (from https://pypi.python.org/simple/http_signature/), version: 0.1.4
    Using version 0.1.4 (newest of versions: 0.1.4, 0.1.3, 0.1.2, 0.1.1, 0.1.0)
    Downloading http_signature-0.1.4.tar.gz
    Downloading from URL https://pypi.python.org/packages/source/h/http_signature/http_signature-0.1.4.tar.gz#md5=015061846254bd5d8c5dbc2913985153 (from https://pypi.python.org/simple/http_signature/)
    Running setup.py (path:/opt/python2.7/venv/project/build/http-signature/setup.py) egg_info for package http-signature
    Running command python setup.py egg_info
    running egg_info
    creating pip-egg-info/http_signature.egg-info
    writing requirements to pip-egg-info/http_signature.egg-info/requires.txt
    writing pip-egg-info/http_signature.egg-info/PKG-INFO
    writing top-level names to pip-egg-info/http_signature.egg-info/top_level.txt
    writing dependency_links to pip-egg-info/http_signature.egg-info/dependency_links.txt
    writing manifest file 'pip-egg-info/http_signature.egg-info/SOURCES.txt'
    warning: manifest_maker: standard file '-c' not found

    reading manifest file 'pip-egg-info/http_signature.egg-info/SOURCES.txt'
    writing manifest file 'pip-egg-info/http_signature.egg-info/SOURCES.txt'
    Source in /opt/python2.7/venv/project/build/http-signature has version 0.1.4, which satisfies requirement http-signature (from djangorestframework-httpsignature)
    Installing collected packages: djangorestframework-httpsignature, http-signature
    Running setup.py install for djangorestframework-httpsignature
    Running command /opt/python2.7/venv/project/bin/python -c "import setuptools, tokenize;file='/opt/python2.7/venv/project/build/djangorestframework-httpsignature/setup.py';exec(compile(getattr(tokenize, 'open', open)(file).read().replace('\r\n', '\n'), file, 'exec'))" install --record /tmp/pip-KlN9KM-record/install-record.txt --single-version-externally-managed --compile --install-headers /opt/python2.7/venv/project/include/site/python2.7
    running install
    running build
    running build_py
    creating build
    creating build/lib
    creating build/lib/rest_framework_httpsignature
    copying rest_framework_httpsignature/views.py -> build/lib/rest_framework_httpsignature
    copying rest_framework_httpsignature/init.py -> build/lib/rest_framework_httpsignature
    copying rest_framework_httpsignature/models.py -> build/lib/rest_framework_httpsignature
    copying rest_framework_httpsignature/authentication.py -> build/lib/rest_framework_httpsignature
    copying rest_framework_httpsignature/tests.py -> build/lib/rest_framework_httpsignature
    running install_lib
    creating /opt/python2.7/venv/project/lib/python2.7/site-packages/rest_framework_httpsignature
    copying build/lib/rest_framework_httpsignature/views.py -> /opt/python2.7/venv/project/lib/python2.7/site-packages/rest_framework_httpsignature
    copying build/lib/rest_framework_httpsignature/init.py -> /opt/python2.7/venv/project/lib/python2.7/site-packages/rest_framework_httpsignature
    copying build/lib/rest_framework_httpsignature/models.py -> /opt/python2.7/venv/project/lib/python2.7/site-packages/rest_framework_httpsignature
    copying build/lib/rest_framework_httpsignature/authentication.py -> /opt/python2.7/venv/project/lib/python2.7/site-packages/rest_framework_httpsignature
    copying build/lib/rest_framework_httpsignature/tests.py -> /opt/python2.7/venv/project/lib/python2.7/site-packages/rest_framework_httpsignature
    byte-compiling /opt/python2.7/venv/project/lib/python2.7/site-packages/rest_framework_httpsignature/views.py to views.pyc
    byte-compiling /opt/python2.7/venv/project/lib/python2.7/site-packages/rest_framework_httpsignature/init.py to init.pyc
    byte-compiling /opt/python2.7/venv/project/lib/python2.7/site-packages/rest_framework_httpsignature/models.py to models.pyc
    byte-compiling /opt/python2.7/venv/project/lib/python2.7/site-packages/rest_framework_httpsignature/authentication.py to authentication.pyc
    byte-compiling /opt/python2.7/venv/project/lib/python2.7/site-packages/rest_framework_httpsignature/tests.py to tests.pyc
    running install_egg_info
    running egg_info
    writing requirements to djangorestframework_httpsignature.egg-info/requires.txt
    writing djangorestframework_httpsignature.egg-info/PKG-INFO
    writing top-level names to djangorestframework_httpsignature.egg-info/top_level.txt
    writing dependency_links to djangorestframework_httpsignature.egg-info/dependency_links.txt
    warning: manifest_maker: standard file '-c' not found

    reading manifest file 'djangorestframework_httpsignature.egg-info/SOURCES.txt'
    reading manifest template 'MANIFEST.in'
    writing manifest file 'djangorestframework_httpsignature.egg-info/SOURCES.txt'
    Copying djangorestframework_httpsignature.egg-info to /opt/python2.7/venv/project/lib/python2.7/site-packages/djangorestframework_httpsignature-0.1.3-py2.7.egg-info
    running install_scripts
    writing list of installed files to '/tmp/pip-KlN9KM-record/install-record.txt'
    Running setup.py install for http-signature
    Running command /opt/python2.7/venv/project/bin/python -c "import setuptools, tokenize;file='/opt/python2.7/venv/project/build/http-signature/setup.py';exec(compile(getattr(tokenize, 'open', open)(file).read().replace('\r\n', '\n'), file, 'exec'))" install --record /tmp/pip-0b13sK-record/install-record.txt --single-version-externally-managed --compile --install-headers /opt/python2.7/venv/project/include/site/python2.7
    running install
    running build
    got version from file http_signature/_version.py {'version': '0.1.4', 'full': '0872fa367ba2fd5c2338de460bd419c5c4ef996d'}
    running build_py
    creating build
    creating build/lib
    creating build/lib/http_signature
    copying http_signature/sign.py -> build/lib/http_signature
    copying http_signature/requests_auth.py -> build/lib/http_signature
    copying http_signature/utils.py -> build/lib/http_signature
    copying http_signature/init.py -> build/lib/http_signature
    copying http_signature/_version.py -> build/lib/http_signature
    running egg_info
    creating http_signature.egg-info
    writing requirements to http_signature.egg-info/requires.txt
    writing http_signature.egg-info/PKG-INFO
    writing top-level names to http_signature.egg-info/top_level.txt
    writing dependency_links to http_signature.egg-info/dependency_links.txt
    writing manifest file 'http_signature.egg-info/SOURCES.txt'
    warning: manifest_maker: standard file '-c' not found

    reading manifest file 'http_signature.egg-info/SOURCES.txt'
    writing manifest file 'http_signature.egg-info/SOURCES.txt'
    UPDATING build/lib/http_signature/_version.py
    running install_lib
    creating /opt/python2.7/venv/project/lib/python2.7/site-packages/http_signature
    copying build/lib/http_signature/sign.py -> /opt/python2.7/venv/project/lib/python2.7/site-packages/http_signature
    copying build/lib/http_signature/requests_auth.py -> /opt/python2.7/venv/project/lib/python2.7/site-packages/http_signature
    copying build/lib/http_signature/utils.py -> /opt/python2.7/venv/project/lib/python2.7/site-packages/http_signature
    copying build/lib/http_signature/init.py -> /opt/python2.7/venv/project/lib/python2.7/site-packages/http_signature
    copying build/lib/http_signature/_version.py -> /opt/python2.7/venv/project/lib/python2.7/site-packages/http_signature
    byte-compiling /opt/python2.7/venv/project/lib/python2.7/site-packages/http_signature/sign.py to sign.pyc
    byte-compiling /opt/python2.7/venv/project/lib/python2.7/site-packages/http_signature/requests_auth.py to requests_auth.pyc
    byte-compiling /opt/python2.7/venv/project/lib/python2.7/site-packages/http_signature/utils.py to utils.pyc
    byte-compiling /opt/python2.7/venv/project/lib/python2.7/site-packages/http_signature/init.py to init.pyc
    byte-compiling /opt/python2.7/venv/project/lib/python2.7/site-packages/http_signature/_version.py to _version.pyc
    running install_egg_info
    Copying http_signature.egg-info to /opt/python2.7/venv/project/lib/python2.7/site-packages/http_signature-0.1.4-py2.7.egg-info
    running install_scripts
    writing list of installed files to '/tmp/pip-0b13sK-record/install-record.txt'
    Successfully installed djangorestframework-httpsignature http-signature
    Cleaning up...
    Removing temporary dir /opt/python2.7/venv/project/build...

You can see pip fetching http_signature 0.1.4. Also, If I check what pip has downloaded for djangorestframework-httpsignature I can see

$ cat /opt/python2.7/venv/project/lib/python2.7/site-packages/djangorestframework_httpsignature-0.1.3-py2.7.egg-info/requires.txt

Django==1.6.2
djangorestframework==2.3.12
pycrypto==2.6.1

No trace of the git repo ... and finally if I try to install it explicitly I get

$ pip install -e git+https://github.com/digitalbazaar/py-http-signature
--editable=git+https://github.com/digitalbazaar/py-http-signature is not the right format; it must have #egg=Package
Storing debug log for failure in /home/vagrant/.pip/pip.log

Any ideas?

Thanks!

401 for bad signature, 403 for insufficient permissions

A 403 returned by this authentication scheme might indicate that the signature is invalid, or that the user doesn't have sufficient permissions.

DRF suggests raising an AuthenticationFailed for a bad signature, resulting in a 401 response (and not bothering to do the permissions check), leaving a 403 to indicate that the user was authenticated but has insufficient permissions. Further, an authenticate_header method could implement a WWW-Authenticate header in the 401 response with signature implementation instructions. i believe this potential exists in all the 3.x DRF releases.

Would that be a welcome PR? i recognize that it could break users' integration tests expecting the current "403" behavior.

Don't prevent installation on Django 1.8

Right now the requirements specify 'Django>=1.6.2,<1.8'. There is no need to restrict installation with the upcoming release. I suggest to have only 'Django>=1.6.2' instead.

Should not assume string.lower().upper() == string.upper()

The code in header_canonical() transform headers first to lower case and then to upper case, while the referred text in https://docs.djangoproject.com/en/1.7/ref/request-response/#django.http.HttpRequest.META (1.6 do no longer exist) state:

With the exception of CONTENT_LENGTH and CONTENT_TYPE, as given above, any HTTP headers in the request are converted to META keys by converting all characters to uppercase, replacing any hyphens with underscores and adding an HTTP_ prefix to the name.

It is not safe to assume that, first converting to lower case and then to upper case will result in the same string as going directly to upper case. For example, depending on the locale, the Turkish dottet capital I, can result in a dodless lower case I, which in turn end up with a dotless capital I. See https://en.wikipedia.org/wiki/Turkish_dotted_and_dotless_I for more info on this example. I am sure there are other examples.

I recommend going directly to upper case in the code.

RSA public key signatures does not work

Hi,

I just tried to use SignatureAuthentication with ALGORITHM = 'rsa-sha256'.
After debugging around, I found out that build_signature() throws exception "TypeError: Private key not available in this object" in line 70. That is because when using RSA public keys that function should be Verify not sign. Sign expects to have private key and that of course is not available in servers end.

Is this library still being developed?

Hi. I am considering to package this library for Debian, and wonder if it is still being developed? I need to set up a django service with signed http request, and this seem like a good alternative.

Upgrade & upload

PyPI is currently down for maintenance. Once it comes back online, version & upload the latest changes (which enable algorithms other than hmac-sha256).

DRF3 compatibility

I am trying to use Django REST Framework 3 along with rest framework-httpsignature but from the requirements I see that the maximum supported versions of DRF is the 2.3. Are there any serious issues preventing me from using it with DRF3?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.