Merge remote-tracking branch 'dulaccc/improve-doc'

Conflicts:
	docs/api.rst
	provider/__init__.py
This commit is contained in:
Alen Mujezinovic 2013-06-14 15:43:43 +01:00
commit 6d68d0225a
16 changed files with 178 additions and 110 deletions

11
.gitignore vendored
View File

@ -1,5 +1,8 @@
build/
dist/
django_oauth2_provider.egg-info/
*.pyc
.DS_Store
_build
.*.sw[po]
*.egg-info
dist
build
venv

View File

@ -14,7 +14,7 @@
:settings: `OAUTH_RESPONSE_TYPE_CHOICES`
The response types as outlined by :draft:`3.1.1`
The response types as outlined by :rfc:`3.1.1`
.. attribute:: SCOPES
@ -28,17 +28,17 @@
:settings: `OAUTH_EXPIRE_DELTA`
:default: `datetime.timedelta(days=365)`
The time to expiry for access tokens as outlined in :draft:`4.2.2` and
:draft:`5.1`.
The time to expiry for access tokens as outlined in :rfc:`4.2.2` and
:rfc:`5.1`.
.. attribute:: EXPIRE_CODE_DELTA
:settings: `OAUTH_EXPIRE_CODE_DELTA`
:default: `datetime.timedelta(seconds=10*60)`
The time to expiry for an authorization code grant as outlined in :draft:`4.1.2`.
The time to expiry for an authorization code grant as outlined in :rfc:`4.1.2`.
.. attribute:: ENFORCE_SECURE
:settings: `OAUTH_ENFORCE_SECURE`

View File

@ -11,7 +11,13 @@
# All configuration values have a default; values that are commented out
# serve to show the default.
import sys, os, provider
import sys, os
PROJECT_DIR = os.path.dirname(__file__)
location = lambda x: os.path.join(os.path.dirname(os.path.realpath(__file__)), x)
sys.path.append(location('..'))
import provider
os.environ['DJANGO_SETTINGS_MODULE'] = 'example.settings'
@ -94,7 +100,7 @@ pygments_style = 'sphinx'
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
html_theme = 'nature'
html_theme = 'default'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
@ -123,7 +129,7 @@ html_theme = 'nature'
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
#html_static_path = ['_static']
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.

96
docs/getting_started.rst Normal file
View File

@ -0,0 +1,96 @@
Getting started
===============
Installation
############
.. sourcecode:: sh
$ pip install django-oauth2-provider
Configuration
#############
Add OAuth2 Provider to :attr:`INSTALLED_APPS`
---------------------------------------------
::
INSTALLED_APPS = (
# ...
'provider',
'provider.oauth2',
)
Modify your settings to match your needs
----------------------------------------
The default settings are available in :attr:`provider.constants`.
Include the OAuth 2 views
-------------------------
Add :attr:`provider.oauth2.urls` to your root ``urls.py`` file.
::
url(r'^oauth2/', include('provider.oauth2.urls', namespace = 'oauth2')),
.. note:: The namespace argument is required.
Sync your database
------------------
.. sourcecode:: sh
$ python manage.py syncdb
$ python manage.py migrate
How to request an :attr:`access token` for the first time ?
###########################################################
Create a :attr:`client` entry in your database
----------------------------------------------
.. note:: To find out which type of :attr:`client` you need to create, read :rfc:`2.1`.
To create a new entry simply use the Django admin panel.
Request an access token
-----------------------
Assuming that you've used the same URL configuration as above, your
client needs to submit a :attr:`POST` request to
:attr:`/oauth2/access_token` including the following parameters:
* ``client_id`` - The client ID you've configured in the Django admin.
* ``client_secret`` - The client secret configured in the Django admin.
* ``username`` - The username with which you want to log in.
* ``password`` - The password corresponding to the user you're logging
in with.
**Request**
.. sourcecode:: sh
$ curl -X POST -d "client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&grant_type=password&username=YOUR_USERNAME&password=YOUR_PASSWORD" http://localhost:8000/oauth2/access_token/
**Response**
.. sourcecode:: json
{"access_token": "<your-access-token>", "scope": "read", "expires_in": 86399, "refresh_token": "<your-refresh-token>"}
This particular way of obtaining an access token is called a **Password
Grant**. All the other ways of acquiring an access token are outlined
in :rfc:`4`.
.. note:: Remember that you should always use HTTPS for all your OAuth
2 requests otherwise you won't be secured.

View File

@ -5,45 +5,15 @@ Welcome to django-oauth2-provider's documentation!
The default implementation makes reasonable assumptions about the allowed grant types and provides clients with two easy accessible URL endpoints. (:attr:`provider.oauth2.urls`)
If you require custom database backends, URLs, wish to extend the OAuth2_ protocol as defined in :draft:`8` or anything else, you can override the default behaviours by subclassing the views in :attr:`provider.views` and add your specific use cases.
If you require custom database backends, URLs, wish to extend the OAuth2_ protocol as defined in :rfc:`8` or anything else, you can override the default behaviours by subclassing the views in :attr:`provider.views` and add your specific use cases.
Installation
############
Getting started
###############
::
.. toctree::
:maxdepth: 2
pip install django-oauth2-provider
Configuration
#############
An example configuration is included in the repository_.
If you're happy using the default backend add these two lines to your settings:
::
INSTALLED_APPS = (
# ...
'provider',
'provider.oauth2',
)
And include :attr:`provider.oauth2.urls` into your root ``urls.py`` file.
::
url(r'^oauth2/', include('provider.oauth2.urls', namespace = 'oauth2')),
.. note:: The namespace argument is required.
Settings
########
The default settings are available in :attr:`provider.constants`.
getting_started
API
###
@ -64,5 +34,4 @@ Changes
Made by `Caffeinehit <http://www.caffeinehit.com/>`_.
.. _OAuth2: http://tools.ietf.org/html/draft-ietf-oauth-v2-23
.. _repository: https://github.com/caffeinehit/django-oauth2-provider/blob/master/example/settings.py
.. _OAuth2: http://tools.ietf.org/html/rfc6749

View File

@ -1,9 +0,0 @@
from django.conf.urls.defaults import patterns, include, url
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
url(r'^admin/', include(admin.site.urls)),
url(r'^oauth2/', include('provider.oauth2.urls', namespace='oauth2')),
)

View File

@ -1 +1,2 @@
__version__ = "0.2.6"

View File

@ -24,8 +24,8 @@ class OAuthValidationError(Exception):
self.cleaned_data.get('grant_type'))
})
The different types of errors are outlined in :draft:`4.2.2.1` and
:draft:`5.2`.
The different types of errors are outlined in :rfc:`4.2.2.1` and
:rfc:`5.2`.
"""
@ -37,8 +37,8 @@ class OAuthForm(forms.Form):
The shallow error dict is reused when returning error responses to the
client.
The different types of errors are outlined in :draft:`4.2.2.1` and
:draft:`5.2`.
The different types of errors are outlined in :rfc:`4.2.2.1` and
:rfc:`5.2`.
"""
def __init__(self, *args, **kwargs):
self.client = kwargs.pop('client', None)

View File

@ -5,7 +5,7 @@ from .models import AccessToken
class BaseBackend(object):
"""
Base backend used to authenticate clients as defined in :draft:`1` against
Base backend used to authenticate clients as defined in :rfc:`1` against
our database.
"""
def authenticate(self, request=None):
@ -19,7 +19,7 @@ class BaseBackend(object):
class BasicClientBackend(object):
"""
Backend that tries to authenticate a client through HTTP authorization
headers as defined in :draft:`2.3.1`.
headers as defined in :rfc:`2.3.1`.
"""
def authenticate(self, request=None):
auth = request.META.get('HTTP_AUTHORIZATION')
@ -47,7 +47,7 @@ class BasicClientBackend(object):
class RequestParamsClientBackend(object):
"""
Backend that tries to authenticate a client through request parameters
which might be in the request body or URI as defined in :draft:`2.3.1`.
which might be in the request body or URI as defined in :rfc:`2.3.1`.
"""
def authenticate(self, request=None):
if request is None:

View File

@ -48,7 +48,7 @@ class ClientAuthForm(forms.Form):
class ScopeChoiceField(forms.ChoiceField):
"""
Custom form field that seperates values on space as defined in
:draft:`3.3`.
:rfc:`3.3`.
"""
widget = forms.SelectMultiple
@ -103,7 +103,7 @@ class AuthorizationRequestForm(ScopeMixin, OAuthForm):
This form is used to validate the request data that the authorization
endpoint receives from clients.
Included data is specified in :draft:`4.1.1`.
Included data is specified in :rfc:`4.1.1`.
"""
# Setting all required fields to false to explicitly check by hand
# and use custom error messages that can be reused in the OAuth2
@ -132,7 +132,7 @@ class AuthorizationRequestForm(ScopeMixin, OAuthForm):
def clean_response_type(self):
"""
:draft:`3.1.1` Lists of values are space delimited.
:rfc:`3.1.1` Lists of values are space delimited.
"""
response_type = self.cleaned_data.get('response_type')
@ -153,7 +153,7 @@ class AuthorizationRequestForm(ScopeMixin, OAuthForm):
def clean_redirect_uri(self):
"""
:draft:`3.1.2` The redirect value has to match what was saved on the
:rfc:`3.1.2` The redirect value has to match what was saved on the
authorization server.
"""
redirect_uri = self.cleaned_data.get('redirect_uri')

View File

@ -35,7 +35,7 @@ class Client(models.Model):
* :attr:`client_secret`
* :attr:`client_type`
Clients are outlined in the :draft:`2` and its subsections.
Clients are outlined in the :rfc:`2` and its subsections.
"""
user = models.ForeignKey(AUTH_USER_MODEL, related_name='oauth2_client',
blank=True, null=True)
@ -55,7 +55,7 @@ class Grant(models.Model):
Default grant implementation. A grant is a code that can be swapped for an
access token. Grants have a limited lifetime as defined by
:attr:`provider.constants.EXPIRE_CODE_DELTA` and outlined in
:draft:`4.1.2`
:rfc:`4.1.2`
Expected fields:
@ -82,7 +82,7 @@ class AccessToken(models.Model):
Default access token implementation. An access token is a time limited
token to access a user's resources.
Access tokens are outlined :draft:`5`.
Access tokens are outlined :rfc:`5`.
Expected fields:

View File

@ -1,13 +1,13 @@
"""
The default implementation of the OAuth provider includes two public endpoints
that are meant for client (as defined in :draft:`1`) interaction.
that are meant for client (as defined in :rfc:`1`) interaction.
.. attribute:: ^authorize/$
This is the URL where a client should redirect a user to for authorization.
This endpoint expects the parameters defined in :draft:`4.1.1` and returns
responses as defined in :draft:`4.1.2` and :draft:`4.1.2.1`.
This endpoint expects the parameters defined in :rfc:`4.1.1` and returns
responses as defined in :rfc:`4.1.2` and :rfc:`4.1.2.1`.
.. attribute:: ^access_token/$
@ -15,21 +15,21 @@ that are meant for client (as defined in :draft:`1`) interaction.
This endpoint expects different parameters depending on the grant type:
* Access tokens: :draft:`4.1.3`
* Refresh tokens: :draft:`6`
* Password grant: :draft:`4.3.2`
* Access tokens: :rfc:`4.1.3`
* Refresh tokens: :rfc:`6`
* Password grant: :rfc:`4.3.2`
This endpoint returns responses depending on the grant type:
* Access tokens: :draft:`4.1.4` and :draft:`5.1`
* Refresh tokens: :draft:`4.1.4` and :draft:`5.1`
* Password grant: :draft:`5.1`
* Access tokens: :rfc:`4.1.4` and :rfc:`5.1`
* Refresh tokens: :rfc:`4.1.4` and :rfc:`5.1`
* Password grant: :rfc:`5.1`
To override, remove or add grant types, override the appropriate methods on
:class:`provider.views.AccessToken` and / or
:class:`provider.oauth2.views.AccessTokenView`.
Errors are outlined in :draft:`5.2`.
Errors are outlined in :rfc:`5.2`.
"""

View File

@ -3,7 +3,7 @@ Custom Sphinx documentation module to link to parts of the OAuth2 draft.
"""
from docutils import nodes, utils
base_url = "http://tools.ietf.org/html/draft-ietf-oauth-v2-23"
base_url = "http://tools.ietf.org/html/rfc6749"
def rfclink(name, rawtext, text, lineno, inliner, options={}, content=[]):
"""Link to the OAuth2 draft.
@ -21,7 +21,7 @@ def rfclink(name, rawtext, text, lineno, inliner, options={}, content=[]):
:param content: The directive content for customization.
"""
node = nodes.reference(rawtext, "Draft Section " + text, refuri="%s#section-%s" % (base_url, text))
node = nodes.reference(rawtext, "Section " + text, refuri="%s#section-%s" % (base_url, text))
return [node], []
@ -31,5 +31,5 @@ def setup(app):
:param app: Sphinx application context.
"""
app.add_role('draft', rfclink)
app.add_role('rfc', rfclink)
return

View File

@ -22,8 +22,8 @@ class OAuthError(Exception):
raise OAuthError({'error': 'invalid_request'})
The different types of errors are outlined in :draft:`4.2.2.1` and
:draft:`5.2`.
The different types of errors are outlined in :rfc:`4.2.2.1` and
:rfc:`5.2`.
"""
@ -32,7 +32,7 @@ class OAuthView(TemplateView):
"""
Base class for any view dealing with the OAuth flow. This class overrides
the dispatch method of :attr:`TemplateView` to add no-caching headers to
every response as outlined in :draft:`5.1`.
every response as outlined in :rfc:`5.1`.
"""
def dispatch(self, request, *args, **kwargs):
@ -87,7 +87,7 @@ class Mixin(object):
class Capture(OAuthView, Mixin):
"""
As stated in section :draft:`3.1.2.5` this view captures all the request
As stated in section :rfc:`3.1.2.5` this view captures all the request
parameters and redirects to another URL to avoid any leakage of request
parameters to potentially harmful JavaScripts.
@ -103,8 +103,8 @@ class Capture(OAuthView, Mixin):
def get_redirect_url(self, request):
"""
Return a redirect to a URL where the resource owner (see :draft:`1`)
authorizes the client (also :draft:`1`).
Return a redirect to a URL where the resource owner (see :rfc:`1`)
authorizes the client (also :rfc:`1`).
:return: :class:`django.http.HttpResponseRedirect`
@ -131,7 +131,7 @@ class Capture(OAuthView, Mixin):
class Authorize(OAuthView, Mixin):
"""
View to handle the client authorization as outlined in :draft:`4`.
View to handle the client authorization as outlined in :rfc:`4`.
Implementation must override a set of methods:
* :attr:`get_redirect_url`
@ -144,11 +144,11 @@ class Authorize(OAuthView, Mixin):
display the authorization form.
On successful authorization, it redirects the user back to the defined
client callback as defined in :draft:`4.1.2`.
client callback as defined in :rfc:`4.1.2`.
On authorization fail :attr:`Authorize` displays an error message to the
user with a modified redirect URL to the callback including the error
and possibly description of the error as defined in :draft:`4.1.2.1`.
and possibly description of the error as defined in :rfc:`4.1.2.1`.
"""
template_name = 'provider/authorize.html'
@ -188,7 +188,7 @@ class Authorize(OAuthView, Mixin):
"""
Save the authorization that the user granted to the client, involving
the creation of a time limited authorization code as outlined in
:draft:`4.1.2`.
:rfc:`4.1.2`.
Should return ``None`` in case authorization is not granted.
Should return a string representing the authorization code grant.
@ -226,7 +226,7 @@ class Authorize(OAuthView, Mixin):
:param request: :attr:`django.http.HttpRequest`
:param error: ``dict``
The different types of errors are outlined in :draft:`4.2.2.1`
The different types of errors are outlined in :rfc:`4.2.2.1`
"""
ctx = {}
ctx.update(error)
@ -338,11 +338,11 @@ class AccessToken(OAuthView, Mixin):
The default implementation supports the grant types defined in
:attr:`grant_types`.
According to :draft:`4.4.2` this endpoint too must support secure
According to :rfc:`4.4.2` this endpoint too must support secure
communication. For strict enforcement of secure communication at
application level set :attr:`settings.OAUTH_ENFORCE_SECURE` to ``True``.
According to :draft:`3.2` we can only accept POST requests.
According to :rfc:`3.2` we can only accept POST requests.
Returns with a status code of *400* in case of errors. *200* in case of
success.
@ -437,7 +437,7 @@ class AccessToken(OAuthView, Mixin):
**kwargs):
"""
Return an error response to the client with default status code of
*400* stating the error as outlined in :draft:`5.2`.
*400* stating the error as outlined in :rfc:`5.2`.
"""
return HttpResponse(json.dumps(error), mimetype=mimetype,
status=status, **kwargs)
@ -445,7 +445,7 @@ class AccessToken(OAuthView, Mixin):
def access_token_response(self, access_token):
"""
Returns a successful response after creating the access token
as defined in :draft:`5.1`.
as defined in :rfc:`5.1`.
"""
return HttpResponse(
json.dumps({
@ -459,7 +459,7 @@ class AccessToken(OAuthView, Mixin):
def authorization_code(self, request, data, client):
"""
Handle ``grant_type=authorization_code`` requests as defined in
:draft:`4.1.3`.
:rfc:`4.1.3`.
"""
grant = self.get_authorization_code_grant(request, request.POST,
client)
@ -476,7 +476,7 @@ class AccessToken(OAuthView, Mixin):
def refresh_token(self, request, data, client):
"""
Handle ``grant_type=refresh_token`` requests as defined in :draft:`6`.
Handle ``grant_type=refresh_token`` requests as defined in :rfc:`6`.
"""
rt = self.get_refresh_token_grant(request, data, client)
@ -491,7 +491,7 @@ class AccessToken(OAuthView, Mixin):
def password(self, request, data, client):
"""
Handle ``grant_type=password`` requests as defined in :draft:`4.3`.
Handle ``grant_type=password`` requests as defined in :rfc:`4.3`.
"""
data = self.get_password_grant(request, data, client)
@ -522,7 +522,7 @@ class AccessToken(OAuthView, Mixin):
def get(self, request):
"""
As per :draft:`3.2` the token endpoint *only* supports POST requests.
As per :rfc:`3.2` the token endpoint *only* supports POST requests.
Returns an error response.
"""
return self.error_response({
@ -531,7 +531,7 @@ class AccessToken(OAuthView, Mixin):
def post(self, request):
"""
As per :draft:`3.2` the token endpoint *only* supports POST requests.
As per :rfc:`3.2` the token endpoint *only* supports POST requests.
"""
if constants.ENFORCE_SECURE and not request.is_secure():
return self.error_response({

View File

@ -0,0 +1,2 @@
Django>=1.2
shortuuid>=0.3

View File

@ -21,7 +21,7 @@ setup(
'Framework :: Django',
],
install_requires=[
"shortuuid>=0.1"
"shortuuid>=0.3"
],
include_package_data=True,
zip_safe=False,