dj-api-auth is a Django application, providing an AWS-alike API auth solution.
When I was seeking a simple solution rather than intricate OAuth, I was inspired by this article Designing a Secure REST (Web) API without OAuth. Thanks to the author and the comments.
- API key, SEC key related forms
- Each API key can be associated with a set of API
- API can be associated with user, your legacy code with
request.user
underneath can work smoothly withdj-api-auth
- Add auth by simply put a decorator on your view.
- Discover API with auth enabled automatically, these auth-required APIs will display in assignable list when creating API keys
- A Django command to scan and update API information to database.
- Generate a pair of API key and SEC key, assign some APIs to it.
- Client put API key and current UNIX time as
apikey
andtimestemp
in requestURL - Client also generate a
signature
by calculate a SHA256 value on the whole URL(withoutsignature
) by its known SEC key. - Server side will verify
- is
timestamp
from client in reasonable drift compare to server time. - is
apikey
from client exists - is the API client trying to access allowed for the
apikey
- compare the
signature
with the one calculated on server side by same algorithm
- is
- if any verification failed, return 403 error with brief message
- Add
djapiauth
toINSTALLED_APPS
insttings.py
- There are two optional settings
API_AUTH_ALLOWED_TIME_DRIFT
- optional, set the allowed time drift between server time and the
timestamp
parameter in coming URL. - format : integer, unit: second
- default : 300, (5 minutes)
- optional, set the allowed time drift between server time and the
API_AUTH_ADMIN_USER_FILTER
- 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.
- format: dictionary, the filter parameter will be passed to
get_user_model().objects.filter()
. e.g.{'name_startswith': 'admin'}
- default: {}, means all users will show in the API key creating form.
If 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
- For legacy views, we provide utility function
url_with_auth
indjapiauth
# add auth for a browser-oriented view
url_with_auth(r'^hello/$', 'djapp.views.index'),
#...
- For API views, simply add
@api_auth
for the view afterfrom djapiauth import api_auth
@api_auth
def api_whoami(request):
return JsonResponse({"user": "feifan", "boss": "lidan zhou"})
For class-baesd views, simply add djapiauth.utility.AuthMixin
as a base class to get auth protection.
from djapiauth import AuthMixin
class ProtectedView(AuthMixin,View):
def get(self, request):
return HttpResponse('hello, auth')
class UnprotectedView(AuthMixin,View):
api_auth = False
def get(self, request):
return HttpResponse('hello, no auth needed')
and add URL mapping in urls.py
...
url(r'^classbased1/$', apis.ProtectedView.as_view())
...
There's a Django command reloadentrypoints
to help you to collect and save all auth-required APIs to database.
since version 0.8
, I start using a tree-alike structure to speed up matching incoming URLs.
when you upgrade from previous versions, you should run following commands to expand database fields and build matching tree for each API key.
python manage.py migrate python manage.py repairapikeys
parameter missing
, any ofapikey
,timestamp
orsignature
missing in URLtime drift xxx
, check your local time and server time. You can implement an API to return server timeentry point not allowed for the API key
, check the assigned API for this API key inadmin
site or anywhere else you manage API keyssignature error
, obviously, signature mismatch
- Source code under
example/djapp
folder. - Test code is under
example/test/
, we havepython
andjavascript
test code ready.
Server application provides 2 APIs
/hello/
: reused the code of index view, add an auth layer on it/goodbye/
: a view you must access it by the signature stuff
DIY:
- Start the djapp
- there's already one pair of API+SEC keys:
483a570a
,d7228d70cd7f456d9bfdc35ed8fee375
- modify variable
URL
intest.py
, orURL
intest.js
- Generate API key and SEC key from localhost:8000/admin/xxx, modify variable
API_KEY
andSEC_KEY
intest.py
ortest.js
- Run
python test.py
ornode test.js
- login admin site with admin user:
admin
/123
, remove all APIs associated with483a570a
, try to run the test code again, you should see 403 errors__main__.APIException: (403, '{"error": "entry point not allowed for the API key"}')
- modify the API key to an invalid one
- modify the SEC key to an invalid one
- modify your local time to one hour ago
Thanks for the Javascript test code from Neil Chen (neil.chen.nj@gmail.com)