{ "info": { "author": "Fan Fei", "author_email": "feifan.pub@gmail.com", "bugtrack_url": null, "classifiers": [ "Environment :: Web Environment", "Framework :: Django", "Intended Audience :: Developers", "License :: OSI Approved :: GNU General Public License v2 (GPLv2)", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.6", "Programming Language :: Python :: 2.7", "Topic :: Internet :: WWW/HTTP", "Topic :: Internet :: WWW/HTTP :: Dynamic Content" ], "description": "dj-api-auth\n===========\n**dj-api-auth** is a Django application, providing an AWS-alike API auth solution.\n\n\nWhen I was seeking a simple solution rather than intricate OAuth, I was inspired by this article \n`Designing a Secure REST (Web) API without OAuth\n`_.\nThanks to the author and the comments.\n\n\nFeatures\n--------\n1. API key, SEC key related forms\n2. Each API key can be associated with a set of API\n3. API can be associated with user, your legacy code with ``request.user`` underneath can work smoothly with ``dj-api-auth``\n4. Add auth by simply put a decorator on your view.\n5. Discover API with auth enabled automatically, these auth-required APIs will display in assignable list when creating API keys\n6. A Django command to scan and update API information to database.\n\n\nHow it works\n------------\n1. Generate a pair of API key and SEC key, assign some APIs to it. \n2. Client put API key and current UNIX time as ``apikey`` and ``timestemp`` in requestURL\n3. Client also generate a ``signature`` by calculate a SHA256 value on the whole URL(without ``signature``) by its known SEC key.\n4. Server side will verify \n\t- is ``timestamp`` from client in reasonable drift compare to server time.\n\t- is ``apikey`` from client exists\n\t- is the API client trying to access allowed for the ``apikey``\n\t- compare the ``signature`` with the one calculated on server side by same algorithm\n\n5. if any verification failed, return 403 error with brief message\n\n\nAdd to your project\n--------------------\n1. Add ``djapiauth`` to ``INSTALLED_APPS`` in ``sttings.py``\n\n2. There are two optional settings \n\n- ``API_AUTH_ALLOWED_TIME_DRIFT``\n\t- **optional**, set the allowed time drift between server time and the ``timestamp`` parameter in coming URL.\n\t- **format** : integer, unit: second\n\t- **default** : 300, (5 minutes) \n\n- ``API_AUTH_ADMIN_USER_FILTER``\n\t- **optional**, when creating API keys, you can assign the API key to an user, this filter is used to filter the users showing in the API key creating form.\n\t- **format**: dictionary, the filter parameter will be passed to ``get_user_model().objects.filter()``. e.g. ``{'name_startswith': 'admin'}``\n\t- **default**: {}, means all users will show in the API key creating form.\n\nGenerate/Manage API and SEC key\n-------------------------------\nIf you have ``admin`` enabled for your project, you can find these features in ``admin`` site. Otherwise, you can import forms from ``djapiauth.forms`` or write your own form based on models in ``djapiauth.models``\n\nAdd auth for function-based views\n----------------------------------\n- For legacy views, we provide utility function ``url_with_auth`` in ``djapiauth``\n\n.. code-block:: python\n\t\n\t# add auth for a browser-oriented view\n\turl_with_auth(r'^hello/$', 'djapp.views.index'),\n\t#...\n\n- For API views, simply add ``@api_auth`` for the view after ``from djapiauth import api_auth``\n\n.. code-block:: python\n\n\t@api_auth\n\tdef api_whoami(request):\n\t\treturn JsonResponse({\"user\": \"feifan\", \"boss\": \"lidan zhou\"})\n\nAdd auth for class-based views\n-------------------------------\nFor class-baesd views, simply add ``djapiauth.utility.AuthMixin`` as a base class to get auth protection.\n\n.. code-block:: python\n\n\tfrom djapiauth import AuthMixin\n\tclass ProtectedView(AuthMixin,View):\n\t def get(self, request):\n\t return HttpResponse('hello, auth')\n\n\n\tclass UnprotectedView(AuthMixin,View):\n\t api_auth = False\n\t def get(self, request):\n\t return HttpResponse('hello, no auth needed')\n\n\nand add URL mapping in ``urls.py``\n\n.. code-block:: python\n\n\t...\n\turl(r'^classbased1/$', apis.ProtectedView.as_view())\n\t...\n\n\nScan API\n-------------------\nThere's a Django command ``reloadentrypoints`` to help you to collect and save all auth-required APIs to database.\n\n\nAPI Key and associate API set\n-------------------------------\nsince version ``0.8``, I start using a tree-alike structure to speed up matching incoming URLs.\n\nwhen you upgrade from previous versions, you should run following commands to expand database fields and build matching tree for each API key.\n\n.. code-block:: \n\n\tpython manage.py migrate\n\tpython manage.py repairapikeys\n\n\n\nError messages\n----------------------\n- ``parameter missing``, any of ``apikey``, ``timestamp`` or ``signature`` missing in URL\n- ``time drift xxx``, check your local time and server time. You can implement an API to return server time\n- ``entry point not allowed for the API key``, check the assigned API for this API key in ``admin`` site or anywhere else you manage API keys\n- ``signature error``, obviously, signature mismatch\n\n\nDEMO\n------\n- Source code under ``example/djapp`` folder. \n- Test code is under ``example/test/``, we have ``python`` and ``javascript`` test code ready.\n\nServer application provides 2 APIs\n\n- ``/hello/`` : reused the code of index view, add an auth layer on it\n- ``/goodbye/`` : a view you must access it by the signature stuff\n\n\n\nDIY:\n\n- Start the djapp\n- there's already one pair of API+SEC keys: ``483a570a``, ``d7228d70cd7f456d9bfdc35ed8fee375``\n- modify variable ``URL`` in ``test.py``, or ``URL`` in ``test.js``\n- Generate API key and SEC key from localhost:8000/admin/xxx, modify variable ``API_KEY`` and ``SEC_KEY`` in ``test.py`` or ``test.js``\n- Run ``python test.py`` or ``node test.js``\n- login admin site with admin user: ``admin``/``123``, remove all APIs associated with ``483a570a``, try to run the test code again, you should see 403 errors ``__main__.APIException: (403, '{\"error\": \"entry point not allowed for the API key\"}')``\n- modify the API key to an invalid one\n- modify the SEC key to an invalid one\n- modify your local time to one hour ago\n\n\nThanks\n------\nThanks for the Javascript test code from Neil Chen (neil.chen.nj@gmail.com)", "description_content_type": null, "docs_url": null, "download_url": "UNKNOWN", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/feifangit/dj-api-auth", "keywords": null, "license": "GPL v2.0", "maintainer": null, "maintainer_email": null, "name": "dj-api-auth", "package_url": "https://pypi.org/project/dj-api-auth/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/dj-api-auth/", "project_urls": { "Download": "UNKNOWN", "Homepage": "https://github.com/feifangit/dj-api-auth" }, "release_url": "https://pypi.org/project/dj-api-auth/0.7/", "requires_dist": null, "requires_python": null, "summary": "A Django application provides an AWS-alike authentication for API access.", "version": "0.7" }, "last_serial": 1746204, "releases": { "0.1": [ { "comment_text": "", "digests": { "md5": "a826007d9a9cda417abf2e7803be6202", "sha256": "0dcf2e70d267e7bd48f806c068440b106ea08e1a0782d8f5ef3efebfab421853" }, "downloads": -1, "filename": "dj-api-auth-0.1.tar.gz", "has_sig": false, "md5_digest": "a826007d9a9cda417abf2e7803be6202", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 19123, "upload_time": "2015-03-08T18:12:10", "url": "https://files.pythonhosted.org/packages/c8/a0/f354b053faa873335dd3bfd7c166ba5084ae62b2d17a6277ff128862ad14/dj-api-auth-0.1.tar.gz" } ], "0.2": [ { "comment_text": "", "digests": { "md5": "b528a86b899a6ed4cc7b6617fa1e60e0", "sha256": "f03423d521ea6242344a3d127ae7fc9a3019644228934e72f106131c86fec089" }, "downloads": -1, "filename": "dj-api-auth-0.2.tar.gz", "has_sig": false, "md5_digest": "b528a86b899a6ed4cc7b6617fa1e60e0", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 36399, "upload_time": "2015-03-08T21:35:52", "url": "https://files.pythonhosted.org/packages/2e/1c/94fce4c22d09d8a031bae78452baf1131093b6c025ecbcc6f078001bcc55/dj-api-auth-0.2.tar.gz" } ], "0.3": [ { "comment_text": "", "digests": { "md5": "624bf8135f56d5bc7c53f34ceb754426", "sha256": "550b2d59bc9f522cb6f6e9102a892634259e1c15ac8e35562c3dd512c9e473ce" }, "downloads": -1, "filename": "dj-api-auth-0.3.tar.gz", "has_sig": false, "md5_digest": "624bf8135f56d5bc7c53f34ceb754426", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 36188, "upload_time": "2015-03-09T00:46:06", "url": "https://files.pythonhosted.org/packages/79/b2/420f4751cef781728fe0fedb8cfb1c8c5d3007bd5cf0b10444d8b91ac8f4/dj-api-auth-0.3.tar.gz" } ], "0.4": [ { "comment_text": "", "digests": { "md5": "8135878f23913df34defd2090b2e34f3", "sha256": "acbe9484e2b7a2682ca437a2a09a1e327efc80c11e004463843283312ffd9715" }, "downloads": -1, "filename": "dj-api-auth-0.4.tar.gz", "has_sig": false, "md5_digest": "8135878f23913df34defd2090b2e34f3", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 35474, "upload_time": "2015-03-09T18:10:36", "url": "https://files.pythonhosted.org/packages/63/15/0349d36129d04a29f31fa2217b38a03f75e69ac0c80f10a06761dbb9614f/dj-api-auth-0.4.tar.gz" } ], "0.5": [ { "comment_text": "", "digests": { "md5": "1ec86d24c5199907abda35925b3556c9", "sha256": "5f2f27f7e40f202c10b4deaf210b66e05791ce358a4df62d1d845c620528106a" }, "downloads": -1, "filename": "dj-api-auth-0.5.tar.gz", "has_sig": false, "md5_digest": "1ec86d24c5199907abda35925b3556c9", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 36014, "upload_time": "2015-03-10T20:41:24", "url": "https://files.pythonhosted.org/packages/b1/17/ec316202f626d6f527c928c0dee9aa83609cef96fb88187e1e6cc2c75c09/dj-api-auth-0.5.tar.gz" } ], "0.6": [ { "comment_text": "", "digests": { "md5": "adecd817531bb57fb353a269c60de94b", "sha256": "137b1e6bb2c3eb3286fcdf535046ed60e9381670fab56b1f88d82ff93ad5c645" }, "downloads": -1, "filename": "dj-api-auth-0.6.tar.gz", "has_sig": false, "md5_digest": "adecd817531bb57fb353a269c60de94b", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 37554, "upload_time": "2015-04-22T22:51:40", "url": "https://files.pythonhosted.org/packages/06/03/2605c06387c5725d6942f1f16420f438695af83ffc4463cff529880102f0/dj-api-auth-0.6.tar.gz" } ], "0.7": [ { "comment_text": "", "digests": { "md5": "ca78ac7945205e30b959666509d43192", "sha256": "6ae66fcb8ab8a27bf3121c06e9b482fbdf2e7e955d41265c73fb04460ef47e37" }, "downloads": -1, "filename": "dj-api-auth-0.7.tar.gz", "has_sig": false, "md5_digest": "ca78ac7945205e30b959666509d43192", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 39080, "upload_time": "2015-09-30T22:15:46", "url": "https://files.pythonhosted.org/packages/cb/de/5970573e656767fbea7e0b5077e02c5aa646aa4d5a9cb36efa17993ac85b/dj-api-auth-0.7.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "ca78ac7945205e30b959666509d43192", "sha256": "6ae66fcb8ab8a27bf3121c06e9b482fbdf2e7e955d41265c73fb04460ef47e37" }, "downloads": -1, "filename": "dj-api-auth-0.7.tar.gz", "has_sig": false, "md5_digest": "ca78ac7945205e30b959666509d43192", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 39080, "upload_time": "2015-09-30T22:15:46", "url": "https://files.pythonhosted.org/packages/cb/de/5970573e656767fbea7e0b5077e02c5aa646aa4d5a9cb36efa17993ac85b/dj-api-auth-0.7.tar.gz" } ] }