1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216
|
.. _authentication:
==============
Authentication
==============
Authentication is the component needed to verify who a
certain user is and to validate their access to the API.
Authentication answers the question "Who is this person?" This usually involves
requiring credentials, such as an API key or username/password or oAuth tokens.
Usage
=====
Using these classes is simple. Simply provide them (or your own class) as a
``Meta`` option to the ``Resource`` in question. For example::
from django.contrib.auth.models import User
from tastypie.authentication import BasicAuthentication
from tastypie.resources import ModelResource
class UserResource(ModelResource):
class Meta:
queryset = User.objects.all()
resource_name = 'auth/user'
excludes = ['email', 'password', 'is_superuser']
# Add it here.
authentication = BasicAuthentication()
Authentication Options
======================
Tastypie ships with the following ``Authentication`` classes:
.. warning:
Tastypie, when used with ``django.contrib.auth.models.User``, will check
to ensure that the ``User.is_active = True`` by default.
You can disable this behavior by initializing your ``Authentication`` class
with ``require_active=False``::
class UserResource(ModelResource):
class Meta:
# ...
authentication = BasicAuthentication(require_active=False)
*The behavior changed to active-by-default in v0.9.12.*
``Authentication``
~~~~~~~~~~~~~~~~~~
The no-op authentication option, the client is always allowed through. Very
useful for development and read-only APIs.
``BasicAuthentication``
~~~~~~~~~~~~~~~~~~~~~~~
This authentication scheme uses HTTP Basic Auth to check a user's credentials.
The username is their ``django.contrib.auth.models.User`` username (assuming
it is present) and their password should also correspond to that entry.
.. warning::
If you're using Apache & ``mod_wsgi``, you will need to enable
``WSGIPassAuthorization On``. See `this post`_ for details.
.. _`this post`: http://www.nerdydork.com/basic-authentication-on-mod_wsgi.html
``ApiKeyAuthentication``
~~~~~~~~~~~~~~~~~~~~~~~~
As an alternative to requiring sensitive data like a password, the
``ApiKeyAuthentication`` allows you to collect just username & a
machine-generated api key. Tastypie ships with a special ``Model`` just for
this purpose, so you'll need to ensure ``tastypie`` is in ``INSTALLED_APPS`` and
that the model's database tables have been created (e.g. via ``django-admin.py syncdb``).
To use this mechanism, the end user can either specify an ``Authorization``
header or pass the ``username/api_key`` combination as ``GET/POST`` parameters.
Examples::
# As a header
# Format is ``Authorization: ApiKey <username>:<api_key>
Authorization: ApiKey daniel:204db7bcfafb2deb7506b89eb3b9b715b09905c8
# As GET params
http://127.0.0.1:8000/api/v1/entries/?username=daniel&api_key=204db7bcfafb2deb7506b89eb3b9b715b09905c8
Tastypie includes a signal function you can use to auto-create ``ApiKey``
objects. Hooking it up looks like::
from django.contrib.auth.models import User
from django.db.models import signals
from tastypie.models import create_api_key
signals.post_save.connect(create_api_key, sender=User)
.. warning::
If you're using Apache & ``mod_wsgi``, you will need to enable
``WSGIPassAuthorization On``, otherwise ``mod_wsgi`` strips out the
``Authorization`` header. See `this post`_ for details (even though it
only mentions Basic auth).
.. note::
In some cases it may be useful to make the ``ApiKey`` model an `abstract
base class`_. To enable this, set ``settings.TASTYPIE_ABSTRACT_APIKEY`` to
``True``. See `the documentation for this setting`_ for more information.
.. _`this post`: http://www.nerdydork.com/basic-authentication-on-mod_wsgi.html
.. _`abstract base class`: https://docs.djangoproject.com/en/dev/topics/db/models/#abstract-base-classes
.. _`the documentation for this setting`: http://django-tastypie.readthedocs.org/en/latest/settings.html#tastypie-abstract-apikey
``SessionAuthentication``
~~~~~~~~~~~~~~~~~~~~~~~~~
This authentication scheme uses the built-in Django sessions to check if
a user is logged. This is typically useful when used by Javascript on the same
site as the API is hosted on.
It requires that the user has logged in & has an active session. They also must
have a valid CSRF token.
``DigestAuthentication``
~~~~~~~~~~~~~~~~~~~~~~~~~
This authentication scheme uses HTTP Digest Auth to check a user's
credentials. The username is their ``django.contrib.auth.models.User``
username (assuming it is present) and their password should be their
machine-generated api key. As with ApiKeyAuthentication, ``tastypie``
should be included in ``INSTALLED_APPS``.
.. warning::
If you're using Apache & ``mod_wsgi``, you will need to enable
``WSGIPassAuthorization On``. See `this post`_ for details (even though it
only mentions Basic auth).
.. _`this post`: http://www.nerdydork.com/basic-authentication-on-mod_wsgi.html
``OAuthAuthentication``
~~~~~~~~~~~~~~~~~~~~~~~
Handles OAuth, which checks a user's credentials against a separate service.
Currently verifies against OAuth 1.0a services.
This does *NOT* provide OAuth authentication in your API, strictly
consumption.
.. warning::
If you're used to in-browser OAuth flow (click a "Sign In" button, get
redirected, login on remote service, get redirected back), this isn't the
same. Most prominently, expecting that would cause API clients to have to use
tools like mechanize_ to fill in forms, which would be difficult.
This authentication expects that you're already followed some sort of OAuth
flow & that the credentials (Nonce/token/etc) are simply being passed to it.
It merely checks that the credentials are valid. No requests are made
to remote services as part of this authentication class.
.. _mechanize: http://pypi.python.org/pypi/mechanize/
``MultiAuthentication``
~~~~~~~~~~~~~~~~~~~~~~~
This authentication class actually wraps any number of other authentication classes,
attempting each until successfully authenticating. For example::
from django.contrib.auth.models import User
from tastypie.authentication import BasicAuthentication, ApiKeyAuthentication, MultiAuthentication
from tastypie.authorization import DjangoAuthorization
from tastypie.resources import ModelResource
class UserResource(ModelResource):
class Meta:
queryset = User.objects.all()
resource_name = 'auth/user'
excludes = ['email', 'password', 'is_superuser']
authentication = MultiAuthentication(BasicAuthentication(), ApiKeyAuthentication())
authorization = DjangoAuthorization()
In the case of an authentication returning a customized HttpUnauthorized, MultiAuthentication defaults to the first returned one. Authentication schemes that need to control the response, such as the included BasicAuthentication and DigestAuthentication, should be placed first.
Implementing Your Own Authentication/Authorization
==================================================
Implementing your own ``Authentication`` classes is a simple
process. ``Authentication`` has two methods to override (one of which is
optional but recommended to be customized)::
from tastypie.authentication import Authentication
class SillyAuthentication(Authentication):
def is_authenticated(self, request, **kwargs):
if 'daniel' in request.user.username:
return True
return False
# Optional but recommended
def get_identifier(self, request):
return request.user.username
Under this scheme, only users with 'daniel' in their username will be allowed
in.
|