Django Oauth Toolkit Readthedocs Io en 1.2.0
Django Oauth Toolkit Readthedocs Io en 1.2.0
Release 1.2.0
Evonove
1 Support 3
2 Requirements 5
3 Index 7
3.1 Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
3.2 Tutorials . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
3.3 Django Rest Framework . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
3.4 Using the views . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
3.5 Templates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
3.6 Views code and details . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
3.7 Models . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
3.8 Advanced topics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
3.9 Signals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
3.10 Settings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
3.11 Separate Resource Server . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
3.12 Management commands . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
3.13 Glossary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
3.14 Contributing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
3.15 Changelog . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
i
ii
Django OAuth Toolkit Documentation, Release 1.2.0
Django OAuth Toolkit can help you providing out of the box all the endpoints, data and logic needed to add OAuth2
capabilities to your Django projects. Django OAuth Toolkit makes extensive use of the excellent OAuthLib, so that
everything is rfc-compliant.
See our Changelog for information on updates.
Contents 1
Django OAuth Toolkit Documentation, Release 1.2.0
2 Contents
CHAPTER 1
Support
If you need support please send a message to the Django OAuth Toolkit Google Group
3
Django OAuth Toolkit Documentation, Release 1.2.0
4 Chapter 1. Support
CHAPTER 2
Requirements
5
Django OAuth Toolkit Documentation, Release 1.2.0
6 Chapter 2. Requirements
CHAPTER 3
Index
3.1 Installation
INSTALLED_APPS = (
...
'oauth2_provider',
)
If you need an OAuth2 provider you’ll want to add the following to your urls.py
urlpatterns = [
...
url(r'^o/', include('oauth2_provider.urls', namespace='oauth2_provider')),
]
7
Django OAuth Toolkit Documentation, Release 1.2.0
3.2 Tutorials
Scenario
You want to make your own Authorization Server to issue access tokens to client applications for a certain API.
During this tutorial you will make an XHR POST from a Heroku deployed app to your localhost instance. Since
the domain that will originate the request (the app on Heroku) is different from the destination domain (your local
instance), you will need to install the django-cors-middleware app. These “cross-domain” requests are by default
forbidden by web browsers unless you use CORS.
Create a virtualenv and install django-oauth-toolkit and django-cors-middleware:
Start a Django project, add oauth2_provider and corsheaders to the installed apps, and enable admin:
INSTALLED_APPS = {
'django.contrib.admin',
# ...
'oauth2_provider',
'corsheaders',
}
Include the Django OAuth Toolkit urls in your urls.py, choosing the urlspace you prefer. For example:
urlpatterns = [
url(r"^admin/", admin.site.urls)),
url(r'^o/', include('oauth2_provider.urls', namespace='oauth2_provider')),
# ...
]
MIDDLEWARE = (
# ...
'corsheaders.middleware.CorsMiddleware',
# ...
)
Allow CORS requests from all domains (just for the scope of this tutorial):
8 Chapter 3. Index
Django OAuth Toolkit Documentation, Release 1.2.0
CORS_ORIGIN_ALLOW_ALL = True
Include the required hidden input in your login template, registration/login.html. The {{ next }} template context
variable will be populated with the correct redirect value. See the Django documentation for details on using login
templates.
As a final step, execute the migrate command, start the internal server, and login with your credentials.
Before your Application can use the Authorization Server for user login, you must first register the app (also known as
the Client.) Once registered, your app will be granted access to the API, subject to approval by its users.
Let’s register your application.
Point your browser to http://localhost:8000/o/applications/ and add an Application instance. Client id and Client Secret
are automatically generated; you have to provide the rest of the informations:
• User: the owner of the Application (e.g. a developer, or the currently logged in user.)
• Redirect uris: Applications must register at least one redirection endpoint before using the authorization
endpoint. The Authorization Server will deliver the access token to the client only if the client speci-
fies one of the verified redirection uris. For this tutorial, paste verbatim the value http://django-oauth-
toolkit.herokuapp.com/consumer/exchange/
• Client type: this value affects the security level at which some communications between the client application
and the authorization server are performed. For this tutorial choose Confidential.
• Authorization grant type: choose Authorization code
• Name: this is the name of the client application on the server, and will be displayed on the authorization request
page, where users can allow/deny access to their data.
Take note of the Client id and the Client Secret then logout (this is needed only for testing the authorization process
we’ll explain shortly)
Your authorization server is ready and can begin issuing access tokens. To test the process you need an OAuth2
consumer; if you are familiar enough with OAuth2, you can use curl, requests, or anything that speaks http. For the
rest of us, there is a consumer service deployed on Heroku to test your provider.
Authorizing an application to access OAuth2 protected data in an Authorization Code flow is always initiated by the
user. Your application can prompt users to click a special link to start the process. Go to the Consumer page and
complete the form by filling in your application’s details obtained from the steps in this tutorial. Submit the form, and
you’ll receive a link your users can use to access the authorization page.
3.2. Tutorials 9
Django OAuth Toolkit Documentation, Release 1.2.0
When a user clicks the link, she is redirected to your (possibly local) Authorization Server. If you’re not logged in,
you will be prompted for username and password. This is because the authorization page is login protected by django-
oauth-toolkit. Login, then you should see the (not so cute) form a user can use to give her authorization to the client
application. Flag the Allow checkbox and click Authorize, you will be redirected again to the consumer service.
If you are not redirected to the correct page after logging in successfully, you probably need to setup your login
template correctly.
At this point your authorization server redirected the user to a special page on the consumer passing in an Autho-
rization Code, a special token the consumer will use to obtain the final access token. This operation is usually done
automatically by the client application during the request/response cycle, but we cannot make a POST request from
Heroku to your localhost, so we proceed manually with this step. Fill the form with the missing data and click Submit.
If everything is ok, you will be routed to another page showing your access token, the token type, its lifetime and the
Refresh Token.
The page showing the access token retrieved from the Authorization Server also let you make a POST request to the
server itself to swap the refresh token for another, brand new access token. Just fill in the missing form fields and
click the Refresh button: if everything goes smoothly you will see the access and refresh token change their values,
otherwise you will likely see an error message. When you have finished playing with your authorization server, take
note of both the access and refresh tokens, we will use them for the next part of the tutorial.
So let’s make an API and protect it with your OAuth2 tokens in the part 2 of the tutorial.
Scenario
It’s very common for an Authorization Server to also be the Resource Server, usually exposing an API to let others
access its own resources. Django OAuth Toolkit implements an easy way to protect the views of a Django application
with OAuth2, in this tutorial we will see how to do it.
We start where we left the part 1 of the tutorial: you have an authorization server and we want it to provide an API
to access some kind of resources. We don’t need an actual resource, so we will simply expose an endpoint protected
with OAuth2: let’s do it in a class based view fashion!
Django OAuth Toolkit provides a set of generic class based view you can use to add OAuth behaviour to your views.
Open your views.py module and import the view:
Then create the view which will respond to the API endpoint:
10 Chapter 3. Index
Django OAuth Toolkit Documentation, Release 1.2.0
class ApiEndpoint(ProtectedResourceView):
def get(self, request, *args, **kwargs):
return HttpResponse('Hello, OAuth2!')
That’s it, our API will expose only one method, responding to GET requests. Now open your urls.py and specify the
URL this view will respond to:
if settings.DEBUG:
# OAuth2 Application Management endpoints
oauth2_endpoint_views += [
url(r'^applications/$', oauth2_views.ApplicationList.as_view(), name="list"),
url(r'^applications/register/$', oauth2_views.ApplicationRegistration.as_
˓→view(), name="register"),
url(r'^applications/(?P<pk>\d+)/$', oauth2_views.ApplicationDetail.as_view(),
˓→name="detail"),
url(r'^applications/(?P<pk>\d+)/delete/$', oauth2_views.ApplicationDelete.as_
˓→view(), name="delete"),
url(r'^applications/(?P<pk>\d+)/update/$', oauth2_views.ApplicationUpdate.as_
˓→view(), name="update"),
url(r'^authorized-tokens/(?P<pk>\d+)/delete/$', oauth2_views.
˓→AuthorizedTokenDeleteView.as_view(),
name="authorized-token-delete"),
]
urlpatterns = [
# OAuth 2 endpoints:
url(r'^o/', include(oauth2_endpoint_views, namespace="oauth2_provider")),
url(r'^api/hello', ApiEndpoint.as_view()), # an example resource endpoint
]
You will probably want to write your own application views to deal with permissions and access control but the ones
packaged with the library can get you started when developing the app.
Since we inherit from ProtectedResourceView, we’re done and our API is OAuth2 protected - for the sake of the lazy
programmer.
3.2. Tutorials 11
Django OAuth Toolkit Documentation, Release 1.2.0
Scenario
You want to use an Access Token to authenticate users against Django’s authentication system.
Setup a provider
You need a fully-functional OAuth2 provider which is able to release access tokens: just follow the steps in the part 1
of the tutorial. To enable OAuth2 token authentication you need a middleware that checks for tokens inside requests
and a custom authentication backend which takes care of token verification. In your settings.py:
AUTHENTICATION_BACKENDS = (
'oauth2_provider.backends.OAuth2Backend',
# Uncomment following if you want to access the admin
#'django.contrib.auth.backends.ModelBackend'
'...',
)
MIDDLEWARE = (
'...',
# If you use SessionAuthenticationMiddleware, be sure it appears before
˓→OAuth2TokenMiddleware.
# Or on Django<1.10:
MIDDLEWARE_CLASSES = (
'...',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'oauth2_provider.middleware.OAuth2TokenMiddleware',
'...',
)
You will likely use the django.contrib.auth.backends.ModelBackend along with the OAuth2 backend (or you might not
be able to log in into the admin), only pay attention to the order in which Django processes authentication backends.
12 Chapter 3. Index
Django OAuth Toolkit Documentation, Release 1.2.0
If you put the OAuth2 backend after the AuthenticationMiddleware and request.user is valid, the backend will do
nothing; if request.user is the Anonymous user it will try to authenticate the user using the OAuth2 access token.
If you put the OAuth2 backend before AuthenticationMiddleware, or AuthenticationMiddleware is not used at all, it
will try to authenticate user with the OAuth2 access token and set request.user and request._cached_user fields so that
AuthenticationMiddleware (when active) will not try to get user from the session.
If you use SessionAuthenticationMiddleware, be sure it appears before OAuth2TokenMiddleware. However Session-
AuthenticationMiddleware is NOT required for using django-oauth-toolkit.
The authentication backend will run smoothly with, for example, login_required decorators, so that you can have a
view like this in your views.py module:
from django.contrib.auth.decorators import login_required
from django.http.response import HttpResponse
@login_required()
def secret_page(request, *args, **kwargs):
return HttpResponse('Secret contents!', status=200)
To check everything works properly, mount the view above to some url:
urlpatterns = [
url(r'^secret$', 'my.views.secret_page', name='secret'),
'...',
]
You should have an Application registered at this point, if you don’t, follow the steps in the previous tutorials to create
one. Obtain an Access Token, either following the OAuth2 flow of your application or manually creating in the Django
admin. Now supposing your access token value is 123456 you can try to access your authenticated view:
curl -H "Authorization: Bearer 123456" -X GET http://localhost:8000/secret
Scenario
You’ve granted a user an Access Token, following part 1 and now you would like to revoke that token, probably in
response to a client request (to logout).
Revoking a Token
Be sure that you’ve granted a valid token. If you’ve hooked in oauth-toolkit into your urls.py as specified in part 1,
you’ll have a URL at /o/revoke_token. By submitting the appropriate request to that URL, you can revoke a user’s
Access Token.
Oauthlib is compliant with https://tools.ietf.org/html/rfc7009, so as specified, the revocation request requires:
• token: REQUIRED, this is the Access Token you want to revoke
• token_type_hint: OPTIONAL, designating either ‘access_token’ or ‘refresh_token’.
Note that these revocation-specific parameters are in addition to the authentication parameters already specified by
your particular client type.
3.2. Tutorials 13
Django OAuth Toolkit Documentation, Release 1.2.0
Setup a Request
Depending on the client type you’re using, the token revocation request you may submit to the authentication server
may vary. A Public client, for example, will not have access to your Client Secret. A revoke request from a public
client would omit that secret, and take the form:
Where token is Access Token specified above, and client_id is the Client id obtained in obtained in part 1. If your
application type is Confidential , it requires a Client secret, you will have to add it as one of the parameters:
The server will respond wih a 200 status code on successful revocation. You can use curl to make a revoke request on
your server. If you have access to a local installation of your authorization server, you can test revoking a token with
a request like that shown below, for a Confidential client.
Django OAuth Toolkit provide a support layer for Django REST Framework. This tutorial is based on the Django
REST Framework example and shows you how to easily integrate with it.
NOTE
The following code has been tested with Django 2.0.3 and Django REST Framework 3.7.7
Start a new Django project and add ‘rest_framework’ and ‘oauth2_provider’ to your INSTALLED_APPS setting.
INSTALLED_APPS = (
'django.contrib.admin',
...
'oauth2_provider',
'rest_framework',
)
Now we need to tell Django REST Framework to use the new authentication backend. To do so add the following
lines at the end of your settings.py module:
14 Chapter 3. Index
Django OAuth Toolkit Documentation, Release 1.2.0
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'oauth2_provider.contrib.rest_framework.OAuth2Authentication',
)
}
class GroupSerializer(serializers.ModelSerializer):
class Meta:
model = Group
fields = ("name", )
class UserDetails(generics.RetrieveAPIView):
permission_classes = [permissions.IsAuthenticated, TokenHasReadWriteScope]
queryset = User.objects.all()
serializer_class = UserSerializer
class GroupList(generics.ListAPIView):
permission_classes = [permissions.IsAuthenticated, TokenHasScope]
required_scopes = ['groups']
queryset = Group.objects.all()
serializer_class = GroupSerializer
# Setup the URLs and include login URLs for the browsable API.
urlpatterns = [
path('admin/', admin.site.urls),
path('o/', include('oauth2_provider.urls', namespace='oauth2_provider')),
path('users/', UserList.as_view()),
path('users/<pk>/', UserDetails.as_view()),
(continues on next page)
OAUTH2_PROVIDER = {
# this is the list of available scopes
'SCOPES': {'read': 'Read scope', 'write': 'Write scope', 'groups': 'Access to
˓→your groups'}
REST_FRAMEWORK = {
# ...
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
)
}
OAUTH2_PROVIDER.SCOPES setting parameter contains the scopes that the application will be aware of, so we can
use them for permission check.
Now run the following commands:
The first command creates the tables, the second creates the admin user account and the last one runs the application.
Next thing you should do is to login in the admin at
http://localhost:8000/admin
and create some users and groups that will be queried later through our API.
To obtain a valid access_token first we must register an application. DOT has a set of customizable views you can use
to CRUD application instances, just point your browser at:
http://localhost:8000/o/applications/
Click on the link to create a new application and fill the form with the following data:
• Name: just a name of your choice
• Client Type: confidential
• Authorization Grant Type: Resource owner password-based
Save your app!
16 Chapter 3. Index
Django OAuth Toolkit Documentation, Release 1.2.0
The user_name and password are the credential of the users registered in your Authorization Server, like any user
created in Step 2. Response should be something like:
{
"access_token": "<your_access_token>",
"token_type": "Bearer",
"expires_in": 36000,
"refresh_token": "<your_refresh_token>",
"scope": "read write groups"
}
Grab your access_token and start using your new OAuth2 API:
# Retrieve users
curl -H "Authorization: Bearer <your_access_token>" http://localhost:8000/users/
curl -H "Authorization: Bearer <your_access_token>" http://localhost:8000/users/1/
# Retrieve groups
curl -H "Authorization: Bearer <your_access_token>" http://localhost:8000/groups/
Let’s try to access resources using a token with a restricted scope adding a scope parameter to the token request
{
"access_token": "<your_access_token>",
"token_type": "Bearer",
"expires_in": 36000,
"refresh_token": "<your_refresh_token>",
"scope": "read"
}
# Retrieve users
curl -H "Authorization: Bearer <your_access_token>" http://localhost:8000/users/
curl -H "Authorization: Bearer <your_access_token>" http://localhost:8000/users/1/
Ok, this one works since users read only requires read scope.
You’ll get a “You do not have permission to perform this action” error because your access_token does not provide
the required scopes groups and write.
3.3.2 Permissions
Django OAuth Toolkit provides a few utility classes to use along with other permissions in Django REST Framework,
so you can easily add scoped-based permission checks to your API views.
More details on how to add custom permissions to your API Endpoints can be found at the official Django REST
Framework documentation
TokenHasScope
The TokenHasScope permission class allows access only when the current access token has been authorized for all the
scopes listed in the required_scopes field of the view.
For example:
class SongView(views.APIView):
authentication_classes = [OAuth2Authentication]
permission_classes = [TokenHasScope]
required_scopes = ['music']
TokenHasReadWriteScope
The TokenHasReadWriteScope permission class allows access based on the READ_SCOPE and WRITE_SCOPE con-
figured in the settings.
When the current request’s method is one of the “safe” methods GET, HEAD, OPTIONS the access is allowed only if
the access token has been authorized for the READ_SCOPE scope. When the request’s method is one of POST, PUT,
PATCH, DELETE the access is allowed if the access token has been authorized for the WRITE_SCOPE.
The required_scopes attribute is optional and can be used by other scopes needed in the view.
For example:
class SongView(views.APIView):
authentication_classes = [OAuth2Authentication]
permission_classes = [TokenHasReadWriteScope]
required_scopes = ['music']
When a request is performed both the READ_SCOPE \ WRITE_SCOPE and ‘music’ scopes are required to be autho-
rized for the current access token.
TokenHasResourceScope
The TokenHasResourceScope permission class allows access only when the current access token has been authorized
for all the scopes listed in the required_scopes field of the view but according of request’s method.
18 Chapter 3. Index
Django OAuth Toolkit Documentation, Release 1.2.0
When the current request’s method is one of the “safe” methods, the access is allowed only if the access token has
been authorized for the scope:read scope (for example music:read). When the request’s method is one of “non safe”
methods, the access is allowed only if the access token has been authorized for the scope:write scope (for example
music:write).
class SongView(views.APIView):
authentication_classes = [OAuth2Authentication]
permission_classes = [TokenHasResourceScope]
required_scopes = ['music']
The required_scopes attribute is mandatory (you just need inform the resource scope).
IsAuthenticatedOrTokenHasScope
The IsAuthenticatedOrTokenHasScope permission class allows access only when the current access token has been
authorized for all the scopes listed in the required_scopes field of the view but according to the request’s method.
It also allows access to Authenticated users who are authenticated in django, but were not authenticated through the
OAuth2Authentication class. This allows for protection of the API using scopes, but still let’s users browse the full
browseable API. To restrict users to only browse the parts of the browseable API they should be allowed to see, you
can combine this with the DjangoModelPermission or the DjangoObjectPermission.
For example:
class SongView(views.APIView):
permission_classes = [IsAuthenticatedOrTokenHasScope, DjangoModelPermission]
required_scopes = ['music']
TokenMatchesOASRequirements
The TokenMatchesOASRequirements permission class allows the access based on a per-method basis and with alter-
native lists of required scopes. This permission provides full functionality required by REST API specifications like
the OpenAPI Specification (OAS) security requirement object.
The required_alternate_scopes attribute is a required map keyed by HTTP method name where each value is a list of
alternative lists of required scopes.
In the follow example GET requires “read” scope, POST requires either “create” scope OR “post” and “widget”
scopes, etc.
class SongView(views.APIView):
authentication_classes = [OAuth2Authentication]
permission_classes = [TokenMatchesOASRequirements]
required_alternate_scopes = {
"GET": [["read"]],
"POST": [["create"], ["post", "widget"]],
"PUT": [["update"], ["put", "widget"]],
"DELETE": [["delete"], ["scope2", "scope3"]],
}
The following is a minimal OAS declaration that shows the same required alternate scopes. It is complete enough to
try it in the swagger editor.
openapi: "3.0.0"
info:
title: songs
version: v1
components:
securitySchemes:
song_auth:
type: oauth2
flows:
implicit:
authorizationUrl: http://localhost:8000/o/authorize
scopes:
read: read about a song
create: create a new song
update: update an existing song
delete: delete a song
post: create a new song
widget: widget scope
scope2: scope too
scope3: another scope
paths:
/songs:
get:
security:
- song_auth: [read]
responses:
'200':
description: A list of songs.
post:
security:
- song_auth: [create]
- song_auth: [post, widget]
responses:
'201':
description: new song added
put:
security:
- song_auth: [update]
- song_auth: [put, widget]
responses:
'204':
description: song updated
delete:
security:
- song_auth: [delete]
- song_auth: [scope2, scope3]
responses:
'200':
description: song deleted
Django OAuth Toolkit provides a set of pre-defined views for different purposes:
20 Chapter 3. Index
Django OAuth Toolkit Documentation, Release 1.2.0
Django OAuth Toolkit provides decorators to help you in protecting your function-based views.
protected_resource(scopes=None, validator_cls=OAuth2Validator, server_cls=Server)
Decorator to protect views by providing OAuth2 authentication out of the box, optionally with scope handling.
Basic usage, without using scopes:
from oauth2_provider.decorators import protected_resource
@protected_resource()
def my_view(request):
# An access token is required to get here...
# ...
pass
If you want to check scopes as well when accessing a view you can pass them along as decorator’s parameter:
from oauth2_provider.decorators import protected_resource
@protected_resource(scopes=['can_make_it can_break_it'])
def my_view(request):
# An access token AND the right scopes are required to get here...
# ...
pass
The decorator also accept server and validator classes if you want or need to use your own OAuth2 logic:
from oauth2_provider.decorators import protected_resource
from myapp.oauth2_validators import MyValidator
@protected_resource(validator_cls=MyValidator)
def my_view(request):
# You have to leverage your own logic to get here...
# ...
pass
@rw_protected_resource()
def my_view(request):
# If this is a POST, you have to provide 'write' scope to get here...
# ...
pass
If you need, you can ask for other scopes over “read” and “write”:
from oauth2_provider.decorators import rw_protected_resource
@rw_protected_resource(scopes=['exotic_scope'])
def my_view(request):
# If this is a POST, you have to provide 'exotic_scope write' scopes to get
˓→here...
# ...
(continues on next page)
Django OAuth Toolkit provides generic classes useful to implement OAuth2 protected endpoints using the Class Based
View approach.
ProtectedResourceView(ProtectedResourceMixin, View):
A view that provides OAuth2 authentication out of the box. To implement a protected endpoint, just define your
CBV as:
class MyEndpoint(ProtectedResourceView):
"""
A GET endpoint that needs OAuth2 authentication
"""
def get(self, request, *args, **kwargs):
return HttpResponse('Hello, World!')
Please notice: OPTION method is not OAuth2 protected to allow preflight requests.
ScopedProtectedResourceView(ScopedResourceMixin, ProtectedResourceView):
A view that provides OAuth2 authentication and scopes handling out of the box. To implement a protected
endpoint, just define your CBV specifying the required_scopes field:
class MyScopedEndpoint(ScopedProtectedResourceView):
required_scopes = ['can_make_it can_break_it']
"""
A GET endpoint that needs OAuth2 authentication
and a set of scopes: 'can_make_it' and 'can_break_it'
"""
def get(self, request, *args, **kwargs):
return HttpResponse('Hello, World!')
ReadWriteScopedResourceView(ReadWriteScopedResourceMixin, ProtectedResourceView):
A view that provides OAuth2 authentication and read/write default scopes. GET, HEAD, OPTIONS http methods
require read scope, others methods need the write scope. If you need, you can always specify an additional
list of scopes in the required_scopes field:
class MyRWEndpoint(ReadWriteScopedResourceView):
required_scopes = ['has_additional_powers'] # optional
"""
A GET endpoint that needs OAuth2 authentication
and the 'read' scope. If required_scopes was specified,
clients also need those scopes.
"""
def get(self, request, *args, **kwargs):
return HttpResponse('Hello, World!')
Generic views in DOT are obtained composing a set of mixins you can find in the views.mixins module: feel free to
use those mixins directly if you want to provide your own class based views.
22 Chapter 3. Index
Django OAuth Toolkit Documentation, Release 1.2.0
A set of views is provided to let users handle application instances without accessing Django Admin Site. Application
views are listed at the url applications/ and you can register a new one at the url applications/register. You can
override default templates located in templates/oauth2_provider folder and provide a custom layout. Every view
provides access only to data belonging to the logged in user who performs the request.
class oauth2_provider.views.application.ApplicationDelete(**kwargs)
View used to delete an application owned by the request.user
class oauth2_provider.views.application.ApplicationDetail(**kwargs)
Detail view for an application instance owned by the request.user
class oauth2_provider.views.application.ApplicationList(**kwargs)
List view for all the applications owned by the request.user
class oauth2_provider.views.application.ApplicationOwnerIsUserMixin
This mixin is used to provide an Application queryset filtered by the current request.user.
class oauth2_provider.views.application.ApplicationRegistration(**kwargs)
View used to register a new Application for the request.user
form_valid(form)
If the form is valid, save the associated model.
get_form_class()
Returns the form class for the application model
class oauth2_provider.views.application.ApplicationUpdate(**kwargs)
View used to update an application owned by the request.user
get_form_class()
Returns the form class for the application model
A set of views is provided to let users handle tokens that have been granted to them, without needing to accessing
Django Admin Site. Every view provides access only to the tokens that have been granted to the user performing the
request.
Granted Token views are listed at the url authorized_tokens/.
For each granted token there is a delete view that allows you to delete such token. You can override default templates
authorized-tokens.html for the list view and authorized-token-delete.html for the delete view; they are located inside
templates/oauth2_provider folder.
class oauth2_provider.views.token.AuthorizedTokenDeleteView(**kwargs)
View for revoking a specific token
get_queryset()
Return the QuerySet that will be used to look up the object.
This method is called by the default implementation of get_object() and may not be called if get_object()
is overridden.
model
alias of oauth2_provider.models.AccessToken
class oauth2_provider.views.token.AuthorizedTokensListView(**kwargs)
Show a page where the current logged-in user can see his tokens so they can revoke them
get_queryset()
Show only user”s tokens
model
alias of oauth2_provider.models.AccessToken
class oauth2_provider.views.mixins.OAuthLibMixin
This mixin decouples Django OAuth Toolkit from OAuthLib.
Users can configure the Server, Validator and OAuthlibCore classes used by this mixin by setting the following
class variables:
• server_class
• validator_class
• oauthlib_backend_class
create_authorization_response(request, scopes, credentials, allow)
A wrapper method that calls create_authorization_response on server_class instance.
Parameters
• request – The current django.http.HttpRequest object
• scopes – A space-separated string of provided scopes
• credentials – Authorization credentials dictionary containing client_id, state, redi-
rect_uri, response_type
• allow – True if the user authorize the client, otherwise False
create_revocation_response(request)
A wrapper method that calls create_revocation_response on the server_class instance.
Parameters request – The current django.http.HttpRequest object
create_token_response(request)
A wrapper method that calls create_token_response on server_class instance.
Parameters request – The current django.http.HttpRequest object
error_response(error, **kwargs)
Return an error to be displayed to the resource owner if anything goes awry.
Parameters error – OAuthToolkitError
classmethod get_oauthlib_backend_class()
Return the OAuthLibCore implementation class to use
classmethod get_oauthlib_core()
Cache and return OAuthlibCore instance so it will be created only on first request
get_scopes()
This should return the list of scopes required to access the resources. By default it returns an empty list.
classmethod get_server()
Return an instance of server_class initialized with a validator_class object
classmethod get_server_class()
Return the OAuthlib server class to use
24 Chapter 3. Index
Django OAuth Toolkit Documentation, Release 1.2.0
classmethod get_validator_class()
Return the RequestValidator implementation class to use
validate_authorization_request(request)
A wrapper method that calls validate_authorization_request on server_class instance.
Parameters request – The current django.http.HttpRequest object
verify_request(request)
A wrapper method that calls verify_request on server_class instance.
Parameters request – The current django.http.HttpRequest object
class oauth2_provider.views.mixins.ProtectedResourceMixin
Helper mixin that implements OAuth2 protection on request dispatch, specially useful for Django Generic Views
class oauth2_provider.views.mixins.ReadWriteScopedResourceMixin
Helper mixin that implements “read and write scopes” behavior
get_scopes(*args, **kwargs)
Return the scopes needed to access the resource
Parameters args – Support scopes injections from the outside (not yet implemented)
class oauth2_provider.views.mixins.ScopedResourceMixin
Helper mixin that implements “scopes handling” behaviour
get_scopes(*args, **kwargs)
Return the scopes needed to access the resource
Parameters args – Support scopes injections from the outside (not yet implemented)
3.5 Templates
A set of templates is provided. These templates range from Django Admin Site alternatives to manage the Apps that
use your App as a provider, to Error and Authorization Templates.
You can override default templates located in templates/oauth2_provider folder and provide a custom lay-
out. To override these templates you just need to create a folder named oauth2_provider inside your templates
folder and, inside this folder, add a file that matches the name of the template you’re trying to override.
The templates available are:
• base.html
• authorize.html
• Management:
– Application:
* application_list.html
* application_form.html
* application_registration_form.html
* application_detail.html
* application_confirm_delete.html
– Token:
* authorized-tokens.html
3.5. Templates 25
Django OAuth Toolkit Documentation, Release 1.2.0
* authorized-token-delete.html
3.5.1 base.html
If you just want a different look and feel you may only override this template. To inherit this template just add {%
extends "oauth2_provider/base.html" %} in the first line of the other templates. This is what is done
with the default templates.
The blocks defined in it are:
• title inside the HTML title tag;
• css inside the head;
• content in the body.
3.5.2 authorize.html
Note: If you haven’t created your own Application Model (see how in Extending the Application model), you will
get an AbstractApplication object.
Note: If it wasn’t provided on the request, the default one has been set (see default_redirect_uri()).
Important: One extra variable, named error will also be available if an Oauth2 exception occurs. This variable is
a dict with error and description
26 Chapter 3. Index
Django OAuth Toolkit Documentation, Release 1.2.0
{% extends "oauth2_provider/base.html" %}
{% load i18n %}
{% block content %}
<div class="block-center">
{% if not error %}
<form id="authorizationForm" method="post">
<h3 class="block-center-heading">{% trans "Authorize" %} {{
˓→application.name }}?</h3>
{% csrf_token %}
{{ form.errors }}
{{ form.non_field_errors }}
<div class="control-group">
<div class="controls">
<input type="submit" class="btn btn-large" value="Cancel"/>
<input type="submit" class="btn btn-large btn-primary" name=
˓→"allow" value="Authorize"/>
</div>
</div>
</form>
{% else %}
<h2>Error: {{ error.error }}</h2>
<p>{{ error.description }}</p>
{% endif %}
</div>
{% endblock %}
3.5.3 Management
The management templates are Django Admin Site alternatives to manage the Apps.
Application
Note: If you haven’t created your own Application Model (see how in Extending the Application model), you will
get an AbstractApplication object.
3.5. Templates 27
Django OAuth Toolkit Documentation, Release 1.2.0
application_list.html
application_form.html
application_registration_form.html
28 Chapter 3. Index
Django OAuth Toolkit Documentation, Release 1.2.0
application_detail.html
application_confirm_delete.html
Important: To override successfully this template you should provide a form that posts to the same URL, example:
<form method="post" action="">
Token
authorized-tokens.html
Important: To override successfully this template you should provide links to revoke the token, exam-
ple: <a href="{% url 'oauth2_provider:authorized-token-delete' authorized_token.
pk %}">revoke</a>
authorized-token-delete.html
Important: To override successfully this template you should provide a form that posts to the same URL, example:
<form method="post" action="">
3.5. Templates 29
Django OAuth Toolkit Documentation, Release 1.2.0
3.6.1 Generic
Generic views are intended to use in a “batteries included” fashion to protect own views with OAuth2 authentication
and Scopes handling.
class oauth2_provider.views.generic.ProtectedResourceView(**kwargs)
Generic view protecting resources by providing OAuth2 authentication out of the box
oauthlib_backend_class
alias of oauth2_provider.oauth2_backends.OAuthLibCore
server_class
alias of oauthlib.oauth2.rfc6749.endpoints.pre_configured.Server
class oauth2_provider.views.generic.ReadWriteScopedResourceView(**kwargs)
Generic view protecting resources with OAuth2 authentication and read/write scopes. GET, HEAD, OPTIONS
http methods require “read” scope. Otherwise “write” scope is required.
class oauth2_provider.views.generic.ScopedProtectedResourceView(**kwargs)
Generic view protecting resources by providing OAuth2 authentication and Scopes handling out of the box
3.6.2 Mixins
These views are mainly for internal use, but advanced users may use them as basic components to customize OAuth2
logic inside their Django applications.
class oauth2_provider.views.mixins.OAuthLibMixin
This mixin decouples Django OAuth Toolkit from OAuthLib.
Users can configure the Server, Validator and OAuthlibCore classes used by this mixin by setting the following
class variables:
• server_class
• validator_class
• oauthlib_backend_class
create_authorization_response(request, scopes, credentials, allow)
A wrapper method that calls create_authorization_response on server_class instance.
Parameters
• request – The current django.http.HttpRequest object
• scopes – A space-separated string of provided scopes
• credentials – Authorization credentials dictionary containing client_id, state, redi-
rect_uri, response_type
• allow – True if the user authorize the client, otherwise False
create_revocation_response(request)
A wrapper method that calls create_revocation_response on the server_class instance.
Parameters request – The current django.http.HttpRequest object
create_token_response(request)
A wrapper method that calls create_token_response on server_class instance.
30 Chapter 3. Index
Django OAuth Toolkit Documentation, Release 1.2.0
3.6.3 Base
Views needed to implement the main OAuth2 authorization flows supported by Django OAuth Toolkit.
class oauth2_provider.views.base.AuthorizationView(**kwargs)
Implements an endpoint to handle Authorization Requests as in RFC6749 Section 4.1.1 and prompting the user
with a form to determine if she authorizes the client application to access her data. This endpoint is reached
two times during the authorization process: * first receive a GET request from user asking authorization for a
certain client application, a form is served possibly showing some useful info and prompting for authorize/do
not authorize.
• then receive a POST request possibly after user authorized the access
Some informations contained in the GET request and needed to create a Grant token during the POST request
would be lost between the two steps above, so they are temporarily stored in hidden fields on the form. A
possible alternative could be keeping such informations in the session.
The endpoint is used in the following flows: * Authorization code * Implicit grant
form_class
alias of oauth2_provider.forms.AllowForm
form_valid(form)
If the form is valid, redirect to the supplied URL.
get(request, *args, **kwargs)
Handle GET requests: instantiate a blank version of the form.
get_initial()
Return the initial data to use for forms on this view.
oauthlib_backend_class
alias of oauth2_provider.oauth2_backends.OAuthLibCore
server_class
alias of oauthlib.oauth2.rfc6749.endpoints.pre_configured.Server
class oauth2_provider.views.base.BaseAuthorizationView(**kwargs)
Implements a generic endpoint to handle Authorization Requests as in RFC6749 Section 4.1.1. The view does
not implement any strategy to determine authorize/do not authorize logic. The endpoint is used in the following
flows:
• Authorization code
• Implicit grant
error_response(error, application, **kwargs)
Handle errors either by redirecting to redirect_uri with a json in the body containing error details or pro-
viding an error response
class oauth2_provider.views.base.RevokeTokenView(**kwargs)
Implements an endpoint to revoke access or refresh tokens
oauthlib_backend_class
alias of oauth2_provider.oauth2_backends.OAuthLibCore
server_class
alias of oauthlib.oauth2.rfc6749.endpoints.pre_configured.Server
class oauth2_provider.views.base.TokenView(**kwargs)
Implements an endpoint to provide access tokens
The endpoint is used in the following flows: * Authorization code * Password * Client credentials
oauthlib_backend_class
alias of oauth2_provider.oauth2_backends.OAuthLibCore
server_class
alias of oauthlib.oauth2.rfc6749.endpoints.pre_configured.Server
32 Chapter 3. Index
Django OAuth Toolkit Documentation, Release 1.2.0
3.7 Models
3.7. Models 33
Django OAuth Toolkit Documentation, Release 1.2.0
clean()
Hook for doing any extra model-wide validation after clean() has been called on every field by
self.clean_fields. Any ValidationError raised by this method will not be associated with a particular field;
it will have a special-case association with the field defined by NON_FIELD_ERRORS.
default_redirect_uri
Returns the default redirect_uri extracting the first item from the redirect_uris string
get_allowed_schemes()
Returns the list of redirect schemes allowed by the Application. By default, returns AL-
LOWED_REDIRECT_URI_SCHEMES.
is_usable(request)
Determines whether the application can be used.
Parameters request – The HTTP request being processed.
redirect_uri_allowed(uri)
Checks if given url is one of the items in redirect_uris string
Parameters uri – Url to check
class oauth2_provider.models.AbstractGrant(*args, **kwargs)
A Grant instance represents a token with a short lifetime that can be swapped for an access token, as described
in RFC6749 Section 4.1.2
Fields:
• user The Django user who requested the grant
• code The authorization code generated by the authorization server
• application Application instance this grant was asked for
• expires Expire time in seconds, defaults to settings.AUTHORIZATION_CODE_EXPIRE_SECONDS
• redirect_uri Self explained
• scope Required scopes, optional
is_expired()
Check token expiration with timezone awareness
class oauth2_provider.models.AbstractRefreshToken(*args, **kwargs)
A RefreshToken instance represents a token that can be swapped for a new access token when it expires.
Fields:
• user The Django user representing resources’ owner
• token Token value
• application Application instance
• access_token AccessToken instance this refresh token is bounded to
• revoked Timestamp of when this refresh token was revoked
revoke()
Mark this refresh token revoked and revoke related access token
class oauth2_provider.models.AccessToken(id, user, source_refresh_token, token, application,
expires, scope, created, updated)
exception DoesNotExist
exception MultipleObjectsReturned
34 Chapter 3. Index
Django OAuth Toolkit Documentation, Release 1.2.0
exception DoesNotExist
exception MultipleObjectsReturned
class oauth2_provider.models.Grant(id, user, code, application, expires, redirect_uri, scope,
created, updated)
exception DoesNotExist
exception MultipleObjectsReturned
class oauth2_provider.models.RefreshToken(id, user, token, application, access_token, cre-
ated, updated, revoked)
exception DoesNotExist
exception MultipleObjectsReturned
oauth2_provider.models.get_access_token_model()
Return the AccessToken model that is active in this project.
oauth2_provider.models.get_application_model()
Return the Application model that is active in this project.
oauth2_provider.models.get_grant_model()
Return the Grant model that is active in this project.
oauth2_provider.models.get_refresh_token_model()
Return the RefreshToken model that is active in this project.
An Application instance represents a Client on the Authorization server. Usually an Application is issued to client’s
developers after they log in on an Authorization Server and pass in some data which identify the Application itself
(let’s say, the application name). Django OAuth Toolkit provides a very basic implementation of the Application
model containing only the data strictly required during all the OAuth processes but you will likely need some extra
info, like application logo, acceptance of some user agreement and so on.
class AbstractApplication(models.Model)
This is the base class implementing the bare minimum for Django OAuth Toolkit to work
• client_id The client identifier issued to the client during the registration process as described in
RFC6749 Section 2.2
• user ref to a Django user
• redirect_uris The list of allowed redirect uri. The string consists of valid URLs separated by space
• client_type Client type as described in RFC6749 Section 2.1
• authorization_grant_type Authorization flows available to the Application
• client_secret Confidential secret issued to the client during the registration process as described in
RFC6749 Section 2.2
class MyApplication(AbstractApplication):
logo = models.ImageField()
agree = models.BooleanField()
Then you need to tell Django OAuth Toolkit which model you want to use to represent applications. Write something
like this in your settings module:
OAUTH2_PROVIDER_APPLICATION_MODEL='your_app_name.MyApplication'
Be aware that, when you intend to swap the application model, you should create and run the migration defining
the swapped application model prior to setting OAUTH2_PROVIDER_APPLICATION_MODEL. You’ll run into
models.E022 in Core system checks if you don’t get the order right.
That’s all, now Django OAuth Toolkit will use your model wherever an Application instance is needed.
Notice: OAUTH2_PROVIDER_APPLICATION_MODEL is the only setting variable that is not names-
paced, this is because of the way Django currently implements swappable models. See issue #90
(https://github.com/jazzband/django-oauth-toolkit/issues/90) for details
Multiple Grants
The default application model supports a single OAuth grant (e.g. authorization code, client credentials). If you need
applications to support multiple grants, override the allows_grant_type method. For example, if you want applications
to support the authorization code and client credentials grants, you might do the following:
class MyApplication(AbstractApplication):
def allows_grant_type(self, *grant_types):
# Assume, for this example, that self.authorization_grant_type is set to self.
˓→GRANT_AUTHORIZATION_CODE
Depending on the OAuth2 flow in use and the access token policy, users might be prompted for the same authorization
multiple times: sometimes this is acceptable or even desirable but other times it isn’t. To control DOT behaviour you
can use the approval_prompt parameter when hitting the authorization endpoint. Possible values are:
• force - users are always prompted for authorization.
• auto - users are prompted only the first time, subsequent authorizations for the same application and scopes will
be automatically accepted.
36 Chapter 3. Index
Django OAuth Toolkit Documentation, Release 1.2.0
You might want to completely bypass the authorization form, for instance if your application is an in-house product or
if you already trust the application owner by other means. To this end, you have to set skip_authorization =
True on the Application model, either programmaticaly or within the Django admin. Users will not be prompted
for authorization, even on the first use of the application.
3.9 Signals
Django-oauth-toolkit sends messages to various signals, depending on the action that has been triggered.
You can easily import signals from oauth2_provider.signals and attach your own listeners.
For example:
app_authorized.connect(handle_app_authorized)
3.10 Settings
Our configurations are all namespaced under the OAUTH2_PROVIDER settings with the exception
of OAUTH2_PROVIDER_APPLICATION_MODEL, OAUTH2_PROVIDER_ACCESS_TOKEN_MODEL,
OAUTH2_PROVIDER_GRANT_MODEL, OAUTH2_PROVIDER_REFRESH_TOKEN_MODEL: this is because
of the way Django currently implements swappable models. See issue #90 (https://github.com/jazzband/
django-oauth-toolkit/issues/90) for details.
For example:
OAUTH2_PROVIDER = {
'SCOPES': {
'read': 'Read scope',
'write': 'Write scope',
},
'CLIENT_ID_GENERATOR_CLASS': 'oauth2_provider.generators.ClientIdGenerator',
A big thank you to the guys from Django REST Framework for inspiring this.
3.9. Signals 37
Django OAuth Toolkit Documentation, Release 1.2.0
ACCESS_TOKEN_EXPIRE_SECONDS
The number of seconds an access token remains valid. Requesting a protected resource after this duration will fail.
Keep this value high enough so clients can cache the token for a reasonable amount of time.
ACCESS_TOKEN_MODEL
The import string of the class (model) representing your access tokens. Overwrite this value if you wrote your own
implementation (subclass of oauth2_provider.models.AccessToken).
ALLOWED_REDIRECT_URI_SCHEMES
APPLICATION_MODEL
The import string of the class (model) representing your applications. Overwrite this value if you wrote your own
implementation (subclass of oauth2_provider.models.Application).
AUTHORIZATION_CODE_EXPIRE_SECONDS
The number of seconds an authorization code remains valid. Requesting an access token after this duration will fail.
RFC6749 Section 4.1.2 recommends a 10 minutes (600 seconds) duration.
CLIENT_ID_GENERATOR_CLASS
The import string of the class responsible for generating client identifiers. These are usually random strings.
CLIENT_SECRET_GENERATOR_CLASS
The import string of the class responsible for generating client secrets. These are usually random strings.
CLIENT_SECRET_GENERATOR_LENGTH
The length of the generated secrets, in characters. If this value is too low, secrets may become subject to bruteforce
guessing.
GRANT_MODEL
The import string of the class (model) representing your grants. Overwrite this value if you wrote your own imple-
mentation (subclass of oauth2_provider.models.Grant).
38 Chapter 3. Index
Django OAuth Toolkit Documentation, Release 1.2.0
OAUTH2_SERVER_CLASS
The import string for the server_class (or oauthlib.oauth2.Server subclass) used in the
OAuthLibMixin that implements OAuth2 grant types.
OAUTH2_VALIDATOR_CLASS
The import string of the oauthlib.oauth2.RequestValidator subclass that validates every step of the
OAuth2 process.
OAUTH2_BACKEND_CLASS
The import string for the oauthlib_backend_class used in the OAuthLibMixin, to get a Server instance.
REFRESH_TOKEN_EXPIRE_SECONDS
The number of seconds before a refresh token gets removed from the database by the cleartokens management
command. Check cleartokens management command for further info.
REFRESH_TOKEN_GRACE_PERIOD_SECONDS
The number of seconds between when a refresh token is first used when it is expired. The most common case of
this for this is native mobile applications that run into issues of network connectivity during the refresh cycle and are
unable to complete the full request/response life cycle. Without a grace period the application, the app then has only a
consumed refresh token and the only recourse is to have the user re-authenticate. A suggested value, if this is enabled,
is 2 minutes.
REFRESH_TOKEN_MODEL
The import string of the class (model) representing your refresh tokens. Overwrite this value if you wrote your own
implementation (subclass of oauth2_provider.models.RefreshToken).
ROTATE_REFRESH_TOKEN
When is set to True (default) a new refresh token is issued to the client when the client refreshes an access token.
REQUEST_APPROVAL_PROMPT
Can be 'force' or 'auto'. The strategy used to display the authorization form. Refer to Skip authorization form.
SCOPES_BACKEND_CLASS
New in 0.12.0. The import string for the scopes backend class. Defaults to oauth2_provider.scopes.
SettingsScopes, which reads scopes through the settings defined below.
3.10. Settings 39
Django OAuth Toolkit Documentation, Release 1.2.0
SCOPES
DEFAULT_SCOPES
A list of scopes that should be returned by default. This is a subset of the keys of the SCOPES setting. By default this
is set to ‘__all__’ meaning that the whole set of SCOPES will be returned.
READ_SCOPE
WRITE_SCOPE
ERROR_RESPONSE_WITH_SCOPES
When authorization fails due to insufficient scopes include the required scopes in the response. Only applicable when
used with Django REST Framework
RESOURCE_SERVER_INTROSPECTION_URL
RESOURCE_SERVER_AUTH_TOKEN
The bearer token to authenticate the introspection request towards the introspection endpoint (RFC7662).
40 Chapter 3. Index
Django OAuth Toolkit Documentation, Release 1.2.0
RESOURCE_SERVER_TOKEN_CACHING_SECONDS
The number of seconds an authorization token received from the introspection endpoint remains valid. If the expire
time of the received token is less than RESOURCE_SERVER_TOKEN_CACHING_SECONDS the expire time will be
used.
Django OAuth Toolkit allows to separate the Authentication Server and the Resource Server. Based on the RFC 7662
Django OAuth Toolkit provides a rfc-compliant introspection endpoint. As well the Django OAuth Toolkit allows to
verify access tokens by the use of an introspection endpoint.
Setup the Authentication Server as described in the tutorial. Create a OAuth2 access token for the Resource Server
and add the introspection-Scope to the settings.
'SCOPES': {
'read': 'Read scope',
'write': 'Write scope',
'introspection': 'Introspect token scope',
...
},
The Authentication Server will listen for introspection requests. The endpoint is located within the
oauth2_provider.urls as /introspect/.
Example Request:
token=uH3Po4KXWP4dsY4zgyxH
Example Response:
HTTP/1.1 200 OK
Content-Type: application/json
{
"active": true,
"client_id": "oUdofn7rfhRtKWbmhyVk",
"username": "jdoe",
"scope": "read write dolphin",
"exp": 1419356238
}
Setup the Resource Server like the Authentication Server as described in the tutorial. Add
RESOURCE_SERVER_INTROSPECTION_URL and either RESOURCE_SERVER_AUTH_TOKEN or
RESOURCE_SERVER_INTROSPECTION_CREDENTIALS as a (id,secret) tuple to your settings. The
Resource Server will try to verify its requests on the Authentication Server.
OAUTH2_PROVIDER = {
...
'RESOURCE_SERVER_INTROSPECTION_URL': 'https://example.org/o/introspect/',
'RESOURCE_SERVER_AUTH_TOKEN': '3yUqsWtwKYKHnfivFcJu', # OR this but not both:
# 'RESOURCE_SERVER_INTROSPECTION_CREDENTIALS': ('rs_client_id','rs_client_secret
˓→'),
...
}
Django OAuth Toolkit exposes some useful management commands that can be run via shell or by other means (eg:
cron)
3.12.1 cleartokens
The cleartokens management command allows the user to remove those refresh tokens whose lifetime is greater
than the amount specified by REFRESH_TOKEN_EXPIRE_SECONDS settings. It is important that this command is
run regularly (eg: via cron) to avoid cluttering the database with expired refresh tokens.
If cleartokens runs daily the maximum delay before a refresh token is removed is
REFRESH_TOKEN_EXPIRE_SECONDS + 1 day. This is normally not a problem since refresh tokens are
long lived.
Note: Refresh tokens need to expire before AccessTokens can be removed from the database. Using cleartokens
without REFRESH_TOKEN_EXPIRE_SECONDS has limited effect.
3.13 Glossary
Authorization Server The authorization server asks resource owners for their consensus to let client applications
access their data. It also manages and issues the tokens needed for all the authorization flows supported by
OAuth2 spec. Usually the same application offering resources through an OAuth2-protected API also behaves
like an authorization server.
Resource Server An application providing access to its own resources through an API protected following the
OAuth2 spec.
Application An Application represents a Client on the Authorization server. Usually an Application is created
manually by client’s developers after logging in on an Authorization Server.
42 Chapter 3. Index
Django OAuth Toolkit Documentation, Release 1.2.0
Client A client is an application authorized to access OAuth2-protected resources on behalf and with the authorization
of the resource owner.
Resource Owner The user of an application which exposes resources to third party applications through OAuth2.
The resource owner must give her authorization for third party applications to be able to access her data.
Access Token A token needed to access resources protected by OAuth2. It has a lifetime which is usually quite short.
Authorization Code The authorization code is obtained by using an authorization server as an intermediary between
the client and resource owner. It is used to authenticate the client and grant the transmission of the Access
Token.
Authorization Token A token the authorization server issues to clients that can be swapped for an access token. It
has a very short lifetime since the swap has to be performed shortly after users provide their authorization.
Refresh Token A token the authorization server may issue to clients and can be swapped for a brand new access
token, without repeating the authorization process. It has no expire time.
3.14 Contributing
3.14.1 Setup
3.14.2 Issues
You can find the list of bugs, enhancements and feature requests on the issue tracker. If you want to fix an issue, pick
up one and add a comment stating you’re working on it. If the resolution implies a discussion or if you realize the
comments on the issue are growing pretty fast, move the discussion to the Google Group.
Please avoid providing a pull request from your master and use topic branches instead; you can add as many commits
as you want but please keep them in one branch which aims to solve one single issue. Then submit your pull request.
To create a topic branch, simply do:
When you’re ready to submit your pull request, first push the topic branch to your GitHub repo:
Now you can go to your repository dashboard on GitHub and open a pull request starting from your topic branch.
You can apply your pull request to the master branch of django-oauth-toolkit (this should be the default behaviour of
GitHub user interface).
Next you should add a comment about your branch, and if the pull request refers to a certain issue, insert a link to it.
The repo managers will be notified of your pull request and it will be reviewed, in the meantime you can continue to
add commits to your topic branch (and push them up to GitHub) either if you see something that needs changing, or
in response to a reviewer’s comments. If a reviewer asks for changes, you do not need to close the pull and reissue
3.14. Contributing 43
Django OAuth Toolkit Documentation, Release 1.2.0
it after making changes. Just make the changes locally, push them to GitHub, then add a comment to the discussion
section of the pull request.
It’s a good practice to pull upstream changes from master into your fork on a regular basis, in fact if you work on
outdated code and your changes diverge too far from master, the pull request has to be rejected.
To pull in upstream changes:
git remote add upstream https://github.com/jazzband/django-oauth-toolkit.git
git fetch upstream
Note: Please be sure to rebase your commits on the master when possible, so your commits can be fast-forwarded:
we try to avoid merge commits when they are not necessary.
We really want your code, so please follow these simple guidelines to make the process as smooth as possible.
Django OAuth Toolkit aims to support different Python and Django versions, so we use tox to run tests on multiple
configurations. At any time during the development and at least before submitting the pull request, please run the
testsuite via:
tox
The first thing the core committers will do is run this command. Any pull request that fails this test suite will be
immediately rejected.
Whenever you add code, you have to add tests as well. We cannot accept untested code, so unless it is a peculiar
situation you previously discussed with the core committers, if your pull request reduces the test coverage it will be
immediately rejected.
There are no good nor bad conventions, just follow PEP8 (run some lint tool for this) and nobody will argue. Try
reading our code and grasp the overall philosophy regarding method and variable names, avoid black magics for the
sake of readability, keep in mind that simple is better than complex. If you feel the code is not straightforward, add a
comment. If you think a function is not trivial, add a docstrings.
The contents of this page are heavily based on the docs from django-admin2
44 Chapter 3. Index
Django OAuth Toolkit Documentation, Release 1.2.0
3.15 Changelog
• New feature: Class-based scopes backends. Listing scopes, available scopes and default scopes is now
done through the class that the SCOPES_BACKEND_CLASS setting points to. By default, this is set to
oauth2_provider.scopes.SettingsScopes which implements the legacy settings-based scope behaviour. No
changes are necessary.
• Dropped support for Python 3.2 and Python 3.3, added support for Python 3.6
• Support for the scopes query parameter, deprecated in 0.6.1, has been dropped
• #448: Added support for customizing applications’ allowed grant types
• #141: The is_usable(request) method on the Application model can be overridden to dynamically enable or
disable applications.
• #434: Relax URL patterns to allow for UUID primary keys
• #424: Added a ROTATE_REFRESH_TOKEN setting to control whether refresh tokens are reused or not
• #315: AuthorizationView does not overwrite requests on get
• #425: Added support for Django 1.10
• #396: Added an IsAuthenticatedOrTokenHasScope Permission
• #357: Support multiple-user clients by allowing User to be NULL for Applications
• #389: Reuse refresh tokens if enabled.
• #322: dropping support for python 2.6 and django 1.4, 1.5, 1.6
• #310: Fixed error that could occur sometimes when checking validity of incomplete AccessToken/Grant
• #333: Added possibility to specify the default list of scopes returned when scope parameter is missing
• #325: Added management views of issued tokens
• #249: Added a command to clean expired tokens
• #323: Application registration view uses custom application model in form class
• #299: ‘server_class’ is now pluggable through Django settings
• #309: Add the py35-django19 env to travis
• #308: Use compact syntax for tox envs
• #306: Django 1.9 compatibility
• #288: Put additional information when generating token responses
• #297: Fixed doc about SessionAuthenticationMiddleware
• #273: Generic read write scope by resource
3.15. Changelog 45
Django OAuth Toolkit Documentation, Release 1.2.0
46 Chapter 3. Index
Django OAuth Toolkit Documentation, Release 1.2.0
• added support for scope query parameter keeping backwards compatibility for the original scopes parameter.
• __str__ method in Application model returns name when available
3.15. Changelog 47
Django OAuth Toolkit Documentation, Release 1.2.0
New Features
• Add Application management views, you no more need the admin to register, update and delete your application.
• Add support to configurable application model
• Add support for function based views
Backwards incompatible changes in 0.4.0
• SCOPE attribute in settings is now a dictionary to store {‘scope_name’: ‘scope_description’}
• Namespace ‘oauth2_provider’ is mandatory in urls. See issue #36
Bugfixes
• Issue #25: Bug in the Basic Auth parsing in Oauth2RequestValidator
• Issue #24: Avoid generation of client_id with “:” colon char when using HTTP Basic Auth
• Issue #21: IndexError when trying to authorize an application
• Issue #9: Default_redirect_uri is mandatory when grant_type is implicit, authorization_code or all-in-one
• Issue #22: Scopes need a verbose description
• Issue #33: Add django-oauth-toolkit version on example main page
• Issue #36: Add mandatory namespace to urls
• Issue #31: Add docstring to OAuthToolkitError and FatalClientError
• Issue #32: Add docstring to validate_uris
• Issue #34: Documentation tutorial part1 needs corsheaders explanation
• Issue #36: Add mandatory namespace to urls
• Issue #45: Add docs for AbstractApplication
• Issue #47: Add docs for views decorators
48 Chapter 3. Index
Django OAuth Toolkit Documentation, Release 1.2.0
• Core optimizations
3.15. Changelog 49
Django OAuth Toolkit Documentation, Release 1.2.0
50 Chapter 3. Index
CHAPTER 4
• genindex
• modindex
51
Django OAuth Toolkit Documentation, Release 1.2.0
o
oauth2_provider.models, 33
oauth2_provider.views.application, 23
oauth2_provider.views.base, 31
oauth2_provider.views.generic, 30
oauth2_provider.views.mixins, 24
oauth2_provider.views.token, 23
53
Django OAuth Toolkit Documentation, Release 1.2.0
A oauth2_provider.views.token), 23
AbstractAccessToken (class in oauth2_provider.models),
33
B
AbstractApplication (built-in class), 35 BaseAuthorizationView (class in
AbstractApplication (class in oauth2_provider.models), oauth2_provider.views.base), 32
33
AbstractGrant (class in oauth2_provider.models), 34
C
AbstractRefreshToken (class in oauth2_provider.models), clean() (oauth2_provider.models.AbstractApplication
34 method), 33
Access Token, 43 Client, 43
AccessToken (class in oauth2_provider.models), 34 create_authorization_response()
AccessToken.DoesNotExist, 34 (oauth2_provider.views.mixins.OAuthLibMixin
AccessToken.MultipleObjectsReturned, 34 method), 24, 30
create_revocation_response()
allow_scopes() (oauth2_provider.models.AbstractAccessToken
method), 33 (oauth2_provider.views.mixins.OAuthLibMixin
Application, 42 method), 24, 30
Application (class in oauth2_provider.models), 34 create_token_response() (oauth2_provider.views.mixins.OAuthLibMixin
Application.DoesNotExist, 35 method), 24, 30
Application.MultipleObjectsReturned, 35
ApplicationDelete (class in
D
oauth2_provider.views.application), 23 default_redirect_uri (oauth2_provider.models.AbstractApplication
ApplicationDetail (class in attribute), 34
oauth2_provider.views.application), 23
ApplicationList (class in
E
oauth2_provider.views.application), 23 error_response() (oauth2_provider.views.base.BaseAuthorizationView
ApplicationOwnerIsUserMixin (class in method), 32
oauth2_provider.views.application), 23 error_response() (oauth2_provider.views.mixins.OAuthLibMixin
ApplicationRegistration (class in method), 24, 31
oauth2_provider.views.application), 23
ApplicationUpdate (class in
F
oauth2_provider.views.application), 23 form_class (oauth2_provider.views.base.AuthorizationView
Authorization Code, 43 attribute), 32
Authorization Server, 42 form_valid() (oauth2_provider.views.application.ApplicationRegistration
Authorization Token, 43 method), 23
AuthorizationView (class in oauth2_provider.views.base), form_valid() (oauth2_provider.views.base.AuthorizationView
31 method), 32
AuthorizedTokenDeleteView (class in
oauth2_provider.views.token), 23
G
AuthorizedTokensListView (class in get() (oauth2_provider.views.base.AuthorizationView
method), 32
55
Django OAuth Toolkit Documentation, Release 1.2.0
56 Index
Django OAuth Toolkit Documentation, Release 1.2.0
scopes (oauth2_provider.models.AbstractAccessToken
attribute), 33
server_class (oauth2_provider.views.base.AuthorizationView
attribute), 32
server_class (oauth2_provider.views.base.RevokeTokenView
attribute), 32
server_class (oauth2_provider.views.base.TokenView at-
tribute), 32
server_class (oauth2_provider.views.generic.ProtectedResourceView
attribute), 30
T
TokenView (class in oauth2_provider.views.base), 32
V
validate_authorization_request()
(oauth2_provider.views.mixins.OAuthLibMixin
method), 25, 31
verify_request() (oauth2_provider.views.mixins.OAuthLibMixin
method), 25, 31
Index 57